X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=gcrypt.c;h=1fde479e1be97656bd01002a2071a3d6f1b4b026;hp=f4dbeb8e32c7aee89a5d1b6bd6444811616a0a8c;hb=e79198e9851faddfd64e47654b5bc66fbc574255;hpb=eab41e874f0edcdce4ec4d861c613ee7c7a83865;ds=sidebyside diff --git a/gcrypt.c b/gcrypt.c index f4dbeb8e..1fde479e 100644 --- a/gcrypt.c +++ b/gcrypt.c @@ -64,15 +64,13 @@ void get_random_bytes_or_die(unsigned char *buf, int num) */ void init_random_seed_or_die(void) { - const char *ver, *req_ver; - - ver = gcry_check_version(NULL); - req_ver = "1.5.0"; - if (!gcry_check_version(req_ver)) { - PARA_EMERG_LOG("fatal: need at least libgcrypt-%s, have: %s\n", - req_ver, ver); - exit(EXIT_FAILURE); - } + const char *req_ver = "1.5.0"; + + if (gcry_check_version(req_ver)) + return; + PARA_EMERG_LOG("fatal: need at least libgcrypt-%s, have: %s\n", + req_ver, gcry_check_version(NULL)); + exit(EXIT_FAILURE); } /** S-expression for the public part of an RSA key. */ @@ -191,64 +189,6 @@ static inline int get_long_form_num_length_bytes(unsigned char c) return c & 0x7f; } -static int find_pubkey_bignum_offset(const unsigned char *data, int len) -{ - const unsigned char *p = data, *end = data + len; - - /* the whole thing starts with one sequence */ - if (*p != ASN1_TYPE_SEQUENCE) - return -E_ASN1_PARSE; - p++; - if (p >= end) - return -E_ASN1_PARSE; - if (is_short_form(*p)) - p++; - else - p += 1 + get_long_form_num_length_bytes(*p); - if (p >= end) - return -E_ASN1_PARSE; - /* another sequence containing the object id, skip it */ - if (*p != ASN1_TYPE_SEQUENCE) - return -E_ASN1_PARSE; - p++; - if (p >= end) - return -E_ASN1_PARSE; - if (!is_short_form(*p)) - return -E_ASN1_PARSE; - p += 1 + get_short_form_length(*p); - if (p >= end) - return -E_ASN1_PARSE; - /* all numbers are wrapped in a bit string object that follows */ - if (*p != ASN1_TYPE_BIT_STRING) - return -E_ASN1_PARSE; - p++; - if (p >= end) - return -E_ASN1_PARSE; - if (is_short_form(*p)) - p++; - else - p += 1 + get_long_form_num_length_bytes(*p); - p++; /* skip number of unused bits in the bit string */ - if (p >= end) - return -E_ASN1_PARSE; - - /* next, we have a sequence of two integers (n and e) */ - if (*p != ASN1_TYPE_SEQUENCE) - return -E_ASN1_PARSE; - p++; - if (p >= end) - return -E_ASN1_PARSE; - if (is_short_form(*p)) - p++; - else - p += 1 + get_long_form_num_length_bytes(*p); - if (p >= end) - return -E_ASN1_PARSE; - if (*p != ASN1_TYPE_INTEGER) - return -E_ASN1_PARSE; - return p - data; -} - /* * Returns: Number of bytes scanned. This may differ from the value returned via * bn_bytes because the latter does not include the ASN.1 prefix and a leading @@ -350,6 +290,7 @@ static int get_private_key(const char *key_file, struct asymmetric_key **result) gcry_sexp_t sexp; struct asymmetric_key *key; + *result = NULL; ret = decode_key(key_file, PRIVATE_KEY_HEADER, PRIVATE_KEY_FOOTER, &blob); if (ret < 0) @@ -428,65 +369,6 @@ free_blob: return ret; } -/** Public keys start with this header. */ -#define PUBLIC_KEY_HEADER "-----BEGIN PUBLIC KEY-----" -/** Public keys end with this footer. */ -#define PUBLIC_KEY_FOOTER "-----END PUBLIC KEY-----" - -static int get_asn_public_key(const char *key_file, struct asymmetric_key **result) -{ - gcry_mpi_t n = NULL, e = NULL; - unsigned char *blob, *cp, *end; - int blob_size, ret, n_size; - gcry_error_t gret; - size_t erroff; - gcry_sexp_t sexp; - struct asymmetric_key *key; - - ret = decode_key(key_file, PUBLIC_KEY_HEADER, PUBLIC_KEY_FOOTER, - &blob); - if (ret < 0) - return ret; - blob_size = ret; - end = blob + blob_size; - ret = find_pubkey_bignum_offset(blob, blob_size); - if (ret < 0) - goto free_blob; - PARA_DEBUG_LOG("decoding public RSA params at offset %d\n", ret); - cp = blob + ret; - - ret = read_bignum(cp, end, &n, &n_size); - if (ret < 0) - goto free_blob; - cp += ret; - - ret = read_bignum(cp, end, &e, NULL); - if (ret < 0) - goto release_n; - - gret = gcry_sexp_build(&sexp, &erroff, RSA_PUBKEY_SEXP, n, e); - if (gret) { - PARA_ERROR_LOG("offset %zu: %s\n", erroff, - gcry_strerror(gcry_err_code(gret))); - ret = -E_SEXP_BUILD; - goto release_e; - } - key = para_malloc(sizeof(*key)); - key->sexp = sexp; - key->num_bytes = n_size; - *result = key; - ret = n_size; - PARA_INFO_LOG("successfully read %d bit asn public key\n", n_size * 8); - -release_e: - gcry_mpi_release(e); -release_n: - gcry_mpi_release(n); -free_blob: - free(blob); - return ret; -} - static int get_ssh_public_key(unsigned char *data, int size, gcry_sexp_t *result) { int ret; @@ -548,8 +430,7 @@ free_blob: return ret; } -int get_asymmetric_key(const char *key_file, int private, - struct asymmetric_key **result) +int get_public_key(const char *key_file, struct asymmetric_key **result) { int ret, ret2; void *map; @@ -558,17 +439,13 @@ int get_asymmetric_key(const char *key_file, int private, gcry_sexp_t sexp; struct asymmetric_key *key; - if (private) - return get_private_key(key_file, result); ret = mmap_full_file(key_file, O_RDONLY, &map, &map_size, NULL); if (ret < 0) return ret; ret = is_ssh_rsa_key(map, map_size); if (!ret) { - ret = para_munmap(map, map_size); - if (ret < 0) - return ret; - return get_asn_public_key(key_file, result); + para_munmap(map, map_size); + return -E_SSH_PARSE; } start = map + ret; end = map + map_size; @@ -589,7 +466,7 @@ unmap: return ret; } -void free_asymmetric_key(struct asymmetric_key *key) +void free_public_key(struct asymmetric_key *key) { if (!key) return; @@ -601,10 +478,8 @@ static int decode_rsa(gcry_sexp_t sexp, unsigned char *outbuf, size_t *nbytes) { const char *p = gcry_sexp_nth_data(sexp, 1, nbytes); - if (!p) { - PARA_ERROR_LOG("could not get data from list\n"); - return -E_OEAP; - } + if (!p) + return -E_RSA_DECODE; memcpy(outbuf, p, *nbytes); return 1; } @@ -619,7 +494,7 @@ int priv_decrypt(const char *key_file, unsigned char *outbuf, gcry_sexp_t in, out, priv_key; size_t nbytes; - ret = check_key_file(key_file, true); + ret = check_private_key_file(key_file); if (ret < 0) return ret; PARA_INFO_LOG("decrypting %d byte input\n", inlen); @@ -671,7 +546,8 @@ in_mpi_release: key_release: gcry_sexp_release(priv_key); free_key: - free_asymmetric_key(priv); + gcry_sexp_release(priv->sexp); + free(priv); return ret; } @@ -741,33 +617,20 @@ struct stream_cipher { gcry_cipher_hd_t handle; }; -struct stream_cipher *sc_new(const unsigned char *data, int len, - bool use_aes) +struct stream_cipher *sc_new(const unsigned char *data, int len) { gcry_error_t gret; struct stream_cipher *sc = para_malloc(sizeof(*sc)); - if (use_aes) { - assert(len >= 2 * AES_CRT128_BLOCK_SIZE); - gret = gcry_cipher_open(&sc->handle, GCRY_CIPHER_AES128, - GCRY_CIPHER_MODE_CTR, 0); - assert(gret == 0); - gret = gcry_cipher_setkey(sc->handle, data, - AES_CRT128_BLOCK_SIZE); - assert(gret == 0); - gret = gcry_cipher_setctr(sc->handle, - data + AES_CRT128_BLOCK_SIZE, AES_CRT128_BLOCK_SIZE); - assert(gret == 0); - return sc; - } - gret = gcry_cipher_open(&sc->handle, GCRY_CIPHER_ARCFOUR, - GCRY_CIPHER_MODE_STREAM, 0); - if (gret) { - PARA_ERROR_LOG("%s\n", gcrypt_strerror(gret)); - free(sc); - return NULL; - } - gret = gcry_cipher_setkey(sc->handle, data, (size_t)len); + assert(len >= 2 * AES_CRT128_BLOCK_SIZE); + gret = gcry_cipher_open(&sc->handle, GCRY_CIPHER_AES128, + GCRY_CIPHER_MODE_CTR, 0); + assert(gret == 0); + gret = gcry_cipher_setkey(sc->handle, data, + AES_CRT128_BLOCK_SIZE); + assert(gret == 0); + gret = gcry_cipher_setctr(sc->handle, + data + AES_CRT128_BLOCK_SIZE, AES_CRT128_BLOCK_SIZE); assert(gret == 0); return sc; }