summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2018-03-02 14:51:31 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2018-03-02 23:45:07 +0100
commit8deb88e713dc3a5a0682d88bebd4e9a24707f184 (patch)
tree6f7a236017bd398b79e57d4ab8212360c906dae9
parent7ac0e16bde3b54ed6b6f435a88f180b64056f9f7 (diff)
downloadgnutls-8deb88e713dc3a5a0682d88bebd4e9a24707f184.tar.gz
gnutls_privkey_import_ext4: enhanced with GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS flag
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>
-rw-r--r--lib/abstract_int.h1
-rw-r--r--lib/includes/gnutls/abstract.h3
-rw-r--r--lib/privkey.c12
-rw-r--r--tests/sign-verify-ext4.c5
-rw-r--r--tests/tls-neg-ext4-key.c5
5 files changed, 23 insertions, 3 deletions
diff --git a/lib/abstract_int.h b/lib/abstract_int.h
index 4013296653..5eaf6e9460 100644
--- a/lib/abstract_int.h
+++ b/lib/abstract_int.h
@@ -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;
diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h
index 4c638fda42..e15bd3a0f5 100644
--- a/lib/includes/gnutls/abstract.h
+++ b/lib/includes/gnutls/abstract.h
@@ -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);
diff --git a/lib/privkey.c b/lib/privkey.c
index 63cc7fcbd3..10afdf90f1 100644
--- a/lib/privkey.c
+++ b/lib/privkey.c
@@ -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;
diff --git a/tests/sign-verify-ext4.c b/tests/sign-verify-ext4.c
index 94daf000e7..81aa345bf0 100644
--- a/tests/sign-verify-ext4.c
+++ b/tests/sign-verify-ext4.c
@@ -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;
diff --git a/tests/tls-neg-ext4-key.c b/tests/tls-neg-ext4-key.c
index b916294d3e..04365c598d 100644
--- a/tests/tls-neg-ext4-key.c
+++ b/tests/tls-neg-ext4-key.c
@@ -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;