diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2017-07-21 23:56:20 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-08-03 11:57:52 +0200 |
commit | 7ee95dc1c31133f6dde92f4b104359061bfeb700 (patch) | |
tree | cc8af8a792328db8813f51257c2626590a974194 /lib | |
parent | 7b1f0ab57a596fc2bde709ecf5a2c56f69593b5a (diff) | |
download | gnutls-7ee95dc1c31133f6dde92f4b104359061bfeb700.tar.gz |
Pass the signature algorithm lower in the verification stack
This will allow enhancing the back-ends (PKCS#11 and ext) for
signing with the new signature algorithms like RSA-PSS and Ed25519.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/abstract_int.h | 8 | ||||
-rw-r--r-- | lib/algorithms.h | 1 | ||||
-rw-r--r-- | lib/algorithms/sign.c | 25 | ||||
-rw-r--r-- | lib/privkey.c | 77 | ||||
-rw-r--r-- | lib/x509/crq.c | 3 | ||||
-rw-r--r-- | lib/x509/pkcs7.c | 3 | ||||
-rw-r--r-- | lib/x509/sign.c | 9 |
7 files changed, 76 insertions, 50 deletions
diff --git a/lib/abstract_int.h b/lib/abstract_int.h index f82e4f922a..2fefa2cf37 100644 --- a/lib/abstract_int.h +++ b/lib/abstract_int.h @@ -81,14 +81,16 @@ int _gnutls_privkey_update_sign_params(gnutls_privkey_t key, void _gnutls_privkey_cleanup(gnutls_privkey_t key); int privkey_sign_and_hash_data(gnutls_privkey_t signer, + const gnutls_sign_entry_st *se, const gnutls_datum_t * data, gnutls_datum_t * signature, gnutls_x509_spki_st *params); int privkey_sign_raw_data(gnutls_privkey_t key, - const gnutls_datum_t * data, - gnutls_datum_t * signature, - gnutls_x509_spki_st * params); + const gnutls_sign_entry_st *se, + const gnutls_datum_t * data, + gnutls_datum_t * signature, + gnutls_x509_spki_st * params); unsigned pubkey_to_bits(gnutls_pk_algorithm_t pk, gnutls_pk_params_st * params); int _gnutls_pubkey_compatible_with_sig(gnutls_session_t, diff --git a/lib/algorithms.h b/lib/algorithms.h index 97404ec8c1..631675462e 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -321,6 +321,7 @@ struct gnutls_sign_entry_st { typedef struct gnutls_sign_entry_st gnutls_sign_entry_st; const gnutls_sign_entry_st *_gnutls_sign_to_entry(gnutls_sign_algorithm_t sign); +const gnutls_sign_entry_st *_gnutls_pk_to_sign_entry(gnutls_pk_algorithm_t, gnutls_digest_algorithm_t); gnutls_pk_algorithm_t _gnutls_x509_sign_to_pk(gnutls_sign_algorithm_t sign); diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c index 062d926fcf..eca76fa487 100644 --- a/lib/algorithms/sign.c +++ b/lib/algorithms/sign.c @@ -281,6 +281,17 @@ gnutls_sign_algorithm_t gnutls_oid_to_sign(const char *oid) return ret; } +const gnutls_sign_entry_st *_gnutls_pk_to_sign_entry(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash) +{ + GNUTLS_SIGN_LOOP( + if (pk == p->pk && hash == p->hash) { + return p; + } + ); + + return NULL; +} + /** * gnutls_pk_to_sign: * @pk: is a public key algorithm @@ -294,18 +305,12 @@ gnutls_sign_algorithm_t gnutls_oid_to_sign(const char *oid) gnutls_sign_algorithm_t gnutls_pk_to_sign(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash) { - gnutls_sign_algorithm_t ret = 0; + const gnutls_sign_entry_st *e; - GNUTLS_SIGN_LOOP( - if (pk == p->pk && hash == p->hash) { - ret = p->id; - break; - } - ); - - if (ret == 0) + e = _gnutls_pk_to_sign_entry(pk, hash); + if (e == NULL) return GNUTLS_SIGN_UNKNOWN; - return ret; + return e->id; } /** diff --git a/lib/privkey.c b/lib/privkey.c index e026ca4895..911829de16 100644 --- a/lib/privkey.c +++ b/lib/privkey.c @@ -39,9 +39,10 @@ static int privkey_sign_prehashed(gnutls_privkey_t signer, - const gnutls_datum_t * hash_data, - gnutls_datum_t * signature, - gnutls_x509_spki_st * params, unsigned flags); + const gnutls_sign_entry_st *se, + const gnutls_datum_t * hash_data, + gnutls_datum_t * signature, + gnutls_x509_spki_st * params, unsigned flags); /** * gnutls_privkey_get_type: @@ -1007,7 +1008,7 @@ gnutls_privkey_sign_data(gnutls_privkey_t signer, return ret; } - return privkey_sign_and_hash_data(signer, data, signature, ¶ms); + return privkey_sign_and_hash_data(signer, _gnutls_pk_to_sign_entry(params.pk, hash), data, signature, ¶ms); } /** @@ -1059,7 +1060,7 @@ gnutls_privkey_sign_data2(gnutls_privkey_t signer, return ret; } - return privkey_sign_and_hash_data(signer, data, signature, ¶ms); + return privkey_sign_and_hash_data(signer, _gnutls_sign_to_entry(algo), data, signature, ¶ms); } /** @@ -1099,10 +1100,10 @@ gnutls_privkey_sign_hash2(gnutls_privkey_t signer, { int ret; gnutls_x509_spki_st params; - const gnutls_sign_entry_st *e; + const gnutls_sign_entry_st *se; - e = _gnutls_sign_to_entry(algo); - if (e == NULL) + se = _gnutls_sign_to_entry(algo); + if (se == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); ret = _gnutls_privkey_get_sign_params(signer, ¶ms); @@ -1111,18 +1112,19 @@ gnutls_privkey_sign_hash2(gnutls_privkey_t signer, return ret; } - ret = _gnutls_privkey_update_sign_params(signer, e->pk, e->hash, + ret = _gnutls_privkey_update_sign_params(signer, se->pk, se->hash, flags, ¶ms); if (ret < 0) { gnutls_assert(); return ret; } - return privkey_sign_prehashed(signer, hash_data, signature, ¶ms, flags); + return privkey_sign_prehashed(signer, se, hash_data, signature, ¶ms, flags); } int privkey_sign_and_hash_data(gnutls_privkey_t signer, + const gnutls_sign_entry_st *se, const gnutls_datum_t * data, gnutls_datum_t * signature, gnutls_x509_spki_st * params) @@ -1131,34 +1133,30 @@ privkey_sign_and_hash_data(gnutls_privkey_t signer, gnutls_datum_t digest; const mac_entry_st *me; - if (_gnutls_pk_is_not_prehashed(signer->pk_algorithm)) { - if (params->dig != GNUTLS_DIG_UNKNOWN && - gnutls_pk_to_sign(params->pk, params->dig) == GNUTLS_SIGN_UNKNOWN) - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + if (se == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - return privkey_sign_raw_data(signer, data, signature, params); + if (_gnutls_pk_is_not_prehashed(se->pk)) { + return privkey_sign_raw_data(signer, se, data, signature, params); } - if (gnutls_pk_to_sign(params->pk, params->dig) == GNUTLS_SIGN_UNKNOWN) - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - - me = hash_to_entry(params->dig); + me = hash_to_entry(se->hash); if (me == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - ret = pk_hash_data(params->pk, me, NULL, data, &digest); + ret = pk_hash_data(se->pk, me, NULL, data, &digest); if (ret < 0) { gnutls_assert(); return ret; } - ret = pk_prepare_hash(params->pk, me, &digest); + ret = pk_prepare_hash(se->pk, me, &digest); if (ret < 0) { gnutls_assert(); goto cleanup; } - ret = privkey_sign_raw_data(signer, &digest, signature, params); + ret = privkey_sign_raw_data(signer, se, &digest, signature, params); _gnutls_free_datum(&digest); if (ret < 0) { @@ -1225,21 +1223,24 @@ gnutls_privkey_sign_hash(gnutls_privkey_t signer, return ret; } - return privkey_sign_prehashed(signer, hash_data, signature, ¶ms, flags); + return privkey_sign_prehashed(signer, _gnutls_pk_to_sign_entry(params.pk, hash_algo), + hash_data, signature, ¶ms, flags); } static int privkey_sign_prehashed(gnutls_privkey_t signer, - const gnutls_datum_t * hash_data, - gnutls_datum_t * signature, - gnutls_x509_spki_st * params, - unsigned flags) + const gnutls_sign_entry_st *se, + const gnutls_datum_t * hash_data, + gnutls_datum_t * signature, + gnutls_x509_spki_st * params, + unsigned flags) { int ret; gnutls_datum_t digest; if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA) return privkey_sign_raw_data(signer, + se, hash_data, signature, params); @@ -1247,6 +1248,9 @@ privkey_sign_prehashed(gnutls_privkey_t signer, return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } + if (se == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + digest.data = gnutls_malloc(hash_data->size); if (digest.data == NULL) { gnutls_assert(); @@ -1255,13 +1259,14 @@ privkey_sign_prehashed(gnutls_privkey_t signer, digest.size = hash_data->size; memcpy(digest.data, hash_data->data, digest.size); - ret = pk_prepare_hash(params->pk, hash_to_entry(params->dig), &digest); + ret = pk_prepare_hash(se->pk, hash_to_entry(se->hash), &digest); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = privkey_sign_raw_data(signer, + se, &digest, signature, params); if (ret < 0) { @@ -1299,10 +1304,18 @@ privkey_sign_prehashed(gnutls_privkey_t signer, -*/ int privkey_sign_raw_data(gnutls_privkey_t key, - const gnutls_datum_t * data, - gnutls_datum_t * signature, - gnutls_x509_spki_st * params) + const gnutls_sign_entry_st *se, + const gnutls_datum_t * data, + gnutls_datum_t * signature, + gnutls_x509_spki_st * params) { + gnutls_pk_algorithm_t pk; + + if (se == NULL) /* it can be null when signing raw-rsa */ + pk = params->pk; + else + pk = se->pk; + switch (key->type) { #ifdef ENABLE_PKCS11 case GNUTLS_PRIVKEY_PKCS11: @@ -1310,7 +1323,7 @@ privkey_sign_raw_data(gnutls_privkey_t key, data, signature); #endif case GNUTLS_PRIVKEY_X509: - return _gnutls_pk_sign(params->pk, signature, data, + return _gnutls_pk_sign(pk, signature, data, &key->key.x509->params, params); case GNUTLS_PRIVKEY_EXT: if (key->key.ext.sign_func == NULL) diff --git a/lib/x509/crq.c b/lib/x509/crq.c index 0f91278b4e..fc90e3296d 100644 --- a/lib/x509/crq.c +++ b/lib/x509/crq.c @@ -2862,7 +2862,8 @@ gnutls_x509_crq_privkey_sign(gnutls_x509_crq_t crq, gnutls_privkey_t key, return result; } - result = privkey_sign_and_hash_data(key, &tbs, &signature, ¶ms); + result = privkey_sign_and_hash_data(key, _gnutls_pk_to_sign_entry(params.pk, dig), + &tbs, &signature, ¶ms); gnutls_free(tbs.data); if (result < 0) { diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c index c0b0810b0c..4bb8d863a8 100644 --- a/lib/x509/pkcs7.c +++ b/lib/x509/pkcs7.c @@ -2536,7 +2536,8 @@ int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7, goto cleanup; } - ret = privkey_sign_and_hash_data(signer_key, &sigdata, &signature, ¶ms); + ret = privkey_sign_and_hash_data(signer_key, _gnutls_pk_to_sign_entry(params.pk, dig), + &sigdata, &signature, ¶ms); if (ret < 0) { gnutls_assert(); goto cleanup; diff --git a/lib/x509/sign.c b/lib/x509/sign.c index dd688ea9ab..8a00d77411 100644 --- a/lib/x509/sign.c +++ b/lib/x509/sign.c @@ -111,6 +111,7 @@ _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name, char name[128]; gnutls_pk_algorithm_t pk; gnutls_x509_spki_st key_params, params; + const gnutls_sign_entry_st *se; pk = gnutls_x509_crt_get_pk_algorithm(issuer, NULL); if (pk == GNUTLS_PK_UNKNOWN) @@ -168,10 +169,12 @@ _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name, return result; } - if (_gnutls_pk_is_not_prehashed(issuer_key->pk_algorithm)) { - result = privkey_sign_raw_data(issuer_key, &tbs, &signature, ¶ms); + se = _gnutls_pk_to_sign_entry(params.pk, dig); + if (_gnutls_pk_is_not_prehashed(params.pk)) { + result = privkey_sign_raw_data(issuer_key, se, &tbs, &signature, ¶ms); } else { - result = privkey_sign_and_hash_data(issuer_key, &tbs, &signature, ¶ms); + result = privkey_sign_and_hash_data(issuer_key, se, + &tbs, &signature, ¶ms); } gnutls_free(tbs.data); |