X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=gcrypt.c;h=763fa6de3252d2f5f188fc3f447f2029d0f5775a;hb=1f33eda05b3e96b32817a133287bcfc5e99ed6b4;hp=5d151a3cc9f7c42e6322f1748902b14281b49f1c;hpb=3f6b7dd0ed39f7008ec09def9239f379b87cd7c1;p=paraslash.git diff --git a/gcrypt.c b/gcrypt.c index 5d151a3c..763fa6de 100644 --- a/gcrypt.c +++ b/gcrypt.c @@ -46,6 +46,22 @@ void hash_function(const char *data, unsigned long len, unsigned char *hash) gcry_md_close(handle); } +void hash2_function(const char *data, unsigned long len, unsigned char *hash) +{ + gcry_error_t gret; + gcry_md_hd_t handle; + unsigned char *md; + + gret = gcry_md_open(&handle, GCRY_MD_SHA256, 0); + assert(gret == 0); + gcry_md_write(handle, data, (size_t)len); + gcry_md_final(handle); + md = gcry_md_read(handle, GCRY_MD_SHA256); + assert(md); + memcpy(hash, md, HASH2_SIZE); + gcry_md_close(handle); +} + void get_random_bytes_or_die(unsigned char *buf, int num) { gcry_randomize(buf, (size_t)num, GCRY_STRONG_RANDOM); @@ -106,64 +122,6 @@ static const char *gcrypt_strerror(gcry_error_t gret) return gcry_strerror(gcry_err_code(gret)); } -/** Private keys start with this header. */ -#define PRIVATE_KEY_HEADER "-----BEGIN RSA PRIVATE KEY-----" -/** Private keys end with this footer. */ -#define PRIVATE_KEY_FOOTER "-----END RSA PRIVATE KEY-----" - -static int decode_key(const char *key_file, unsigned char **result, - size_t *blob_size) -{ - int ret, ret2, i, j; - 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_KEY_HEADER, strlen(PRIVATE_KEY_HEADER))) - goto unmap; - footer = strstr(map, PRIVATE_KEY_FOOTER); - ret = -E_KEY_MARKER; - if (!footer) - goto unmap; - begin = map + strlen(PRIVATE_KEY_HEADER); - /* 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); -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; -} - /** ASN Types and their code. */ enum asn1_types { /** The next object is an integer. */ @@ -208,7 +166,7 @@ static inline int get_long_form_num_length_bytes(unsigned char c) * bitsp because the latter does not include the ASN.1 prefix and a leading * zero is not considered as an additional byte for the number of bits. */ -static int read_bignum(unsigned char *start, unsigned char *end, gcry_mpi_t *bn, +static int read_pem_bignum(unsigned char *start, unsigned char *end, gcry_mpi_t *bn, unsigned *bitsp) { int i, bn_size; @@ -267,27 +225,27 @@ static int read_pem_rsa_params(unsigned char *start, unsigned char *end, unsigned bits; int ret; - ret = read_bignum(cp, end, &p->n, &bits); + ret = read_pem_bignum(cp, end, &p->n, &bits); if (ret < 0) return ret; cp += ret; - ret = read_bignum(cp, end, &p->e, NULL); + ret = read_pem_bignum(cp, end, &p->e, NULL); if (ret < 0) goto release_n; cp += ret; - ret = read_bignum(cp, end, &p->d, NULL); + ret = read_pem_bignum(cp, end, &p->d, NULL); if (ret < 0) goto release_e; cp += ret; - ret = read_bignum(cp, end, &p->p, NULL); + ret = read_pem_bignum(cp, end, &p->p, NULL); if (ret < 0) goto release_d; cp += ret; - ret = read_bignum(cp, end, &p->q, NULL); + ret = read_pem_bignum(cp, end, &p->q, NULL); if (ret < 0) goto release_p; cp += ret; - ret = read_bignum(cp, end, &p->u, NULL); + ret = read_pem_bignum(cp, end, &p->u, NULL); if (ret < 0) goto release_q; return bits; @@ -304,7 +262,7 @@ release_n: return ret; } -static int find_privkey_bignum_offset(const unsigned char *data, int len) +static int find_pem_bignum_offset(const unsigned char *data, int len) { const unsigned char *p = data, *end = data + len; @@ -356,27 +314,78 @@ static int read_openssh_bignum(unsigned char *start, unsigned char *end, return nscanned; } +static int read_openssh_rsa_params(unsigned char *start, unsigned char *end, + struct rsa_params *p) +{ + unsigned char *cp = start; + unsigned bits; + int ret; + + ret = read_openssh_bignum(cp, end, &p->n, &bits); + if (ret < 0) + return ret; + cp += ret; + ret = read_openssh_bignum(cp, end, &p->e, NULL); + if (ret < 0) + goto release_n; + cp += ret; + ret = read_openssh_bignum(cp, end, &p->d, NULL); + if (ret < 0) + goto release_e; + cp += ret; + ret = read_openssh_bignum(cp, end, &p->u, NULL); + if (ret < 0) + goto release_d; + cp += ret; + ret = read_openssh_bignum(cp, end, &p->p, NULL); + if (ret < 0) + goto release_u; + cp += ret; + ret = read_openssh_bignum(cp, end, &p->q, NULL); + if (ret < 0) + goto release_p; + return bits; +release_p: + gcry_mpi_release(p->p); +release_u: + gcry_mpi_release(p->u); +release_d: + gcry_mpi_release(p->d); +release_e: + gcry_mpi_release(p->e); +release_n: + gcry_mpi_release(p->n); + return ret; +} + static int get_private_key(const char *key_file, struct asymmetric_key **result) { struct rsa_params params; unsigned char *blob, *end; - int ret; unsigned bits; + int ret, key_type; gcry_error_t gret; size_t erroff, blob_size; gcry_sexp_t sexp; struct asymmetric_key *key; *result = NULL; - ret = decode_key(key_file, &blob, &blob_size); + ret = decode_private_key(key_file, &blob, &blob_size); if (ret < 0) return ret; + key_type = ret; end = blob + blob_size; - ret = find_privkey_bignum_offset(blob, blob_size); + if (key_type == PKT_PEM) + ret = find_pem_bignum_offset(blob, blob_size); + else + ret = find_openssh_bignum_offset(blob, blob_size); if (ret < 0) goto free_blob; PARA_INFO_LOG("reading RSA params at offset %d\n", ret); - ret = read_pem_rsa_params(blob + ret, end, ¶ms); + if (key_type == PKT_PEM) + ret = read_pem_rsa_params(blob + ret, end, ¶ms); + else + ret = read_openssh_rsa_params(blob + ret, end, ¶ms); if (ret < 0) goto free_blob; bits = ret; @@ -397,7 +406,7 @@ static int get_private_key(const char *key_file, struct asymmetric_key **result) ret = -E_SEXP_BUILD; goto free_params; } - key = para_malloc(sizeof(*key)); + key = alloc(sizeof(*key)); key->sexp = sexp; *result = key; ret = bits; @@ -426,7 +435,7 @@ int apc_get_pubkey(const char *key_file, struct asymmetric_key **result) struct asymmetric_key *key; unsigned bits; - ret = decode_ssh_key(key_file, &blob, &decoded_size); + ret = decode_public_key(key_file, &blob, &decoded_size); if (ret < 0) return ret; p = blob + ret; @@ -447,7 +456,7 @@ int apc_get_pubkey(const char *key_file, struct asymmetric_key **result) goto release_n; } PARA_INFO_LOG("successfully read %u bit ssh public key\n", bits); - key = para_malloc(sizeof(*key)); + key = alloc(sizeof(*key)); key->num_bytes = ret; key->sexp = sexp; *result = key; @@ -615,7 +624,7 @@ struct stream_cipher { struct stream_cipher *sc_new(const unsigned char *data, int len) { gcry_error_t gret; - struct stream_cipher *sc = para_malloc(sizeof(*sc)); + struct stream_cipher *sc = alloc(sizeof(*sc)); assert(len >= 2 * AES_CRT128_BLOCK_SIZE); gret = gcry_cipher_open(&sc->handle, GCRY_CIPHER_AES128,