summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2018-03-03 15:28:08 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2018-03-03 15:28:08 +0000
commitc8d7f94b1a9dab8b97b3277eed8a052adcb89689 (patch)
treea8503d518e418e774eef46450239606d25942826
parent8bc71dc0ed272c10b6430a678858b8e973828cf8 (diff)
parent991b9daffd32e470372479f49a75f1bd83209e91 (diff)
downloadgnutls-c8d7f94b1a9dab8b97b3277eed8a052adcb89689.tar.gz
Merge branch 'tmp-rsa-pss-fix' into 'master'
_gnutls_find_rsa_pss_salt_size: add a validity check for salt size Closes #402 See merge request gnutls/gnutls!607
-rw-r--r--lib/abstract_int.h1
-rw-r--r--lib/includes/gnutls/abstract.h3
-rw-r--r--lib/pk.c18
-rw-r--r--lib/pk.h4
-rw-r--r--lib/pkcs11_int.h1
-rw-r--r--lib/pkcs11_privkey.c12
-rw-r--r--lib/privkey.c21
-rw-r--r--lib/pubkey.c8
-rw-r--r--lib/x509/crq.c7
-rw-r--r--lib/x509/privkey.c9
-rw-r--r--lib/x509/x509_write.c8
-rw-r--r--tests/sign-verify-ext4.c5
-rw-r--r--tests/tls-neg-ext4-key.c5
13 files changed, 82 insertions, 20 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/pk.c b/lib/pk.c
index be1d8b6a85..3014396bc0 100644
--- a/lib/pk.c
+++ b/lib/pk.c
@@ -382,19 +382,29 @@ void gnutls_pk_params_clear(gnutls_pk_params_st * p)
}
}
-unsigned
+int
_gnutls_find_rsa_pss_salt_size(unsigned bits, const mac_entry_st *me,
unsigned salt_size)
{
- unsigned max_salt_size, digest_size;
+ unsigned digest_size;
+ int max_salt_size;
+ unsigned key_size;
digest_size = _gnutls_hash_get_algo_len(me);
- max_salt_size = (bits + 7) / 8 - digest_size - 2;
+ key_size = (bits + 7) / 8;
+
+ if (key_size == 0) {
+ return gnutls_assert_val(GNUTLS_E_PK_INVALID_PUBKEY);
+ } else {
+ max_salt_size = key_size - digest_size - 2;
+ if (max_salt_size < 0)
+ return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
+ }
if (salt_size < digest_size)
salt_size = digest_size;
- if (salt_size > max_salt_size)
+ if (salt_size > (unsigned)max_salt_size)
salt_size = max_salt_size;
return salt_size;
diff --git a/lib/pk.h b/lib/pk.h
index 7ff76d12df..a6eb043333 100644
--- a/lib/pk.h
+++ b/lib/pk.h
@@ -104,7 +104,7 @@ int pk_hash_data(gnutls_pk_algorithm_t pk, const mac_entry_st * hash,
gnutls_pk_params_st * params, const gnutls_datum_t * data,
gnutls_datum_t * digest);
-unsigned _gnutls_find_rsa_pss_salt_size(unsigned bits, const mac_entry_st *me,
- unsigned salt_size);
+int _gnutls_find_rsa_pss_salt_size(unsigned bits, const mac_entry_st *me,
+ unsigned salt_size);
#endif /* GNUTLS_PK_H */
diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h
index 3ba9c55013..2b0b07ad2d 100644
--- a/lib/pkcs11_int.h
+++ b/lib/pkcs11_int.h
@@ -64,6 +64,7 @@ struct gnutls_pkcs11_obj_st {
struct gnutls_pkcs11_privkey_st {
gnutls_pk_algorithm_t pk_algorithm;
unsigned int rsa_pss_ok; /* if it is an RSA key, it can do RSA-PSS */
+ unsigned int bits;
unsigned int flags;
struct p11_kit_uri *uinfo;
diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c
index fd1997c8cc..48e4836ab2 100644
--- a/lib/pkcs11_privkey.c
+++ b/lib/pkcs11_privkey.c
@@ -156,7 +156,7 @@ gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,
unsigned int *bits)
{
if (bits)
- *bits = 0; /* FIXME */
+ *bits = key->bits;
return key->pk_algorithm;
}
@@ -567,7 +567,6 @@ gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
a[0].type = CKA_KEY_TYPE;
a[0].value = &key_type;
a[0].value_len = sizeof(key_type);
-
if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
== CKR_OK) {
pkey->pk_algorithm = key_type_to_pk(key_type);
@@ -580,7 +579,16 @@ gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
goto cleanup;
}
+
if (pkey->pk_algorithm == GNUTLS_PK_RSA) { /* determine whether it can do rsa-pss */
+ a[0].type = CKA_MODULUS;
+ a[0].value = NULL;
+ a[0].value_len = 0;
+ if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
+ == CKR_OK) {
+ pkey->bits = a[0].value_len*8;
+ }
+
ret = gnutls_pkcs11_token_check_mechanism(url, CKM_RSA_PKCS_PSS, NULL, 0, 0);
if (ret != 0)
pkey->rsa_pss_ok = 1;
diff --git a/lib/privkey.c b/lib/privkey.c
index 6c1a52ee30..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();
@@ -333,6 +334,7 @@ _gnutls_privkey_update_spki_params(gnutls_privkey_t key,
if (pk == GNUTLS_PK_RSA_PSS) {
const mac_entry_st *me;
+ int ret;
me = hash_to_entry(dig);
if (unlikely(me == NULL))
@@ -350,8 +352,12 @@ _gnutls_privkey_update_spki_params(gnutls_privkey_t key,
if (flags & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE)
params->salt_size = 0;
- else
- params->salt_size = _gnutls_find_rsa_pss_salt_size(bits, me, salt_size);
+ else {
+ ret = _gnutls_find_rsa_pss_salt_size(bits, me, salt_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ params->salt_size = ret;
+ }
params->rsa_pss_dig = dig;
}
@@ -811,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.
@@ -854,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/lib/pubkey.c b/lib/pubkey.c
index a53122f68a..466e2dee63 100644
--- a/lib/pubkey.c
+++ b/lib/pubkey.c
@@ -1527,7 +1527,7 @@ int fixup_spki_params(const gnutls_pk_params_st *key_params, const gnutls_sign_e
}
if (params->pk == GNUTLS_PK_RSA_PSS) {
-
+ int ret;
if (!GNUTLS_PK_IS_RSA(key_params->algo))
return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR);
@@ -1537,7 +1537,11 @@ int fixup_spki_params(const gnutls_pk_params_st *key_params, const gnutls_sign_e
if (key_params->algo == GNUTLS_PK_RSA || params->rsa_pss_dig == 0) {
bits = pubkey_to_bits(key_params);
params->rsa_pss_dig = se->hash;
- params->salt_size = _gnutls_find_rsa_pss_salt_size(bits, me, 0);
+ ret = _gnutls_find_rsa_pss_salt_size(bits, me, 0);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ params->salt_size = ret;
}
if (params->rsa_pss_dig != se->hash)
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index ac58529f6f..417d630405 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -3052,9 +3052,14 @@ gnutls_x509_crq_set_spki(gnutls_x509_crq_t crq,
/* If salt size is zero, find the optimal salt size. */
if (spki->salt_size == 0) {
- tpki.salt_size =
+ ret =
_gnutls_find_rsa_pss_salt_size(bits, me,
spki->salt_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ tpki.salt_size = ret;
} else
tpki.salt_size = spki->salt_size;
} else if (crq_pk == GNUTLS_PK_RSA_PSS) {
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index badeb945df..d4be99ef05 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -1682,8 +1682,13 @@ gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key,
goto cleanup;
}
- key->params.spki.salt_size =
- _gnutls_find_rsa_pss_salt_size(bits, me, 0);
+ ret = _gnutls_find_rsa_pss_salt_size(bits, me, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ key->params.spki.salt_size = ret;
}
ret = _gnutls_pk_generate_keys(algo, bits, &key->params, 0);
diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c
index 6d5ed6a52e..db90dab9c4 100644
--- a/lib/x509/x509_write.c
+++ b/lib/x509/x509_write.c
@@ -2080,9 +2080,13 @@ gnutls_x509_crt_set_spki(gnutls_x509_crt_t crt,
/* If salt size is zero, find the optimal salt size. */
if (spki->salt_size == 0) {
- tpki.salt_size =
- _gnutls_find_rsa_pss_salt_size(bits, me,
+ ret = _gnutls_find_rsa_pss_salt_size(bits, me,
spki->salt_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ tpki.salt_size = ret;
} else
tpki.salt_size = spki->salt_size;
} else if (crt_pk == GNUTLS_PK_RSA_PSS) {
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;