diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2018-03-03 15:28:08 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2018-03-03 15:28:08 +0000 |
commit | c8d7f94b1a9dab8b97b3277eed8a052adcb89689 (patch) | |
tree | a8503d518e418e774eef46450239606d25942826 | |
parent | 8bc71dc0ed272c10b6430a678858b8e973828cf8 (diff) | |
parent | 991b9daffd32e470372479f49a75f1bd83209e91 (diff) | |
download | gnutls-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.h | 1 | ||||
-rw-r--r-- | lib/includes/gnutls/abstract.h | 3 | ||||
-rw-r--r-- | lib/pk.c | 18 | ||||
-rw-r--r-- | lib/pk.h | 4 | ||||
-rw-r--r-- | lib/pkcs11_int.h | 1 | ||||
-rw-r--r-- | lib/pkcs11_privkey.c | 12 | ||||
-rw-r--r-- | lib/privkey.c | 21 | ||||
-rw-r--r-- | lib/pubkey.c | 8 | ||||
-rw-r--r-- | lib/x509/crq.c | 7 | ||||
-rw-r--r-- | lib/x509/privkey.c | 9 | ||||
-rw-r--r-- | lib/x509/x509_write.c | 8 | ||||
-rw-r--r-- | tests/sign-verify-ext4.c | 5 | ||||
-rw-r--r-- | tests/tls-neg-ext4-key.c | 5 |
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); @@ -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; @@ -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; |