@@ -29,7 +29,7 @@ const struct ssh_blockcipher ssh_ciphers[] =
2929{
3030 { "none" , "" , 0 , none },
3131 { "aes256-cbc" , "aes" , 256 / 8 , cbc },
32- { 0 },
32+ { "aes256-ctr" , "aes" , 256 / 8 , ctr },
3333};
3434
3535struct kdf_options {
@@ -232,9 +232,14 @@ static int s_decode_private_key(const unsigned char *in, unsigned long *inlen, l
232232static int s_decrypt_private_keys (unsigned char * in , unsigned long * inlen , struct kdf_options * opts )
233233{
234234 int err , cipher ;
235- unsigned char symkey [128 ];
236235 unsigned long symkey_len ;
237- symmetric_CBC cbc_ctx ;
236+ struct {
237+ unsigned char symkey [128 ];
238+ union {
239+ symmetric_CBC cbc ;
240+ symmetric_CTR ctr ;
241+ } ctx ;
242+ } s ;
238243
239244 LTC_ARGCHK (in != NULL );
240245 LTC_ARGCHK (inlen != NULL );
@@ -246,27 +251,41 @@ static int s_decrypt_private_keys(unsigned char *in, unsigned long *inlen, struc
246251 }
247252 symkey_len = opts -> cipher -> len + cipher_descriptor [cipher ].block_length ;
248253
249- if (sizeof (symkey ) < symkey_len ) {
254+ if (sizeof (s . symkey ) < symkey_len ) {
250255 return CRYPT_OVERFLOW ;
251256 }
252257
253- if ((err = bcrypt_pbkdf_openbsd (opts -> pw .pw , opts -> pw .l , opts -> salt , opts -> saltlen , opts -> num_rounds , find_hash ("sha512" ), symkey , & symkey_len )) != CRYPT_OK ) {
258+ if ((err = bcrypt_pbkdf_openbsd (opts -> pw .pw , opts -> pw .l , opts -> salt , opts -> saltlen ,
259+ opts -> num_rounds , find_hash ("sha512" ), s .symkey , & symkey_len )) != CRYPT_OK ) {
254260 return err ;
255261 }
256262
257- if ((err = cbc_start (cipher , symkey + opts -> cipher -> len , symkey , opts -> cipher -> len , 0 , & cbc_ctx )) != CRYPT_OK ) {
258- goto cleanup ;
259- }
260- if ((err = cbc_decrypt (in , in , * inlen , & cbc_ctx )) != CRYPT_OK ) {
261- goto cleanup ;
262- }
263- if ((err = cbc_done (& cbc_ctx )) != CRYPT_OK ) {
264- goto cleanup ;
263+ if (opts -> cipher -> mode == cbc ) {
264+ if ((err = cbc_start (cipher , s .symkey + opts -> cipher -> len , s .symkey , opts -> cipher -> len ,
265+ 0 , & s .ctx .cbc )) != CRYPT_OK ) {
266+ goto cleanup ;
267+ }
268+ if ((err = cbc_decrypt (in , in , * inlen , & s .ctx .cbc )) != CRYPT_OK ) {
269+ goto cleanup ;
270+ }
271+ if ((err = cbc_done (& s .ctx .cbc )) != CRYPT_OK ) {
272+ goto cleanup ;
273+ }
274+ } else if (opts -> cipher -> mode == ctr ) {
275+ if ((err = ctr_start (cipher , s .symkey + opts -> cipher -> len , s .symkey , opts -> cipher -> len ,
276+ 0 , CTR_COUNTER_BIG_ENDIAN , & s .ctx .ctr )) != CRYPT_OK ) {
277+ goto cleanup ;
278+ }
279+ if ((err = ctr_decrypt (in , in , * inlen , & s .ctx .ctr )) != CRYPT_OK ) {
280+ goto cleanup ;
281+ }
282+ if ((err = ctr_done (& s .ctx .ctr )) != CRYPT_OK ) {
283+ goto cleanup ;
284+ }
265285 }
266286
267287cleanup :
268- zeromem (symkey , sizeof (symkey ));
269- zeromem (& cbc_ctx , sizeof (cbc_ctx ));
288+ zeromem (& s , sizeof (s ));
270289
271290 return err ;
272291}
0 commit comments