]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
gnutls_privkey_import_ext4: enhanced with GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS flag
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 2 Mar 2018 13:51:31 +0000 (14:51 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 2 Mar 2018 22:45:07 +0000 (23:45 +0100)
That flag is utilized by the information function to obtain the
value of the parameters (e.g., modulus). That information is necessary
to safely handle RSA-PSS keys.

For RSA-PSS keys this is a regression since 3.6.0 where this API was
introduced, but as this change is necessary and 3.6.x is not yet marked
as stable, it should be acceptable.

Relates #402

Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
lib/abstract_int.h
lib/includes/gnutls/abstract.h
lib/privkey.c
tests/sign-verify-ext4.c
tests/tls-neg-ext4-key.c

index 401329665365ac00ced0c80df10b10a23d2f8dd2..5eaf6e9460aa055a59f166ab2118e988e79166af 100644 (file)
@@ -42,6 +42,7 @@ struct gnutls_privkey_st {
                        gnutls_privkey_deinit_func deinit_func;
                        gnutls_privkey_info_func info_func;
                        void *userdata;
+                       unsigned bits;
                } ext;
        } key;
 
index 4c638fda42343f953b5d2f1d034a0062bf979f71..e15bd3a0f52f80d0d8e8d702abca0af343e83210 100644 (file)
@@ -115,6 +115,9 @@ typedef void (*gnutls_privkey_deinit_func) (gnutls_privkey_t key,
  * (obtained with GNUTLS_FLAGS_TO_SIGN_ALGO) is supported.
  */
 #define GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO (1<<2)
+/* Should return the number of bits of the public key algorithm (required for RSA-PSS)
+ * It is the value that should be retuned by gnutls_pubkey_get_pk_algorithm() */
+#define GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS (1<<3)
 
 /* returns information on the public key associated with userdata */
 typedef int (*gnutls_privkey_info_func) (gnutls_privkey_t key, unsigned int flags, void *userdata);
index 63cc7fcbd3bb22028d280946b1197bedf37209b5..10afdf90f1605ff439c94c564b77581583bee383 100644 (file)
@@ -137,7 +137,8 @@ int gnutls_privkey_get_pk_algorithm(gnutls_privkey_t key, unsigned int *bits)
                return gnutls_x509_privkey_get_pk_algorithm(key->key.x509);
        case GNUTLS_PRIVKEY_EXT:
                if (bits)
-                       *bits = 0;
+                       *bits = key->key.ext.bits;
+
                return key->pk_algorithm;
        default:
                gnutls_assert();
@@ -816,8 +817,9 @@ gnutls_privkey_import_ext3(gnutls_privkey_t pkey,
  * unless prohibited by the type of the algorithm (e.g., as with Ed25519).
  *
  * The @info_fn must provide information on the signature algorithms supported by
- * this private key, and should support the flags %GNUTLS_PRIVKEY_INFO_PK_ALGO and
- * %GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO. It must return -1 on unknown flags.
+ * this private key, and should support the flags %GNUTLS_PRIVKEY_INFO_PK_ALGO,
+ * %GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO and %GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS.
+ * It must return -1 on unknown flags.
  *
  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
  *   negative error value.
@@ -859,6 +861,10 @@ gnutls_privkey_import_ext4(gnutls_privkey_t pkey,
 
        pkey->pk_algorithm = pkey->key.ext.info_func(pkey, GNUTLS_PRIVKEY_INFO_PK_ALGO, pkey->key.ext.userdata);
 
+       ret = pkey->key.ext.info_func(pkey, GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS, pkey->key.ext.userdata);
+       if (ret >= 0)
+               pkey->key.ext.bits = ret;
+
        /* Ensure gnutls_privkey_deinit() calls the deinit_func */
        if (deinit_fn)
                pkey->flags |= GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE;
index 94daf000e76e7861ee94ee051834424c1de5d282..81aa345bf09fcfea25daf171e4d205040e070a88 100644 (file)
@@ -71,6 +71,7 @@ struct key_cb_data {
        gnutls_privkey_t rkey; /* the real thing */
        unsigned pk;
        unsigned sig;
+       unsigned bits;
 };
 
 static int key_cb_info_func(gnutls_privkey_t key, unsigned int flags, void *userdata)
@@ -79,6 +80,8 @@ static int key_cb_info_func(gnutls_privkey_t key, unsigned int flags, void *user
 
        if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO)
                return p->pk;
+       else if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS)
+               return p->bits;
        else if (flags & GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO) {
                unsigned sig = GNUTLS_FLAGS_TO_SIGN_ALGO(flags);
 
@@ -153,6 +156,8 @@ static gnutls_privkey_t load_virt_privkey(const gnutls_datum_t *txtkey, gnutls_p
        if (ret < 0)
                fail("gnutls_privkey_import\n");
 
+       gnutls_privkey_get_pk_algorithm(userdata->rkey, &userdata->bits);
+
        userdata->pk = pk;
        userdata->sig = sig;
 
index b916294d3e74c19910ee789443e272f7f3dbf2a8..04365c598da0338edcc8dd2c707e41fe255329e8 100644 (file)
@@ -73,6 +73,7 @@ struct key_cb_data {
        gnutls_privkey_t rkey; /* the real thing */
        unsigned pk;
        unsigned sig;
+       unsigned bits;
 };
 
 static int key_cb_info_func(gnutls_privkey_t key, unsigned int flags, void *userdata)
@@ -81,6 +82,8 @@ static int key_cb_info_func(gnutls_privkey_t key, unsigned int flags, void *user
 
        if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO)
                return p->pk;
+       else if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS)
+               return p->bits;
        else if (flags & GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO) {
                unsigned sig = GNUTLS_FLAGS_TO_SIGN_ALGO(flags);
 
@@ -159,6 +162,8 @@ static gnutls_privkey_t load_virt_privkey(const char *name, const gnutls_datum_t
        if (ret < 0)
                testfail("gnutls_privkey_import\n");
 
+       gnutls_privkey_get_pk_algorithm(userdata->rkey, &userdata->bits);
+
        userdata->pk = pk;
        userdata->sig = sig;