diff options
Diffstat (limited to 'keyimport.c')
-rw-r--r-- | keyimport.c | 1200 |
1 files changed, 601 insertions, 599 deletions
diff --git a/keyimport.c b/keyimport.c index 1f9952d..d64a6f7 100644 --- a/keyimport.c +++ b/keyimport.c @@ -36,9 +36,11 @@ #include "dbutil.h" #include "ecc.h" +#if DROPBEAR_ECDSA static const unsigned char OID_SEC256R1_BLOB[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}; static const unsigned char OID_SEC384R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x22}; static const unsigned char OID_SEC521R1_BLOB[] = {0x2b, 0x81, 0x04, 0x00, 0x23}; +#endif #define PUT_32BIT(cp, value) do { \ (cp)[3] = (unsigned char)(value); \ @@ -71,11 +73,11 @@ static int sshcom_write(const char *filename, struct ssh2_userkey *key, int import_encrypted(const char* filename, int filetype) { - if (filetype == KEYFILE_OPENSSH) { - return openssh_encrypted(filename); + if (filetype == KEYFILE_OPENSSH) { + return openssh_encrypted(filename); #if 0 - } else if (filetype == KEYFILE_SSHCOM) { - return sshcom_encrypted(filename, NULL); + } else if (filetype == KEYFILE_SSHCOM) { + return sshcom_encrypted(filename, NULL); #endif } return 0; @@ -83,101 +85,101 @@ int import_encrypted(const char* filename, int filetype) { sign_key *import_read(const char *filename, char *passphrase, int filetype) { - if (filetype == KEYFILE_OPENSSH) { - return openssh_read(filename, passphrase); - } else if (filetype == KEYFILE_DROPBEAR) { - return dropbear_read(filename); + if (filetype == KEYFILE_OPENSSH) { + return openssh_read(filename, passphrase); + } else if (filetype == KEYFILE_DROPBEAR) { + return dropbear_read(filename); #if 0 - } else if (filetype == KEYFILE_SSHCOM) { - return sshcom_read(filename, passphrase); + } else if (filetype == KEYFILE_SSHCOM) { + return sshcom_read(filename, passphrase); #endif - } + } return NULL; } int import_write(const char *filename, sign_key *key, char *passphrase, - int filetype) { + int filetype) { - if (filetype == KEYFILE_OPENSSH) { - return openssh_write(filename, key, passphrase); - } else if (filetype == KEYFILE_DROPBEAR) { - return dropbear_write(filename, key); + if (filetype == KEYFILE_OPENSSH) { + return openssh_write(filename, key, passphrase); + } else if (filetype == KEYFILE_DROPBEAR) { + return dropbear_write(filename, key); #if 0 - } else if (filetype == KEYFILE_SSHCOM) { - return sshcom_write(filename, key, passphrase); + } else if (filetype == KEYFILE_SSHCOM) { + return sshcom_write(filename, key, passphrase); #endif - } + } return 0; } static sign_key *dropbear_read(const char* filename) { - buffer * buf = NULL; - sign_key *ret = NULL; - enum signkey_type type; + buffer * buf = NULL; + sign_key *ret = NULL; + enum signkey_type type; - buf = buf_new(MAX_PRIVKEY_SIZE); - if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) { - goto error; - } + buf = buf_new(MAX_PRIVKEY_SIZE); + if (buf_readfile(buf, filename) == DROPBEAR_FAILURE) { + goto error; + } - buf_setpos(buf, 0); - ret = new_sign_key(); + buf_setpos(buf, 0); + ret = new_sign_key(); - type = DROPBEAR_SIGNKEY_ANY; - if (buf_get_priv_key(buf, ret, &type) == DROPBEAR_FAILURE){ - goto error; - } - buf_free(buf); + type = DROPBEAR_SIGNKEY_ANY; + if (buf_get_priv_key(buf, ret, &type) == DROPBEAR_FAILURE){ + goto error; + } + buf_free(buf); - ret->type = type; + ret->type = type; - return ret; + return ret; error: - if (buf) { - buf_free(buf); - } - if (ret) { - sign_key_free(ret); - } - return NULL; + if (buf) { + buf_free(buf); + } + if (ret) { + sign_key_free(ret); + } + return NULL; } /* returns 0 on fail, 1 on success */ static int dropbear_write(const char*filename, sign_key * key) { - buffer * buf; - FILE*fp; - int len; - int ret; + buffer * buf; + FILE*fp; + int len; + int ret; - buf = buf_new(MAX_PRIVKEY_SIZE); - buf_put_priv_key(buf, key, key->type); + buf = buf_new(MAX_PRIVKEY_SIZE); + buf_put_priv_key(buf, key, key->type); - fp = fopen(filename, "w"); - if (!fp) { - ret = 0; - goto out; - } + fp = fopen(filename, "w"); + if (!fp) { + ret = 0; + goto out; + } - buf_setpos(buf, 0); - do { - len = fwrite(buf_getptr(buf, buf->len - buf->pos), - 1, buf->len - buf->pos, fp); - buf_incrpos(buf, len); - } while (len > 0 && buf->len != buf->pos); + buf_setpos(buf, 0); + do { + len = fwrite(buf_getptr(buf, buf->len - buf->pos), + 1, buf->len - buf->pos, fp); + buf_incrpos(buf, len); + } while (len > 0 && buf->len != buf->pos); - fclose(fp); + fclose(fp); - if (buf->pos != buf->len) { - ret = 0; - } else { - ret = 1; - } + if (buf->pos != buf->len) { + ret = 0; + } else { + ret = 1; + } out: - buf_free(buf); - return ret; + buf_free(buf); + return ret; } @@ -185,7 +187,7 @@ out: * Helper routines. (The base64 ones are defined in sshpubk.c.) */ -#define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \ +#define isbase64(c) ( ((c) >= 'A' && (c) <= 'Z') || \ ((c) >= 'a' && (c) <= 'z') || \ ((c) >= '0' && (c) <= '9') || \ (c) == '+' || (c) == '/' || (c) == '=' \ @@ -193,24 +195,24 @@ out: /* cpl has to be less than 100 */ static void base64_encode_fp(FILE * fp, unsigned char *data, - int datalen, int cpl) + int datalen, int cpl) { - unsigned char out[100]; - int n; - unsigned long outlen; - int rawcpl; - rawcpl = cpl * 3 / 4; - dropbear_assert((unsigned int)cpl < sizeof(out)); - - while (datalen > 0) { - n = (datalen < rawcpl ? datalen : rawcpl); - outlen = sizeof(out); - base64_encode(data, n, out, &outlen); - data += n; - datalen -= n; - fwrite(out, 1, outlen, fp); - fputc('\n', fp); - } + unsigned char out[100]; + int n; + unsigned long outlen; + int rawcpl; + rawcpl = cpl * 3 / 4; + dropbear_assert((unsigned int)cpl < sizeof(out)); + + while (datalen > 0) { + n = (datalen < rawcpl ? datalen : rawcpl); + outlen = sizeof(out); + base64_encode(data, n, out, &outlen); + data += n; + datalen -= n; + fwrite(out, 1, outlen, fp); + fputc('\n', fp); + } } /* * Read an ASN.1/BER identifier and length pair. @@ -222,14 +224,14 @@ static void base64_encode_fp(FILE * fp, unsigned char *data, */ /* ASN.1 tag classes. */ -#define ASN1_CLASS_UNIVERSAL (0 << 6) -#define ASN1_CLASS_APPLICATION (1 << 6) +#define ASN1_CLASS_UNIVERSAL (0 << 6) +#define ASN1_CLASS_APPLICATION (1 << 6) #define ASN1_CLASS_CONTEXT_SPECIFIC (2 << 6) -#define ASN1_CLASS_PRIVATE (3 << 6) -#define ASN1_CLASS_MASK (3 << 6) +#define ASN1_CLASS_PRIVATE (3 << 6) +#define ASN1_CLASS_MASK (3 << 6) /* Primitive versus constructed bit. */ -#define ASN1_CONSTRUCTED (1 << 5) +#define ASN1_CONSTRUCTED (1 << 5) static int ber_read_id_len(void *source, int sourcelen, int *id, int *length, int *flags) @@ -309,7 +311,7 @@ static int ber_write_id_len(void *dest, int id, int length, int flags) len++; if (d) *d++ = 0x1F | flags; for (n = 1; (id >> (7*n)) > 0; n++) - continue; /* count the bytes */ + continue; /* count the bytes */ while (n--) { len++; if (d) *d++ = (n ? 0x80 : 0) | ((id >> (7*n)) & 0x7F); @@ -330,7 +332,7 @@ static int ber_write_id_len(void *dest, int id, int length, int flags) * encode the actual length. */ for (n = 1; (length >> (8*n)) > 0; n++) - continue; /* count the bytes */ + continue; /* count the bytes */ len++; if (d) *d++ = 0x80 | n; while (n--) { @@ -356,29 +358,29 @@ struct openssh_key { int encrypted; char iv[32]; unsigned char *keyblob; - unsigned int keyblob_len, keyblob_size; + unsigned int keyblob_len, keyblob_size; }; static struct openssh_key *load_openssh_key(const char *filename) { struct openssh_key *ret; - FILE *fp = NULL; + FILE *fp = NULL; char buffer[256]; - char *errmsg = NULL, *p = NULL; + char *errmsg = NULL, *p = NULL; int headers_done; - unsigned long len, outlen; + unsigned long len, outlen; - ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key)); + ret = (struct openssh_key*)m_malloc(sizeof(struct openssh_key)); ret->keyblob = NULL; ret->keyblob_len = ret->keyblob_size = 0; ret->encrypted = 0; memset(ret->iv, 0, sizeof(ret->iv)); - if (strlen(filename) == 1 && filename[0] == '-') { - fp = stdin; - } else { - fp = fopen(filename, "r"); - } + if (strlen(filename) == 1 && filename[0] == '-') { + fp = stdin; + } else { + fp = fopen(filename, "r"); + } if (!fp) { errmsg = "Unable to open key file"; goto error; @@ -393,8 +395,8 @@ static struct openssh_key *load_openssh_key(const char *filename) ret->type = OSSH_RSA; else if (!strcmp(buffer, "-----BEGIN DSA PRIVATE KEY-----\n")) ret->type = OSSH_DSA; - else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n")) - ret->type = OSSH_EC; + else if (!strcmp(buffer, "-----BEGIN EC PRIVATE KEY-----\n")) + ret->type = OSSH_EC; else { errmsg = "Unrecognised key type"; goto error; @@ -408,7 +410,7 @@ static struct openssh_key *load_openssh_key(const char *filename) } if (0 == strncmp(buffer, "-----END ", 9) && 0 == strcmp(buffer+strlen(buffer)-17, "PRIVATE KEY-----\n")) - break; /* done */ + break; /* done */ if ((p = strchr(buffer, ':')) != NULL) { if (headers_done) { errmsg = "Header found in body of key data"; @@ -445,22 +447,22 @@ static struct openssh_key *load_openssh_key(const char *filename) } } else { headers_done = 1; - len = strlen(buffer); - outlen = len*4/3; - if (ret->keyblob_len + outlen > ret->keyblob_size) { - ret->keyblob_size = ret->keyblob_len + outlen + 256; - ret->keyblob = (unsigned char*)m_realloc(ret->keyblob, - ret->keyblob_size); - } - outlen = ret->keyblob_size - ret->keyblob_len; - if (base64_decode((const unsigned char *)buffer, len, - ret->keyblob + ret->keyblob_len, &outlen) != CRYPT_OK){ - errmsg = "Error decoding base64"; - goto error; - } - ret->keyblob_len += outlen; - } + len = strlen(buffer); + outlen = len*4/3; + if (ret->keyblob_len + outlen > ret->keyblob_size) { + ret->keyblob_size = ret->keyblob_len + outlen + 256; + ret->keyblob = (unsigned char*)m_realloc(ret->keyblob, + ret->keyblob_size); + } + outlen = ret->keyblob_size - ret->keyblob_len; + if (base64_decode((const unsigned char *)buffer, len, + ret->keyblob + ret->keyblob_len, &outlen) != CRYPT_OK){ + errmsg = "Error decoding base64"; + goto error; + } + ret->keyblob_len += outlen; } + } if (ret->keyblob_len == 0 || !ret->keyblob) { errmsg = "Key body not present"; @@ -509,31 +511,31 @@ static int openssh_encrypted(const char *filename) static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) { - struct openssh_key *key; + struct openssh_key *key; unsigned char *p; int ret, id, len, flags; - int i, num_integers = 0; - sign_key *retval = NULL; + int i, num_integers = 0; + sign_key *retval = NULL; char *errmsg; - unsigned char *modptr = NULL; - int modlen = -9999; - enum signkey_type type; + unsigned char *modptr = NULL; + int modlen = -9999; + enum signkey_type type; - sign_key *retkey; - buffer * blobbuf = NULL; + sign_key *retkey; + buffer * blobbuf = NULL; - retkey = new_sign_key(); + retkey = new_sign_key(); - key = load_openssh_key(filename); + key = load_openssh_key(filename); if (!key) return NULL; if (key->encrypted) { - errmsg = "encrypted keys not supported currently"; - goto error; + errmsg = "encrypted keys not supported currently"; + goto error; #if 0 - /* matt TODO */ + /* matt TODO */ /* * Derive encryption key from passphrase and iv/salt: * @@ -578,11 +580,11 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) * depends on the key type: * * - For RSA, we expect the integers to be 0, n, e, d, p, q, - * dmp1, dmq1, iqmp in that order. (The last three are d mod - * (p-1), d mod (q-1), inverse of q mod p respectively.) + * dmp1, dmq1, iqmp in that order. (The last three are d mod + * (p-1), d mod (q-1), inverse of q mod p respectively.) * * - For DSA, we expect them to be 0, p, q, g, y, x in that - * order. + * order. */ p = key->keyblob; @@ -601,25 +603,25 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) num_integers = 9; else if (key->type == OSSH_DSA) num_integers = 6; - else if (key->type == OSSH_EC) - num_integers = 1; + else if (key->type == OSSH_EC) + num_integers = 1; /* * Space to create key blob in. */ - blobbuf = buf_new(3000); + blobbuf = buf_new(3000); -#ifdef DROPBEAR_DSS - if (key->type == OSSH_DSA) { - buf_putstring(blobbuf, "ssh-dss", 7); - retkey->type = DROPBEAR_SIGNKEY_DSS; - } +#if DROPBEAR_DSS + if (key->type == OSSH_DSA) { + buf_putstring(blobbuf, "ssh-dss", 7); + retkey->type = DROPBEAR_SIGNKEY_DSS; + } #endif -#ifdef DROPBEAR_RSA - if (key->type == OSSH_RSA) { - buf_putstring(blobbuf, "ssh-rsa", 7); - retkey->type = DROPBEAR_SIGNKEY_RSA; - } +#if DROPBEAR_RSA + if (key->type == OSSH_RSA) { + buf_putstring(blobbuf, "ssh-rsa", 7); + retkey->type = DROPBEAR_SIGNKEY_RSA; + } #endif for (i = 0; i < num_integers; i++) { @@ -633,160 +635,160 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) } if (i == 0) { - /* First integer is a version indicator */ - int expected = -1; - switch (key->type) { - case OSSH_RSA: - case OSSH_DSA: - expected = 0; - break; - case OSSH_EC: - expected = 1; - break; - } - if (len != 1 || p[0] != expected) { + /* First integer is a version indicator */ + int expected = -1; + switch (key->type) { + case OSSH_RSA: + case OSSH_DSA: + expected = 0; + break; + case OSSH_EC: + expected = 1; + break; + } + if (len != 1 || p[0] != expected) { errmsg = "Version number mismatch"; goto error; } } else if (key->type == OSSH_RSA) { /* - * OpenSSH key order is n, e, d, p, q, dmp1, dmq1, iqmp - * but we want e, n, d, p, q + * OpenSSH key order is n, e, d, p, q, dmp1, dmq1, iqmp + * but we want e, n, d, p, q */ if (i == 1) { /* Save the details for after we deal with number 2. */ - modptr = p; + modptr = p; modlen = len; - } else if (i >= 2 && i <= 5) { - buf_putstring(blobbuf, (const char*)p, len); + } else if (i >= 2 && i <= 5) { + buf_putstring(blobbuf, (const char*)p, len); if (i == 2) { - buf_putstring(blobbuf, (const char*)modptr, modlen); + buf_putstring(blobbuf, (const char*)modptr, modlen); } } } else if (key->type == OSSH_DSA) { /* - * OpenSSH key order is p, q, g, y, x, - * we want the same. + * OpenSSH key order is p, q, g, y, x, + * we want the same. */ - buf_putstring(blobbuf, (const char*)p, len); + buf_putstring(blobbuf, (const char*)p, len); } /* Skip past the number. */ p += len; } -#ifdef DROPBEAR_ECDSA - if (key->type == OSSH_EC) { - unsigned char* private_key_bytes = NULL; - int private_key_len = 0; - unsigned char* public_key_bytes = NULL; - int public_key_len = 0; - ecc_key *ecc = NULL; - const struct dropbear_ecc_curve *curve = NULL; +#if DROPBEAR_ECDSA + if (key->type == OSSH_EC) { + unsigned char* private_key_bytes = NULL; + int private_key_len = 0; + unsigned char* public_key_bytes = NULL; + int public_key_len = 0; + ecc_key *ecc = NULL; + const struct dropbear_ecc_curve *curve = NULL; - /* See SEC1 v2, Appendix C.4 */ - /* OpenSSL (so OpenSSH) seems to include the optional parts. */ + /* See SEC1 v2, Appendix C.4 */ + /* OpenSSL (so OpenSSH) seems to include the optional parts. */ - /* privateKey OCTET STRING, */ - ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, - &id, &len, &flags); - p += ret; - /* id==4 for octet string */ + /* privateKey OCTET STRING, */ + ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, + &id, &len, &flags); + p += ret; + /* id==4 for octet string */ if (ret < 0 || id != 4 || len < 0 || - key->keyblob+key->keyblob_len-p < len) { - errmsg = "ASN.1 decoding failure"; - goto error; - } - private_key_bytes = p; - private_key_len = len; - p += len; - - /* parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, */ - ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, - &id, &len, &flags); - p += ret; - /* id==0 */ + key->keyblob+key->keyblob_len-p < len) { + errmsg = "ASN.1 decoding failure"; + goto error; + } + private_key_bytes = p; + private_key_len = len; + p += len; + + /* parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, */ + ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, + &id, &len, &flags); + p += ret; + /* id==0 */ if (ret < 0 || id != 0 || len < 0) { - errmsg = "ASN.1 decoding failure"; - goto error; - } + errmsg = "ASN.1 decoding failure"; + goto error; + } - ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, - &id, &len, &flags); - p += ret; - /* id==6 for object */ + ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, + &id, &len, &flags); + p += ret; + /* id==6 for object */ if (ret < 0 || id != 6 || len < 0 || - key->keyblob+key->keyblob_len-p < len) { - errmsg = "ASN.1 decoding failure"; - goto error; - } + key->keyblob+key->keyblob_len-p < len) { + errmsg = "ASN.1 decoding failure"; + goto error; + } - if (0) {} -#ifdef DROPBEAR_ECC_256 - else if (len == sizeof(OID_SEC256R1_BLOB) - && memcmp(p, OID_SEC256R1_BLOB, len) == 0) { - retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256; - curve = &ecc_curve_nistp256; - } + if (0) {} +#if DROPBEAR_ECC_256 + else if (len == sizeof(OID_SEC256R1_BLOB) + && memcmp(p, OID_SEC256R1_BLOB, len) == 0) { + retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP256; + curve = &ecc_curve_nistp256; + } #endif -#ifdef DROPBEAR_ECC_384 - else if (len == sizeof(OID_SEC384R1_BLOB) - && memcmp(p, OID_SEC384R1_BLOB, len) == 0) { - retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384; - curve = &ecc_curve_nistp384; - } +#if DROPBEAR_ECC_384 + else if (len == sizeof(OID_SEC384R1_BLOB) + && memcmp(p, OID_SEC384R1_BLOB, len) == 0) { + retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP384; + curve = &ecc_curve_nistp384; + } #endif -#ifdef DROPBEAR_ECC_521 - else if (len == sizeof(OID_SEC521R1_BLOB) - && memcmp(p, OID_SEC521R1_BLOB, len) == 0) { - retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521; - curve = &ecc_curve_nistp521; - } +#if DROPBEAR_ECC_521 + else if (len == sizeof(OID_SEC521R1_BLOB) + && memcmp(p, OID_SEC521R1_BLOB, len) == 0) { + retkey->type = DROPBEAR_SIGNKEY_ECDSA_NISTP521; + curve = &ecc_curve_nistp521; + } #endif - else { - errmsg = "Unknown ECC key type"; - goto error; - } - p += len; + else { + errmsg = "Unknown ECC key type"; + goto error; + } + p += len; - /* publicKey [1] BIT STRING OPTIONAL */ - ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, - &id, &len, &flags); - p += ret; - /* id==1 */ + /* publicKey [1] BIT STRING OPTIONAL */ + ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, + &id, &len, &flags); + p += ret; + /* id==1 */ if (ret < 0 || id != 1 || len < 0) { - errmsg = "ASN.1 decoding failure"; - goto error; - } + errmsg = "ASN.1 decoding failure"; + goto error; + } - ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, - &id, &len, &flags); - p += ret; - /* id==3 for bit string */ + ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, + &id, &len, &flags); + p += ret; + /* id==3 for bit string */ if (ret < 0 || id != 3 || len < 0 || - key->keyblob+key->keyblob_len-p < len) { - errmsg = "ASN.1 decoding failure"; - goto error; - } - public_key_bytes = p+1; - public_key_len = len-1; - p += len; - - buf_putbytes(blobbuf, public_key_bytes, public_key_len); - ecc = buf_get_ecc_raw_pubkey(blobbuf, curve); - if (!ecc) { - errmsg = "Error parsing ECC key"; - goto error; - } - m_mp_alloc_init_multi((mp_int**)&ecc->k, NULL); - if (mp_read_unsigned_bin(ecc->k, private_key_bytes, private_key_len) - != MP_OKAY) { - errmsg = "Error parsing ECC key"; - goto error; - } + key->keyblob+key->keyblob_len-p < len) { + errmsg = "ASN.1 decoding failure"; + goto error; + } + public_key_bytes = p+1; + public_key_len = len-1; + p += len; - *signkey_key_ptr(retkey, retkey->type) = ecc; + buf_putbytes(blobbuf, public_key_bytes, public_key_len); + ecc = buf_get_ecc_raw_pubkey(blobbuf, curve); + if (!ecc) { + errmsg = "Error parsing ECC key"; + goto error; + } + m_mp_alloc_init_multi((mp_int**)&ecc->k, NULL); + if (mp_read_unsigned_bin(ecc->k, private_key_bytes, private_key_len) + != MP_OKAY) { + errmsg = "Error parsing ECC key"; + goto error; } + + *signkey_key_ptr(retkey, retkey->type) = ecc; + } #endif /* DROPBEAR_ECDSA */ /* @@ -795,19 +797,19 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) * functions; this is a bit faffy but it does mean we get all * the sanity checks for free. */ - if (key->type == OSSH_RSA || key->type == OSSH_DSA) { - buf_setpos(blobbuf, 0); - type = DROPBEAR_SIGNKEY_ANY; - if (buf_get_priv_key(blobbuf, retkey, &type) - != DROPBEAR_SUCCESS) { - errmsg = "unable to create key structure"; - sign_key_free(retkey); - retkey = NULL; - goto error; - } + if (key->type == OSSH_RSA || key->type == OSSH_DSA) { + buf_setpos(blobbuf, 0); + type = DROPBEAR_SIGNKEY_ANY; + if (buf_get_priv_key(blobbuf, retkey, &type) + != DROPBEAR_SUCCESS) { + errmsg = "unable to create key structure"; + sign_key_free(retkey); + retkey = NULL; + goto error; } + } - errmsg = NULL; /* no error */ + errmsg = NULL; /* no error */ retval = retkey; error: @@ -828,301 +830,301 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase)) static int openssh_write(const char *filename, sign_key *key, char *passphrase) { - buffer * keyblob = NULL; - buffer * extrablob = NULL; /* used for calculated values to write */ - unsigned char *outblob = NULL; - int outlen = -9999; + buffer * keyblob = NULL; + buffer * extrablob = NULL; /* used for calculated values to write */ + unsigned char *outblob = NULL; + int outlen = -9999; struct mpint_pos numbers[9]; - int nnumbers = -1, pos = 0, len = 0, seqlen, i; - char *header = NULL, *footer = NULL; + int nnumbers = -1, pos = 0, len = 0, seqlen, i; + char *header = NULL, *footer = NULL; char zero[1]; int ret = 0; FILE *fp; -#ifdef DROPBEAR_RSA - mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */ +#if DROPBEAR_RSA + mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */ #endif - if ( -#ifdef DROPBEAR_RSA - key->type == DROPBEAR_SIGNKEY_RSA || + if ( +#if DROPBEAR_RSA + key->type == DROPBEAR_SIGNKEY_RSA || #endif -#ifdef DROPBEAR_DSS - key->type == DROPBEAR_SIGNKEY_DSS || +#if DROPBEAR_DSS + key->type == DROPBEAR_SIGNKEY_DSS || #endif - 0) - { - /* - * Fetch the key blobs. - */ - keyblob = buf_new(3000); - buf_put_priv_key(keyblob, key, key->type); - - buf_setpos(keyblob, 0); - /* skip the "ssh-rsa" or "ssh-dss" header */ - buf_incrpos(keyblob, buf_getint(keyblob)); - - /* - * Find the sequence of integers to be encoded into the OpenSSH - * key blob, and also decide on the header line. - */ - numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0'; - - #ifdef DROPBEAR_RSA - if (key->type == DROPBEAR_SIGNKEY_RSA) { - - if (key->rsakey->p == NULL || key->rsakey->q == NULL) { - fprintf(stderr, "Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n"); - goto error; - } - - /* e */ - numbers[2].bytes = buf_getint(keyblob); - numbers[2].start = buf_getptr(keyblob, numbers[2].bytes); - buf_incrpos(keyblob, numbers[2].bytes); - - /* n */ - numbers[1].bytes = buf_getint(keyblob); - numbers[1].start = buf_getptr(keyblob, numbers[1].bytes); - buf_incrpos(keyblob, numbers[1].bytes); - - /* d */ - numbers[3].bytes = buf_getint(keyblob); - numbers[3].start = buf_getptr(keyblob, numbers[3].bytes); - buf_incrpos(keyblob, numbers[3].bytes); - - /* p */ - numbers[4].bytes = buf_getint(keyblob); - numbers[4].start = buf_getptr(keyblob, numbers[4].bytes); - buf_incrpos(keyblob, numbers[4].bytes); - - /* q */ - numbers[5].bytes = buf_getint(keyblob); - numbers[5].start = buf_getptr(keyblob, numbers[5].bytes); - buf_incrpos(keyblob, numbers[5].bytes); - - /* now calculate some extra parameters: */ - m_mp_init(&tmpval); - m_mp_init(&dmp1); - m_mp_init(&dmq1); - m_mp_init(&iqmp); - - /* dmp1 = d mod (p-1) */ - if (mp_sub_d(key->rsakey->p, 1, &tmpval) != MP_OKAY) { - fprintf(stderr, "Bignum error for p-1\n"); - goto error; - } - if (mp_mod(key->rsakey->d, &tmpval, &dmp1) != MP_OKAY) { - fprintf(stderr, "Bignum error for dmp1\n"); - goto error; - } - - /* dmq1 = d mod (q-1) */ - if (mp_sub_d(key->rsakey->q, 1, &tmpval) != MP_OKAY) { - fprintf(stderr, "Bignum error for q-1\n"); - goto error; - } - if (mp_mod(key->rsakey->d, &tmpval, &dmq1) != MP_OKAY) { - fprintf(stderr, "Bignum error for dmq1\n"); - goto error; - } - - /* iqmp = (q^-1) mod p */ - if (mp_invmod(key->rsakey->q, key->rsakey->p, &iqmp) != MP_OKAY) { - fprintf(stderr, "Bignum error for iqmp\n"); - goto error; - } - - extrablob = buf_new(2000); - buf_putmpint(extrablob, &dmp1); - buf_putmpint(extrablob, &dmq1); - buf_putmpint(extrablob, &iqmp); - buf_setpos(extrablob, 0); - mp_clear(&dmp1); - mp_clear(&dmq1); - mp_clear(&iqmp); - mp_clear(&tmpval); - - /* dmp1 */ - numbers[6].bytes = buf_getint(extrablob); - numbers[6].start = buf_getptr(extrablob, numbers[6].bytes); - buf_incrpos(extrablob, numbers[6].bytes); - - /* dmq1 */ - numbers[7].bytes = buf_getint(extrablob); - numbers[7].start = buf_getptr(extrablob, numbers[7].bytes); - buf_incrpos(extrablob, numbers[7].bytes); - - /* iqmp */ - numbers[8].bytes = buf_getint(extrablob); - numbers[8].start = buf_getptr(extrablob, numbers[8].bytes); - buf_incrpos(extrablob, numbers[8].bytes); - - nnumbers = 9; - header = "-----BEGIN RSA PRIVATE KEY-----\n"; - footer = "-----END RSA PRIVATE KEY-----\n"; - } - #endif /* DROPBEAR_RSA */ - - #ifdef DROPBEAR_DSS - if (key->type == DROPBEAR_SIGNKEY_DSS) { + 0) + { + /* + * Fetch the key blobs. + */ + keyblob = buf_new(3000); + buf_put_priv_key(keyblob, key, key->type); - /* p */ - numbers[1].bytes = buf_getint(keyblob); - numbers[1].start = buf_getptr(keyblob, numbers[1].bytes); - buf_incrpos(keyblob, numbers[1].bytes); + buf_setpos(keyblob, 0); + /* skip the "ssh-rsa" or "ssh-dss" header */ + buf_incrpos(keyblob, buf_getint(keyblob)); - /* q */ - numbers[2].bytes = buf_getint(keyblob); - numbers[2].start = buf_getptr(keyblob, numbers[2].bytes); - buf_incrpos(keyblob, numbers[2].bytes); + /* + * Find the sequence of integers to be encoded into the OpenSSH + * key blob, and also decide on the header line. + */ + numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0'; - /* g */ - numbers[3].bytes = buf_getint(keyblob); - numbers[3].start = buf_getptr(keyblob, numbers[3].bytes); - buf_incrpos(keyblob, numbers[3].bytes); + #ifdef DROPBEAR_RSA + if (key->type == DROPBEAR_SIGNKEY_RSA) { - /* y */ - numbers[4].bytes = buf_getint(keyblob); - numbers[4].start = buf_getptr(keyblob, numbers[4].bytes); - buf_incrpos(keyblob, numbers[4].bytes); + if (key->rsakey->p == NULL || key->rsakey->q == NULL) { + fprintf(stderr, "Pre-0.33 Dropbear keys cannot be converted to OpenSSH keys.\n"); + goto error; + } - /* x */ - numbers[5].bytes = buf_getint(keyblob); - numbers[5].start = buf_getptr(keyblob, numbers[5].bytes); - buf_incrpos(keyblob, numbers[5].bytes); + /* e */ + numbers[2].bytes = buf_getint(keyblob); + numbers[2].start = buf_getptr(keyblob, numbers[2].bytes); + buf_incrpos(keyblob, numbers[2].bytes); + + /* n */ + numbers[1].bytes = buf_getint(keyblob); + numbers[1].start = buf_getptr(keyblob, numbers[1].bytes); + buf_incrpos(keyblob, numbers[1].bytes); + + /* d */ + numbers[3].bytes = buf_getint(keyblob); + numbers[3].start = buf_getptr(keyblob, numbers[3].bytes); + buf_incrpos(keyblob, numbers[3].bytes); + + /* p */ + numbers[4].bytes = buf_getint(keyblob); + numbers[4].start = buf_getptr(keyblob, numbers[4].bytes); + buf_incrpos(keyblob, numbers[4].bytes); + + /* q */ + numbers[5].bytes = buf_getint(keyblob); + numbers[5].start = buf_getptr(keyblob, numbers[5].bytes); + buf_incrpos(keyblob, numbers[5].bytes); + + /* now calculate some extra parameters: */ + m_mp_init(&tmpval); + m_mp_init(&dmp1); + m_mp_init(&dmq1); + m_mp_init(&iqmp); + + /* dmp1 = d mod (p-1) */ + if (mp_sub_d(key->rsakey->p, 1, &tmpval) != MP_OKAY) { + fprintf(stderr, "Bignum error for p-1\n"); + goto error; + } + if (mp_mod(key->rsakey->d, &tmpval, &dmp1) != MP_OKAY) { + fprintf(stderr, "Bignum error for dmp1\n"); + goto error; + } - nnumbers = 6; - header = "-----BEGIN DSA PRIVATE KEY-----\n"; - footer = "-----END DSA PRIVATE KEY-----\n"; - } - #endif /* DROPBEAR_DSS */ + /* dmq1 = d mod (q-1) */ + if (mp_sub_d(key->rsakey->q, 1, &tmpval) != MP_OKAY) { + fprintf(stderr, "Bignum error for q-1\n"); + goto error; + } + if (mp_mod(key->rsakey->d, &tmpval, &dmq1) != MP_OKAY) { + fprintf(stderr, "Bignum error for dmq1\n"); + goto error; + } - /* - * Now count up the total size of the ASN.1 encoded integers, - * so as to determine the length of the containing SEQUENCE. - */ - len = 0; - for (i = 0; i < nnumbers; i++) { - len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0); - len += numbers[i].bytes; - } - seqlen = len; - /* Now add on the SEQUENCE header. */ - len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED); - /* Round up to the cipher block size, ensuring we have at least one - * byte of padding (see below). */ - outlen = len; - if (passphrase) - outlen = (outlen+8) &~ 7; + /* iqmp = (q^-1) mod p */ + if (mp_invmod(key->rsakey->q, key->rsakey->p, &iqmp) != MP_OKAY) { + fprintf(stderr, "Bignum error for iqmp\n"); + goto error; + } - /* - * Now we know how big outblob needs to be. Allocate it. - */ - outblob = (unsigned char*)m_malloc(outlen); + extrablob = buf_new(2000); + buf_putmpint(extrablob, &dmp1); + buf_putmpint(extrablob, &dmq1); + buf_putmpint(extrablob, &iqmp); + buf_setpos(extrablob, 0); + mp_clear(&dmp1); + mp_clear(&dmq1); + mp_clear(&iqmp); + mp_clear(&tmpval); + + /* dmp1 */ + numbers[6].bytes = buf_getint(extrablob); + numbers[6].start = buf_getptr(extrablob, numbers[6].bytes); + buf_incrpos(extrablob, numbers[6].bytes); + + /* dmq1 */ + numbers[7].bytes = buf_getint(extrablob); + numbers[7].start = buf_getptr(extrablob, numbers[7].bytes); + buf_incrpos(extrablob, numbers[7].bytes); + + /* iqmp */ + numbers[8].bytes = buf_getint(extrablob); + numbers[8].start = buf_getptr(extrablob, numbers[8].bytes); + buf_incrpos(extrablob, numbers[8].bytes); + + nnumbers = 9; + header = "-----BEGIN RSA PRIVATE KEY-----\n"; + footer = "-----END RSA PRIVATE KEY-----\n"; + } + #endif /* DROPBEAR_RSA */ + + #ifdef DROPBEAR_DSS + if (key->type == DROPBEAR_SIGNKEY_DSS) { + + /* p */ + numbers[1].bytes = buf_getint(keyblob); + numbers[1].start = buf_getptr(keyblob, numbers[1].bytes); + buf_incrpos(keyblob, numbers[1].bytes); + + /* q */ + numbers[2].bytes = buf_getint(keyblob); + numbers[2].start = buf_getptr(keyblob, numbers[2].bytes); + buf_incrpos(keyblob, numbers[2].bytes); + + /* g */ + numbers[3].bytes = buf_getint(keyblob); + numbers[3].start = buf_getptr(keyblob, numbers[3].bytes); + buf_incrpos(keyblob, numbers[3].bytes); + + /* y */ + numbers[4].bytes = buf_getint(keyblob); + numbers[4].start = buf_getptr(keyblob, numbers[4].bytes); + buf_incrpos(keyblob, numbers[4].bytes); + + /* x */ + numbers[5].bytes = buf_getint(keyblob); + numbers[5].start = buf_getptr(keyblob, numbers[5].bytes); + buf_incrpos(keyblob, numbers[5].bytes); + + nnumbers = 6; + header = "-----BEGIN DSA PRIVATE KEY-----\n"; + footer = "-----END DSA PRIVATE KEY-----\n"; + } + #endif /* DROPBEAR_DSS */ - /* - * And write the data into it. - */ - pos = 0; - pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED); - for (i = 0; i < nnumbers; i++) { - pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0); - memcpy(outblob+pos, numbers[i].start, numbers[i].bytes); - pos += numbers[i].bytes; - } - } /* end RSA and DSS handling */ - -#ifdef DROPBEAR_ECDSA - if (key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP256 - || key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP384 - || key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) { - - /* SEC1 V2 appendix c.4 - ECPrivateKey ::= SEQUENCE { - version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - privateKey OCTET STRING, - parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, - publicKey [1] BIT STRING OPTIONAL - } - */ - buffer *seq_buf = buf_new(400); - ecc_key **eck = (ecc_key**)signkey_key_ptr(key, key->type); - const long curve_size = (*eck)->dp->size; - int curve_oid_len = 0; - const void* curve_oid = NULL; - unsigned long pubkey_size = 2*curve_size+1; - int k_size; - int err = 0; - - /* version. less than 10 bytes */ - buf_incrwritepos(seq_buf, - ber_write_id_len(buf_getwriteptr(seq_buf, 10), 2, 1, 0)); - buf_putbyte(seq_buf, 1); - - /* privateKey */ - k_size = mp_unsigned_bin_size((*eck)->k); - dropbear_assert(k_size <= curve_size); - buf_incrwritepos(seq_buf, - ber_write_id_len(buf_getwriteptr(seq_buf, 10), 4, k_size, 0)); - mp_to_unsigned_bin((*eck)->k, buf_getwriteptr(seq_buf, k_size)); - buf_incrwritepos(seq_buf, k_size); - - /* SECGCurveNames */ - switch (key->type) - { - case DROPBEAR_SIGNKEY_ECDSA_NISTP256: - curve_oid_len = sizeof(OID_SEC256R1_BLOB); - curve_oid = OID_SEC256R1_BLOB; - break; - case DROPBEAR_SIGNKEY_ECDSA_NISTP384: - curve_oid_len = sizeof(OID_SEC384R1_BLOB); - curve_oid = OID_SEC384R1_BLOB; - break; - case DROPBEAR_SIGNKEY_ECDSA_NISTP521: - curve_oid_len = sizeof(OID_SEC521R1_BLOB); - curve_oid = OID_SEC521R1_BLOB; - break; - default: - dropbear_exit("Internal error"); - } + /* + * Now count up the total size of the ASN.1 encoded integers, + * so as to determine the length of the containing SEQUENCE. + */ + len = 0; + for (i = 0; i < nnumbers; i++) { + len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0); + len += numbers[i].bytes; + } + seqlen = len; + /* Now add on the SEQUENCE header. */ + len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED); + /* Round up to the cipher block size, ensuring we have at least one + * byte of padding (see below). */ + outlen = len; + if (passphrase) + outlen = (outlen+8) &~ 7; - buf_incrwritepos(seq_buf, - ber_write_id_len(buf_getwriteptr(seq_buf, 10), 0, 2+curve_oid_len, 0xa0)); - /* object == 6 */ - buf_incrwritepos(seq_buf, - ber_write_id_len(buf_getwriteptr(seq_buf, 10), 6, curve_oid_len, 0)); - buf_putbytes(seq_buf, curve_oid, curve_oid_len); - - buf_incrwritepos(seq_buf, - ber_write_id_len(buf_getwriteptr(seq_buf, 10), 1, 2+1+pubkey_size, 0xa0)); - buf_incrwritepos(seq_buf, - ber_write_id_len(buf_getwriteptr(seq_buf, 10), 3, 1+pubkey_size, 0)); - buf_putbyte(seq_buf, 0); - err = ecc_ansi_x963_export(*eck, buf_getwriteptr(seq_buf, pubkey_size), &pubkey_size); - if (err != CRYPT_OK) { - dropbear_exit("ECC error"); - } - buf_incrwritepos(seq_buf, pubkey_size); + /* + * Now we know how big outblob needs to be. Allocate it. + */ + outblob = (unsigned char*)m_malloc(outlen); - buf_setpos(seq_buf, 0); - - outblob = (unsigned char*)m_malloc(1000); + /* + * And write the data into it. + */ + pos = 0; + pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED); + for (i = 0; i < nnumbers; i++) { + pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0); + memcpy(outblob+pos, numbers[i].start, numbers[i].bytes); + pos += numbers[i].bytes; + } + } /* end RSA and DSS handling */ + +#if DROPBEAR_ECDSA + if (key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP256 + || key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP384 + || key->type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) { + + /* SEC1 V2 appendix c.4 + ECPrivateKey ::= SEQUENCE { + version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + privateKey OCTET STRING, + parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL, + publicKey [1] BIT STRING OPTIONAL + } + */ + buffer *seq_buf = buf_new(400); + ecc_key **eck = (ecc_key**)signkey_key_ptr(key, key->type); + const long curve_size = (*eck)->dp->size; + int curve_oid_len = 0; + const void* curve_oid = NULL; + unsigned long pubkey_size = 2*curve_size+1; + int k_size; + int err = 0; + + /* version. less than 10 bytes */ + buf_incrwritepos(seq_buf, + ber_write_id_len(buf_getwriteptr(seq_buf, 10), 2, 1, 0)); + buf_putbyte(seq_buf, 1); + + /* privateKey */ + k_size = mp_unsigned_bin_size((*eck)->k); + dropbear_assert(k_size <= curve_size); + buf_incrwritepos(seq_buf, + ber_write_id_len(buf_getwriteptr(seq_buf, 10), 4, k_size, 0)); + mp_to_unsigned_bin((*eck)->k, buf_getwriteptr(seq_buf, k_size)); + buf_incrwritepos(seq_buf, k_size); + + /* SECGCurveNames */ + switch (key->type) + { + case DROPBEAR_SIGNKEY_ECDSA_NISTP256: + curve_oid_len = sizeof(OID_SEC256R1_BLOB); + curve_oid = OID_SEC256R1_BLOB; + break; + case DROPBEAR_SIGNKEY_ECDSA_NISTP384: + curve_oid_len = sizeof(OID_SEC384R1_BLOB); + curve_oid = OID_SEC384R1_BLOB; + break; + case DROPBEAR_SIGNKEY_ECDSA_NISTP521: + curve_oid_len = sizeof(OID_SEC521R1_BLOB); + curve_oid = OID_SEC521R1_BLOB; + break; + default: + dropbear_exit("Internal error"); + } - pos = 0; - pos += ber_write_id_len(outblob+pos, 16, seq_buf->len, ASN1_CONSTRUCTED); - memcpy(&outblob[pos], seq_buf->data, seq_buf->len); - pos += seq_buf->len; - len = pos; - outlen = len; + buf_incrwritepos(seq_buf, + ber_write_id_len(buf_getwriteptr(seq_buf, 10), 0, 2+curve_oid_len, 0xa0)); + /* object == 6 */ + buf_incrwritepos(seq_buf, + ber_write_id_len(buf_getwriteptr(seq_buf, 10), 6, curve_oid_len, 0)); + buf_putbytes(seq_buf, curve_oid, curve_oid_len); + + buf_incrwritepos(seq_buf, + ber_write_id_len(buf_getwriteptr(seq_buf, 10), 1, 2+1+pubkey_size, 0xa0)); + buf_incrwritepos(seq_buf, + ber_write_id_len(buf_getwriteptr(seq_buf, 10), 3, 1+pubkey_size, 0)); + buf_putbyte(seq_buf, 0); + err = ecc_ansi_x963_export(*eck, buf_getwriteptr(seq_buf, pubkey_size), &pubkey_size); + if (err != CRYPT_OK) { + dropbear_exit("ECC error"); + } + buf_incrwritepos(seq_buf, pubkey_size); - buf_burn(seq_buf); - buf_free(seq_buf); - seq_buf = NULL; + buf_setpos(seq_buf, 0); + + outblob = (unsigned char*)m_malloc(1000); - header = "-----BEGIN EC PRIVATE KEY-----\n"; - footer = "-----END EC PRIVATE KEY-----\n"; - } + pos = 0; + pos += ber_write_id_len(outblob+pos, 16, seq_buf->len, ASN1_CONSTRUCTED); + memcpy(&outblob[pos], seq_buf->data, seq_buf->len); + pos += seq_buf->len; + len = pos; + outlen = len; + + buf_burn(seq_buf); + buf_free(seq_buf); + seq_buf = NULL; + + header = "-----BEGIN EC PRIVATE KEY-----\n"; + footer = "-----END EC PRIVATE KEY-----\n"; + } #endif /* @@ -1142,7 +1144,7 @@ static int openssh_write(const char *filename, sign_key *key, * with the same value. Those are all removed and the rest is * returned. */ - dropbear_assert(pos == len); + dropbear_assert(pos == len); while (pos < outlen) { outblob[pos++] = outlen - len; } @@ -1151,25 +1153,25 @@ static int openssh_write(const char *filename, sign_key *key, * Encrypt the key. */ if (passphrase) { - fprintf(stderr, "Encrypted keys aren't supported currently\n"); - goto error; + fprintf(stderr, "Encrypted keys aren't supported currently\n"); + goto error; } /* * And save it. We'll use Unix line endings just in case it's * subsequently transferred in binary mode. */ - if (strlen(filename) == 1 && filename[0] == '-') { - fp = stdout; - } else { - fp = fopen(filename, "wb"); /* ensure Unix line endings */ - } - if (!fp) { - fprintf(stderr, "Failed opening output file\n"); + if (strlen(filename) == 1 && filename[0] == '-') { + fp = stdout; + } else { + fp = fopen(filename, "wb"); /* ensure Unix line endings */ + } + if (!fp) { + fprintf(stderr, "Failed opening output file\n"); goto error; - } + } fputs(header, fp); - base64_encode_fp(fp, outblob, outlen, 64); + base64_encode_fp(fp, outblob, outlen, 64); fputs(footer, fp); fclose(fp); ret = 1; @@ -1205,10 +1207,10 @@ static int openssh_write(const char *filename, sign_key *key, * * So. The blob contains: * - * - uint32 0x3f6ff9eb (magic number) - * - uint32 size (total blob size) - * - string key-type (see below) - * - string cipher-type (tells you if key is encrypted) + * - uint32 0x3f6ff9eb (magic number) + * - uint32 size (total blob size) + * - string key-type (see below) + * - string cipher-type (tells you if key is encrypted) * - string encrypted-blob * * (The first size field includes the size field itself and the @@ -1264,13 +1266,13 @@ static int openssh_write(const char *filename, sign_key *key, * - first 16 bytes are MD5(passphrase) * - next 16 bytes are MD5(passphrase || first 16 bytes) * - if there were more, they'd be MD5(passphrase || first 32), - * and so on. + * and so on. */ #define SSHCOM_MAGIC_NUMBER 0x3f6ff9eb struct sshcom_key { - char comment[256]; /* allowing any length is overkill */ + char comment[256]; /* allowing any length is overkill */ unsigned char *keyblob; int keyblob_len, keyblob_size; }; @@ -1291,7 +1293,7 @@ static struct sshcom_key *load_sshcom_key(const char *filename) ret->keyblob = NULL; ret->keyblob_len = ret->keyblob_size = 0; - fp = fopen(filename, "r"); + fp = fopen(filename, "r"); if (!fp) { errmsg = "Unable to open key file"; goto error; @@ -1309,7 +1311,7 @@ static struct sshcom_key *load_sshcom_key(const char *filename) goto error; } if (!strcmp(buffer, "---- END SSH2 ENCRYPTED PRIVATE KEY ----\n")) - break; /* done */ + break; /* done */ if ((p = strchr(buffer, ':')) != NULL) { if (headers_done) { errmsg = "Header found in body of key data"; @@ -1386,10 +1388,10 @@ static struct sshcom_key *load_sshcom_key(const char *filename) if (ret) { if (ret->keyblob) { memset(ret->keyblob, 0, ret->keyblob_size); - m_free(ret->keyblob); + m_free(ret->keyblob); } memset(ret, 0, sizeof(*ret)); - m_free(ret); + m_free(ret); } return NULL; } @@ -1407,7 +1409,7 @@ int sshcom_encrypted(const char *filename, char **comment) * Check magic number. */ if (GET_32BIT(key->keyblob) != 0x3f6ff9eb) - return 0; /* key is invalid */ + return 0; /* key is invalid */ /* * Find the cipher-type string. @@ -1415,23 +1417,23 @@ int sshcom_encrypted(const char *filename, char **comment) answer = 0; pos = 8; if (key->keyblob_len < pos+4) - goto done; /* key is far too short */ + goto done; /* key is far too short */ len = toint(GET_32BIT(key->keyblob + pos)); if (len < 0 || len > key->keyblob_len - pos - 4) - goto done; /* key is far too short */ + goto done; /* key is far too short */ pos += 4 + len; /* skip key type */ len = toint(GET_32BIT(key->keyblob + pos)); /* find cipher-type length */ if (len < 0 || len > key->keyblob_len - pos - 4) - goto done; /* cipher type string is incomplete */ + goto done; /* cipher type string is incomplete */ if (len != 4 || 0 != memcmp(key->keyblob + pos + 4, "none", 4)) answer = 1; done: *comment = dupstr(key->comment); memset(key->keyblob, 0, key->keyblob_size); - m_free(key->keyblob); + m_free(key->keyblob); memset(key, 0, sizeof(*key)); - m_free(key); + m_free(key); return answer; } @@ -1455,7 +1457,7 @@ static int sshcom_read_mpint(void *data, int len, struct mpint_pos *ret) error: ret->start = NULL; ret->bytes = -1; - return len; /* ensure further calls fail as well */ + return len; /* ensure further calls fail as well */ } static int sshcom_put_mpint(void *target, void *data, int len) @@ -1681,13 +1683,13 @@ sign_key *sshcom_read(const char *filename, char *passphrase) } else return NULL; - dropbear_assert(privlen > 0); /* should have bombed by now if not */ + dropbear_assert(privlen > 0); /* should have bombed by now if not */ retkey = snew(struct ssh2_userkey); retkey->alg = alg; retkey->data = alg->createkey(blob, publen, blob+publen, privlen); if (!retkey->data) { - m_free(retkey); + m_free(retkey); errmsg = "unable to create key data structure"; goto error; } @@ -1699,12 +1701,12 @@ sign_key *sshcom_read(const char *filename, char *passphrase) error: if (blob) { memset(blob, 0, blobsize); - m_free(blob); + m_free(blob); } memset(key->keyblob, 0, key->keyblob_size); - m_free(key->keyblob); + m_free(key->keyblob); memset(key, 0, sizeof(*key)); - m_free(key); + m_free(key); return ret; } @@ -1747,7 +1749,7 @@ int sshcom_write(const char *filename, sign_key *key, pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q); pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp); - dropbear_assert(e.start && iqmp.start); /* can't go wrong */ + dropbear_assert(e.start && iqmp.start); /* can't go wrong */ numbers[0] = e; numbers[1] = d; @@ -1771,7 +1773,7 @@ int sshcom_write(const char *filename, sign_key *key, pos = 0; pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x); - dropbear_assert(y.start && x.start); /* can't go wrong */ + dropbear_assert(y.start && x.start); /* can't go wrong */ numbers[0] = p; numbers[1] = g; @@ -1783,7 +1785,7 @@ int sshcom_write(const char *filename, sign_key *key, initial_zero = 1; type = "dl-modp{sign{dsa-nist-sha1},dh{plain}}"; } else { - dropbear_assert(0); /* zoinks! */ + dropbear_assert(0); /* zoinks! */ } /* @@ -1801,15 +1803,15 @@ int sshcom_write(const char *filename, sign_key *key, */ pos = 0; PUT_32BIT(outblob+pos, SSHCOM_MAGIC_NUMBER); pos += 4; - pos += 4; /* length field, fill in later */ + pos += 4; /* length field, fill in later */ pos += put_string(outblob+pos, type, strlen(type)); { char *ciphertype = passphrase ? "3des-cbc" : "none"; pos += put_string(outblob+pos, ciphertype, strlen(ciphertype)); } - lenpos = pos; /* remember this position */ - pos += 4; /* encrypted-blob size */ - pos += 4; /* encrypted-payload size */ + lenpos = pos; /* remember this position */ + pos += 4; /* encrypted-blob size */ + pos += 4; /* encrypted-payload size */ if (initial_zero) { PUT_32BIT(outblob+pos, 0); pos += 4; @@ -1827,13 +1829,13 @@ int sshcom_write(const char *filename, sign_key *key, } ciphertext = (char *)outblob+lenpos+4; cipherlen = pos - (lenpos+4); - dropbear_assert(!passphrase || cipherlen % 8 == 0); + dropbear_assert(!passphrase || cipherlen % 8 == 0); /* Wrap up the encrypted blob string. */ PUT_32BIT(outblob+lenpos, cipherlen); /* And finally fill in the total length field. */ PUT_32BIT(outblob+4, pos); - dropbear_assert(pos < outlen); + dropbear_assert(pos < outlen); /* * Encrypt the key. @@ -1874,7 +1876,7 @@ int sshcom_write(const char *filename, sign_key *key, * And save it. We'll use Unix line endings just in case it's * subsequently transferred in binary mode. */ - fp = fopen(filename, "wb"); /* ensure Unix line endings */ + fp = fopen(filename, "wb"); /* ensure Unix line endings */ if (!fp) goto error; fputs("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----\n", fp); @@ -1886,16 +1888,16 @@ int sshcom_write(const char *filename, sign_key *key, * Don't ask me, I didn't design it. */ { - int slen = 60; /* starts at 60 due to "Comment: " */ + int slen = 60; /* starts at 60 due to "Comment: " */ char *c = key->comment; while ((int)strlen(c) > slen) { fprintf(fp, "%.*s\\\n", slen, c); c += slen; - slen = 70; /* allow 70 chars on subsequent lines */ + slen = 70; /* allow 70 chars on subsequent lines */ } fprintf(fp, "%s\"\n", c); } - base64_encode_fp(fp, outblob, pos, 70); + base64_encode_fp(fp, outblob, pos, 70); fputs("---- END SSH2 ENCRYPTED PRIVATE KEY ----\n", fp); fclose(fp); ret = 1; @@ -1903,15 +1905,15 @@ int sshcom_write(const char *filename, sign_key *key, error: if (outblob) { memset(outblob, 0, outlen); - m_free(outblob); + m_free(outblob); } if (privblob) { memset(privblob, 0, privlen); - m_free(privblob); + m_free(privblob); } if (pubblob) { memset(pubblob, 0, publen); - m_free(pubblob); + m_free(pubblob); } return ret; } |