X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=crypt_common.c;h=277897f2b47a3c9587d4bb08a5b634b7d4c53f46;hp=235b8b8d3e398551fc28bfbc746349c5dc8f6f1c;hb=74f74cde7afdba9cfe316998aba9286764bb5d34;hpb=e2167286448ce2ed9a01a548e7e9832563035088 diff --git a/crypt_common.c b/crypt_common.c index 235b8b8d..277897f2 100644 --- a/crypt_common.c +++ b/crypt_common.c @@ -85,7 +85,7 @@ static int check_ssh_key_header(const unsigned char *blob, int blen) * * \sa \ref uudecode(). */ -int decode_ssh_key(const char *filename, unsigned char **blob, +int decode_public_key(const char *filename, unsigned char **blob, size_t *decoded_size) { int ret, ret2; @@ -159,3 +159,74 @@ int hash_compare(unsigned char *h1, unsigned char *h2) } return 0; } + +/** + * Check header of an openssh private key and compute bignum offset. + * + * \param data The base64-decoded key. + * \param len The size of the decoded key. + * + * Several assumptions are made about the key. Most notably, we only support + * single unencrypted keys without comments. + * + * \return The offset at which the first bignum of the private key (the public + * exponent n) starts. Negative error code on failure. + */ +int find_openssh_bignum_offset(const unsigned char *data, int len) +{ + /* + * Unencrypted keys without comments always start with the below byte + * sequence. See PROTOCOL.key of the openssh package. + */ + static const unsigned char valid_openssh_header[] = { + /* string "openssh-key-v1" */ + 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x68, 0x2d, 0x6b, 0x65, + 0x79, 0x2d, 0x76, 0x31, + /* length of the cipher name */ + 0x00, 0x00, 0x00, 0x00, 0x04, + /* cipher name: "none" */ + 0x6e, 0x6f, 0x6e, 0x65, + /* length of the kdfname (only used for encrypted keys) */ + 0x00, 0x00, 0x00, 0x04, + /* kdfname: "none" */ + 0x6e, 0x6f, 0x6e, 0x65, + /* length of kdfoptions */ + 0x00, 0x00, 0x00, 0x00, + /* number of keys */ + 0x00, 0x00, 0x00, 0x01, + }; + uint32_t val; + const unsigned char *p, *end = data + len; + + if (len <= sizeof(valid_openssh_header) + 4) + return -E_OPENSSH_PARSE; + if (memcmp(data, valid_openssh_header, sizeof(valid_openssh_header))) + return -E_OPENSSH_PARSE; + p = data + sizeof(valid_openssh_header); + /* length of public key */ + val = read_u32_be(p); + if (val > end - p - 4) + return -E_OPENSSH_PARSE; + p += val + 4; + /* length of private key */ + val = read_u32_be(p); + if (val > end - p - 4) + return -E_OPENSSH_PARSE; + p += 4; + /* two equal random integers ("checkint") */ + if (p + 8 > end) + return -E_OPENSSH_PARSE; + if (read_u32_be(p) != read_u32_be(p + 4)) + return -E_OPENSSH_PARSE; + p += 8; + /* length of name of key type "ssh-rsa" */ + if (p + 11 > end) + return -E_OPENSSH_PARSE; + if (read_u32_be(p) != 7) + return -E_OPENSSH_PARSE; + if (memcmp(p + 4, "ssh-rsa", 7)) + return -E_OPENSSH_PARSE; + p += 11; + return p - data; +} +