gcrypt: Introduce read_openssh_bignum().
authorAndre Noll <maan@tuebingen.mpg.de>
Wed, 29 Aug 2018 10:20:39 +0000 (12:20 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Tue, 25 Dec 2018 16:45:24 +0000 (17:45 +0100)
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

index 58fa507..5d151a3 100644 (file)
--- 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: