*/
enum { OSSH_DSA, OSSH_RSA };
+enum { OSSH_ENC_3DES, OSSH_ENC_AES };
struct openssh_key {
int type;
- int encrypted;
+ int encrypted, encryption;
char iv[32];
unsigned char *keyblob;
int keyblob_len, keyblob_size;
ret->encrypted = 0;
memset(ret->iv, 0, sizeof(ret->iv));
- fp = f_open(*filename, "r");
+ fp = f_open(filename, "r", FALSE);
if (!fp) {
errmsg = "unable to open key file";
goto error;
if (!strcmp(p, "ENCRYPTED"))
ret->encrypted = 1;
} else if (!strcmp(line, "DEK-Info")) {
- int i, j;
-
- if (strncmp(p, "DES-EDE3-CBC,", 13)) {
- errmsg = "ciphers other than DES-EDE3-CBC not supported";
+ int i, j, ivlen;
+
+ if (!strncmp(p, "DES-EDE3-CBC,", 13)) {
+ ret->encryption = OSSH_ENC_3DES;
+ ivlen = 8;
+ } else if (!strncmp(p, "AES-128-CBC,", 12)) {
+ ret->encryption = OSSH_ENC_AES;
+ ivlen = 16;
+ } else {
+ errmsg = "unsupported cipher";
goto error;
}
- p += 13;
- for (i = 0; i < 8; i++) {
- if (1 != sscanf(p, "%2x", &j))
- break;
+ p = strchr(p, ',') + 1;/* always non-NULL, by above checks */
+ for (i = 0; i < ivlen; i++) {
+ if (1 != sscanf(p, "%2x", &j)) {
+ errmsg = "expected more iv data in DEK-Info";
+ goto error;
+ }
ret->iv[i] = j;
p += 2;
}
- if (i < 8) {
- errmsg = "expected 16-digit iv in DEK-Info";
+ if (*p) {
+ errmsg = "more iv data than expected in DEK-Info";
goto error;
}
}
* - let block B equal MD5(A || passphrase || iv)
* - block C would be MD5(B || passphrase || iv) and so on
* - encryption key is the first N bytes of A || B
+ *
+ * (Note that only 8 bytes of the iv are used for key
+ * derivation, even when the key is encrypted with AES and
+ * hence there are 16 bytes available.)
*/
struct MD5Context md5c;
unsigned char keybuf[32];
/*
* Now decrypt the key blob.
*/
- des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv,
- key->keyblob, key->keyblob_len);
+ if (key->encryption == OSSH_ENC_3DES)
+ des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv,
+ key->keyblob, key->keyblob_len);
+ else {
+ void *ctx;
+ assert(key->encryption == OSSH_ENC_AES);
+ ctx = aes_make_context();
+ aes128_key(ctx, keybuf);
+ aes_iv(ctx, (unsigned char *)key->iv);
+ aes_ssh2_decrypt_blk(ctx, key->keyblob, key->keyblob_len);
+ aes_free_context(ctx);
+ }
memset(&md5c, 0, sizeof(md5c));
memset(keybuf, 0, sizeof(keybuf));
/*
* Encrypt the key.
+ *
+ * For the moment, we still encrypt our OpenSSH keys using
+ * old-style 3DES.
*/
if (passphrase) {
/*
* And save it. We'll use Unix line endings just in case it's
* subsequently transferred in binary mode.
*/
- fp = f_open(*filename, "wb"); /* ensure Unix line endings */
+ fp = f_open(filename, "wb", TRUE); /* ensure Unix line endings */
if (!fp)
goto error;
fputs(header, fp);
ret->keyblob = NULL;
ret->keyblob_len = ret->keyblob_size = 0;
- fp = f_open(*filename, "r");
+ fp = f_open(filename, "r", FALSE);
if (!fp) {
errmsg = "unable to open key file";
goto error;
* And save it. We'll use Unix line endings just in case it's
* subsequently transferred in binary mode.
*/
- fp = f_open(*filename, "wb"); /* ensure Unix line endings */
+ fp = f_open(filename, "wb", TRUE); /* ensure Unix line endings */
if (!fp)
goto error;
fputs("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n", fp);