diff --git a/cmdgen.c b/cmdgen.c index e7e5a202..0b488f6d 100644 --- a/cmdgen.c +++ b/cmdgen.c @@ -246,10 +246,9 @@ int main(int argc, char **argv) int sshver = 0; struct ssh2_userkey *ssh2key = NULL; struct RSAKey *ssh1key = NULL; - unsigned char *ssh2blob = NULL; + strbuf *ssh2blob = NULL; char *ssh2alg = NULL; const struct ssh_signkey *ssh2algf = NULL; - int ssh2bloblen; char *old_passphrase = NULL, *new_passphrase = NULL; int load_encrypted; progfn_t progressfn = is_interactive() ? progress_update : no_progress; @@ -807,29 +806,33 @@ int main(int argc, char **argv) case SSH_KEYTYPE_SSH1_PUBLIC: ssh1key = snew(struct RSAKey); if (!load_encrypted) { - void *vblob; - unsigned char *blob; - int n, l, bloblen; + strbuf *blob; + int n, l; - ret = rsa_ssh1_loadpub(infilename, &vblob, &bloblen, + blob = strbuf_new(); + ret = rsa_ssh1_loadpub(infilename, BinarySink_UPCAST(blob), &origcomment, &error); - blob = (unsigned char *)vblob; n = 4; /* skip modulus bits */ - - l = ssh1_read_bignum(blob + n, bloblen - n, + + l = ssh1_read_bignum(blob->u + n, + blob->len - n, &ssh1key->exponent); if (l < 0) { error = "SSH-1 public key blob was too short"; } else { n += l; - l = ssh1_read_bignum(blob + n, bloblen - n, - &ssh1key->modulus); + l = ssh1_read_bignum( + blob->u + n, + blob->len - n, &ssh1key->modulus); if (l < 0) { error = "SSH-1 public key blob was too short"; } else n += l; } + + strbuf_free(blob); + ssh1key->comment = dupstr(origcomment); ssh1key->private_exponent = NULL; ssh1key->p = NULL; @@ -849,16 +852,18 @@ int main(int argc, char **argv) case SSH_KEYTYPE_SSH2_PUBLIC_RFC4716: case SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH: if (!load_encrypted) { - ssh2blob = ssh2_userkey_loadpub(infilename, &ssh2alg, - &ssh2bloblen, &origcomment, - &error); - if (ssh2blob) { + ssh2blob = strbuf_new(); + if (ssh2_userkey_loadpub(infilename, &ssh2alg, BinarySink_UPCAST(ssh2blob), + &origcomment, &error)) { ssh2algf = find_pubkey_alg(ssh2alg); if (ssh2algf) bits = ssh2algf->pubkey_bits(ssh2algf, - ssh2blob, ssh2bloblen); + ssh2blob->s, + ssh2blob->len); else bits = -1; + } else { + strbuf_free(ssh2blob); } sfree(ssh2alg); } else { @@ -1007,12 +1012,12 @@ int main(int argc, char **argv) } else { if (!ssh2blob) { assert(ssh2key); - ssh2blob = ssh2key->alg->public_blob(ssh2key->data, - &ssh2bloblen); + ssh2blob = strbuf_new(); + ssh2key->alg->public_blob(ssh2key->data, BinarySink_UPCAST(ssh2blob)); } ssh2_write_pubkey(fp, ssh2key ? ssh2key->comment : origcomment, - ssh2blob, ssh2bloblen, + ssh2blob->s, ssh2blob->len, (outtype == PUBLIC ? SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 : SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH)); @@ -1038,7 +1043,8 @@ int main(int argc, char **argv) ssh2key->data); } else { assert(ssh2blob); - fingerprint = ssh2_fingerprint_blob(ssh2blob, ssh2bloblen); + fingerprint = ssh2_fingerprint_blob( + ssh2blob->s, ssh2blob->len); } } diff --git a/import.c b/import.c index 5d7bf88a..5bbfe2dc 100644 --- a/import.c +++ b/import.c @@ -924,8 +924,9 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, char *passphrase) { - unsigned char *pubblob, *privblob, *spareblob; - int publen, privlen, sparelen = 0; + strbuf *pubblob, *privblob; + unsigned char *spareblob; + int sparelen = 0; unsigned char *outblob; int outlen; struct mpint_pos numbers[9]; @@ -939,8 +940,10 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, /* * Fetch the key blobs. */ - pubblob = key->alg->public_blob(key->data, &publen); - privblob = key->alg->private_blob(key->data, &privlen); + pubblob = strbuf_new(); + key->alg->public_blob(key->data, BinarySink_UPCAST(pubblob)); + privblob = strbuf_new(); + key->alg->private_blob(key->data, BinarySink_UPCAST(privblob)); spareblob = outblob = NULL; outblob = NULL; @@ -967,14 +970,14 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, * These blobs were generated from inside PuTTY, so we needn't * treat them as untrusted. */ - pos = 4 + GET_32BIT(pubblob); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n); + pos = 4 + GET_32BIT(pubblob->u); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &e); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &n); pos = 0; - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d); - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p); - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q); - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &d); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &p); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &q); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &iqmp); assert(e.start && iqmp.start); /* can't go wrong */ @@ -1024,13 +1027,13 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, * These blobs were generated from inside PuTTY, so we needn't * treat them as untrusted. */ - pos = 4 + GET_32BIT(pubblob); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y); + pos = 4 + GET_32BIT(pubblob->u); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &p); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &q); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &g); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &y); pos = 0; - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &x); assert(y.start && x.start); /* can't go wrong */ @@ -1097,8 +1100,8 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, len = ber_write_id_len(NULL, 2, 1, 0); len += 1; - len += ber_write_id_len(NULL, 4, privlen - 4, 0); - len+= privlen - 4; + len += ber_write_id_len(NULL, 4, privblob->len - 4, 0); + len+= privblob->len - 4; len += ber_write_id_len(NULL, 0, oidlen + ber_write_id_len(NULL, 6, oidlen, 0), ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED); @@ -1120,9 +1123,9 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED); pos += ber_write_id_len(outblob+pos, 2, 1, 0); outblob[pos++] = 1; - pos += ber_write_id_len(outblob+pos, 4, privlen - 4, 0); - memcpy(outblob+pos, privblob + 4, privlen - 4); - pos += privlen - 4; + pos += ber_write_id_len(outblob+pos, 4, privblob->len - 4, 0); + memcpy(outblob+pos, privblob->u + 4, privblob->len - 4); + pos += privblob->len - 4; pos += ber_write_id_len(outblob+pos, 0, oidlen + ber_write_id_len(NULL, 6, oidlen, 0), ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED); @@ -1134,7 +1137,7 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED); pos += ber_write_id_len(outblob+pos, 3, 2 + pointlen, 0); outblob[pos++] = 0; - memcpy(outblob+pos, pubblob+39, 1 + pointlen); + memcpy(outblob+pos, pubblob->u+39, 1 + pointlen); pos += 1 + pointlen; header = "-----BEGIN EC PRIVATE KEY-----\n"; @@ -1254,14 +1257,10 @@ int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key, smemclr(spareblob, sparelen); sfree(spareblob); } - if (privblob) { - smemclr(privblob, privlen); - sfree(privblob); - } - if (pubblob) { - smemclr(pubblob, publen); - sfree(pubblob); - } + if (privblob) + strbuf_free(privblob); + if (pubblob) + strbuf_free(pubblob); return ret; } @@ -1747,9 +1746,10 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename, int openssh_new_write(const Filename *filename, struct ssh2_userkey *key, char *passphrase) { - unsigned char *pubblob, *privblob, *outblob, *p; + strbuf *pubblob, *privblob; + unsigned char *outblob, *p; unsigned char *private_section_start, *private_section_length_field; - int publen, privlen, commentlen, maxsize, padvalue, i; + int commentlen, maxsize, padvalue, i; unsigned checkint; int ret = 0; unsigned char bcrypt_salt[16]; @@ -1759,11 +1759,10 @@ int openssh_new_write(const Filename *filename, struct ssh2_userkey *key, /* * Fetch the key blobs and find out the lengths of things. */ - pubblob = key->alg->public_blob(key->data, &publen); - i = key->alg->openssh_fmtkey(key->data, NULL, 0); - privblob = snewn(i, unsigned char); - privlen = key->alg->openssh_fmtkey(key->data, privblob, i); - assert(privlen == i); + pubblob = strbuf_new(); + key->alg->public_blob(key->data, BinarySink_UPCAST(pubblob)); + privblob = strbuf_new(); + key->alg->openssh_fmtkey(key->data, BinarySink_UPCAST(privblob)); commentlen = strlen(key->comment); /* @@ -1775,11 +1774,11 @@ int openssh_new_write(const Filename *filename, struct ssh2_userkey *key, 32 + /* kdf name string */ 64 + /* kdf options string */ 4 + /* key count */ - 4+publen + /* public key string */ + 4+pubblob->len + /* public key string */ 4 + /* string header for private section */ 8 + /* checkint x 2 */ 4+strlen(key->alg->name) + /* key type string */ - privlen + /* private blob */ + privblob->len + /* private blob */ 4+commentlen + /* comment string */ 16); /* padding at end of private section */ outblob = snewn(maxsize, unsigned char); @@ -1816,7 +1815,7 @@ int openssh_new_write(const Filename *filename, struct ssh2_userkey *key, p += write_uint32(p, 1); /* Public blob. */ - p += write_string(p, pubblob, publen); + p += write_string(p, pubblob->u, pubblob->len); /* Begin private section. */ private_section_length_field = p; @@ -1833,8 +1832,8 @@ int openssh_new_write(const Filename *filename, struct ssh2_userkey *key, /* Private key. The main private blob goes inline, with no string * wrapper. */ p += write_string_z(p, key->alg->name); - memcpy(p, privblob, privlen); - p += privlen; + memcpy(p, privblob->u, privblob->len); + p += privblob->len; /* Comment. */ p += write_string_z(p, key->comment); @@ -1891,14 +1890,10 @@ int openssh_new_write(const Filename *filename, struct ssh2_userkey *key, smemclr(outblob, maxsize); sfree(outblob); } - if (privblob) { - smemclr(privblob, privlen); - sfree(privblob); - } - if (pubblob) { - smemclr(pubblob, publen); - sfree(pubblob); - } + if (privblob) + strbuf_free(privblob); + if (pubblob) + strbuf_free(pubblob); return ret; } @@ -2497,8 +2492,7 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase, int sshcom_write(const Filename *filename, struct ssh2_userkey *key, char *passphrase) { - unsigned char *pubblob, *privblob; - int publen, privlen; + strbuf *pubblob, *privblob; unsigned char *outblob; int outlen; struct mpint_pos numbers[6]; @@ -2512,8 +2506,10 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key, /* * Fetch the key blobs. */ - pubblob = key->alg->public_blob(key->data, &publen); - privblob = key->alg->private_blob(key->data, &privlen); + pubblob = strbuf_new(); + key->alg->public_blob(key->data, BinarySink_UPCAST(pubblob)); + privblob = strbuf_new(); + key->alg->private_blob(key->data, BinarySink_UPCAST(privblob)); outblob = NULL; /* @@ -2528,14 +2524,14 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key, * These blobs were generated from inside PuTTY, so we needn't * treat them as untrusted. */ - pos = 4 + GET_32BIT(pubblob); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n); + pos = 4 + GET_32BIT(pubblob->u); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &e); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &n); pos = 0; - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d); - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p); - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q); - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &d); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &p); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &q); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &iqmp); assert(e.start && iqmp.start); /* can't go wrong */ @@ -2557,13 +2553,13 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key, * These blobs were generated from inside PuTTY, so we needn't * treat them as untrusted. */ - pos = 4 + GET_32BIT(pubblob); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g); - pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y); + pos = 4 + GET_32BIT(pubblob->u); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &p); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &q); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &g); + pos += ssh2_read_mpint(pubblob->u+pos, pubblob->len-pos, &y); pos = 0; - pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x); + pos += ssh2_read_mpint(privblob->u+pos, privblob->len-pos, &x); assert(y.start && x.start); /* can't go wrong */ @@ -2700,13 +2696,9 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key, smemclr(outblob, outlen); sfree(outblob); } - if (privblob) { - smemclr(privblob, privlen); - sfree(privblob); - } - if (pubblob) { - smemclr(pubblob, publen); - sfree(pubblob); - } + if (privblob) + strbuf_free(privblob); + if (pubblob) + strbuf_free(pubblob); return ret; } diff --git a/pageant.c b/pageant.c index c3446a89..671cabab 100644 --- a/pageant.c +++ b/pageant.c @@ -34,16 +34,6 @@ static int pageant_local = FALSE; */ static tree234 *rsakeys, *ssh2keys; -/* - * Blob structure for passing to the asymmetric SSH-2 key compare - * function, prototyped here. - */ -struct blob { - const unsigned char *blob; - int len; -}; -static int cmpkeys_ssh2_asymm(void *av, void *bv); - /* * Key comparison function for the 2-3-4 tree of RSA keys. */ @@ -84,128 +74,77 @@ static int cmpkeys_rsa(void *av, void *bv) return 0; } -/* - * Key comparison function for the 2-3-4 tree of SSH-2 keys. - */ -static int cmpkeys_ssh2(void *av, void *bv) -{ - struct ssh2_userkey *a = (struct ssh2_userkey *) av; - struct ssh2_userkey *b = (struct ssh2_userkey *) bv; - int i; - int alen, blen; - unsigned char *ablob, *bblob; - int c; - - /* - * Compare purely by public blob. - */ - ablob = a->alg->public_blob(a->data, &alen); - bblob = b->alg->public_blob(b->data, &blen); - - c = 0; - for (i = 0; i < alen && i < blen; i++) { - if (ablob[i] < bblob[i]) { - c = -1; - break; - } else if (ablob[i] > bblob[i]) { - c = +1; - break; - } - } - if (c == 0 && i < alen) - c = +1; /* a is longer */ - if (c == 0 && i < blen) - c = -1; /* a is longer */ - - sfree(ablob); - sfree(bblob); - - return c; -} - /* * Key comparison function for looking up a blob in the 2-3-4 tree * of SSH-2 keys. */ static int cmpkeys_ssh2_asymm(void *av, void *bv) { - struct blob *a = (struct blob *) av; + strbuf *ablob = (strbuf *) av; struct ssh2_userkey *b = (struct ssh2_userkey *) bv; - int i; - int alen, blen; - const unsigned char *ablob; - unsigned char *bblob; - int c; + strbuf *bblob; + int i, c; /* * Compare purely by public blob. */ - ablob = a->blob; - alen = a->len; - bblob = b->alg->public_blob(b->data, &blen); + bblob = strbuf_new(); + b->alg->public_blob(b->data, BinarySink_UPCAST(bblob)); c = 0; - for (i = 0; i < alen && i < blen; i++) { - if (ablob[i] < bblob[i]) { + for (i = 0; i < ablob->len && i < bblob->len; i++) { + if (ablob->u[i] < bblob->u[i]) { c = -1; break; - } else if (ablob[i] > bblob[i]) { + } else if (ablob->u[i] > bblob->u[i]) { c = +1; break; } } - if (c == 0 && i < alen) + if (c == 0 && i < ablob->len) c = +1; /* a is longer */ - if (c == 0 && i < blen) + if (c == 0 && i < bblob->len) c = -1; /* a is longer */ - sfree(bblob); + strbuf_free(bblob); return c; } +/* + * Main key comparison function for the 2-3-4 tree of SSH-2 keys. + */ +static int cmpkeys_ssh2(void *av, void *bv) +{ + struct ssh2_userkey *a = (struct ssh2_userkey *) av; + strbuf *ablob; + int toret; + + ablob = strbuf_new(); + a->alg->public_blob(a->data, BinarySink_UPCAST(ablob)); + toret = cmpkeys_ssh2_asymm(ablob, bv); + strbuf_free(ablob); + return toret; +} + /* * Create an SSH-1 key list in a malloc'ed buffer; return its * length. */ void *pageant_make_keylist1(int *length) { - int i, nkeys, len; + strbuf *buf = strbuf_new(); + BinarySink *bs = BinarySink_UPCAST(buf); + int i; struct RSAKey *key; - unsigned char *blob, *p, *ret; - int bloblen; - /* - * Count up the number and length of keys we hold. - */ - len = 4; - nkeys = 0; + put_uint32(bs, count234(rsakeys)); for (i = 0; NULL != (key = index234(rsakeys, i)); i++) { - nkeys++; - blob = rsa_ssh1_public_blob(key, &bloblen, RSA_SSH1_EXPONENT_FIRST); - len += bloblen; - sfree(blob); - len += 4 + strlen(key->comment); + rsa_ssh1_public_blob(bs, key, RSA_SSH1_EXPONENT_FIRST); + put_stringz(bs, key->comment); } - /* Allocate the buffer. */ - p = ret = snewn(len, unsigned char); - if (length) *length = len; - - PUT_32BIT(p, nkeys); - p += 4; - for (i = 0; NULL != (key = index234(rsakeys, i)); i++) { - blob = rsa_ssh1_public_blob(key, &bloblen, RSA_SSH1_EXPONENT_FIRST); - memcpy(p, blob, bloblen); - p += bloblen; - sfree(blob); - PUT_32BIT(p, strlen(key->comment)); - memcpy(p + 4, key->comment, strlen(key->comment)); - p += 4 + strlen(key->comment); - } - - assert(p - ret == len); - return ret; + return strbuf_to_str(buf); } /* @@ -214,49 +153,20 @@ void *pageant_make_keylist1(int *length) */ void *pageant_make_keylist2(int *length) { + strbuf *buf = strbuf_new(); + BinarySink *bs = BinarySink_UPCAST(buf); + int i; struct ssh2_userkey *key; - int i, len, nkeys; - unsigned char *blob, *p, *ret; - int bloblen; - /* - * Count up the number and length of keys we hold. - */ - len = 4; - nkeys = 0; + put_uint32(bs, count234(ssh2keys)); for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) { - nkeys++; - len += 4; /* length field */ - blob = key->alg->public_blob(key->data, &bloblen); - len += bloblen; - sfree(blob); - len += 4 + strlen(key->comment); + strbuf *blob = strbuf_new(); + key->alg->public_blob(key->data, BinarySink_UPCAST(blob)); + put_stringsb(bs, blob); + put_stringz(bs, key->comment); } - /* Allocate the buffer. */ - p = ret = snewn(len, unsigned char); - if (length) *length = len; - - /* - * Packet header is the obvious five bytes, plus four - * bytes for the key count. - */ - PUT_32BIT(p, nkeys); - p += 4; - for (i = 0; NULL != (key = index234(ssh2keys, i)); i++) { - blob = key->alg->public_blob(key->data, &bloblen); - PUT_32BIT(p, bloblen); - p += 4; - memcpy(p, blob, bloblen); - p += bloblen; - sfree(blob); - PUT_32BIT(p, strlen(key->comment)); - memcpy(p + 4, key->comment, strlen(key->comment)); - p += 4 + strlen(key->comment); - } - - assert(p - ret == len); - return ret; + return strbuf_to_str(buf); } static void plog(void *logctx, pageant_logfn_t logfn, const char *fmt, ...) @@ -480,10 +390,11 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen, */ { struct ssh2_userkey *key; - struct blob b; + const void *blobp; + int bloblen; const unsigned char *data; - unsigned char *signature; - int datalen, siglen, len; + strbuf *signature; + int datalen, len; plog(logctx, logfn, "request: SSH2_AGENTC_SIGN_REQUEST"); @@ -491,14 +402,14 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen, fail_reason = "request truncated before public key"; goto failure; } - b.len = toint(GET_32BIT(p)); - if (b.len < 0 || b.len > msgend - (p+4)) { + bloblen = toint(GET_32BIT(p)); + if (bloblen < 0 || bloblen > msgend - (p+4)) { fail_reason = "request truncated before public key"; goto failure; } p += 4; - b.blob = p; - p += b.len; + blobp = p; + p += bloblen; if (msgend < p+4) { fail_reason = "request truncated before string to sign"; goto failure; @@ -511,23 +422,29 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen, } data = p; if (logfn) { - char *fingerprint = ssh2_fingerprint_blob(b.blob, b.len); + char *fingerprint = ssh2_fingerprint_blob(blobp, bloblen); plog(logctx, logfn, "requested key: %s", fingerprint); sfree(fingerprint); } - key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm); + { + strbuf *blob = strbuf_new(); + put_data(blob, blobp, bloblen); + key = find234(ssh2keys, blob, cmpkeys_ssh2_asymm); + strbuf_free(blob); + } if (!key) { fail_reason = "key not found"; goto failure; } - signature = key->alg->sign(key->data, (const char *)data, - datalen, &siglen); - len = 5 + 4 + siglen; + signature = strbuf_new(); + key->alg->sign(key->data, (const char *)data, datalen, + BinarySink_UPCAST(signature)); + len = 5 + 4 + signature->len; PUT_32BIT(ret, len - 4); ret[4] = SSH2_AGENT_SIGN_RESPONSE; - PUT_32BIT(ret + 5, siglen); - memcpy(ret + 5 + 4, signature, siglen); - sfree(signature); + PUT_32BIT(ret + 5, signature->len); + memcpy(ret + 5 + 4, signature->s, signature->len); + strbuf_free(signature); plog(logctx, logfn, "reply: SSH2_AGENT_SIGN_RESPONSE"); } @@ -788,7 +705,8 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen, */ { struct ssh2_userkey *key; - struct blob b; + const void *blobp; + int bloblen; plog(logctx, logfn, "request: SSH2_AGENTC_REMOVE_IDENTITY"); @@ -796,23 +714,28 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen, fail_reason = "request truncated before public key"; goto failure; } - b.len = toint(GET_32BIT(p)); + bloblen = toint(GET_32BIT(p)); p += 4; - if (b.len < 0 || b.len > msgend - p) { + if (bloblen < 0 || bloblen > msgend - p) { fail_reason = "request truncated before public key"; goto failure; } - b.blob = p; - p += b.len; + blobp = p; + p += bloblen; if (logfn) { - char *fingerprint = ssh2_fingerprint_blob(b.blob, b.len); + char *fingerprint = ssh2_fingerprint_blob(blobp, bloblen); plog(logctx, logfn, "unwanted key: %s", fingerprint); sfree(fingerprint); } - key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm); + { + strbuf *blob = strbuf_new(); + put_data(blob, blobp, bloblen); + key = find234(ssh2keys, blob, cmpkeys_ssh2_asymm); + strbuf_free(blob); + } if (!key) { fail_reason = "key not found"; goto failure; @@ -1283,55 +1206,53 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, * which may or may not be us). */ { - void *blob; + strbuf *blob = strbuf_new(); unsigned char *keylist, *p; - int i, nkeys, bloblen, keylistlen; + int i, nkeys, keylistlen; if (type == SSH_KEYTYPE_SSH1) { - if (!rsa_ssh1_loadpub(filename, &blob, &bloblen, NULL, &error)) { + if (!rsa_ssh1_loadpub(filename, BinarySink_UPCAST(blob), NULL, &error)) { *retstr = dupprintf("Couldn't load private key (%s)", error); + strbuf_free(blob); return PAGEANT_ACTION_FAILURE; } keylist = pageant_get_keylist1(&keylistlen); } else { - unsigned char *blob2; - blob = ssh2_userkey_loadpub(filename, NULL, &bloblen, - NULL, &error); - if (!blob) { + /* For our purposes we want the blob prefixed with its + * length, so add a placeholder here to fill in + * afterwards */ + put_uint32(blob, 0); + if (!ssh2_userkey_loadpub(filename, NULL, BinarySink_UPCAST(blob), + NULL, &error)) { *retstr = dupprintf("Couldn't load private key (%s)", error); + strbuf_free(blob); return PAGEANT_ACTION_FAILURE; } - /* For our purposes we want the blob prefixed with its length */ - blob2 = snewn(bloblen+4, unsigned char); - PUT_32BIT(blob2, bloblen); - memcpy(blob2 + 4, blob, bloblen); - sfree(blob); - blob = blob2; - + PUT_32BIT(blob->s, blob->len - 4); keylist = pageant_get_keylist2(&keylistlen); } if (keylist) { if (keylistlen < 4) { *retstr = dupstr("Received broken key list from agent"); sfree(keylist); - sfree(blob); + strbuf_free(blob); return PAGEANT_ACTION_FAILURE; } nkeys = toint(GET_32BIT(keylist)); if (nkeys < 0) { *retstr = dupstr("Received broken key list from agent"); sfree(keylist); - sfree(blob); + strbuf_free(blob); return PAGEANT_ACTION_FAILURE; } p = keylist + 4; keylistlen -= 4; for (i = 0; i < nkeys; i++) { - if (!memcmp(blob, p, bloblen)) { + if (!memcmp(blob->s, p, blob->len)) { /* Key is already present; we can now leave. */ sfree(keylist); - sfree(blob); + strbuf_free(blob); return PAGEANT_ACTION_OK; } /* Now skip over public blob */ @@ -1340,7 +1261,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, if (n < 0) { *retstr = dupstr("Received broken key list from agent"); sfree(keylist); - sfree(blob); + strbuf_free(blob); return PAGEANT_ACTION_FAILURE; } p += n; @@ -1350,7 +1271,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, if (keylistlen < 4) { *retstr = dupstr("Received broken key list from agent"); sfree(keylist); - sfree(blob); + strbuf_free(blob); return PAGEANT_ACTION_FAILURE; } n = GET_32BIT(p); @@ -1360,7 +1281,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, if (n < 0 || n > keylistlen) { *retstr = dupstr("Received broken key list from agent"); sfree(keylist); - sfree(blob); + strbuf_free(blob); return PAGEANT_ACTION_FAILURE; } p += n; @@ -1372,7 +1293,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, if (keylistlen < 4) { *retstr = dupstr("Received broken key list from agent"); sfree(keylist); - sfree(blob); + strbuf_free(blob); return PAGEANT_ACTION_FAILURE; } n = GET_32BIT(p); @@ -1382,7 +1303,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, if (n < 0 || n > keylistlen) { *retstr = dupstr("Received broken key list from agent"); sfree(keylist); - sfree(blob); + strbuf_free(blob); return PAGEANT_ACTION_FAILURE; } p += n; @@ -1393,7 +1314,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, sfree(keylist); } - sfree(blob); + strbuf_free(blob); } error = NULL; @@ -1551,15 +1472,17 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, if (!pageant_local) { unsigned char *request, *response; void *vresponse; - int reqlen, alglen, clen, keybloblen, resplen; + strbuf *keyblob; + int reqlen, alglen, clen, resplen; alglen = strlen(skey->alg->name); clen = strlen(skey->comment); - keybloblen = skey->alg->openssh_fmtkey(skey->data, NULL, 0); + keyblob = strbuf_new(); + skey->alg->openssh_fmtkey(skey->data, BinarySink_UPCAST(keyblob)); reqlen = 4 + 1 + /* length, message type */ 4 + alglen + /* algorithm name */ - keybloblen + /* key data */ + keyblob->len + /* key data */ 4 + clen /* comment */ ; @@ -1571,9 +1494,8 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, reqlen += 4; memcpy(request + reqlen, skey->alg->name, alglen); reqlen += alglen; - reqlen += skey->alg->openssh_fmtkey(skey->data, - request + reqlen, - keybloblen); + memcpy(request + reqlen, keyblob->s, keyblob->len); + reqlen += keyblob->len; PUT_32BIT(request + reqlen, clen); memcpy(request + reqlen + 4, skey->comment, clen); reqlen += clen + 4; @@ -1660,12 +1582,13 @@ int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx, comment = dupprintf("%.*s", (int)n, (const char *)p); p += n, keylistlen -= n; - cbkey.blob = rsa_ssh1_public_blob(&rkey, &cbkey.bloblen, - RSA_SSH1_EXPONENT_FIRST); + cbkey.blob = strbuf_new(); + rsa_ssh1_public_blob(BinarySink_UPCAST(cbkey.blob), &rkey, + RSA_SSH1_EXPONENT_FIRST); cbkey.comment = comment; cbkey.ssh_version = 1; callback(callback_ctx, fingerprint, comment, &cbkey); - sfree(cbkey.blob); + strbuf_free(cbkey.blob); freersakey(&rkey); sfree(comment); } @@ -1710,8 +1633,8 @@ int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx, return PAGEANT_ACTION_FAILURE; } fingerprint = ssh2_fingerprint_blob(p, n); - cbkey.blob = p; - cbkey.bloblen = n; + cbkey.blob = strbuf_new(); + put_data(cbkey.blob, p, n); p += n, keylistlen -= n; /* comment */ @@ -1756,18 +1679,18 @@ int pageant_delete_key(struct pageant_pubkey *key, char **retstr) void *vresponse; if (key->ssh_version == 1) { - reqlen = 5 + key->bloblen; + reqlen = 5 + key->blob->len; request = snewn(reqlen, unsigned char); PUT_32BIT(request, reqlen - 4); request[4] = SSH1_AGENTC_REMOVE_RSA_IDENTITY; - memcpy(request + 5, key->blob, key->bloblen); + memcpy(request + 5, key->blob->s, key->blob->len); } else { - reqlen = 9 + key->bloblen; + reqlen = 9 + key->blob->len; request = snewn(reqlen, unsigned char); PUT_32BIT(request, reqlen - 4); request[4] = SSH2_AGENTC_REMOVE_IDENTITY; - PUT_32BIT(request + 5, key->bloblen); - memcpy(request + 9, key->blob, key->bloblen); + PUT_32BIT(request + 5, key->blob->len); + memcpy(request + 9, key->blob->s, key->blob->len); } agent_query_synchronous(request, reqlen, &vresponse, &resplen); @@ -1821,9 +1744,8 @@ int pageant_delete_all_keys(char **retstr) struct pageant_pubkey *pageant_pubkey_copy(struct pageant_pubkey *key) { struct pageant_pubkey *ret = snew(struct pageant_pubkey); - ret->blob = snewn(key->bloblen, unsigned char); - memcpy(ret->blob, key->blob, key->bloblen); - ret->bloblen = key->bloblen; + ret->blob = strbuf_new(); + put_data(ret->blob, key->blob->s, key->blob->len); ret->comment = key->comment ? dupstr(key->comment) : NULL; ret->ssh_version = key->ssh_version; return ret; @@ -1832,6 +1754,6 @@ struct pageant_pubkey *pageant_pubkey_copy(struct pageant_pubkey *key) void pageant_pubkey_free(struct pageant_pubkey *key) { sfree(key->comment); - sfree(key->blob); + strbuf_free(key->blob); sfree(key); } diff --git a/pageant.h b/pageant.h index 6e29f40c..b98a0c4d 100644 --- a/pageant.h +++ b/pageant.h @@ -125,8 +125,7 @@ struct pageant_pubkey { /* Everything needed to identify a public key found by * pageant_enum_keys and pass it back to the agent or other code * later */ - void *blob; - int bloblen; + strbuf *blob; char *comment; int ssh_version; }; diff --git a/ssh.c b/ssh.c index 47d44584..8372aa25 100644 --- a/ssh.c +++ b/ssh.c @@ -4144,16 +4144,18 @@ int verify_ssh_manual_host_key(Ssh ssh, const char *fingerprint, * Construct the base64-encoded public key blob and see if * that's listed. */ - unsigned char *binblob; + strbuf *binblob; char *base64blob; - int binlen, atoms, i; - binblob = ssh2keytype->public_blob(ssh2keydata, &binlen); - atoms = (binlen + 2) / 3; + int atoms, i; + binblob = strbuf_new(); + ssh2keytype->public_blob(ssh2keydata, BinarySink_UPCAST(binblob)); + atoms = (binblob->len + 2) / 3; base64blob = snewn(atoms * 4 + 1, char); for (i = 0; i < atoms; i++) - base64_encode_atom(binblob + 3*i, binlen - 3*i, base64blob + 4*i); + base64_encode_atom(binblob->u + 3*i, + binblob->len - 3*i, base64blob + 4*i); base64blob[atoms * 4] = '\0'; - sfree(binblob); + strbuf_free(binblob); if (conf_get_str_str_opt(ssh->conf, CONF_ssh_manual_hostkeys, base64blob)) { sfree(base64blob); @@ -4191,8 +4193,7 @@ static void do_ssh1_login(void *vctx) unsigned char cookie[8]; unsigned char session_id[16]; int cipher_type; - void *publickey_blob; - int publickey_bloblen; + strbuf *publickey_blob; char *publickey_comment; int privatekey_available, privatekey_encrypted; prompts_t *cur_prompt; @@ -4529,8 +4530,9 @@ static void do_ssh1_login(void *vctx) if (keytype == SSH_KEYTYPE_SSH1 || keytype == SSH_KEYTYPE_SSH1_PUBLIC) { const char *error; + s->publickey_blob = strbuf_new(); if (rsa_ssh1_loadpub(s->keyfile, - &s->publickey_blob, &s->publickey_bloblen, + BinarySink_UPCAST(s->publickey_blob), &s->publickey_comment, &error)) { s->privatekey_available = (keytype == SSH_KEYTYPE_SSH1); if (!s->privatekey_available) @@ -4545,7 +4547,8 @@ static void do_ssh1_login(void *vctx) error); c_write_str(ssh, msgbuf); sfree(msgbuf); - s->publickey_blob = NULL; + strbuf_free(s->publickey_blob); + s->publickey_blob = NULL; } } else { char *msgbuf; @@ -4634,8 +4637,8 @@ static void do_ssh1_login(void *vctx) } } if (s->publickey_blob) { - if (!memcmp(pkblob, s->publickey_blob, - s->publickey_bloblen)) { + if (!memcmp(pkblob, s->publickey_blob->s, + s->publickey_blob->len)) { logeventf(ssh, "Pageant key #%d matches " "configured key file", s->keyi); s->tried_publickey = 1; @@ -5161,7 +5164,7 @@ static void do_ssh1_login(void *vctx) /* Clear up */ if (s->publickey_blob) { - sfree(s->publickey_blob); + strbuf_free(s->publickey_blob); sfree(s->publickey_comment); } @@ -6456,8 +6459,7 @@ static struct kexinit_algorithm *ssh2_kexinit_addalg(struct kexinit_algorithm */ struct ssh_transient_hostkey_cache_entry { const struct ssh_signkey *alg; - unsigned char *pub_blob; - int pub_len; + strbuf *pub_blob; }; static int ssh_transient_hostkey_cache_cmp(void *av, void *bv) @@ -6486,7 +6488,7 @@ static void ssh_cleanup_transient_hostkey_store(Ssh ssh) { struct ssh_transient_hostkey_cache_entry *ent; while ((ent = delpos234(ssh->transient_hostkey_cache, 0)) != NULL) { - sfree(ent->pub_blob); + strbuf_free(ent->pub_blob); sfree(ent); } freetree234(ssh->transient_hostkey_cache); @@ -6499,13 +6501,14 @@ static void ssh_store_transient_hostkey( if ((ent = find234(ssh->transient_hostkey_cache, (void *)alg, ssh_transient_hostkey_cache_find)) != NULL) { - sfree(ent->pub_blob); + strbuf_free(ent->pub_blob); sfree(ent); } ent = snew(struct ssh_transient_hostkey_cache_entry); ent->alg = alg; - ent->pub_blob = alg->public_blob(key, &ent->pub_len); + ent->pub_blob = strbuf_new(); + alg->public_blob(key, BinarySink_UPCAST(ent->pub_blob)); retd = add234(ssh->transient_hostkey_cache, ent); assert(retd == ent); } @@ -6518,14 +6521,15 @@ static int ssh_verify_transient_hostkey( if ((ent = find234(ssh->transient_hostkey_cache, (void *)alg, ssh_transient_hostkey_cache_find)) != NULL) { - int this_len; - unsigned char *this_blob = alg->public_blob(key, &this_len); + strbuf *this_blob = strbuf_new(); + alg->public_blob(key, BinarySink_UPCAST(this_blob)); - if (this_len == ent->pub_len && - !memcmp(this_blob, ent->pub_blob, this_len)) + if (this_blob->len == ent->pub_blob->len && + !memcmp(this_blob->s, ent->pub_blob->s, + this_blob->len)) toret = TRUE; - sfree(this_blob); + strbuf_free(this_blob); } return toret; @@ -7430,18 +7434,11 @@ static void do_ssh2_transport(void *vctx) crStopV; } + s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_ECDH_INIT); { - char *publicPoint; - int publicPointLength; - publicPoint = ssh_ecdhkex_getpublic(s->eckey, &publicPointLength); - if (!publicPoint) { - ssh_ecdhkex_freekey(s->eckey); - bombout(("Unable to encode public key for ECDH")); - crStopV; - } - s->pktout = ssh2_pkt_init(SSH2_MSG_KEX_ECDH_INIT); - put_string(s->pktout, publicPoint, publicPointLength); - sfree(publicPoint); + strbuf *pubpoint = strbuf_new(); + ssh_ecdhkex_getpublic(s->eckey, BinarySink_UPCAST(pubpoint)); + put_stringsb(s->pktout, pubpoint); } ssh2_pkt_send_noqueue(ssh, s->pktout); @@ -7463,17 +7460,11 @@ static void do_ssh2_transport(void *vctx) s->hostkeydata, s->hostkeylen); { - char *publicPoint; - int publicPointLength; - publicPoint = ssh_ecdhkex_getpublic(s->eckey, &publicPointLength); - if (!publicPoint) { - ssh_ecdhkex_freekey(s->eckey); - bombout(("Unable to encode public key for ECDH hash")); - crStopV; - } + strbuf *pubpoint = strbuf_new(); + ssh_ecdhkex_getpublic(s->eckey, BinarySink_UPCAST(pubpoint)); hash_string(ssh->kex->hash, ssh->exhash, - publicPoint, publicPointLength); - sfree(publicPoint); + pubpoint->u, pubpoint->len); + strbuf_free(pubpoint); } { @@ -9955,8 +9946,7 @@ static void do_ssh2_userauth(void *vctx) char *username; char *password; int got_username; - void *publickey_blob; - int publickey_bloblen; + strbuf *publickey_blob; int privatekey_available, privatekey_encrypted; char *publickey_algorithm; char *publickey_comment; @@ -10053,12 +10043,11 @@ static void do_ssh2_userauth(void *vctx) keytype == SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 || keytype == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH) { const char *error; - s->publickey_blob = - ssh2_userkey_loadpub(s->keyfile, + s->publickey_blob = strbuf_new(); + if (ssh2_userkey_loadpub(s->keyfile, &s->publickey_algorithm, - &s->publickey_bloblen, - &s->publickey_comment, &error); - if (s->publickey_blob) { + BinarySink_UPCAST(s->publickey_blob), + &s->publickey_comment, &error)) { s->privatekey_available = (keytype == SSH_KEYTYPE_SSH2); if (!s->privatekey_available) logeventf(ssh, "Key file contains public key only"); @@ -10074,6 +10063,8 @@ static void do_ssh2_userauth(void *vctx) error); c_write_str(ssh, msgbuf); sfree(msgbuf); + strbuf_free(s->publickey_blob); + s->publickey_blob = NULL; } } else { char *msgbuf; @@ -10171,9 +10162,9 @@ static void do_ssh2_userauth(void *vctx) /* See if configured key is in agent. */ for (keyi = 0; keyi < s->nkeys; keyi++) { s->pklen = toint(GET_32BIT(p)); - if (s->pklen == s->publickey_bloblen && - !memcmp(p+4, s->publickey_blob, - s->publickey_bloblen)) { + if (s->pklen == s->publickey_blob->len && + !memcmp(p+4, s->publickey_blob->s, + s->publickey_blob->len)) { logeventf(ssh, "Pageant key #%d matches " "configured key file", keyi); s->keyi = keyi; @@ -10626,7 +10617,8 @@ static void do_ssh2_userauth(void *vctx) put_bool(s->pktout, FALSE); /* no signature included */ put_stringz(s->pktout, s->publickey_algorithm); - put_string(s->pktout, s->publickey_blob, s->publickey_bloblen); + put_string(s->pktout, s->publickey_blob->s, + s->publickey_blob->len); ssh2_pkt_send(ssh, s->pktout); logevent("Offered public key"); @@ -10720,9 +10712,7 @@ static void do_ssh2_userauth(void *vctx) } if (key) { - unsigned char *pkblob, *sigblob, *sigdata; - int pkblob_len, sigblob_len, sigdata_len; - int p; + strbuf *pkblob, *sigdata, *sigblob; /* * We have loaded the private key and the server @@ -10736,9 +10726,9 @@ static void do_ssh2_userauth(void *vctx) put_stringz(s->pktout, "publickey"); /* method */ put_bool(s->pktout, TRUE); /* signature follows */ put_stringz(s->pktout, key->alg->name); - pkblob = key->alg->public_blob(key->data, - &pkblob_len); - put_string(s->pktout, pkblob, pkblob_len); + pkblob = strbuf_new(); + key->alg->public_blob(key->data, BinarySink_UPCAST(pkblob)); + put_string(s->pktout, pkblob->s, pkblob->len); /* * The data to be signed is: @@ -10748,30 +10738,24 @@ static void do_ssh2_userauth(void *vctx) * followed by everything so far placed in the * outgoing packet. */ - sigdata_len = s->pktout->length - 5 + 4 + - ssh->v2_session_id_len; - if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID) - sigdata_len -= 4; - sigdata = snewn(sigdata_len, unsigned char); - p = 0; - if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) { - PUT_32BIT(sigdata+p, ssh->v2_session_id_len); - p += 4; - } - memcpy(sigdata+p, ssh->v2_session_id, - ssh->v2_session_id_len); - p += ssh->v2_session_id_len; - memcpy(sigdata+p, s->pktout->data + 5, - s->pktout->length - 5); - p += s->pktout->length - 5; - assert(p == sigdata_len); - sigblob = key->alg->sign(key->data, (char *)sigdata, - sigdata_len, &sigblob_len); - ssh2_add_sigblob(ssh, s->pktout, pkblob, pkblob_len, - sigblob, sigblob_len); - sfree(pkblob); - sfree(sigblob); - sfree(sigdata); + sigdata = strbuf_new(); + if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID) { + put_data(sigdata, ssh->v2_session_id, + ssh->v2_session_id_len); + } else { + put_string(sigdata, ssh->v2_session_id, + ssh->v2_session_id_len); + } + put_data(sigdata, s->pktout->data + 5, + s->pktout->length - 5); + sigblob = strbuf_new(); + key->alg->sign(key->data, sigdata->s, sigdata->len, + BinarySink_UPCAST(sigblob)); + strbuf_free(sigdata); + ssh2_add_sigblob(ssh, s->pktout, pkblob->s, pkblob->len, + sigblob->s, sigblob->len); + strbuf_free(pkblob); + strbuf_free(sigblob); ssh2_pkt_send(ssh, s->pktout); logevent("Sent public key signature"); @@ -11363,7 +11347,7 @@ static void do_ssh2_userauth(void *vctx) /* Clear up various bits and pieces from authentication. */ if (s->publickey_blob) { sfree(s->publickey_algorithm); - sfree(s->publickey_blob); + strbuf_free(s->publickey_blob); sfree(s->publickey_comment); } if (s->agent_response) diff --git a/ssh.h b/ssh.h index 7b6751f0..bf341ceb 100644 --- a/ssh.h +++ b/ssh.h @@ -194,8 +194,8 @@ int rsastr_len(struct RSAKey *key); void rsastr_fmt(char *str, struct RSAKey *key); void rsa_fingerprint(char *str, int len, struct RSAKey *key); int rsa_verify(struct RSAKey *key); -unsigned char *rsa_ssh1_public_blob(struct RSAKey *key, int *len, - RsaSsh1Order order); +void rsa_ssh1_public_blob(BinarySink *bs, struct RSAKey *key, + RsaSsh1Order order); int rsa_public_blob_len(void *data, int maxlen); void freersakey(struct RSAKey *key); @@ -228,7 +228,7 @@ struct ssh_kex; const char *ssh_ecdhkex_curve_textname(const struct ssh_kex *kex); void *ssh_ecdhkex_newkey(const struct ssh_kex *kex); void ssh_ecdhkex_freekey(void *key); -char *ssh_ecdhkex_getpublic(void *key, int *len); +void ssh_ecdhkex_getpublic(void *key, BinarySink *bs); Bignum ssh_ecdhkex_getkey(void *key, char *remoteKey, int remoteKeyLen); /* @@ -400,14 +400,14 @@ struct ssh_signkey { const char *data, int len); void (*freekey) (void *key); char *(*fmtkey) (void *key); - unsigned char *(*public_blob) (void *key, int *len); - unsigned char *(*private_blob) (void *key, int *len); + void (*public_blob)(void *key, BinarySink *); + void (*private_blob)(void *key, BinarySink *); void *(*createkey) (const struct ssh_signkey *self, const unsigned char *pub_blob, int pub_len, const unsigned char *priv_blob, int priv_len); void *(*openssh_createkey) (const struct ssh_signkey *self, const unsigned char **blob, int *len); - int (*openssh_fmtkey) (void *key, unsigned char *blob, int len); + void (*openssh_fmtkey) (void *key, BinarySink *); /* OpenSSH private key blobs, as created by openssh_fmtkey and * consumed by openssh_createkey, always (at least so far...) take * the form of a number of SSH-2 strings / mpints concatenated @@ -421,8 +421,7 @@ struct ssh_signkey { const void *blob, int len); int (*verifysig) (void *key, const char *sig, int siglen, const char *data, int datalen); - unsigned char *(*sign) (void *key, const char *data, int datalen, - int *siglen); + void (*sign) (void *key, const char *data, int datalen, BinarySink *); const char *name; const char *keytype; /* for host key cache */ const void *extra; /* private to the public key methods */ @@ -719,7 +718,7 @@ const char *dh_validate_f(void *handle, Bignum f); Bignum dh_find_K(void *, Bignum f); int rsa_ssh1_encrypted(const Filename *filename, char **comment); -int rsa_ssh1_loadpub(const Filename *filename, void **blob, int *bloblen, +int rsa_ssh1_loadpub(const Filename *filename, BinarySink *bs, char **commentptr, const char **errorstr); int rsa_ssh1_loadkey(const Filename *filename, struct RSAKey *key, const char *passphrase, const char **errorstr); @@ -740,9 +739,9 @@ int ssh2_userkey_encrypted(const Filename *filename, char **comment); struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, const char *passphrase, const char **errorstr); -unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm, - int *pub_blob_len, char **commentptr, - const char **errorstr); +int ssh2_userkey_loadpub(const Filename *filename, char **algorithm, + BinarySink *bs, + char **commentptr, const char **errorstr); int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key, char *passphrase); const struct ssh_signkey *find_pubkey_alg(const char *name); diff --git a/sshdss.c b/sshdss.c index 02d7fc63..5c53be82 100644 --- a/sshdss.c +++ b/sshdss.c @@ -271,72 +271,22 @@ static int dss_verifysig(void *key, const char *sig, int siglen, return ret; } -static unsigned char *dss_public_blob(void *key, int *len) +static void dss_public_blob(void *key, BinarySink *bs) { struct dss_key *dss = (struct dss_key *) key; - int plen, qlen, glen, ylen, bloblen; - int i; - unsigned char *blob, *p; - plen = (bignum_bitcount(dss->p) + 8) / 8; - qlen = (bignum_bitcount(dss->q) + 8) / 8; - glen = (bignum_bitcount(dss->g) + 8) / 8; - ylen = (bignum_bitcount(dss->y) + 8) / 8; - - /* - * string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total - * 27 + sum of lengths. (five length fields, 20+7=27). - */ - bloblen = 27 + plen + qlen + glen + ylen; - blob = snewn(bloblen, unsigned char); - p = blob; - PUT_32BIT(p, 7); - p += 4; - memcpy(p, "ssh-dss", 7); - p += 7; - PUT_32BIT(p, plen); - p += 4; - for (i = plen; i--;) - *p++ = bignum_byte(dss->p, i); - PUT_32BIT(p, qlen); - p += 4; - for (i = qlen; i--;) - *p++ = bignum_byte(dss->q, i); - PUT_32BIT(p, glen); - p += 4; - for (i = glen; i--;) - *p++ = bignum_byte(dss->g, i); - PUT_32BIT(p, ylen); - p += 4; - for (i = ylen; i--;) - *p++ = bignum_byte(dss->y, i); - assert(p == blob + bloblen); - *len = bloblen; - return blob; + put_stringz(bs, "ssh-dss"); + put_mp_ssh2(bs, dss->p); + put_mp_ssh2(bs, dss->q); + put_mp_ssh2(bs, dss->g); + put_mp_ssh2(bs, dss->y); } -static unsigned char *dss_private_blob(void *key, int *len) +static void dss_private_blob(void *key, BinarySink *bs) { struct dss_key *dss = (struct dss_key *) key; - int xlen, bloblen; - int i; - unsigned char *blob, *p; - xlen = (bignum_bitcount(dss->x) + 8) / 8; - - /* - * mpint x, string[20] the SHA of p||q||g. Total 4 + xlen. - */ - bloblen = 4 + xlen; - blob = snewn(bloblen, unsigned char); - p = blob; - PUT_32BIT(p, xlen); - p += 4; - for (i = xlen; i--;) - *p++ = bignum_byte(dss->x, i); - assert(p == blob + bloblen); - *len = bloblen; - return blob; + put_mp_ssh2(bs, dss->x); } static void *dss_createkey(const struct ssh_signkey *self, @@ -415,32 +365,15 @@ static void *dss_openssh_createkey(const struct ssh_signkey *self, return dss; } -static int dss_openssh_fmtkey(void *key, unsigned char *blob, int len) +static void dss_openssh_fmtkey(void *key, BinarySink *bs) { struct dss_key *dss = (struct dss_key *) key; - int bloblen, i; - bloblen = - ssh2_bignum_length(dss->p) + - ssh2_bignum_length(dss->q) + - ssh2_bignum_length(dss->g) + - ssh2_bignum_length(dss->y) + - ssh2_bignum_length(dss->x); - - if (bloblen > len) - return bloblen; - - bloblen = 0; -#define ENC(x) \ - PUT_32BIT(blob+bloblen, ssh2_bignum_length((x))-4); bloblen += 4; \ - for (i = ssh2_bignum_length((x))-4; i-- ;) blob[bloblen++]=bignum_byte((x),i); - ENC(dss->p); - ENC(dss->q); - ENC(dss->g); - ENC(dss->y); - ENC(dss->x); - - return bloblen; + put_mp_ssh2(bs, dss->p); + put_mp_ssh2(bs, dss->q); + put_mp_ssh2(bs, dss->g); + put_mp_ssh2(bs, dss->y); + put_mp_ssh2(bs, dss->x); } static int dss_pubkey_bits(const struct ssh_signkey *self, @@ -578,14 +511,13 @@ Bignum *dss_gen_k(const char *id_string, Bignum modulus, Bignum private_key, } } -static unsigned char *dss_sign(void *key, const char *data, int datalen, - int *siglen) +static void dss_sign(void *key, const char *data, int datalen, + BinarySink *bs) { struct dss_key *dss = (struct dss_key *) key; Bignum k, gkp, hash, kinv, hxr, r, s; unsigned char digest[20]; - unsigned char *bytes; - int nbytes, i; + int i; SHA_Simple(data, datalen, digest); @@ -609,28 +541,14 @@ static unsigned char *dss_sign(void *key, const char *data, int datalen, freebn(k); freebn(hash); - /* - * Signature blob is - * - * string "ssh-dss" - * string two 20-byte numbers r and s, end to end - * - * i.e. 4+7 + 4+40 bytes. - */ - nbytes = 4 + 7 + 4 + 40; - bytes = snewn(nbytes, unsigned char); - PUT_32BIT(bytes, 7); - memcpy(bytes + 4, "ssh-dss", 7); - PUT_32BIT(bytes + 4 + 7, 40); - for (i = 0; i < 20; i++) { - bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i); - bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i); - } + put_stringz(bs, "ssh-dss"); + put_uint32(bs, 40); + for (i = 0; i < 20; i++) + put_byte(bs, bignum_byte(r, 19 - i)); + for (i = 0; i < 20; i++) + put_byte(bs, bignum_byte(s, 19 - i)); freebn(r); freebn(s); - - *siglen = nbytes; - return bytes; } const struct ssh_signkey ssh_dss = { diff --git a/sshecc.c b/sshecc.c index 64375966..1a632d9f 100644 --- a/sshecc.c +++ b/sshecc.c @@ -1837,89 +1837,53 @@ static char *ecdsa_fmtkey(void *key) return p; } -static unsigned char *ecdsa_public_blob(void *key, int *len) +static void ecdsa_public_blob(void *key, BinarySink *bs) { struct ec_key *ec = (struct ec_key *) key; - int pointlen, bloblen, fullnamelen, namelen; + int pointlen; int i; - unsigned char *blob, *p; - - fullnamelen = strlen(ec->signalg->name); if (ec->publicKey.curve->type == EC_EDWARDS) { /* Edwards compressed form "ssh-ed25519" point y[:-1] + x[0:1] */ pointlen = ec->publicKey.curve->fieldBits / 8; - /* Can't handle this in our loop */ - if (pointlen < 2) return NULL; + assert(pointlen >= 2); - bloblen = 4 + fullnamelen + 4 + pointlen; - blob = snewn(bloblen, unsigned char); - - p = blob; - PUT_32BIT(p, fullnamelen); - p += 4; - memcpy(p, ec->signalg->name, fullnamelen); - p += fullnamelen; - PUT_32BIT(p, pointlen); - p += 4; + put_stringz(bs, ec->signalg->name); + put_uint32(bs, pointlen); /* Unset last bit of y and set first bit of x in its place */ - for (i = 0; i < pointlen - 1; ++i) { - *p++ = bignum_byte(ec->publicKey.y, i); - } + for (i = 0; i < pointlen - 1; ++i) + put_byte(bs, bignum_byte(ec->publicKey.y, i)); /* Unset last bit of y and set first bit of x in its place */ - *p = bignum_byte(ec->publicKey.y, i) & 0x7f; - *p++ |= bignum_bit(ec->publicKey.x, 0) << 7; + put_byte(bs, ((bignum_byte(ec->publicKey.y, i) & 0x7f) | + (bignum_bit(ec->publicKey.x, 0) << 7))); } else if (ec->publicKey.curve->type == EC_WEIERSTRASS) { assert(ec->publicKey.curve->name); - namelen = strlen(ec->publicKey.curve->name); pointlen = (bignum_bitcount(ec->publicKey.curve->p) + 7) / 8; - /* - * string "ecdsa-sha2-", string "", 0x04 point x, y. - */ - bloblen = 4 + fullnamelen + 4 + namelen + 4 + 1 + (pointlen * 2); - blob = snewn(bloblen, unsigned char); - - p = blob; - PUT_32BIT(p, fullnamelen); - p += 4; - memcpy(p, ec->signalg->name, fullnamelen); - p += fullnamelen; - PUT_32BIT(p, namelen); - p += 4; - memcpy(p, ec->publicKey.curve->name, namelen); - p += namelen; - PUT_32BIT(p, (2 * pointlen) + 1); - p += 4; - *p++ = 0x04; - for (i = pointlen; i--;) { - *p++ = bignum_byte(ec->publicKey.x, i); - } - for (i = pointlen; i--;) { - *p++ = bignum_byte(ec->publicKey.y, i); - } + put_stringz(bs, ec->signalg->name); + put_stringz(bs, ec->publicKey.curve->name); + put_uint32(bs, (2 * pointlen) + 1); + put_byte(bs, 0x04); + for (i = pointlen; i--;) + put_byte(bs, bignum_byte(ec->publicKey.x, i)); + for (i = pointlen; i--;) + put_byte(bs, bignum_byte(ec->publicKey.y, i)); } else { - return NULL; + assert(0 && "Bad key type in ecdsa_public_blob"); } - - assert(p == blob + bloblen); - *len = bloblen; - - return blob; } -static unsigned char *ecdsa_private_blob(void *key, int *len) +static void ecdsa_private_blob(void *key, BinarySink *bs) { struct ec_key *ec = (struct ec_key *) key; - int keylen, bloblen; + int keylen; int i; - unsigned char *blob, *p; - if (!ec->privateKey) return NULL; + assert(ec->privateKey); if (ec->publicKey.curve->type == EC_EDWARDS) { /* Unsigned */ @@ -1929,27 +1893,15 @@ static unsigned char *ecdsa_private_blob(void *key, int *len) keylen = (bignum_bitcount(ec->privateKey) + 8) / 8; } - /* - * mpint privateKey. Total 4 + keylen. - */ - bloblen = 4 + keylen; - blob = snewn(bloblen, unsigned char); - - p = blob; - PUT_32BIT(p, keylen); - p += 4; + put_uint32(bs, keylen); if (ec->publicKey.curve->type == EC_EDWARDS) { /* Little endian */ for (i = 0; i < keylen; ++i) - *p++ = bignum_byte(ec->privateKey, i); + put_byte(bs, bignum_byte(ec->privateKey, i)); } else { for (i = keylen; i--;) - *p++ = bignum_byte(ec->privateKey, i); + put_byte(bs, bignum_byte(ec->privateKey, i)); } - - assert(p == blob + bloblen); - *len = bloblen; - return blob; } static void *ecdsa_createkey(const struct ssh_signkey *self, @@ -2060,53 +2012,40 @@ static void *ed25519_openssh_createkey(const struct ssh_signkey *self, return ec; } -static int ed25519_openssh_fmtkey(void *key, unsigned char *blob, int len) +static void ed25519_openssh_fmtkey(void *key, BinarySink *bs) { struct ec_key *ec = (struct ec_key *) key; + strbuf *pub; int pointlen; int keylen; - int bloblen; int i; - if (ec->publicKey.curve->type != EC_EDWARDS) { - return 0; - } + assert(ec->publicKey.curve->type == EC_EDWARDS); pointlen = (bignum_bitcount(ec->publicKey.y) + 7) / 8; keylen = (bignum_bitcount(ec->privateKey) + 7) / 8; - bloblen = 4 + pointlen + 4 + keylen + pointlen; - - if (bloblen > len) - return bloblen; /* Encode the public point */ - PUT_32BIT(blob, pointlen); - blob += 4; - - for (i = 0; i < pointlen - 1; ++i) { - *blob++ = bignum_byte(ec->publicKey.y, i); - } + pub = strbuf_new(); + put_uint32(pub, pointlen); + for (i = 0; i < pointlen - 1; ++i) + put_byte(pub, bignum_byte(ec->publicKey.y, i)); /* Unset last bit of y and set first bit of x in its place */ - *blob = bignum_byte(ec->publicKey.y, i) & 0x7f; - *blob++ |= bignum_bit(ec->publicKey.x, 0) << 7; + put_byte(pub, ((bignum_byte(ec->publicKey.y, i) & 0x7f) | + (bignum_bit(ec->publicKey.x, 0) << 7))); - PUT_32BIT(blob, keylen + pointlen); - blob += 4; - for (i = 0; i < keylen; ++i) { - *blob++ = bignum_byte(ec->privateKey, i); - } + put_data(bs, pub->s, pub->len); + + put_uint32(bs, keylen + pointlen); + for (i = 0; i < keylen; ++i) + put_byte(bs, bignum_byte(ec->privateKey, i)); /* Now encode an extra copy of the public point as the second half * of the private key string, as the OpenSSH format for some * reason requires */ - for (i = 0; i < pointlen - 1; ++i) { - *blob++ = bignum_byte(ec->publicKey.y, i); - } - /* Unset last bit of y and set first bit of x in its place */ - *blob = bignum_byte(ec->publicKey.y, i) & 0x7f; - *blob++ |= bignum_bit(ec->publicKey.x, 0) << 7; + put_data(bs, pub->s + 4, pub->len - 4); - return bloblen; + strbuf_free(pub); } static void *ecdsa_openssh_createkey(const struct ssh_signkey *self, @@ -2180,51 +2119,27 @@ static void *ecdsa_openssh_createkey(const struct ssh_signkey *self, return ec; } -static int ecdsa_openssh_fmtkey(void *key, unsigned char *blob, int len) +static void ecdsa_openssh_fmtkey(void *key, BinarySink *bs) { struct ec_key *ec = (struct ec_key *) key; int pointlen; - int namelen; - int bloblen; int i; - if (ec->publicKey.curve->type != EC_WEIERSTRASS) { - return 0; - } + assert(ec->publicKey.curve->type == EC_WEIERSTRASS); pointlen = (bignum_bitcount(ec->publicKey.curve->p) + 7) / 8; - namelen = strlen(ec->publicKey.curve->name); - bloblen = - 4 + namelen /* nistpXXX */ - + 4 + 1 + (pointlen * 2) /* 0x04 pX pY */ - + ssh2_bignum_length(ec->privateKey); - if (bloblen > len) - return bloblen; + put_stringz(bs, ec->publicKey.curve->name); - bloblen = 0; - - PUT_32BIT(blob+bloblen, namelen); - bloblen += 4; - memcpy(blob+bloblen, ec->publicKey.curve->name, namelen); - bloblen += namelen; - - PUT_32BIT(blob+bloblen, 1 + (pointlen * 2)); - bloblen += 4; - blob[bloblen++] = 0x04; + put_uint32(bs, 1 + (pointlen * 2)); + put_byte(bs, 0x04); for (i = pointlen; i--; ) - blob[bloblen++] = bignum_byte(ec->publicKey.x, i); + put_byte(bs, bignum_byte(ec->publicKey.x, i)); for (i = pointlen; i--; ) - blob[bloblen++] = bignum_byte(ec->publicKey.y, i); + put_byte(bs, bignum_byte(ec->publicKey.y, i)); - pointlen = (bignum_bitcount(ec->privateKey) + 8) / 8; - PUT_32BIT(blob+bloblen, pointlen); - bloblen += 4; - for (i = pointlen; i--; ) - blob[bloblen++] = bignum_byte(ec->privateKey, i); - - return bloblen; + put_mp_ssh2(bs, ec->privateKey); } static int ecdsa_pubkey_bits(const struct ssh_signkey *self, @@ -2392,8 +2307,8 @@ static int ecdsa_verifysig(void *key, const char *sig, int siglen, return ret; } -static unsigned char *ecdsa_sign(void *key, const char *data, int datalen, - int *siglen) +static void ecdsa_sign(void *key, const char *data, int datalen, + BinarySink *bs) { struct ec_key *ec = (struct ec_key *) key; const struct ecsign_extra *extra = @@ -2401,13 +2316,10 @@ static unsigned char *ecdsa_sign(void *key, const char *data, int datalen, unsigned char digest[512 / 8]; int digestLen; Bignum r = NULL, s = NULL; - unsigned char *buf, *p; - int rlen, slen, namelen; int i; - if (!ec->privateKey || !ec->publicKey.curve) { - return NULL; - } + assert(ec->privateKey); + assert(ec->publicKey.curve); if (ec->publicKey.curve->type == EC_EDWARDS) { struct ec_point *rp; @@ -2448,11 +2360,7 @@ static unsigned char *ecdsa_sign(void *key, const char *data, int datalen, r = bignum_from_bytes_le(hash, 512/8); rp = ecp_mul(&ec->publicKey.curve->e.B, r); - if (!rp) { - freebn(r); - freebn(a); - return NULL; - } + assert(rp); /* Now calculate s */ SHA512_Init(&hs); @@ -2490,34 +2398,25 @@ static unsigned char *ecdsa_sign(void *key, const char *data, int datalen, } /* Format the output */ - namelen = strlen(ec->signalg->name); - *siglen = 4+namelen+4+((ec->publicKey.curve->fieldBits / 8)*2); - buf = snewn(*siglen, unsigned char); - p = buf; - PUT_32BIT(p, namelen); - p += 4; - memcpy(p, ec->signalg->name, namelen); - p += namelen; - PUT_32BIT(p, ((ec->publicKey.curve->fieldBits / 8)*2)); - p += 4; + put_stringz(bs, ec->signalg->name); + pointlen = ec->publicKey.curve->fieldBits / 8; + put_uint32(bs, pointlen * 2); /* Encode the point */ - pointlen = ec->publicKey.curve->fieldBits / 8; - for (i = 0; i < pointlen - 1; ++i) { - *p++ = bignum_byte(rp->y, i); - } + for (i = 0; i < pointlen - 1; ++i) + put_byte(bs, bignum_byte(rp->y, i)); /* Unset last bit of y and set first bit of x in its place */ - *p = bignum_byte(rp->y, i) & 0x7f; - *p++ |= bignum_bit(rp->x, 0) << 7; + put_byte(bs, ((bignum_byte(rp->y, i) & 0x7f) | + (bignum_bit(rp->x, 0) << 7))); ec_point_free(rp); /* Encode the int */ - for (i = 0; i < pointlen; ++i) { - *p++ = bignum_byte(s, i); - } + for (i = 0; i < pointlen; ++i) + put_byte(bs, bignum_byte(s, i)); freebn(s); } else { void *hashctx; + strbuf *substr; digestLen = extra->hash->hlen; assert(digestLen <= sizeof(digest)); @@ -2527,41 +2426,20 @@ static unsigned char *ecdsa_sign(void *key, const char *data, int datalen, /* Do the signature */ _ecdsa_sign(ec->privateKey, ec->publicKey.curve, digest, digestLen, &r, &s); - if (!r || !s) { - if (r) freebn(r); - if (s) freebn(s); - return NULL; - } - - rlen = (bignum_bitcount(r) + 8) / 8; - slen = (bignum_bitcount(s) + 8) / 8; - - namelen = strlen(ec->signalg->name); + assert(r); + assert(s); /* Format the output */ - *siglen = 8+namelen+rlen+slen+8; - buf = snewn(*siglen, unsigned char); - p = buf; - PUT_32BIT(p, namelen); - p += 4; - memcpy(p, ec->signalg->name, namelen); - p += namelen; - PUT_32BIT(p, rlen + slen + 8); - p += 4; - PUT_32BIT(p, rlen); - p += 4; - for (i = rlen; i--;) - *p++ = bignum_byte(r, i); - PUT_32BIT(p, slen); - p += 4; - for (i = slen; i--;) - *p++ = bignum_byte(s, i); + put_stringz(bs, ec->signalg->name); + + substr = strbuf_new(); + put_mp_ssh2(substr, r); + put_mp_ssh2(substr, s); + put_stringsb(bs, substr); freebn(r); freebn(s); } - - return buf; } const struct ecsign_extra sign_extra_ed25519 = { @@ -2782,38 +2660,24 @@ void *ssh_ecdhkex_newkey(const struct ssh_kex *kex) return key; } -char *ssh_ecdhkex_getpublic(void *key, int *len) +void ssh_ecdhkex_getpublic(void *key, BinarySink *bs) { struct ec_key *ec = (struct ec_key*)key; - char *point, *p; int i; int pointlen; pointlen = (bignum_bitcount(ec->publicKey.curve->p) + 7) / 8; if (ec->publicKey.curve->type == EC_WEIERSTRASS) { - *len = 1 + pointlen * 2; + put_byte(bs, 0x04); + for (i = pointlen; i--;) + put_byte(bs, bignum_byte(ec->publicKey.x, i)); + for (i = pointlen; i--;) + put_byte(bs, bignum_byte(ec->publicKey.y, i)); } else { - *len = pointlen; + for (i = 0; i < pointlen; ++i) + put_byte(bs, bignum_byte(ec->publicKey.x, i)); } - point = (char*)snewn(*len, char); - - p = point; - if (ec->publicKey.curve->type == EC_WEIERSTRASS) { - *p++ = 0x04; - for (i = pointlen; i--;) { - *p++ = bignum_byte(ec->publicKey.x, i); - } - for (i = pointlen; i--;) { - *p++ = bignum_byte(ec->publicKey.y, i); - } - } else { - for (i = 0; i < pointlen; ++i) { - *p++ = bignum_byte(ec->publicKey.x, i); - } - } - - return point; } Bignum ssh_ecdhkex_getkey(void *key, char *remoteKey, int remoteKeyLen) diff --git a/sshpubk.c b/sshpubk.c index 4b4264ca..f9b6e974 100644 --- a/sshpubk.c +++ b/sshpubk.c @@ -226,11 +226,10 @@ int rsa_ssh1_encrypted(const Filename *filename, char **comment) } /* - * Return a malloc'ed chunk of memory containing the public blob of - * an RSA key, as given in the agent protocol (modulus bits, - * exponent, modulus). + * Read the public part of an SSH-1 RSA key from a file (public or + * private), and generate its public blob in exponent-first order. */ -int rsa_ssh1_loadpub(const Filename *filename, void **blob, int *bloblen, +int rsa_ssh1_loadpub(const Filename *filename, BinarySink *bs, char **commentptr, const char **errorstr) { FILE *fp; @@ -240,9 +239,7 @@ int rsa_ssh1_loadpub(const Filename *filename, void **blob, int *bloblen, const char *error = NULL; /* Default return if we fail. */ - *blob = NULL; - *bloblen = 0; - ret = 0; + ret = FALSE; fp = f_open(filename, "rb", FALSE); if (!fp) { @@ -257,10 +254,9 @@ int rsa_ssh1_loadpub(const Filename *filename, void **blob, int *bloblen, if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) { memset(&key, 0, sizeof(key)); if (rsa_ssh1_load_main(fp, &key, TRUE, commentptr, NULL, &error)) { - *blob = rsa_ssh1_public_blob(&key, bloblen, - RSA_SSH1_EXPONENT_FIRST); + rsa_ssh1_public_blob(bs, &key, RSA_SSH1_EXPONENT_FIRST); freersakey(&key); - ret = 1; + ret = TRUE; } fp = NULL; /* rsa_ssh1_load_main unconditionally closes fp */ } else { @@ -308,11 +304,11 @@ int rsa_ssh1_loadpub(const Filename *filename, void **blob, int *bloblen, } if (commentptr) *commentptr = commentp ? dupstr(commentp) : NULL; - *blob = rsa_ssh1_public_blob(&key, bloblen, RSA_SSH1_EXPONENT_FIRST); + rsa_ssh1_public_blob(bs, &key, RSA_SSH1_EXPONENT_FIRST); freersakey(&key); sfree(line); fclose(fp); - return 1; + return TRUE; not_public_either: sfree(line); @@ -569,41 +565,40 @@ static char *read_body(FILE * fp) } } -static unsigned char *read_blob(FILE * fp, int nlines, int *bloblen) +static int read_blob(FILE *fp, int nlines, BinarySink *bs) { unsigned char *blob; char *line; - int linelen, len; + int linelen; int i, j, k; /* We expect at most 64 base64 characters, ie 48 real bytes, per line. */ blob = snewn(48 * nlines, unsigned char); - len = 0; for (i = 0; i < nlines; i++) { line = read_body(fp); if (!line) { sfree(blob); - return NULL; + return FALSE; } linelen = strlen(line); if (linelen % 4 != 0 || linelen > 64) { sfree(blob); sfree(line); - return NULL; + return FALSE; } for (j = 0; j < linelen; j += 4) { - k = base64_decode_atom(line + j, blob + len); + unsigned char decoded[3]; + k = base64_decode_atom(line + j, decoded); if (!k) { sfree(line); sfree(blob); - return NULL; + return FALSE; } - len += k; + put_data(bs, decoded, k); } sfree(line); } - *bloblen = len; - return blob; + return TRUE; } /* @@ -645,8 +640,7 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, const struct ssh_signkey *alg; struct ssh2_userkey *ret; int cipher, cipherblk; - unsigned char *public_blob, *private_blob; - int public_blob_len, private_blob_len; + strbuf *public_blob, *private_blob; int i, is_mac, old_fmt; int passlen = passphrase ? strlen(passphrase) : 0; const char *error = NULL; @@ -718,7 +712,8 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, goto error; i = atoi(b); sfree(b); - if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL) + public_blob = strbuf_new(); + if (!read_blob(fp, i, BinarySink_UPCAST(public_blob))) goto error; /* Read the Private-Lines header line and the Private blob. */ @@ -728,7 +723,8 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, goto error; i = atoi(b); sfree(b); - if ((private_blob = read_blob(fp, i, &private_blob_len)) == NULL) + private_blob = strbuf_new(); + if (!read_blob(fp, i, BinarySink_UPCAST(private_blob))) goto error; /* Read the Private-MAC or Private-Hash header line. */ @@ -757,7 +753,7 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, if (!passphrase) goto error; - if (private_blob_len % cipherblk) + if (private_blob->len % cipherblk) goto error; SHA_Init(&s); @@ -768,7 +764,7 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, put_uint32(&s, 1); put_data(&s, passphrase, passlen); SHA_Final(&s, key + 20); - aes256_decrypt_pubkey(key, private_blob, private_blob_len); + aes256_decrypt_pubkey(key, private_blob->u, private_blob->len); } /* @@ -783,8 +779,8 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, if (old_fmt) { /* MAC (or hash) only covers the private blob. */ - macdata = private_blob; - maclen = private_blob_len; + macdata = private_blob->u; + maclen = private_blob->len; free_macdata = 0; } else { unsigned char *p; @@ -794,16 +790,16 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, maclen = (4 + namelen + 4 + enclen + 4 + commlen + - 4 + public_blob_len + - 4 + private_blob_len); + 4 + public_blob->len + + 4 + private_blob->len); macdata = snewn(maclen, unsigned char); p = macdata; #define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len) DO_STR(alg->name, namelen); DO_STR(encryption, enclen); DO_STR(comment, commlen); - DO_STR(public_blob, public_blob_len); - DO_STR(private_blob, private_blob_len); + DO_STR(public_blob->s, public_blob->len); + DO_STR(private_blob->s, private_blob->len); free_macdata = 1; } @@ -857,17 +853,16 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, ret = snew(struct ssh2_userkey); ret->alg = alg; ret->comment = comment; - ret->data = alg->createkey(alg, public_blob, public_blob_len, - private_blob, private_blob_len); + ret->data = alg->createkey(alg, public_blob->u, public_blob->len, + private_blob->u, private_blob->len); if (!ret->data) { sfree(ret); ret = NULL; error = "createkey failed"; goto error; } - sfree(public_blob); - smemclr(private_blob, private_blob_len); - sfree(private_blob); + strbuf_free(public_blob); + strbuf_free(private_blob); sfree(encryption); if (errorstr) *errorstr = NULL; @@ -886,19 +881,17 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, if (mac) sfree(mac); if (public_blob) - sfree(public_blob); - if (private_blob) { - smemclr(private_blob, private_blob_len); - sfree(private_blob); - } + strbuf_free(public_blob); + if (private_blob) + strbuf_free(private_blob); if (errorstr) *errorstr = error; return ret; } -unsigned char *rfc4716_loadpub(FILE *fp, char **algorithm, - int *pub_blob_len, char **commentptr, - const char **errorstr) +int rfc4716_loadpub(FILE *fp, char **algorithm, + BinarySink *bs, + char **commentptr, const char **errorstr) { const char *error; char *line, *colon, *value; @@ -1013,13 +1006,13 @@ unsigned char *rfc4716_loadpub(FILE *fp, char **algorithm, } if (algorithm) *algorithm = dupprintf("%.*s", alglen, pubblob+4); - if (pub_blob_len) - *pub_blob_len = pubbloblen; if (commentptr) *commentptr = comment; else sfree(comment); - return pubblob; + put_data(bs, pubblob, pubbloblen); + sfree(pubblob); + return TRUE; error: sfree(line); @@ -1027,12 +1020,12 @@ unsigned char *rfc4716_loadpub(FILE *fp, char **algorithm, sfree(pubblob); if (errorstr) *errorstr = error; - return NULL; + return FALSE; } -unsigned char *openssh_loadpub(FILE *fp, char **algorithm, - int *pub_blob_len, char **commentptr, - const char **errorstr) +int openssh_loadpub(FILE *fp, char **algorithm, + BinarySink *bs, + char **commentptr, const char **errorstr) { const char *error; char *line, *base64; @@ -1088,14 +1081,14 @@ unsigned char *openssh_loadpub(FILE *fp, char **algorithm, */ if (algorithm) *algorithm = dupstr(line); - if (pub_blob_len) - *pub_blob_len = pubbloblen; if (commentptr) *commentptr = comment; else sfree(comment); sfree(line); - return pubblob; + put_data(bs, pubblob, pubbloblen); + sfree(pubblob); + return TRUE; error: sfree(line); @@ -1103,24 +1096,20 @@ unsigned char *openssh_loadpub(FILE *fp, char **algorithm, sfree(pubblob); if (errorstr) *errorstr = error; - return NULL; + return FALSE; } -unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm, - int *pub_blob_len, char **commentptr, - const char **errorstr) +int ssh2_userkey_loadpub(const Filename *filename, char **algorithm, + BinarySink *bs, + char **commentptr, const char **errorstr) { FILE *fp; char header[40], *b; const struct ssh_signkey *alg; - unsigned char *public_blob; - int public_blob_len; int type, i; const char *error = NULL; char *comment = NULL; - public_blob = NULL; - fp = f_open(filename, "rb", FALSE); if (!fp) { error = "can't open file"; @@ -1131,13 +1120,11 @@ unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm, * we'll be asked to read a public blob from one of those. */ type = key_type_fp(fp); if (type == SSH_KEYTYPE_SSH2_PUBLIC_RFC4716) { - unsigned char *ret = rfc4716_loadpub(fp, algorithm, pub_blob_len, - commentptr, errorstr); + int ret = rfc4716_loadpub(fp, algorithm, bs, commentptr, errorstr); fclose(fp); return ret; } else if (type == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH) { - unsigned char *ret = openssh_loadpub(fp, algorithm, pub_blob_len, - commentptr, errorstr); + int ret = openssh_loadpub(fp, algorithm, bs, commentptr, errorstr); fclose(fp); return ret; } else if (type != SSH_KEYTYPE_SSH2) { @@ -1190,15 +1177,13 @@ unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm, goto error; i = atoi(b); sfree(b); - if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL) + if (!read_blob(fp, i, bs)) goto error; fclose(fp); - if (pub_blob_len) - *pub_blob_len = public_blob_len; if (algorithm) *algorithm = dupstr(alg->name); - return public_blob; + return TRUE; /* * Error processing. @@ -1206,15 +1191,13 @@ unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm, error: if (fp) fclose(fp); - if (public_blob) - sfree(public_blob); if (errorstr) *errorstr = error; if (comment && commentptr) { sfree(comment); *commentptr = NULL; } - return NULL; + return FALSE; } int ssh2_userkey_encrypted(const Filename *filename, char **commentptr) @@ -1309,8 +1292,9 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key, char *passphrase) { FILE *fp; - unsigned char *pub_blob, *priv_blob, *priv_blob_encrypted; - int pub_blob_len, priv_blob_len, priv_encrypted_len; + strbuf *pub_blob, *priv_blob; + unsigned char *priv_blob_encrypted; + int priv_encrypted_len; int passlen; int cipherblk; int i; @@ -1320,13 +1304,10 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key, /* * Fetch the key component blobs. */ - pub_blob = key->alg->public_blob(key->data, &pub_blob_len); - priv_blob = key->alg->private_blob(key->data, &priv_blob_len); - if (!pub_blob || !priv_blob) { - sfree(pub_blob); - sfree(priv_blob); - return 0; - } + pub_blob = strbuf_new(); + key->alg->public_blob(key->data, BinarySink_UPCAST(pub_blob)); + priv_blob = strbuf_new(); + key->alg->private_blob(key->data, BinarySink_UPCAST(priv_blob)); /* * Determine encryption details, and encrypt the private blob. @@ -1338,17 +1319,17 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key, cipherstr = "none"; cipherblk = 1; } - priv_encrypted_len = priv_blob_len + cipherblk - 1; + priv_encrypted_len = priv_blob->len + cipherblk - 1; priv_encrypted_len -= priv_encrypted_len % cipherblk; priv_blob_encrypted = snewn(priv_encrypted_len, unsigned char); memset(priv_blob_encrypted, 0, priv_encrypted_len); - memcpy(priv_blob_encrypted, priv_blob, priv_blob_len); + memcpy(priv_blob_encrypted, priv_blob->u, priv_blob->len); /* Create padding based on the SHA hash of the unpadded blob. This prevents * too easy a known-plaintext attack on the last block. */ - SHA_Simple(priv_blob, priv_blob_len, priv_mac); - assert(priv_encrypted_len - priv_blob_len < 20); - memcpy(priv_blob_encrypted + priv_blob_len, priv_mac, - priv_encrypted_len - priv_blob_len); + SHA_Simple(priv_blob->u, priv_blob->len, priv_mac); + assert(priv_encrypted_len - priv_blob->len < 20); + memcpy(priv_blob_encrypted + priv_blob->len, priv_mac, + priv_encrypted_len - priv_blob->len); /* Now create the MAC. */ { @@ -1365,7 +1346,7 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key, maclen = (4 + namelen + 4 + enclen + 4 + commlen + - 4 + pub_blob_len + + 4 + pub_blob->len + 4 + priv_encrypted_len); macdata = snewn(maclen, unsigned char); p = macdata; @@ -1373,7 +1354,7 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key, DO_STR(key->alg->name, namelen); DO_STR(cipherstr, enclen); DO_STR(key->comment, commlen); - DO_STR(pub_blob, pub_blob_len); + DO_STR(pub_blob->u, pub_blob->len); DO_STR(priv_blob_encrypted, priv_encrypted_len); SHA_Init(&s); @@ -1411,18 +1392,17 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key, fp = f_open(filename, "w", TRUE); if (!fp) { - sfree(pub_blob); - smemclr(priv_blob, priv_blob_len); - sfree(priv_blob); - smemclr(priv_blob_encrypted, priv_blob_len); + strbuf_free(pub_blob); + strbuf_free(priv_blob); + smemclr(priv_blob_encrypted, priv_encrypted_len); sfree(priv_blob_encrypted); return 0; } fprintf(fp, "PuTTY-User-Key-File-2: %s\n", key->alg->name); fprintf(fp, "Encryption: %s\n", cipherstr); fprintf(fp, "Comment: %s\n", key->comment); - fprintf(fp, "Public-Lines: %d\n", base64_lines(pub_blob_len)); - base64_encode(fp, pub_blob, pub_blob_len, 64); + fprintf(fp, "Public-Lines: %d\n", base64_lines(pub_blob->len)); + base64_encode(fp, pub_blob->u, pub_blob->len, 64); fprintf(fp, "Private-Lines: %d\n", base64_lines(priv_encrypted_len)); base64_encode(fp, priv_blob_encrypted, priv_encrypted_len, 64); fprintf(fp, "Private-MAC: "); @@ -1431,10 +1411,9 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key, fprintf(fp, "\n"); fclose(fp); - sfree(pub_blob); - smemclr(priv_blob, priv_blob_len); - sfree(priv_blob); - smemclr(priv_blob_encrypted, priv_blob_len); + strbuf_free(pub_blob); + strbuf_free(priv_blob); + smemclr(priv_blob_encrypted, priv_encrypted_len); sfree(priv_blob_encrypted); return 1; } @@ -1513,13 +1492,14 @@ static char *ssh2_pubkey_openssh_str_internal(const char *comment, char *ssh2_pubkey_openssh_str(struct ssh2_userkey *key) { - int bloblen; - unsigned char *blob; + strbuf *blob; char *ret; - blob = key->alg->public_blob(key->data, &bloblen); - ret = ssh2_pubkey_openssh_str_internal(key->comment, blob, bloblen); - sfree(blob); + blob = strbuf_new(); + key->alg->public_blob(key->data, BinarySink_UPCAST(blob)); + ret = ssh2_pubkey_openssh_str_internal( + key->comment, blob->s, blob->len); + strbuf_free(blob); return ret; } @@ -1623,10 +1603,10 @@ char *ssh2_fingerprint_blob(const void *blob, int bloblen) char *ssh2_fingerprint(const struct ssh_signkey *alg, void *data) { - int len; - unsigned char *blob = alg->public_blob(data, &len); - char *ret = ssh2_fingerprint_blob(blob, len); - sfree(blob); + strbuf *blob = strbuf_new(); + alg->public_blob(data, BinarySink_UPCAST(blob)); + char *ret = ssh2_fingerprint_blob(blob->s, blob->len); + strbuf_free(blob); return ret; } diff --git a/sshrsa.c b/sshrsa.c index a9c11f54..107739b4 100644 --- a/sshrsa.c +++ b/sshrsa.c @@ -439,28 +439,17 @@ int rsa_verify(struct RSAKey *key) return 1; } -unsigned char *rsa_ssh1_public_blob(struct RSAKey *key, int *len, - RsaSsh1Order order) +void rsa_ssh1_public_blob(BinarySink *bs, struct RSAKey *key, + RsaSsh1Order order) { - int length, pos; - unsigned char *ret; - - length = (ssh1_bignum_length(key->modulus) + - ssh1_bignum_length(key->exponent) + 4); - ret = snewn(length, unsigned char); - - PUT_32BIT(ret, bignum_bitcount(key->modulus)); - pos = 4; + put_uint32(bs, bignum_bitcount(key->modulus)); if (order == RSA_SSH1_EXPONENT_FIRST) { - pos += ssh1_write_bignum(ret + pos, key->exponent); - pos += ssh1_write_bignum(ret + pos, key->modulus); + put_mp_ssh1(bs, key->exponent); + put_mp_ssh1(bs, key->modulus); } else { - pos += ssh1_write_bignum(ret + pos, key->modulus); - pos += ssh1_write_bignum(ret + pos, key->exponent); + put_mp_ssh1(bs, key->modulus); + put_mp_ssh1(bs, key->exponent); } - - *len = length; - return ret; } /* Given a public blob, determine its length. */ @@ -588,78 +577,23 @@ static char *rsa2_fmtkey(void *key) return p; } -static unsigned char *rsa2_public_blob(void *key, int *len) +static void rsa2_public_blob(void *key, BinarySink *bs) { struct RSAKey *rsa = (struct RSAKey *) key; - int elen, mlen, bloblen; - int i; - unsigned char *blob, *p; - elen = (bignum_bitcount(rsa->exponent) + 8) / 8; - mlen = (bignum_bitcount(rsa->modulus) + 8) / 8; - - /* - * string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen. - * (three length fields, 12+7=19). - */ - bloblen = 19 + elen + mlen; - blob = snewn(bloblen, unsigned char); - p = blob; - PUT_32BIT(p, 7); - p += 4; - memcpy(p, "ssh-rsa", 7); - p += 7; - PUT_32BIT(p, elen); - p += 4; - for (i = elen; i--;) - *p++ = bignum_byte(rsa->exponent, i); - PUT_32BIT(p, mlen); - p += 4; - for (i = mlen; i--;) - *p++ = bignum_byte(rsa->modulus, i); - assert(p == blob + bloblen); - *len = bloblen; - return blob; + put_stringz(bs, "ssh-rsa"); + put_mp_ssh2(bs, rsa->exponent); + put_mp_ssh2(bs, rsa->modulus); } -static unsigned char *rsa2_private_blob(void *key, int *len) +static void rsa2_private_blob(void *key, BinarySink *bs) { struct RSAKey *rsa = (struct RSAKey *) key; - int dlen, plen, qlen, ulen, bloblen; - int i; - unsigned char *blob, *p; - dlen = (bignum_bitcount(rsa->private_exponent) + 8) / 8; - plen = (bignum_bitcount(rsa->p) + 8) / 8; - qlen = (bignum_bitcount(rsa->q) + 8) / 8; - ulen = (bignum_bitcount(rsa->iqmp) + 8) / 8; - - /* - * mpint private_exp, mpint p, mpint q, mpint iqmp. Total 16 + - * sum of lengths. - */ - bloblen = 16 + dlen + plen + qlen + ulen; - blob = snewn(bloblen, unsigned char); - p = blob; - PUT_32BIT(p, dlen); - p += 4; - for (i = dlen; i--;) - *p++ = bignum_byte(rsa->private_exponent, i); - PUT_32BIT(p, plen); - p += 4; - for (i = plen; i--;) - *p++ = bignum_byte(rsa->p, i); - PUT_32BIT(p, qlen); - p += 4; - for (i = qlen; i--;) - *p++ = bignum_byte(rsa->q, i); - PUT_32BIT(p, ulen); - p += 4; - for (i = ulen; i--;) - *p++ = bignum_byte(rsa->iqmp, i); - assert(p == blob + bloblen); - *len = bloblen; - return blob; + put_mp_ssh2(bs, rsa->private_exponent); + put_mp_ssh2(bs, rsa->p); + put_mp_ssh2(bs, rsa->q); + put_mp_ssh2(bs, rsa->iqmp); } static void *rsa2_createkey(const struct ssh_signkey *self, @@ -713,33 +647,16 @@ static void *rsa2_openssh_createkey(const struct ssh_signkey *self, return rsa; } -static int rsa2_openssh_fmtkey(void *key, unsigned char *blob, int len) +static void rsa2_openssh_fmtkey(void *key, BinarySink *bs) { struct RSAKey *rsa = (struct RSAKey *) key; - int bloblen, i; - bloblen = - ssh2_bignum_length(rsa->modulus) + - ssh2_bignum_length(rsa->exponent) + - ssh2_bignum_length(rsa->private_exponent) + - ssh2_bignum_length(rsa->iqmp) + - ssh2_bignum_length(rsa->p) + ssh2_bignum_length(rsa->q); - - if (bloblen > len) - return bloblen; - - bloblen = 0; -#define ENC(x) \ - PUT_32BIT(blob+bloblen, ssh2_bignum_length((x))-4); bloblen += 4; \ - for (i = ssh2_bignum_length((x))-4; i-- ;) blob[bloblen++]=bignum_byte((x),i); - ENC(rsa->modulus); - ENC(rsa->exponent); - ENC(rsa->private_exponent); - ENC(rsa->iqmp); - ENC(rsa->p); - ENC(rsa->q); - - return bloblen; + put_mp_ssh2(bs, rsa->modulus); + put_mp_ssh2(bs, rsa->exponent); + put_mp_ssh2(bs, rsa->private_exponent); + put_mp_ssh2(bs, rsa->iqmp); + put_mp_ssh2(bs, rsa->p); + put_mp_ssh2(bs, rsa->q); } static int rsa2_pubkey_bits(const struct ssh_signkey *self, @@ -838,8 +755,8 @@ static int rsa2_verifysig(void *key, const char *sig, int siglen, return ret; } -static unsigned char *rsa2_sign(void *key, const char *data, int datalen, - int *siglen) +static void rsa2_sign(void *key, const char *data, int datalen, + BinarySink *bs) { struct RSAKey *rsa = (struct RSAKey *) key; unsigned char *bytes; @@ -868,17 +785,13 @@ static unsigned char *rsa2_sign(void *key, const char *data, int datalen, out = rsa_privkey_op(in, rsa); freebn(in); + put_stringz(bs, "ssh-rsa"); nbytes = (bignum_bitcount(out) + 7) / 8; - bytes = snewn(4 + 7 + 4 + nbytes, unsigned char); - PUT_32BIT(bytes, 7); - memcpy(bytes + 4, "ssh-rsa", 7); - PUT_32BIT(bytes + 4 + 7, nbytes); + put_uint32(bs, nbytes); for (i = 0; i < nbytes; i++) - bytes[4 + 7 + 4 + i] = bignum_byte(out, nbytes - 1 - i); - freebn(out); + put_byte(bs, bignum_byte(out, nbytes - 1 - i)); - *siglen = 4 + 7 + 4 + nbytes; - return bytes; + freebn(out); } const struct ssh_signkey ssh_rsa = { diff --git a/unix/uxpgnt.c b/unix/uxpgnt.c index f7408325..b8244cec 100644 --- a/unix/uxpgnt.c +++ b/unix/uxpgnt.c @@ -556,8 +556,11 @@ struct pageant_pubkey *find_key(const char *string, char **retstr) keytype == SSH_KEYTYPE_SSH1_PUBLIC) { const char *error; - if (!rsa_ssh1_loadpub(fn, &key_in.blob, &key_in.bloblen, + key_in.blob = strbuf_new(); + if (!rsa_ssh1_loadpub(fn, BinarySink_UPCAST(key_in.blob), NULL, &error)) { + strbuf_free(key_in.blob); + key_in.blob = NULL; if (file_errors) { *retstr = dupprintf("unable to load file '%s': %s", string, error); @@ -573,7 +576,8 @@ struct pageant_pubkey *find_key(const char *string, char **retstr) key_in.ssh_version = 1; key_in.comment = NULL; key_ret = pageant_pubkey_copy(&key_in); - sfree(key_in.blob); + strbuf_free(key_in.blob); + key_in.blob = NULL; filename_free(fn); return key_ret; } @@ -582,9 +586,11 @@ struct pageant_pubkey *find_key(const char *string, char **retstr) keytype == SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH) { const char *error; - if ((key_in.blob = ssh2_userkey_loadpub(fn, NULL, - &key_in.bloblen, - NULL, &error)) == NULL) { + key_in.blob = strbuf_new(); + if (!ssh2_userkey_loadpub(fn, NULL, BinarySink_UPCAST(key_in.blob), + NULL, &error)) { + strbuf_free(key_in.blob); + key_in.blob = NULL; if (file_errors) { *retstr = dupprintf("unable to load file '%s': %s", string, error); @@ -600,7 +606,8 @@ struct pageant_pubkey *find_key(const char *string, char **retstr) key_in.ssh_version = 2; key_in.comment = NULL; key_ret = pageant_pubkey_copy(&key_in); - sfree(key_in.blob); + strbuf_free(key_in.blob); + key_in.blob = NULL; filename_free(fn); return key_ret; } @@ -696,12 +703,14 @@ void run_client(void) struct RSAKey rkey; memset(&rkey, 0, sizeof(rkey)); rkey.comment = dupstr(key->comment); - rsa_ssh1_readpub(key->blob, key->bloblen, &rkey, NULL, + rsa_ssh1_readpub(key->blob->u, key->blob->len, &rkey, NULL, RSA_SSH1_EXPONENT_FIRST); ssh1_write_pubkey(fp, &rkey); freersakey(&rkey); } else { - ssh2_write_pubkey(fp, key->comment, key->blob,key->bloblen, + ssh2_write_pubkey(fp, key->comment, + key->blob->u, + key->blob->len, (act->action == KEYACT_CLIENT_PUBLIC ? SSH_KEYTYPE_SSH2_PUBLIC_RFC4716 : SSH_KEYTYPE_SSH2_PUBLIC_OPENSSH)); diff --git a/windows/winpgen.c b/windows/winpgen.c index e253f9cb..dbe74465 100644 --- a/windows/winpgen.c +++ b/windows/winpgen.c @@ -1321,13 +1321,13 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg, "PuTTYgen Error", MB_OK | MB_ICONERROR); } else { if (state->ssh2) { - int bloblen; - unsigned char *blob; - blob = state->ssh2key.alg->public_blob - (state->ssh2key.data, &bloblen); + strbuf *blob = strbuf_new(); + state->ssh2key.alg->public_blob( + state->ssh2key.data, BinarySink_UPCAST(blob)); ssh2_write_pubkey(fp, state->ssh2key.comment, - blob, bloblen, + blob->u, blob->len, SSH_KEYTYPE_SSH2_PUBLIC_RFC4716); + strbuf_free(blob); } else { ssh1_write_pubkey(fp, &state->key); }