зеркало из https://github.com/github/putty.git
Change ssh.h crypto APIs to output to BinarySink.
This affects all the functions that generate public and private key and signature blobs of all kinds, plus ssh_ecdhkex_getpublic. Instead of returning a bare block of memory and taking an extra 'int *length' parameter, all these functions now write to a BinarySink, and it's the caller's job to have prepared an appropriate one where they want the output to go (usually a strbuf). The main value of this change is that those blob-generation functions were chock full of ad-hoc length-counting and data marshalling. You have only to look at rsa2_{public,private}_blob, for example, to see the kind of thing I was keen to get rid of!
This commit is contained in:
Родитель
a990738aca
Коммит
67de463cca
46
cmdgen.c
46
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
144
import.c
144
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;
|
||||
}
|
||||
|
|
320
pageant.c
320
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
156
ssh.c
156
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)
|
||||
|
|
23
ssh.h
23
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);
|
||||
|
|
128
sshdss.c
128
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 = {
|
||||
|
|
294
sshecc.c
294
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-<name>", string "<name>", 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 /* <LEN> nistpXXX */
|
||||
+ 4 + 1 + (pointlen * 2) /* <LEN> 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)
|
||||
|
|
204
sshpubk.c
204
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;
|
||||
}
|
||||
|
||||
|
|
145
sshrsa.c
145
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 = {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче