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

Padding on the end of the encrypted data in OpenSSH key format was

broken: the OpenSSL EVP layer specifies a very particular form of
padding, which I wasn't generating because it hadn't occurred to me
that it might be mandatory. Irritatingly this was causing our
exported OpenSSH keys to load perfectly happily back in through our
OpenSSH import routines, but to be rejected by OpenSSH proper. Sigh.

[originally from svn r1733]
This commit is contained in:
Simon Tatham 2002-06-15 16:31:22 +00:00
parent ab1d4f5dce
commit 729512abc2

View File

@ -777,14 +777,15 @@ int openssh_write(char *filename, struct ssh2_userkey *key, char *passphrase)
seqlen = len;
/* Now add on the SEQUENCE header. */
len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
/* And round up to the cipher block size. */
/* Round up to the cipher block size, ensuring we have at least one
* byte of padding (see below). */
outlen = len;
if (passphrase)
len = (len+7) &~ 7;
outlen = (outlen+8) &~ 7;
/*
* Now we know how big outblob needs to be. Allocate it.
*/
outlen = len;
outblob = smalloc(outlen);
/*
@ -797,8 +798,27 @@ int openssh_write(char *filename, struct ssh2_userkey *key, char *passphrase)
memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
pos += numbers[i].bytes;
}
/*
* Padding on OpenSSH keys is deterministic. The number of
* padding bytes is always more than zero, and always at most
* the cipher block length. The value of each padding byte is
* equal to the number of padding bytes. So a plaintext that's
* an exact multiple of the block size will be padded with 08
* 08 08 08 08 08 08 08 (assuming a 64-bit block cipher); a
* plaintext one byte less than a multiple of the block size
* will be padded with just 01.
*
* This enables the OpenSSL key decryption function to strip
* off the padding algorithmically and return the unpadded
* plaintext to the next layer: it looks at the final byte, and
* then expects to find that many bytes at the end of the data
* with the same value. Those are all removed and the rest is
* returned.
*/
assert(pos == len);
while (pos < outlen) {
outblob[pos++] = random_byte();
outblob[pos++] = outlen - len;
}
/*