From 3f6b7dd0ed39f7008ec09def9239f379b87cd7c1 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Wed, 29 Aug 2018 12:20:39 +0200 Subject: [PATCH] gcrypt: Introduce read_openssh_bignum(). This functionality was open-coded twice in apc_get_pubkey() which reads the two public rsa params. Use the new function instead to get rid of the duplication. It will be turn out to be useful for the subsequent work which adds support for RFC4716 keys. Since the function is specific to libgcrypt, it has to stay in gcrypt.c. --- gcrypt.c | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/gcrypt.c b/gcrypt.c index 58fa507b..5d151a3c 100644 --- a/gcrypt.c +++ b/gcrypt.c @@ -336,6 +336,26 @@ static int find_privkey_bignum_offset(const unsigned char *data, int len) return p - data; } +static int read_openssh_bignum(unsigned char *start, unsigned char *end, + gcry_mpi_t *bn, unsigned *bitsp) +{ + gcry_error_t gret; + size_t nscanned; + unsigned bits; + + gret = gcry_mpi_scan(bn, GCRYMPI_FMT_SSH, start, end - start, &nscanned); + if (gret) { + PARA_ERROR_LOG("gcry_mpi_scan: %s\n", + gcry_strerror(gcry_err_code(gret))); + return -E_MPI_SCAN; + } + bits = (nscanned - 4 - (start[4] == '\0')) * 8; + if (bitsp) + *bitsp = bits; + PARA_DEBUG_LOG("scanned %u-bit bignum\n", bits); + return nscanned; +} + static int get_private_key(const char *key_file, struct asymmetric_key **result) { struct rsa_params params; @@ -400,10 +420,11 @@ int apc_get_pubkey(const char *key_file, struct asymmetric_key **result) unsigned char *blob, *p, *end; int ret; gcry_error_t gret; - size_t nr_scanned, erroff, decoded_size; + size_t erroff, decoded_size; gcry_mpi_t e, n; gcry_sexp_t sexp; struct asymmetric_key *key; + unsigned bits; ret = decode_ssh_key(key_file, &blob, &decoded_size); if (ret < 0) @@ -411,23 +432,13 @@ int apc_get_pubkey(const char *key_file, struct asymmetric_key **result) p = blob + ret; end = blob + decoded_size; PARA_DEBUG_LOG("scanning modulus and public exponent\n"); - gret = gcry_mpi_scan(&e, GCRYMPI_FMT_SSH, p, end - p, &nr_scanned); - if (gret) { - ret = -E_MPI_SCAN; - PARA_CRIT_LOG("%s\n", gcry_strerror(gcry_err_code(gret))); + ret = read_openssh_bignum(p, end, &e, NULL); + if (ret < 0) goto free_blob; - } - PARA_DEBUG_LOG("scanned e (%zu bytes)\n", nr_scanned); - p += nr_scanned; - if (p >= end) - goto release_e; - gret = gcry_mpi_scan(&n, GCRYMPI_FMT_SSH, p, end - p, &nr_scanned); - if (gret) { - ret = -E_MPI_SCAN; - PARA_ERROR_LOG("%s\n", gcry_strerror(gcry_err_code(gret))); + p += ret; + ret = read_openssh_bignum(p, end, &n, &bits); + if (ret < 0) goto release_e; - } - PARA_DEBUG_LOG("scanned n (%zu bytes)\n", nr_scanned); gret = gcry_sexp_build(&sexp, &erroff, RSA_PUBKEY_SEXP, n, e); if (gret) { PARA_ERROR_LOG("offset %zu: %s\n", erroff, @@ -435,12 +446,12 @@ int apc_get_pubkey(const char *key_file, struct asymmetric_key **result) ret = -E_SEXP_BUILD; goto release_n; } - ret = ROUND_DOWN(nr_scanned, 32); - PARA_INFO_LOG("successfully read %d bit ssh public key\n", ret * 8); + PARA_INFO_LOG("successfully read %u bit ssh public key\n", bits); key = para_malloc(sizeof(*key)); key->num_bytes = ret; key->sexp = sexp; *result = key; + ret = bits; release_n: gcry_mpi_release(n); release_e: -- 2.39.5