Skip to content

Commit 95a249b

Browse files
committed
Add support for aes256-ctr encrypted SSH keys
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent 957f4a9 commit 95a249b

File tree

2 files changed

+42
-15
lines changed

2 files changed

+42
-15
lines changed

src/misc/pem/pem_ssh.c

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

3535
struct kdf_options {
@@ -232,9 +232,14 @@ static int s_decode_private_key(const unsigned char *in, unsigned long *inlen, l
232232
static 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

267287
cleanup:
268-
zeromem(symkey, sizeof(symkey));
269-
zeromem(&cbc_ctx, sizeof(cbc_ctx));
288+
zeromem(&s, sizeof(s));
270289

271290
return err;
272291
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-----BEGIN OPENSSH PRIVATE KEY-----
2+
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBYWWGgpa
3+
+aAsoGsV6JUqJ3AAAAGAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIEVemuQ8wNLBW205
4+
dbGF8l0DjxP7xLIWvmollyOm+9RoAAAAkK4XJkJqpHsZ0rYuwfnZu02gpmy3GnNmexMcyU
5+
SEtgIJNuTJbIlIn0oGBNt5xIWN6hweHq34gPvb6q9nbxgb6eS5WBFJI7+4Xng2hOrZ8rTm
6+
WR1YJLCnw4zk8dKKDehik+K6psMb5l7JqIUvu/F95NzO+LZXErhZ2/e6v2X2mqhSelg9fm
7+
gSe+OOWNesOUNtCQ==
8+
-----END OPENSSH PRIVATE KEY-----

0 commit comments

Comments
 (0)