X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/c232b3e336238048cb3a8c3548906182ee54c9cd..86916870d36cb70e7ef0ea760e75a6ae8b2d83a5:/import.c diff --git a/import.c b/import.c index 7ad09ac7..2ec1fa2d 100644 --- a/import.c +++ b/import.c @@ -122,11 +122,6 @@ int export_ssh2(char *filename, int type, (c) == '+' || (c) == '/' || (c) == '=' \ ) -extern int base64_decode_atom(char *atom, unsigned char *out); -extern int base64_lines(int datalen); -extern void base64_encode_atom(unsigned char *data, int n, char *out); -extern void base64_encode(FILE *fp, unsigned char *data, int datalen, int cpl); - /* * Read an ASN.1/BER identifier and length pair. * @@ -485,6 +480,8 @@ struct ssh2_userkey *openssh_read(char *filename, char *passphrase) char *modptr; int modlen; + blob = NULL; + if (!key) return NULL; @@ -777,14 +774,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 +795,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; } /* @@ -1006,9 +1023,9 @@ struct sshcom_key *load_sshcom_key(char *filename) * Header lines can end in a trailing backslash for * continuation. */ - while ((len = strlen(p)) > sizeof(buffer) - (p-buffer) -1 || + while ((len = strlen(p)) > (int)(sizeof(buffer) - (p-buffer) -1) || p[len-1] != '\n' || p[len-2] == '\\') { - if (len > (p-buffer) + sizeof(buffer)-2) { + if (len > (int)((p-buffer) + sizeof(buffer)-2)) { errmsg = "Header line too long to deal with"; goto error; } @@ -1568,7 +1585,7 @@ int sshcom_write(char *filename, struct ssh2_userkey *key, char *passphrase) { int slen = 60; /* starts at 60 due to "Comment: " */ char *c = key->comment; - while (strlen(c) > slen) { + while ((int)strlen(c) > slen) { fprintf(fp, "%.*s\\\n", slen, c); c += slen; slen = 70; /* allow 70 chars on subsequent lines */