X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=import.c;h=adf68777dcd96de71faef9e3de49f5a0aed0ddf1;hb=510f49e405e71ba5c97875e7a019364e1ef5fac9;hp=34f29acf3600007a9a2149645e78ac1c8c041796;hpb=90af5bed04f8e4dcf7e42c464b1be6cc7056f768;p=PuTTY.git diff --git a/import.c b/import.c index 34f29acf..adf68777 100644 --- a/import.c +++ b/import.c @@ -195,14 +195,16 @@ static int ber_read_id_len(void *source, int sourcelen, return -1; if (*p & 0x80) { + unsigned len; int n = *p & 0x7F; p++, sourcelen--; if (sourcelen < n) return -1; - *length = 0; + len = 0; while (n--) - *length = (*length << 8) | (*p++); + len = (len << 8) | (*p++); sourcelen -= n; + *length = toint(len); } else { *length = *p; p++, sourcelen--; @@ -362,7 +364,8 @@ static struct openssh_pem_key *load_openssh_pem_key(const Filename *filename, struct openssh_pem_key *ret; FILE *fp = NULL; char *line = NULL; - char *errmsg, *p; + const char *errmsg; + char *p; int headers_done; char base64_bit[4]; int base64_chars = 0; @@ -382,8 +385,8 @@ static struct openssh_pem_key *load_openssh_pem_key(const Filename *filename, goto error; } strip_crlf(line); - if (0 != strncmp(line, "-----BEGIN ", 11) || - 0 != strcmp(line+strlen(line)-16, "PRIVATE KEY-----")) { + if (!strstartswith(line, "-----BEGIN ") || + !strendswith(line, "PRIVATE KEY-----")) { errmsg = "file does not begin with OpenSSH key header"; goto error; } @@ -420,8 +423,8 @@ static struct openssh_pem_key *load_openssh_pem_key(const Filename *filename, goto error; } strip_crlf(line); - if (0 == strncmp(line, "-----END ", 9) && - 0 == strcmp(line+strlen(line)-16, "PRIVATE KEY-----")) { + if (strstartswith(line, "-----END ") && + strendswith(line, "PRIVATE KEY-----")) { sfree(line); line = NULL; break; /* done */ @@ -566,11 +569,11 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, { struct openssh_pem_key *key = load_openssh_pem_key(filename, errmsg_p); struct ssh2_userkey *retkey; - unsigned char *p; + unsigned char *p, *q; int ret, id, len, flags; int i, num_integers; struct ssh2_userkey *retval = NULL; - char *errmsg; + const char *errmsg; unsigned char *blob; int blobsize = 0, blobptr, privptr; char *modptr = NULL; @@ -656,7 +659,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, * decrypt, if the key was encrypted. */ ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags); p += ret; - if (ret < 0 || id != 16) { + if (ret < 0 || id != 16 || len < 0 || + key->keyblob+key->keyblob_len-p < len) { errmsg = "ASN.1 decoding failure"; retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL; goto error; @@ -675,13 +679,15 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, /* And now for something completely different */ unsigned char *priv; int privlen; - struct ec_curve *curve; + const struct ssh_signkey *alg; + const struct ec_curve *curve; + int algnamelen, curvenamelen; /* Read INTEGER 1 */ ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, &id, &len, &flags); p += ret; - if (ret < 0 || id != 2 || key->keyblob+key->keyblob_len-p < len || - len != 1 || p[0] != 1) { + if (ret < 0 || id != 2 || len != 1 || + key->keyblob+key->keyblob_len-p < len || p[0] != 1) { errmsg = "ASN.1 decoding failure"; retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL; goto error; @@ -691,7 +697,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, &id, &len, &flags); p += ret; - if (ret < 0 || id != 4 || key->keyblob+key->keyblob_len-p < len) { + if (ret < 0 || id != 4 || len < 0 || + key->keyblob+key->keyblob_len-p < len) { errmsg = "ASN.1 decoding failure"; retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL; goto error; @@ -703,7 +710,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, &id, &len, &flags); p += ret; - if (ret < 0 || id != 0 || key->keyblob+key->keyblob_len-p < len) { + if (ret < 0 || id != 0 || len < 0 || + key->keyblob+key->keyblob_len-p < len) { errmsg = "ASN.1 decoding failure"; retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL; goto error; @@ -711,20 +719,14 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, &id, &len, &flags); p += ret; - if (ret < 0 || id != 6 || key->keyblob+key->keyblob_len-p < len) { + if (ret < 0 || id != 6 || len < 0 || + key->keyblob+key->keyblob_len-p < len) { errmsg = "ASN.1 decoding failure"; retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL; goto error; } - if (len == 8 && !memcmp(p, nistp256_oid, nistp256_oid_len)) { - curve = ec_p256(); - } else if (len == 5 && !memcmp(p, nistp384_oid, - nistp384_oid_len)) { - curve = ec_p384(); - } else if (len == 5 && !memcmp(p, nistp521_oid, - nistp521_oid_len)) { - curve = ec_p521(); - } else { + alg = ec_alg_by_oid(len, p, &curve); + if (!alg) { errmsg = "Unsupported ECDSA curve."; retval = NULL; goto error; @@ -734,7 +736,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, &id, &len, &flags); p += ret; - if (ret < 0 || id != 1 || key->keyblob+key->keyblob_len-p < len) { + if (ret < 0 || id != 1 || len < 0 || + key->keyblob+key->keyblob_len-p < len) { errmsg = "ASN.1 decoding failure"; retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL; goto error; @@ -742,7 +745,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, &id, &len, &flags); p += ret; - if (ret < 0 || id != 3 || key->keyblob+key->keyblob_len-p < len || + if (ret < 0 || id != 3 || len < 0 || + key->keyblob+key->keyblob_len-p < len || len != ((((curve->fieldBits + 7) / 8) * 2) + 2)) { errmsg = "ASN.1 decoding failure"; retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL; @@ -756,30 +760,42 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, errmsg = "out of memory"; goto error; } - if (curve->fieldBits == 256) { - retkey->alg = &ssh_ecdsa_nistp256; - } else if (curve->fieldBits == 384) { - retkey->alg = &ssh_ecdsa_nistp384; - } else { - retkey->alg = &ssh_ecdsa_nistp521; - } - blob = snewn((4+19 + 4+8 + 4+len) + (4+privlen), unsigned char); + retkey->alg = alg; + blob = snewn((4+19 + 4+8 + 4+len) + (4+1+privlen), unsigned char); if (!blob) { sfree(retkey); errmsg = "out of memory"; goto error; } - PUT_32BIT(blob, 19); - sprintf((char*)blob+4, "ecdsa-sha2-nistp%d", curve->fieldBits); - PUT_32BIT(blob+4+19, 8); - sprintf((char*)blob+4+19+4, "nistp%d", curve->fieldBits); - PUT_32BIT(blob+4+19+4+8, len); - memcpy(blob+4+19+4+8+4, p, len); - PUT_32BIT(blob+4+19+4+8+4+len, privlen); - memcpy(blob+4+19+4+8+4+len+4, priv, privlen); - retkey->data = retkey->alg->createkey(blob, 4+19+4+8+4+len, - blob+4+19+4+8+4+len, - 4+privlen); + + q = blob; + + algnamelen = strlen(alg->name); + PUT_32BIT(q, algnamelen); q += 4; + memcpy(q, alg->name, algnamelen); q += algnamelen; + + curvenamelen = strlen(curve->name); + PUT_32BIT(q, curvenamelen); q += 4; + memcpy(q, curve->name, curvenamelen); q += curvenamelen; + + PUT_32BIT(q, len); q += 4; + memcpy(q, p, len); q += len; + + /* + * To be acceptable to our createkey(), the private blob must + * contain a valid mpint, i.e. without the top bit set. But + * the input private string may have the top bit set, so we + * prefix a zero byte to ensure createkey() doesn't fail for + * that reason. + */ + PUT_32BIT(q, privlen+1); + q[4] = 0; + memcpy(q+5, priv, privlen); + + retkey->data = retkey->alg->createkey(retkey->alg, + blob, q-blob, + q, 5+privlen); + if (!retkey->data) { sfree(retkey); errmsg = "unable to create key data structure"; @@ -805,7 +821,7 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p, &id, &len, &flags); p += ret; - if (ret < 0 || id != 2 || + if (ret < 0 || id != 2 || len < 0 || key->keyblob+key->keyblob_len-p < len) { errmsg = "ASN.1 decoding failure"; retval = key->encrypted ? SSH2_WRONG_PASSPHRASE : NULL; @@ -867,7 +883,7 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, assert(privptr > 0); /* should have bombed by now if not */ retkey = snew(struct ssh2_userkey); retkey->alg = (key->keytype == OP_RSA ? &ssh_rsa : &ssh_dss); - retkey->data = retkey->alg->createkey(blob, privptr, + retkey->data = retkey->alg->createkey(retkey->alg, blob, privptr, blob+privptr, blobptr-privptr); if (!retkey->data) { @@ -878,6 +894,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, } else { assert(0 && "Bad key type from load_openssh_pem_key"); + errmsg = "Bad key type from load_openssh_pem_key"; + goto error; } /* @@ -911,7 +929,7 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, int outlen; struct mpint_pos numbers[9]; int nnumbers, pos, len, seqlen, i; - char *header, *footer; + const char *header, *footer; char zero[1]; unsigned char iv[8]; int ret = 0; @@ -1058,7 +1076,7 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, } else if (key->alg == &ssh_ecdsa_nistp256 || key->alg == &ssh_ecdsa_nistp384 || key->alg == &ssh_ecdsa_nistp521) { - unsigned char *oid; + const unsigned char *oid; int oidlen; int pointlen; @@ -1072,28 +1090,9 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, * [1] * BIT STRING (0x00 public key point) */ - switch (((struct ec_key *)key->data)->publicKey.curve->fieldBits) { - case 256: - /* OID: 1.2.840.10045.3.1.7 (ansiX9p256r1) */ - oid = nistp256_oid; - oidlen = nistp256_oid_len; - pointlen = 32 * 2; - break; - case 384: - /* OID: 1.3.132.0.34 (secp384r1) */ - oid = nistp384_oid; - oidlen = nistp384_oid_len; - pointlen = 48 * 2; - break; - case 521: - /* OID: 1.3.132.0.35 (secp521r1) */ - oid = nistp521_oid; - oidlen = nistp521_oid_len; - pointlen = 66 * 2; - break; - default: - assert(0); - } + oid = ec_alg_oid(key->alg, &oidlen); + pointlen = (((struct ec_key *)key->data)->publicKey.curve->fieldBits + + 7) / 8 * 2; len = ber_write_id_len(NULL, 2, 1, 0); len += 1; @@ -1303,7 +1302,8 @@ static struct openssh_new_key *load_openssh_new_key(const Filename *filename, struct openssh_new_key *ret; FILE *fp = NULL; char *line = NULL; - char *errmsg, *p; + const char *errmsg; + char *p; char base64_bit[4]; int base64_chars = 0; const void *filedata; @@ -1543,18 +1543,14 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename, const char **errmsg_p) { struct openssh_new_key *key = load_openssh_new_key(filename, errmsg_p); - struct ssh2_userkey *retkey; + struct ssh2_userkey *retkey = NULL; int i; struct ssh2_userkey *retval = NULL; - char *errmsg; - unsigned char *blob; - int blobsize = 0; + const char *errmsg; unsigned checkint0, checkint1; const void *priv, *string; int privlen, stringlen, key_index; - const struct ssh_signkey *alg; - - blob = NULL; + const struct ssh_signkey *alg = NULL; if (!key) return NULL; @@ -1678,10 +1674,10 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename, (const unsigned char *)thiskey); if (key_index == key->key_wanted) { retkey = snew(struct ssh2_userkey); + retkey->comment = NULL; retkey->alg = alg; - retkey->data = alg->openssh_createkey(&thiskey, &thiskeylen); + retkey->data = alg->openssh_createkey(alg, &thiskey, &thiskeylen); if (!retkey->data) { - sfree(retkey); errmsg = "unable to create key data structure"; goto error; } @@ -1718,11 +1714,16 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename, errmsg = NULL; /* no error */ retval = retkey; + retkey = NULL; /* prevent the free */ error: - if (blob) { - smemclr(blob, blobsize); - sfree(blob); + if (retkey) { + sfree(retkey->comment); + if (retkey->data) { + assert(alg); + alg->freekey(retkey->data); + } + sfree(retkey); } smemclr(key->keyblob, key->keyblob_size); sfree(key->keyblob); @@ -2001,7 +2002,8 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename, FILE *fp; char *line = NULL; int hdrstart, len; - char *errmsg, *p; + const char *errmsg; + char *p; int headers_done; char base64_bit[4]; int base64_chars = 0; @@ -2246,7 +2248,7 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase, const char **errmsg_p) { struct sshcom_key *key = load_sshcom_key(filename, errmsg_p); - char *errmsg; + const char *errmsg; int pos, len; const char prefix_rsa[] = "if-modn{sign{rsa"; const char prefix_dsa[] = "dl-modp{sign{dsa"; @@ -2457,7 +2459,7 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase, retkey = snew(struct ssh2_userkey); retkey->alg = alg; - retkey->data = alg->createkey(blob, publen, blob+publen, privlen); + retkey->data = alg->createkey(alg, blob, publen, blob+publen, privlen); if (!retkey->data) { sfree(retkey); errmsg = "unable to create key data structure"; @@ -2490,7 +2492,7 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key, int outlen; struct mpint_pos numbers[6]; int nnumbers, initial_zero, pos, lenpos, i; - char *type; + const char *type; char *ciphertext; int cipherlen; int ret = 0; @@ -2586,7 +2588,7 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key, pos += 4; /* length field, fill in later */ pos += put_string(outblob+pos, type, strlen(type)); { - char *ciphertype = passphrase ? "3des-cbc" : "none"; + const char *ciphertype = passphrase ? "3des-cbc" : "none"; pos += put_string(outblob+pos, ciphertype, strlen(ciphertype)); } lenpos = pos; /* remember this position */