X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/96d19bc96ba1e93fe09561f3ceefe427e7d30386..68a49acbf3f96fbbbc385620655dcb577e62c328:/import.c diff --git a/import.c b/import.c index 2ff36980..ff438161 100644 --- a/import.c +++ b/import.c @@ -62,7 +62,7 @@ int import_target_type(int type) int import_encrypted(char *filename, int type, char **comment) { if (type == SSH_KEYTYPE_OPENSSH) { - *comment = filename; /* OpenSSH doesn't do key comments */ + *comment = dupstr(filename); /* OpenSSH doesn't do key comments */ return openssh_encrypted(filename); } if (type == SSH_KEYTYPE_SSHCOM) { @@ -485,6 +485,8 @@ struct ssh2_userkey *openssh_read(char *filename, char *passphrase) char *modptr; int modlen; + blob = NULL; + if (!key) return NULL; @@ -777,14 +779,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 +800,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 +1028,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 +1590,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 */