X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=crypt_common.c;h=3a44dbdddcd1cf59108ba110c8d83c4fac11d609;hb=2bad70d84e763b4d866d7b97dbc1cdc8e030bd45;hp=277897f2b47a3c9587d4bb08a5b634b7d4c53f46;hpb=74f74cde7afdba9cfe316998aba9286764bb5d34;p=paraslash.git diff --git a/crypt_common.c b/crypt_common.c index 277897f2..3a44dbdd 100644 --- a/crypt_common.c +++ b/crypt_common.c @@ -135,7 +135,7 @@ int check_private_key_file(const char *file) return 1; } -void hash_to_asc(unsigned char *hash, char *asc) +void hash_to_asc(const unsigned char *hash, char *asc) { int i; const char hexchar[] = "0123456789abcdef"; @@ -147,7 +147,7 @@ void hash_to_asc(unsigned char *hash, char *asc) asc[2 * HASH_SIZE] = '\0'; } -int hash_compare(unsigned char *h1, unsigned char *h2) +int hash_compare(const unsigned char *h1, const unsigned char *h2) { int i; @@ -160,6 +160,31 @@ int hash_compare(unsigned char *h1, unsigned char *h2) return 0; } +void hash2_to_asc(const unsigned char *hash, char *asc) +{ + int i; + const char hexchar[] = "0123456789abcdef"; + + for (i = 0; i < HASH2_SIZE; i++) { + asc[2 * i] = hexchar[hash[i] >> 4]; + asc[2 * i + 1] = hexchar[hash[i] & 0xf]; + } + asc[2 * HASH2_SIZE] = '\0'; +} + +int hash2_compare(const unsigned char *h1, const unsigned char *h2) +{ + int i; + + for (i = 0; i < HASH2_SIZE; i++) { + if (h1[i] < h2[i]) + return -1; + if (h1[i] > h2[i]) + return 1; + } + return 0; +} + /** * Check header of an openssh private key and compute bignum offset. * @@ -230,3 +255,90 @@ int find_openssh_bignum_offset(const unsigned char *data, int len) return p - data; } +/** Private PEM keys (legacy format) start with this header. */ +#define PRIVATE_PEM_KEY_HEADER "-----BEGIN RSA PRIVATE KEY-----" +/** Private OPENSSH keys (RFC4716) start with this header. */ +#define PRIVATE_OPENSSH_KEY_HEADER "-----BEGIN OPENSSH PRIVATE KEY-----" +/** Private PEM keys (legacy format) end with this footer. */ +#define PRIVATE_PEM_KEY_FOOTER "-----END RSA PRIVATE KEY-----" +/** Private OPENSSH keys (RFC4716) end with this footer. */ +#define PRIVATE_OPENSSH_KEY_FOOTER "-----END OPENSSH PRIVATE KEY-----" + +/** + * Decode an openssh-v1 (aka RFC4716) or PEM (aka ASN.1) private key. + * + * \param key_file The private key file (usually id_rsa). + * \param result Pointer to base64-decoded blob is returned here. + * \param blob_size The size of the decoded blob. + * + * This only checks header and footer and base64-decodes the part in between. + * No attempt to read the decoded part is made. + * + * \return Negative on errors, PKT_PEM or PKT_OPENSSH on success, indicating + * the type of key. + */ +int decode_private_key(const char *key_file, unsigned char **result, + size_t *blob_size) +{ + int ret, ret2, i, j, key_type; + void *map; + size_t map_size, key_size; + unsigned char *blob = NULL; + char *begin, *footer, *key; + + ret = mmap_full_file(key_file, O_RDONLY, &map, &map_size, NULL); + if (ret < 0) + goto out; + ret = -E_KEY_MARKER; + if (strncmp(map, PRIVATE_PEM_KEY_HEADER, + strlen(PRIVATE_PEM_KEY_HEADER)) == 0) { + key_type = PKT_PEM; + begin = map + strlen(PRIVATE_PEM_KEY_HEADER); + footer = strstr(map, PRIVATE_PEM_KEY_FOOTER); + PARA_INFO_LOG("detected legacy PEM key %s\n", key_file); + } else if (strncmp(map, PRIVATE_OPENSSH_KEY_HEADER, + strlen(PRIVATE_OPENSSH_KEY_HEADER)) == 0) { + key_type = PKT_OPENSSH; + begin = map + strlen(PRIVATE_OPENSSH_KEY_HEADER); + footer = strstr(map, PRIVATE_OPENSSH_KEY_FOOTER); + PARA_INFO_LOG("detected openssh key %s\n", key_file); + } else + goto unmap; + if (!footer) + goto unmap; + /* skip whitespace at the beginning */ + for (; begin < footer; begin++) { + if (para_isspace(*begin)) + continue; + break; + } + ret = -E_KEY_MARKER; + if (begin >= footer) + goto unmap; + + key_size = footer - begin; + key = para_malloc(key_size + 1); + for (i = 0, j = 0; begin + i < footer; i++) { + if (para_isspace(begin[i])) + continue; + key[j++] = begin[i]; + } + key[j] = '\0'; + ret = base64_decode(key, j, (char **)&blob, blob_size); + free(key); + if (ret < 0) + goto unmap; + ret = key_type; +unmap: + ret2 = para_munmap(map, map_size); + if (ret >= 0 && ret2 < 0) + ret = ret2; + if (ret < 0) { + free(blob); + blob = NULL; + } +out: + *result = blob; + return ret; +} +