From 3699a583f3a7e9514c0f47b8b07f56b050430b67 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Tue, 28 Aug 2018 20:50:53 +0200 Subject: [PATCH] gcrypt: Factor out read_pem_rsa_params(). We'll soon add a similar function which reads bignums from an RFC4716 key file, so it's good to separate this functionality from the rest of get_private_key(). The patch also introduces struct rsa_params which contains the six bignums used for RSA private key operations. This way read_pem_rsa_params() only needs three arguments. --- gcrypt.c | 114 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 48 deletions(-) diff --git a/gcrypt.c b/gcrypt.c index abc3272a..58fa507b 100644 --- a/gcrypt.c +++ b/gcrypt.c @@ -256,6 +256,54 @@ static int read_bignum(unsigned char *start, unsigned char *end, gcry_mpi_t *bn, return cp - start; } +struct rsa_params { + gcry_mpi_t n, e, d, p, q, u; +}; + +static int read_pem_rsa_params(unsigned char *start, unsigned char *end, + struct rsa_params *p) +{ + unsigned char *cp = start; + unsigned bits; + int ret; + + ret = read_bignum(cp, end, &p->n, &bits); + if (ret < 0) + return ret; + cp += ret; + ret = read_bignum(cp, end, &p->e, NULL); + if (ret < 0) + goto release_n; + cp += ret; + ret = read_bignum(cp, end, &p->d, NULL); + if (ret < 0) + goto release_e; + cp += ret; + ret = read_bignum(cp, end, &p->p, NULL); + if (ret < 0) + goto release_d; + cp += ret; + ret = read_bignum(cp, end, &p->q, NULL); + if (ret < 0) + goto release_p; + cp += ret; + ret = read_bignum(cp, end, &p->u, NULL); + if (ret < 0) + goto release_q; + return bits; +release_q: + gcry_mpi_release(p->q); +release_p: + gcry_mpi_release(p->p); +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 find_privkey_bignum_offset(const unsigned char *data, int len) { const unsigned char *p = data, *end = data + len; @@ -290,9 +338,8 @@ static int find_privkey_bignum_offset(const unsigned char *data, int len) static int get_private_key(const char *key_file, struct asymmetric_key **result) { - gcry_mpi_t n = NULL, e = NULL, d = NULL, p = NULL, q = NULL, - u = NULL; - unsigned char *blob, *cp, *end; + struct rsa_params params; + unsigned char *blob, *end; int ret; unsigned bits; gcry_error_t gret; @@ -309,69 +356,40 @@ static int get_private_key(const char *key_file, struct asymmetric_key **result) if (ret < 0) goto free_blob; PARA_INFO_LOG("reading RSA params at offset %d\n", ret); - cp = blob + ret; - - ret = read_bignum(cp, end, &n, &bits); + ret = read_pem_rsa_params(blob + ret, end, ¶ms); if (ret < 0) goto free_blob; - cp += ret; - - ret = read_bignum(cp, end, &e, NULL); - if (ret < 0) - goto release_n; - cp += ret; - - ret = read_bignum(cp, end, &d, NULL); - if (ret < 0) - goto release_e; - cp += ret; - - ret = read_bignum(cp, end, &p, NULL); - if (ret < 0) - goto release_d; - cp += ret; - - ret = read_bignum(cp, end, &q, NULL); - if (ret < 0) - goto release_p; - cp += ret; - ret = read_bignum(cp, end, &u, NULL); - if (ret < 0) - goto release_q; + bits = ret; /* * OpenSSL uses slightly different parameters than gcrypt. To use these * parameters we need to swap the values of p and q and recompute u. */ - if (gcry_mpi_cmp(p, q) > 0) { - gcry_mpi_swap(p, q); - gcry_mpi_invm(u, p, q); + if (gcry_mpi_cmp(params.p, params.q) > 0) { + gcry_mpi_swap(params.p, params.q); + gcry_mpi_invm(params.u, params.p, params.q); } - gret = gcry_sexp_build(&sexp, &erroff, RSA_PRIVKEY_SEXP, - n, e, d, p, q, u); + gret = gcry_sexp_build(&sexp, &erroff, RSA_PRIVKEY_SEXP, params.n, + params.e, params.d, params.p, params.q, params.u); if (gret) { PARA_ERROR_LOG("offset %zu: %s\n", erroff, gcry_strerror(gcry_err_code(gret))); ret = -E_SEXP_BUILD; - goto release_u; + goto free_params; } key = para_malloc(sizeof(*key)); key->sexp = sexp; *result = key; ret = bits; PARA_INFO_LOG("succesfully read %d bit private key\n", ret); -release_u: - gcry_mpi_release(u); -release_q: - gcry_mpi_release(q); -release_p: - gcry_mpi_release(p); -release_d: - gcry_mpi_release(d); -release_e: - gcry_mpi_release(e); -release_n: - gcry_mpi_release(n); +free_params: + gcry_mpi_release(params.n); + gcry_mpi_release(params.e); + gcry_mpi_release(params.d); + gcry_mpi_release(params.u); + gcry_mpi_release(params.p); + gcry_mpi_release(params.q); + free_blob: free(blob); return ret; -- 2.39.5