mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
Rewrite key loading functions using BinarySource.
This does for sshpubk.c's handling of PuTTY's native key formats what the previous commit did for the foreign formats handled by import.c.
This commit is contained in:
parent
59e83a8c75
commit
28c086ca9a
157
sshpubk.c
157
sshpubk.c
@ -27,70 +27,52 @@ static int rsa_ssh1_load_main(FILE * fp, struct RSAKey *key, int pub_only,
|
|||||||
char **commentptr, const char *passphrase,
|
char **commentptr, const char *passphrase,
|
||||||
const char **error)
|
const char **error)
|
||||||
{
|
{
|
||||||
unsigned char buf[16384];
|
strbuf *buf;
|
||||||
unsigned char keybuf[16];
|
int ciphertype;
|
||||||
int len;
|
|
||||||
int i, j, ciphertype;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct MD5Context md5c;
|
struct MD5Context md5c;
|
||||||
char *comment;
|
ptrlen comment;
|
||||||
|
BinarySource src[1];
|
||||||
|
|
||||||
*error = NULL;
|
*error = NULL;
|
||||||
|
|
||||||
/* Slurp the whole file (minus the header) into a buffer. */
|
/* Slurp the whole file (minus the header) into a buffer. */
|
||||||
len = fread(buf, 1, sizeof(buf), fp);
|
buf = strbuf_new();
|
||||||
fclose(fp);
|
{
|
||||||
if (len < 0 || len == sizeof(buf)) {
|
int ch;
|
||||||
*error = "error reading file";
|
while ((ch = fgetc(fp)) != EOF)
|
||||||
goto end; /* file too big or not read */
|
put_byte(buf, ch);
|
||||||
}
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
BinarySource_BARE_INIT(src, buf->u, buf->len);
|
||||||
|
|
||||||
i = 0;
|
|
||||||
*error = "file format error";
|
*error = "file format error";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A zero byte. (The signature includes a terminating NUL.)
|
* A zero byte. (The signature includes a terminating NUL, which
|
||||||
|
* we haven't gone past yet because we read it using fgets which
|
||||||
|
* stopped after the \n.)
|
||||||
*/
|
*/
|
||||||
if (len - i < 1 || buf[i] != 0)
|
if (get_byte(src) != 0)
|
||||||
goto end;
|
goto end;
|
||||||
i++;
|
|
||||||
|
|
||||||
/* One byte giving encryption type, and one reserved uint32. */
|
/* One byte giving encryption type, and one reserved uint32. */
|
||||||
if (len - i < 1)
|
ciphertype = get_byte(src);
|
||||||
goto end;
|
|
||||||
ciphertype = buf[i];
|
|
||||||
if (ciphertype != 0 && ciphertype != SSH_CIPHER_3DES)
|
if (ciphertype != 0 && ciphertype != SSH_CIPHER_3DES)
|
||||||
goto end;
|
goto end;
|
||||||
i++;
|
if (get_uint32(src) != 0)
|
||||||
if (len - i < 4)
|
goto end; /* reserved field nonzero, panic! */
|
||||||
goto end; /* reserved field not present */
|
|
||||||
if (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0
|
|
||||||
|| buf[i + 3] != 0) goto end; /* reserved field nonzero, panic! */
|
|
||||||
i += 4;
|
|
||||||
|
|
||||||
/* Now the serious stuff. An ordinary SSH-1 public key. */
|
/* Now the serious stuff. An ordinary SSH-1 public key. */
|
||||||
j = rsa_ssh1_readpub(buf + i, len - i, key, NULL, RSA_SSH1_MODULUS_FIRST);
|
get_rsa_ssh1_pub(src, key, NULL, RSA_SSH1_MODULUS_FIRST);
|
||||||
if (j < 0)
|
|
||||||
goto end; /* overran */
|
|
||||||
i += j;
|
|
||||||
|
|
||||||
/* Next, the comment field. */
|
/* Next, the comment field. */
|
||||||
j = toint(GET_32BIT(buf + i));
|
comment = get_string(src);
|
||||||
i += 4;
|
|
||||||
if (j < 0 || len - i < j)
|
|
||||||
goto end;
|
|
||||||
comment = snewn(j + 1, char);
|
|
||||||
if (comment) {
|
|
||||||
memcpy(comment, buf + i, j);
|
|
||||||
comment[j] = '\0';
|
|
||||||
}
|
|
||||||
i += j;
|
|
||||||
if (commentptr)
|
if (commentptr)
|
||||||
*commentptr = dupstr(comment);
|
*commentptr = mkstr(comment);
|
||||||
if (key)
|
if (key)
|
||||||
key->comment = comment;
|
key->comment = mkstr(comment);
|
||||||
else
|
|
||||||
sfree(comment);
|
|
||||||
|
|
||||||
if (pub_only) {
|
if (pub_only) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@ -107,10 +89,16 @@ static int rsa_ssh1_load_main(FILE * fp, struct RSAKey *key, int pub_only,
|
|||||||
* Decrypt remainder of buffer.
|
* Decrypt remainder of buffer.
|
||||||
*/
|
*/
|
||||||
if (ciphertype) {
|
if (ciphertype) {
|
||||||
|
unsigned char keybuf[16];
|
||||||
|
size_t enclen = buf->len - src->pos;
|
||||||
|
|
||||||
|
if (enclen & 7)
|
||||||
|
goto end;
|
||||||
|
|
||||||
MD5Init(&md5c);
|
MD5Init(&md5c);
|
||||||
put_data(&md5c, passphrase, strlen(passphrase));
|
put_data(&md5c, passphrase, strlen(passphrase));
|
||||||
MD5Final(keybuf, &md5c);
|
MD5Final(keybuf, &md5c);
|
||||||
des3_decrypt_pubkey(keybuf, buf + i, (len - i + 7) & ~7);
|
des3_decrypt_pubkey(keybuf, buf->u + src->pos, enclen);
|
||||||
smemclr(keybuf, sizeof(keybuf)); /* burn the evidence */
|
smemclr(keybuf, sizeof(keybuf)); /* burn the evidence */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,32 +106,27 @@ static int rsa_ssh1_load_main(FILE * fp, struct RSAKey *key, int pub_only,
|
|||||||
* We are now in the secret part of the key. The first four
|
* We are now in the secret part of the key. The first four
|
||||||
* bytes should be of the form a, b, a, b.
|
* bytes should be of the form a, b, a, b.
|
||||||
*/
|
*/
|
||||||
if (len - i < 4)
|
{
|
||||||
goto end;
|
int b0a = get_byte(src);
|
||||||
if (buf[i] != buf[i + 2] || buf[i + 1] != buf[i + 3]) {
|
int b1a = get_byte(src);
|
||||||
*error = "wrong passphrase";
|
int b0b = get_byte(src);
|
||||||
ret = -1;
|
int b1b = get_byte(src);
|
||||||
goto end;
|
if (b0a != b0b || b1a != b1b) {
|
||||||
|
*error = "wrong passphrase";
|
||||||
|
ret = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i += 4;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* After that, we have one further bignum which is our
|
* After that, we have one further bignum which is our
|
||||||
* decryption exponent, and then the three auxiliary values
|
* decryption exponent, and then the three auxiliary values
|
||||||
* (iqmp, q, p).
|
* (iqmp, q, p).
|
||||||
*/
|
*/
|
||||||
j = rsa_ssh1_readpriv(buf + i, len - i, key);
|
get_rsa_ssh1_priv(src, key);
|
||||||
if (j < 0) goto end;
|
key->iqmp = get_mp_ssh1(src);
|
||||||
i += j;
|
key->q = get_mp_ssh1(src);
|
||||||
j = ssh1_read_bignum(buf + i, len - i, &key->iqmp);
|
key->p = get_mp_ssh1(src);
|
||||||
if (j < 0) goto end;
|
|
||||||
i += j;
|
|
||||||
j = ssh1_read_bignum(buf + i, len - i, &key->q);
|
|
||||||
if (j < 0) goto end;
|
|
||||||
i += j;
|
|
||||||
j = ssh1_read_bignum(buf + i, len - i, &key->p);
|
|
||||||
if (j < 0) goto end;
|
|
||||||
i += j;
|
|
||||||
|
|
||||||
if (!rsa_verify(key)) {
|
if (!rsa_verify(key)) {
|
||||||
*error = "rsa_verify failed";
|
*error = "rsa_verify failed";
|
||||||
@ -153,7 +136,7 @@ static int rsa_ssh1_load_main(FILE * fp, struct RSAKey *key, int pub_only,
|
|||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
smemclr(buf, sizeof(buf)); /* burn the evidence */
|
strbuf_free(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1400,31 +1383,25 @@ static char *ssh2_pubkey_openssh_str_internal(const char *comment,
|
|||||||
int pub_len)
|
int pub_len)
|
||||||
{
|
{
|
||||||
const unsigned char *ssh2blob = (const unsigned char *)v_pub_blob;
|
const unsigned char *ssh2blob = (const unsigned char *)v_pub_blob;
|
||||||
const char *alg;
|
ptrlen alg;
|
||||||
int alglen;
|
|
||||||
char *buffer, *p;
|
char *buffer, *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (pub_len < 4) {
|
{
|
||||||
alg = NULL;
|
BinarySource src[1];
|
||||||
} else {
|
BinarySource_BARE_INIT(src, ssh2blob, pub_len);
|
||||||
alglen = GET_32BIT(ssh2blob);
|
alg = get_string(src);
|
||||||
if (alglen > 0 && alglen < pub_len - 4) {
|
if (get_err(src)) {
|
||||||
alg = (const char *)ssh2blob + 4;
|
const char *replacement_str = "INVALID-ALGORITHM";
|
||||||
} else {
|
alg.ptr = replacement_str;
|
||||||
alg = NULL;
|
alg.len = strlen(replacement_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!alg) {
|
buffer = snewn(alg.len +
|
||||||
alg = "INVALID-ALGORITHM";
|
|
||||||
alglen = strlen(alg);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = snewn(alglen +
|
|
||||||
4 * ((pub_len+2) / 3) +
|
4 * ((pub_len+2) / 3) +
|
||||||
(comment ? strlen(comment) : 0) + 3, char);
|
(comment ? strlen(comment) : 0) + 3, char);
|
||||||
p = buffer + sprintf(buffer, "%.*s ", alglen, alg);
|
p = buffer + sprintf(buffer, "%.*s ", PTRLEN_PRINTF(alg));
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < pub_len) {
|
while (i < pub_len) {
|
||||||
int n = (pub_len - i < 3 ? pub_len - i : 3);
|
int n = (pub_len - i < 3 ? pub_len - i : 3);
|
||||||
@ -1512,10 +1489,10 @@ char *ssh2_fingerprint_blob(const void *blob, int bloblen)
|
|||||||
{
|
{
|
||||||
unsigned char digest[16];
|
unsigned char digest[16];
|
||||||
char fingerprint_str[16*3];
|
char fingerprint_str[16*3];
|
||||||
const char *algstr;
|
ptrlen algname;
|
||||||
int alglen;
|
|
||||||
const ssh_keyalg *alg;
|
const ssh_keyalg *alg;
|
||||||
int i;
|
int i;
|
||||||
|
BinarySource src[1];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The fingerprint hash itself is always just the MD5 of the blob.
|
* The fingerprint hash itself is always just the MD5 of the blob.
|
||||||
@ -1527,21 +1504,17 @@ char *ssh2_fingerprint_blob(const void *blob, int bloblen)
|
|||||||
/*
|
/*
|
||||||
* Identify the key algorithm, if possible.
|
* Identify the key algorithm, if possible.
|
||||||
*/
|
*/
|
||||||
alglen = toint(GET_32BIT((const unsigned char *)blob));
|
BinarySource_BARE_INIT(src, blob, bloblen);
|
||||||
if (alglen > 0 && alglen < bloblen-4) {
|
algname = get_string(src);
|
||||||
algstr = (const char *)blob + 4;
|
if (!get_err(src)) {
|
||||||
|
alg = find_pubkey_alg_len(algname);
|
||||||
/*
|
|
||||||
* If we can actually identify the algorithm as one we know
|
|
||||||
* about, get hold of the key's bit count too.
|
|
||||||
*/
|
|
||||||
alg = find_pubkey_alg_len(make_ptrlen(algstr, alglen));
|
|
||||||
if (alg) {
|
if (alg) {
|
||||||
int bits = alg->pubkey_bits(alg, blob, bloblen);
|
int bits = alg->pubkey_bits(alg, blob, bloblen);
|
||||||
return dupprintf("%.*s %d %s", alglen, algstr,
|
return dupprintf("%.*s %d %s", PTRLEN_PRINTF(algname),
|
||||||
bits, fingerprint_str);
|
bits, fingerprint_str);
|
||||||
} else {
|
} else {
|
||||||
return dupprintf("%.*s %s", alglen, algstr, fingerprint_str);
|
return dupprintf("%.*s %s", PTRLEN_PRINTF(algname),
|
||||||
|
fingerprint_str);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user