1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Rewrite ssh2_add_sigblob using BinarySource.

This is the function that breaks apart a signature blob (generated
locally or received from an SSH agent) and adds leading zero bytes in
front of the signature integer, if we think we're talking to a server
that will incorrectly insist on that. The breaking-apart process is
just another instance of SSH-style data unmarshalling, so it should be
done by the new centralised routines.
This commit is contained in:
Simon Tatham 2018-05-29 20:45:42 +01:00
parent 7535f645ab
commit e43605ee05

68
ssh.c
View File

@ -2697,11 +2697,12 @@ void bndebug(char *string, Bignum b)
* BUG_SSH2_RSA_PADDING.
*/
static void ssh2_add_sigblob(Ssh ssh, struct Packet *pkt,
void *pkblob_v, int pkblob_len,
void *sigblob_v, int sigblob_len)
const void *pkblob, int pkblob_len,
const void *sigblob, int sigblob_len)
{
unsigned char *pkblob = (unsigned char *)pkblob_v;
unsigned char *sigblob = (unsigned char *)sigblob_v;
BinarySource pk[1], sig[1];
BinarySource_BARE_INIT(pk, pkblob, pkblob_len);
BinarySource_BARE_INIT(sig, sigblob, sigblob_len);
/* dmemdump(pkblob, pkblob_len); */
/* dmemdump(sigblob, sigblob_len); */
@ -2710,48 +2711,41 @@ static void ssh2_add_sigblob(Ssh ssh, struct Packet *pkt,
* See if this is in fact an ssh-rsa signature and a buggy
* server; otherwise we can just do this the easy way.
*/
if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) && pkblob_len > 4+7+4 &&
(GET_32BIT(pkblob) == 7 && !memcmp(pkblob+4, "ssh-rsa", 7))) {
int pos, len, siglen;
if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) &&
ptrlen_eq_string(get_string(pk), "ssh-rsa") &&
ptrlen_eq_string(get_string(sig), "ssh-rsa")) {
ptrlen mod_mp, sig_mp;
size_t sig_prefix_len;
/*
* Find the byte length of the modulus.
* Find the modulus and signature integers.
*/
get_string(pk); /* skip over exponent */
mod_mp = get_string(pk); /* remember modulus */
sig_prefix_len = sig->pos;
sig_mp = get_string(sig);
if (get_err(pk) || get_err(sig))
goto give_up;
/*
* Find the byte length of the modulus, not counting leading
* zeroes.
*/
while (mod_mp.len > 0 && *(const char *)mod_mp.ptr == 0) {
mod_mp.len--;
mod_mp.ptr = (const char *)mod_mp.ptr + 1;
}
pos = 4+7; /* skip over "ssh-rsa" */
len = toint(GET_32BIT(pkblob+pos)); /* get length of exponent */
if (len < 0 || len > pkblob_len - pos - 4)
goto give_up;
pos += 4 + len; /* skip over exponent */
if (pkblob_len - pos < 4)
goto give_up;
len = toint(GET_32BIT(pkblob+pos)); /* find length of modulus */
if (len < 0 || len > pkblob_len - pos - 4)
goto give_up;
pos += 4; /* find modulus itself */
while (len > 0 && pkblob[pos] == 0)
len--, pos++;
/* debug(("modulus length is %d\n", len)); */
/*
* Now find the signature integer.
*/
pos = 4+7; /* skip over "ssh-rsa" */
if (sigblob_len < pos+4)
goto give_up;
siglen = toint(GET_32BIT(sigblob+pos));
if (siglen != sigblob_len - pos - 4)
goto give_up;
/* debug(("signature length is %d\n", siglen)); */
if (len != siglen) {
if (mod_mp.len != sig_mp.len) {
strbuf *substr = strbuf_new();
put_data(substr, sigblob, pos);
put_uint32(substr, len);
while (len-- > siglen)
put_data(substr, sigblob, sig_prefix_len);
put_uint32(substr, mod_mp.len);
while (mod_mp.len-- > sig_mp.len)
put_byte(substr, 0);
pos += 4; /* point to start of actual sig */
put_data(substr, sigblob+pos, siglen);
put_data(substr, sig_mp.ptr, sig_mp.len);
put_stringsb(pkt, substr);
return;
}