diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/abstract_int.h | 4 | ||||
-rw-r--r-- | lib/algorithms.h | 1 | ||||
-rw-r--r-- | lib/algorithms/sign.c | 22 | ||||
-rw-r--r-- | lib/crypto-backend.h | 7 | ||||
-rw-r--r-- | lib/nettle/pk.c | 6 | ||||
-rw-r--r-- | lib/privkey.c | 28 | ||||
-rw-r--r-- | lib/pubkey.c | 72 | ||||
-rw-r--r-- | lib/x509/common.c | 2 | ||||
-rw-r--r-- | lib/x509/crq.c | 28 | ||||
-rw-r--r-- | lib/x509/key_decode.c | 4 | ||||
-rw-r--r-- | lib/x509/key_encode.c | 2 | ||||
-rw-r--r-- | lib/x509/mpi.c | 100 | ||||
-rw-r--r-- | lib/x509/output.c | 8 | ||||
-rw-r--r-- | lib/x509/pkcs7.c | 28 | ||||
-rw-r--r-- | lib/x509/privkey.c | 8 | ||||
-rw-r--r-- | lib/x509/sign.c | 21 | ||||
-rw-r--r-- | lib/x509/spki.c | 14 | ||||
-rw-r--r-- | lib/x509/verify.c | 17 | ||||
-rw-r--r-- | lib/x509/x509.c | 4 | ||||
-rw-r--r-- | lib/x509/x509_int.h | 37 | ||||
-rw-r--r-- | lib/x509/x509_write.c | 10 |
21 files changed, 251 insertions, 172 deletions
diff --git a/lib/abstract_int.h b/lib/abstract_int.h index 2fefa2cf37..6197f00896 100644 --- a/lib/abstract_int.h +++ b/lib/abstract_int.h @@ -70,9 +70,9 @@ struct gnutls_pubkey_st { int _gnutls_privkey_get_public_mpis(gnutls_privkey_t key, gnutls_pk_params_st *); -int _gnutls_privkey_get_sign_params(gnutls_privkey_t key, +int _gnutls_privkey_get_spki_params(gnutls_privkey_t key, gnutls_x509_spki_st * params); -int _gnutls_privkey_update_sign_params(gnutls_privkey_t key, +int _gnutls_privkey_update_spki_params(gnutls_privkey_t key, gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t dig, unsigned flags, diff --git a/lib/algorithms.h b/lib/algorithms.h index 631675462e..ca137a83ac 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -322,6 +322,7 @@ 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); +const gnutls_sign_entry_st *_gnutls_oid_to_sign_entry(const char *oid); 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 eca76fa487..65fa432dee 100644 --- a/lib/algorithms/sign.c +++ b/lib/algorithms/sign.c @@ -254,6 +254,16 @@ gnutls_sign_algorithm_t gnutls_sign_get_id(const char *name) } +const gnutls_sign_entry_st *_gnutls_oid_to_sign_entry(const char *oid) +{ + GNUTLS_SIGN_LOOP( + if (p->oid && strcmp(oid, p->oid) == 0) { + return p; + } + ); + return NULL; +} + /** * gnutls_oid_to_sign: * @oid: is an object identifier @@ -267,18 +277,14 @@ gnutls_sign_algorithm_t gnutls_sign_get_id(const char *name) **/ gnutls_sign_algorithm_t gnutls_oid_to_sign(const char *oid) { - gnutls_sign_algorithm_t ret = 0; + const gnutls_sign_entry_st *se; - GNUTLS_SIGN_LOOP( - if (p->oid && strcmp(oid, p->oid) == 0) { - ret = p->id; break;} - ); - - if (ret == 0) { + se = _gnutls_oid_to_sign_entry(oid); + if (se == NULL) { _gnutls_debug_log("Unknown SIGN OID: '%s'\n", oid); return GNUTLS_SIGN_UNKNOWN; } - return ret; + return se->id; } const gnutls_sign_entry_st *_gnutls_pk_to_sign_entry(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash) diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h index 07b23cb0f1..9a7c527a0f 100644 --- a/lib/crypto-backend.h +++ b/lib/crypto-backend.h @@ -166,8 +166,13 @@ typedef struct gnutls_crypto_bigint { /* additional information about the public key */ typedef struct gnutls_x509_spki_st { + /* We can have a key which is of type RSA, but a certificate + * of type RSA-PSS; the value here will be the expected value + * for signatures (i.e., RSA-PSS) */ gnutls_pk_algorithm_t pk; - gnutls_digest_algorithm_t dig; + + /* the digest used by RSA-PSS */ + gnutls_digest_algorithm_t rsa_pss_dig; /* the size of salt used by RSA-PSS */ unsigned int salt_size; diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index c2ad4efd30..e69ccb09c9 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -756,7 +756,7 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, mpz_init(s); ret = - _rsa_pss_sign_digest_tr(sign_params->dig, + _rsa_pss_sign_digest_tr(sign_params->rsa_pss_dig, &pub, &priv, NULL, rnd_nonce_func, sign_params->salt_size, @@ -1014,7 +1014,7 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo, goto cleanup; } - ret = _rsa_pss_verify_digest(sign_params->dig, + ret = _rsa_pss_verify_digest(sign_params->rsa_pss_dig, &pub, sign_params->salt_size, vdata->data, vdata->size, @@ -1475,7 +1475,7 @@ char* gen_data = NULL; ddata.data = (void*)gen_data; ddata.size = hash_len; } else if (algo == GNUTLS_PK_RSA_PSS) { - switch (params->sign.dig) { + switch (params->sign.rsa_pss_dig) { case GNUTLS_DIG_SHA256: ddata.data = (void*)const_data_sha256; ddata.size = sizeof(const_data_sha256); diff --git a/lib/privkey.c b/lib/privkey.c index 911829de16..8786501b11 100644 --- a/lib/privkey.c +++ b/lib/privkey.c @@ -274,7 +274,7 @@ _gnutls_privkey_get_public_mpis(gnutls_privkey_t key, /* This function retrieves default sign parameters from KEY. */ int -_gnutls_privkey_get_sign_params(gnutls_privkey_t key, +_gnutls_privkey_get_spki_params(gnutls_privkey_t key, gnutls_x509_spki_st * params) { switch (key->type) { @@ -285,7 +285,7 @@ _gnutls_privkey_get_sign_params(gnutls_privkey_t key, case GNUTLS_PRIVKEY_EXT: break; case GNUTLS_PRIVKEY_X509: - return _gnutls_x509_privkey_get_sign_params(key->key.x509, + return _gnutls_x509_privkey_get_spki_params(key->key.x509, params); default: gnutls_assert(); @@ -299,9 +299,9 @@ _gnutls_privkey_get_sign_params(gnutls_privkey_t key, /* This function fills in PARAMS with the necessary parameters to sign * with PK and DIG. PARAMS must be initialized with - * _gnutls_privkey_get_sign_params in advance. */ + * _gnutls_privkey_get_spki_params in advance. */ int -_gnutls_privkey_update_sign_params(gnutls_privkey_t key, +_gnutls_privkey_update_spki_params(gnutls_privkey_t key, gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t dig, unsigned flags, @@ -342,7 +342,7 @@ _gnutls_privkey_update_sign_params(gnutls_privkey_t key, if (params->pk == GNUTLS_PK_RSA) salt_size = 0; else if (params->pk == GNUTLS_PK_RSA_PSS) { - if (dig != params->dig) { + if (dig != params->rsa_pss_dig) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } @@ -365,7 +365,7 @@ _gnutls_privkey_update_sign_params(gnutls_privkey_t key, } params->pk = pk; - params->dig = dig; + params->rsa_pss_dig = dig; return 0; } @@ -995,13 +995,13 @@ gnutls_privkey_sign_data(gnutls_privkey_t signer, if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - ret = _gnutls_privkey_get_sign_params(signer, ¶ms); + ret = _gnutls_privkey_get_spki_params(signer, ¶ms); if (ret < 0) { gnutls_assert(); return ret; } - ret = _gnutls_privkey_update_sign_params(signer, signer->pk_algorithm, + ret = _gnutls_privkey_update_spki_params(signer, signer->pk_algorithm, hash, flags, ¶ms); if (ret < 0) { gnutls_assert(); @@ -1047,13 +1047,13 @@ gnutls_privkey_sign_data2(gnutls_privkey_t signer, if (e == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - ret = _gnutls_privkey_get_sign_params(signer, ¶ms); + ret = _gnutls_privkey_get_spki_params(signer, ¶ms); if (ret < 0) { gnutls_assert(); return ret; } - ret = _gnutls_privkey_update_sign_params(signer, e->pk, e->hash, + ret = _gnutls_privkey_update_spki_params(signer, e->pk, e->hash, flags, ¶ms); if (ret < 0) { gnutls_assert(); @@ -1106,13 +1106,13 @@ gnutls_privkey_sign_hash2(gnutls_privkey_t signer, if (se == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - ret = _gnutls_privkey_get_sign_params(signer, ¶ms); + ret = _gnutls_privkey_get_spki_params(signer, ¶ms); if (ret < 0) { gnutls_assert(); return ret; } - ret = _gnutls_privkey_update_sign_params(signer, se->pk, se->hash, + ret = _gnutls_privkey_update_spki_params(signer, se->pk, se->hash, flags, ¶ms); if (ret < 0) { gnutls_assert(); @@ -1210,13 +1210,13 @@ gnutls_privkey_sign_hash(gnutls_privkey_t signer, int ret; gnutls_x509_spki_st params; - ret = _gnutls_privkey_get_sign_params(signer, ¶ms); + ret = _gnutls_privkey_get_spki_params(signer, ¶ms); if (ret < 0) { gnutls_assert(); return ret; } - ret = _gnutls_privkey_update_sign_params(signer, signer->pk_algorithm, + ret = _gnutls_privkey_update_spki_params(signer, signer->pk_algorithm, hash_algo, flags, ¶ms); if (ret < 0) { gnutls_assert(); diff --git a/lib/pubkey.c b/lib/pubkey.c index 0b16f28fba..f2d26319c1 100644 --- a/lib/pubkey.c +++ b/lib/pubkey.c @@ -1,6 +1,7 @@ /* * GnuTLS public key support * Copyright (C) 2010-2012 Free Software Foundation, Inc. + * Copyright (C) 2017 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -1514,6 +1515,7 @@ gnutls_pubkey_verify_data2(gnutls_pubkey_t pubkey, int ret; const mac_entry_st *me; gnutls_x509_spki_st params; + const gnutls_sign_entry_st *se; if (pubkey == NULL) { gnutls_assert(); @@ -1525,17 +1527,20 @@ gnutls_pubkey_verify_data2(gnutls_pubkey_t pubkey, memcpy(¶ms, &pubkey->params.sign, sizeof(gnutls_x509_spki_st)); - params.pk = gnutls_sign_get_pk_algorithm(algo); - params.dig = gnutls_sign_get_hash_algorithm(algo); - me = hash_to_entry(params.dig); - if (me == NULL && !_gnutls_pk_is_not_prehashed(params.pk)) + se = _gnutls_sign_to_entry(algo); + if (se == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + params.pk = se->pk; - if (params.pk != pubkey->pk_algorithm) { + me = hash_to_entry(se->hash); + if (me == NULL && !_gnutls_pk_is_not_prehashed(se->pk)) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if (se->pk != pubkey->pk_algorithm) { if (!gnutls_sign_supports_pk_algorithm(algo, pubkey->pk_algorithm)) { _gnutls_debug_log("have key: %s/%d, with sign %s/%d\n", gnutls_pk_get_name(pubkey->pk_algorithm), pubkey->pk_algorithm, - gnutls_sign_get_name(algo), algo); + se->name, algo); return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY); } } @@ -1551,6 +1556,7 @@ gnutls_pubkey_verify_data2(gnutls_pubkey_t pubkey, * it with the same way as gnutls_privkey_sign*. */ if (pubkey->pk_algorithm == GNUTLS_PK_RSA) { gnutls_pubkey_get_pk_algorithm(pubkey, &bits); + params.rsa_pss_dig = se->hash; params.salt_size = _gnutls_find_rsa_pss_salt_size(bits, me, 0); } } @@ -1599,6 +1605,7 @@ gnutls_pubkey_verify_hash2(gnutls_pubkey_t key, { const mac_entry_st *me; gnutls_x509_spki_st params; + const gnutls_sign_entry_st *se; int ret; if (key == NULL) { @@ -1619,27 +1626,32 @@ gnutls_pubkey_verify_hash2(gnutls_pubkey_t key, /* we do not check for insecure algorithms with this flag */ return _gnutls_pk_verify(params.pk, hash, signature, &key->params, ¶ms); + } else if (algo == GNUTLS_SIGN_UNKNOWN) { + params.pk = key->pk_algorithm; + me = NULL; } else { - if (algo == GNUTLS_SIGN_UNKNOWN) { - params.pk = key->pk_algorithm; - me = NULL; - } else { - params.pk = gnutls_sign_get_pk_algorithm(algo); - params.dig = gnutls_sign_get_hash_algorithm(algo); - - me = hash_to_entry(params.dig); - - if (params.pk != key->pk_algorithm) { - if (!gnutls_sign_supports_pk_algorithm(algo, key->pk_algorithm)) { - _gnutls_debug_log("have key: %s/%d, with sign %s/%d\n", - gnutls_pk_get_name(key->pk_algorithm), key->pk_algorithm, - gnutls_sign_get_name(algo), algo); - return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY); - } + se = _gnutls_sign_to_entry(algo); + if (se == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + params.pk = se->pk; + + if (params.pk != key->pk_algorithm) { + if (!gnutls_sign_supports_pk_algorithm(algo, key->pk_algorithm)) { + _gnutls_debug_log("have key: %s/%d, with sign %s/%d\n", + gnutls_pk_get_name(key->pk_algorithm), key->pk_algorithm, + se->name, algo); + return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY); } } + me = hash_to_entry(se->hash); + if (me == NULL && !_gnutls_pk_is_not_prehashed(se->pk)) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + if (params.pk == GNUTLS_PK_RSA_PSS) { + params.rsa_pss_dig = se->hash; + /* The requested sign algorithm is RSA-PSS, while the * pubkey doesn't include parameter information */ if (key->pk_algorithm == GNUTLS_PK_RSA) { @@ -1649,15 +1661,15 @@ gnutls_pubkey_verify_hash2(gnutls_pubkey_t key, _gnutls_find_rsa_pss_salt_size(key->bits, me, 0); } } + } - ret = pubkey_verify_hashed_data(params.pk, me, - hash, signature, - &key->params, - ¶ms); - if (ret < 0) { - gnutls_assert(); - return ret; - } + ret = pubkey_verify_hashed_data(params.pk, me, + hash, signature, + &key->params, + ¶ms); + if (ret < 0) { + gnutls_assert(); + return ret; } if (algo != GNUTLS_SIGN_UNKNOWN && gnutls_sign_is_secure(algo) == 0 && _gnutls_is_broken_sig_allowed(algo, flags) == 0) { diff --git a/lib/x509/common.c b/lib/x509/common.c index b1be062c54..bd78b24b35 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -1285,7 +1285,7 @@ _gnutls_x509_get_signature_algorithm(ASN1_TYPE src, const char *src_name) _gnutls_free_datum(&der); if (result == 0) - result = gnutls_pk_to_sign(params.pk, params.dig); + result = gnutls_pk_to_sign(params.pk, params.rsa_pss_dig); else if (result == GNUTLS_E_UNKNOWN_ALGORITHM) result = GNUTLS_SIGN_UNKNOWN; } else { diff --git a/lib/x509/crq.c b/lib/x509/crq.c index fc90e3296d..8fa172ac14 100644 --- a/lib/x509/crq.c +++ b/lib/x509/crq.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2003-2016 Free Software Foundation, Inc. * Copyright (C) 2012-2016 Nikos Mavrogiannopoulos + * Copyright (C) 2016-2017 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -1325,13 +1326,13 @@ gnutls_x509_crq_get_pk_algorithm2(gnutls_x509_crq_t crq, spki->pk = result; - result = _gnutls_x509_crq_read_sign_params(crq, ¶ms); + result = _gnutls_x509_crq_read_spki_params(crq, ¶ms); if (result < 0) { gnutls_assert(); return result; } - spki->dig = params.dig; + spki->rsa_pss_dig = params.rsa_pss_dig; spki->salt_size = params.salt_size; return spki->pk; @@ -2822,6 +2823,7 @@ gnutls_x509_crq_privkey_sign(gnutls_x509_crq_t crq, gnutls_privkey_t key, gnutls_datum_t tbs; gnutls_pk_algorithm_t pk; gnutls_x509_spki_st params; + const gnutls_sign_entry_st *se; if (crq == NULL) { gnutls_assert(); @@ -2838,14 +2840,14 @@ gnutls_x509_crq_privkey_sign(gnutls_x509_crq_t crq, gnutls_privkey_t key, } } - result = _gnutls_privkey_get_sign_params(key, ¶ms); + result = _gnutls_privkey_get_spki_params(key, ¶ms); if (result < 0) { gnutls_assert(); return result; } pk = gnutls_privkey_get_pk_algorithm(key, NULL); - result = _gnutls_privkey_update_sign_params(key, pk, dig, 0, ¶ms); + result = _gnutls_privkey_update_spki_params(key, pk, dig, 0, ¶ms); if (result < 0) { gnutls_assert(); return result; @@ -2862,7 +2864,11 @@ gnutls_x509_crq_privkey_sign(gnutls_x509_crq_t crq, gnutls_privkey_t key, return result; } - result = privkey_sign_and_hash_data(key, _gnutls_pk_to_sign_entry(params.pk, dig), + se = _gnutls_pk_to_sign_entry(params.pk, dig); + if (se == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + result = privkey_sign_and_hash_data(key, se, &tbs, &signature, ¶ms); gnutls_free(tbs.data); @@ -2888,7 +2894,7 @@ gnutls_x509_crq_privkey_sign(gnutls_x509_crq_t crq, gnutls_privkey_t key, */ result = _gnutls_x509_write_sign_params(crq->crq, "signatureAlgorithm", - ¶ms); + se, ¶ms); if (result < 0) { gnutls_assert(); return result; @@ -3244,7 +3250,7 @@ gnutls_x509_crq_set_pk_algorithm(gnutls_x509_crq_t crq, if (crq_pk == GNUTLS_PK_RSA) { const mac_entry_st *me; - me = hash_to_entry(spki->dig); + me = hash_to_entry(spki->rsa_pss_dig); if (unlikely(me == NULL)) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; @@ -3252,7 +3258,7 @@ gnutls_x509_crq_set_pk_algorithm(gnutls_x509_crq_t crq, memset(¶ms, 0, sizeof(gnutls_x509_spki_st)); params.pk = spki->pk; - params.dig = spki->dig; + params.rsa_pss_dig = spki->rsa_pss_dig; /* If salt size is zero, find the optimal salt size. */ if (spki->salt_size == 0) { @@ -3262,13 +3268,13 @@ gnutls_x509_crq_set_pk_algorithm(gnutls_x509_crq_t crq, } else params.salt_size = spki->salt_size; } else if (crq_pk == GNUTLS_PK_RSA_PSS) { - result = _gnutls_x509_crq_read_sign_params(crq, ¶ms); + result = _gnutls_x509_crq_read_spki_params(crq, ¶ms); if (result < 0) { gnutls_assert(); return result; } - if (params.dig != spki->dig || + if (params.rsa_pss_dig != spki->rsa_pss_dig || params.salt_size > spki->salt_size) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; @@ -3277,7 +3283,7 @@ gnutls_x509_crq_set_pk_algorithm(gnutls_x509_crq_t crq, params.salt_size = spki->salt_size; } - result = _gnutls_x509_write_sign_params(crq->crq, + result = _gnutls_x509_write_spki_params(crq->crq, "certificationRequestInfo." "subjectPKInfo." "algorithm", diff --git a/lib/x509/key_decode.c b/lib/x509/key_decode.c index a9b59d125b..7e9d05a887 100644 --- a/lib/x509/key_decode.c +++ b/lib/x509/key_decode.c @@ -346,7 +346,7 @@ _gnutls_x509_read_rsa_pss_params(uint8_t * der, int dersize, memset(params, 0, sizeof(gnutls_x509_spki_st)); params->pk = GNUTLS_PK_RSA_PSS; - params->dig = digest; + params->rsa_pss_dig = digest; result = _gnutls_x509_read_uint(spk, "saltLength", ¶ms->salt_size); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND || @@ -451,7 +451,7 @@ int _gnutls_x509_check_pubkey_params(gnutls_pk_algorithm_t algo, switch (algo) { case GNUTLS_PK_RSA_PSS: { unsigned bits = pubkey_to_bits(algo, params); - const mac_entry_st *me = hash_to_entry(params->sign.dig); + const mac_entry_st *me = hash_to_entry(params->sign.rsa_pss_dig); size_t hash_size; if (unlikely(me == NULL)) diff --git a/lib/x509/key_encode.c b/lib/x509/key_encode.c index 58b1362c58..c1072cf08f 100644 --- a/lib/x509/key_encode.c +++ b/lib/x509/key_encode.c @@ -344,7 +344,7 @@ _gnutls_x509_write_rsa_pss_params(gnutls_x509_spki_st *params, goto cleanup; } - oid = gnutls_digest_get_oid(params->dig); + oid = gnutls_digest_get_oid(params->rsa_pss_dig); if ((result = asn1_write_value(spk, "hashAlgorithm.algorithm", oid, 1)) != ASN1_SUCCESS) { diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c index 1f562229e3..9b3ded189e 100644 --- a/lib/x509/mpi.c +++ b/lib/x509/mpi.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003-2012 Free Software Foundation, Inc. + * Copyright (C) 2015-2017 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -260,65 +261,27 @@ _gnutls_x509_read_sign_params(ASN1_TYPE src, const char *src_name, return result; } else { + const gnutls_sign_entry_st *se; + memset(params, 0, sizeof(gnutls_x509_spki_st)); - result = gnutls_oid_to_sign(oid); - if (result != GNUTLS_SIGN_UNKNOWN) { - params->pk = gnutls_sign_get_pk_algorithm(result); - params->dig = gnutls_sign_get_hash_algorithm(result); + se = _gnutls_oid_to_sign_entry(oid); + if (se != NULL) { + params->pk = se->pk; } } return 0; } -int -_gnutls_x509_crt_read_sign_params(gnutls_x509_crt_t crt, - gnutls_x509_spki_st *params) -{ - return _gnutls_x509_read_sign_params(crt->cert, - "tbsCertificate." - "subjectPublicKeyInfo." - "algorithm", - params); -} - -int -_gnutls_x509_crq_read_sign_params(gnutls_x509_crq_t crt, - gnutls_x509_spki_st *params) -{ - return _gnutls_x509_read_sign_params(crt->crq, - "certificationRequestInfo." - "subjectPKInfo." - "algorithm", - params); -} - -int -_gnutls_x509_write_sign_params(ASN1_TYPE dst, const char *dst_name, - gnutls_x509_spki_st *params) +static int write_oid_and_params(ASN1_TYPE dst, const char *dst_name, const char *oid, gnutls_x509_spki_st *params) { int result; char name[128]; - const char *oid; _gnutls_str_cpy(name, sizeof(name), dst_name); _gnutls_str_cat(name, sizeof(name), ".algorithm"); - if (params->legacy && params->pk == GNUTLS_PK_RSA) - oid = PK_PKIX1_RSA_OID; - else if (params->pk == GNUTLS_PK_RSA_PSS) - oid = PK_PKIX1_RSA_PSS_OID; - else - oid = gnutls_sign_get_oid(gnutls_pk_to_sign(params->pk, - params->dig)); - if (oid == NULL) { - gnutls_assert(); - _gnutls_debug_log - ("Cannot find OID for sign algorithm pk: %d dig: %d\n", - (int) params->pk, (int) params->dig); - return GNUTLS_E_INVALID_REQUEST; - } /* write the OID. */ @@ -328,7 +291,6 @@ _gnutls_x509_write_sign_params(ASN1_TYPE dst, const char *dst_name, return _gnutls_asn2err(result); } - _gnutls_str_cpy(name, sizeof(name), dst_name); _gnutls_str_cat(name, sizeof(name), ".parameters"); @@ -363,6 +325,54 @@ _gnutls_x509_write_sign_params(ASN1_TYPE dst, const char *dst_name, return 0; } +int +_gnutls_x509_write_spki_params(ASN1_TYPE dst, const char *dst_name, + gnutls_x509_spki_st *params) +{ + const char *oid; + + if (params->legacy && params->pk == GNUTLS_PK_RSA) + oid = PK_PKIX1_RSA_OID; + else if (params->pk == GNUTLS_PK_RSA_PSS) + oid = PK_PKIX1_RSA_PSS_OID; + else + oid = gnutls_pk_get_oid(params->pk); + + if (oid == NULL) { + gnutls_assert(); + _gnutls_debug_log + ("Cannot find OID for public key algorithm %s\n", + gnutls_pk_get_name(params->pk)); + return GNUTLS_E_INVALID_REQUEST; + } + + return write_oid_and_params(dst, dst_name, oid, params); +} + +int +_gnutls_x509_write_sign_params(ASN1_TYPE dst, const char *dst_name, + const gnutls_sign_entry_st *se, gnutls_x509_spki_st *params) +{ + const char *oid; + + if (params->legacy && params->pk == GNUTLS_PK_RSA) + oid = PK_PKIX1_RSA_OID; + else if (params->pk == GNUTLS_PK_RSA_PSS) + oid = PK_PKIX1_RSA_PSS_OID; + else + oid = se->oid; + + if (oid == NULL) { + gnutls_assert(); + _gnutls_debug_log + ("Cannot find OID for sign algorithm %s\n", + se->name); + return GNUTLS_E_INVALID_REQUEST; + } + + return write_oid_and_params(dst, dst_name, oid, params); +} + /* this function reads a (small) unsigned integer * from asn1 structs. Combines the read and the convertion * steps. diff --git a/lib/x509/output.c b/lib/x509/output.c index ac652fee18..7e1cc18f15 100644 --- a/lib/x509/output.c +++ b/lib/x509/output.c @@ -1440,12 +1440,12 @@ print_crt_pubkey_params(gnutls_buffer_st * str, const char *key_name, pk = ret; if (pk == GNUTLS_PK_RSA_PSS) { - ret = _gnutls_x509_crt_read_sign_params(crt, ¶ms); + ret = _gnutls_x509_crt_read_spki_params(crt, ¶ms); if (ret < 0) return ret; addf(str, _("\t%sPublic Key Parameters:\n"), key_name); addf(str, "\t\tHash Algorithm: %s\n", - gnutls_digest_get_name(params.dig)); + gnutls_digest_get_name(params.rsa_pss_dig)); addf(str, "\t\tSalt Length: %d\n", params.salt_size); } @@ -2385,12 +2385,12 @@ print_crq_pubkey_params(gnutls_buffer_st * str, const char *key_name, pk = ret; if (pk == GNUTLS_PK_RSA_PSS) { - ret = _gnutls_x509_crq_read_sign_params(crt, ¶ms); + ret = _gnutls_x509_crq_read_spki_params(crt, ¶ms); if (ret < 0) return ret; addf(str, _("\t%sPublic Key Parameters:\n"), key_name); addf(str, "\t\tHash Algorithm: %s\n", - gnutls_digest_get_name(params.dig)); + gnutls_digest_get_name(params.rsa_pss_dig)); addf(str, "\t\tSalt Length: %d\n", params.salt_size); } diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c index 4bb8d863a8..b22a1cf65b 100644 --- a/lib/x509/pkcs7.c +++ b/lib/x509/pkcs7.c @@ -2349,6 +2349,7 @@ int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7, const mac_entry_st *me = hash_to_entry(dig); unsigned pk, sigalgo; gnutls_x509_spki_st key_params, params; + const gnutls_sign_entry_st *se; if (pkcs7 == NULL || me == NULL) return GNUTLS_E_INVALID_REQUEST; @@ -2486,23 +2487,29 @@ int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7, /* write the signature algorithm */ pk = gnutls_x509_crt_get_pk_algorithm(signer, NULL); - ret = _gnutls_privkey_get_sign_params(signer_key, &key_params); + ret = _gnutls_privkey_get_spki_params(signer_key, &key_params); if (ret < 0) { gnutls_assert(); goto cleanup; } - ret = _gnutls_x509_crt_get_sign_params(signer, &key_params, ¶ms); + ret = _gnutls_x509_crt_get_spki_params(signer, &key_params, ¶ms); if (ret < 0) { gnutls_assert(); goto cleanup; } - result = _gnutls_privkey_update_sign_params(signer_key, pk, dig, 0, + ret = _gnutls_privkey_update_spki_params(signer_key, pk, dig, 0, ¶ms); - if (result < 0) { + if (ret < 0) { gnutls_assert(); - return result; + goto cleanup; + } + + se = _gnutls_pk_to_sign_entry(params.pk, dig); + if (se == NULL) { + ret = gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM); + goto cleanup; } /* RFC5652 is silent on what the values would be and initially I assumed that @@ -2514,18 +2521,13 @@ int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7, ret = _gnutls_x509_write_sign_params(pkcs7->signed_data, "signerInfos.?LAST.signatureAlgorithm", - ¶ms); + se, ¶ms); if (ret < 0) { gnutls_assert(); goto cleanup; } - sigalgo = gnutls_pk_to_sign(pk, dig); - if (sigalgo == GNUTLS_SIGN_UNKNOWN) { - gnutls_assert(); - ret = GNUTLS_E_INVALID_REQUEST; - goto cleanup; - } + sigalgo = se->id; /* sign the data */ ret = @@ -2536,7 +2538,7 @@ int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7, goto cleanup; } - ret = privkey_sign_and_hash_data(signer_key, _gnutls_pk_to_sign_entry(params.pk, dig), + ret = privkey_sign_and_hash_data(signer_key, se, &sigdata, &signature, ¶ms); if (ret < 0) { gnutls_assert(); diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index b4af486dfc..23bc50a152 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -1629,11 +1629,11 @@ gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key, key->params.sign.pk = GNUTLS_PK_RSA_PSS; if (key->params.palgo != GNUTLS_DIG_UNKNOWN) - key->params.sign.dig = key->params.palgo; + key->params.sign.rsa_pss_dig = key->params.palgo; else - key->params.sign.dig = GNUTLS_DIG_SHA256; + key->params.sign.rsa_pss_dig = GNUTLS_DIG_SHA256; - me = hash_to_entry(key->params.sign.dig); + me = hash_to_entry(key->params.sign.rsa_pss_dig); if (unlikely(me == NULL)) { gnutls_assert(); ret = GNUTLS_E_INVALID_REQUEST; @@ -2157,7 +2157,7 @@ void gnutls_x509_privkey_set_flags(gnutls_x509_privkey_t key, } int -_gnutls_x509_privkey_get_sign_params(gnutls_x509_privkey_t key, +_gnutls_x509_privkey_get_spki_params(gnutls_x509_privkey_t key, gnutls_x509_spki_st *params) { memcpy(params, &key->params.sign, sizeof(gnutls_x509_spki_st)); diff --git a/lib/x509/sign.c b/lib/x509/sign.c index 8a00d77411..343b6eb969 100644 --- a/lib/x509/sign.c +++ b/lib/x509/sign.c @@ -50,14 +50,14 @@ _gnutls_x509_get_tbs(ASN1_TYPE cert, const char *tbs_name, } int -_gnutls_x509_crt_get_sign_params(gnutls_x509_crt_t crt, +_gnutls_x509_crt_get_spki_params(gnutls_x509_crt_t crt, const gnutls_x509_spki_st *key_params, gnutls_x509_spki_st *params) { int result; gnutls_x509_spki_st crt_params; - result = _gnutls_x509_crt_read_sign_params(crt, &crt_params); + result = _gnutls_x509_crt_read_spki_params(crt, &crt_params); if (result < 0) { gnutls_assert(); return result; @@ -65,7 +65,7 @@ _gnutls_x509_crt_get_sign_params(gnutls_x509_crt_t crt, if (crt_params.pk == GNUTLS_PK_RSA_PSS) { if (key_params->pk == GNUTLS_PK_RSA_PSS) { - if (crt_params.dig != key_params->dig) { + if (crt_params.rsa_pss_dig != key_params->rsa_pss_dig) { gnutls_assert(); return GNUTLS_E_CERTIFICATE_ERROR; } @@ -117,19 +117,19 @@ _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name, if (pk == GNUTLS_PK_UNKNOWN) pk = gnutls_privkey_get_pk_algorithm(issuer_key, NULL); - result = _gnutls_privkey_get_sign_params(issuer_key, &key_params); + result = _gnutls_privkey_get_spki_params(issuer_key, &key_params); if (result < 0) { gnutls_assert(); return result; } - result = _gnutls_x509_crt_get_sign_params(issuer, &key_params, ¶ms); + result = _gnutls_x509_crt_get_spki_params(issuer, &key_params, ¶ms); if (result < 0) { gnutls_assert(); return result; } - result = _gnutls_privkey_update_sign_params(issuer_key, pk, dig, flags, + result = _gnutls_privkey_update_spki_params(issuer_key, pk, dig, flags, ¶ms); if (result < 0) { gnutls_assert(); @@ -154,7 +154,11 @@ _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name, _gnutls_str_cpy(name, sizeof(name), src_name); _gnutls_str_cat(name, sizeof(name), ".signature"); - result = _gnutls_x509_write_sign_params(src, name, ¶ms); + se = _gnutls_pk_to_sign_entry(params.pk, dig); + if (se == NULL) + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM); + + result = _gnutls_x509_write_sign_params(src, name, se, ¶ms); if (result < 0) { gnutls_assert(); return result; @@ -169,7 +173,6 @@ _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name, return result; } - 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 { @@ -201,7 +204,7 @@ _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name, */ result = _gnutls_x509_write_sign_params(src, "signatureAlgorithm", - ¶ms); + se, ¶ms); if (result < 0) { gnutls_assert(); return result; diff --git a/lib/x509/spki.c b/lib/x509/spki.c index af94ea4a2a..ea4814a448 100644 --- a/lib/x509/spki.c +++ b/lib/x509/spki.c @@ -113,10 +113,12 @@ gnutls_x509_spki_get_pk_algorithm(gnutls_x509_spki_t spki) /** * gnutls_x509_spki_set_digest_algorithm: * @spki: the SubjectPublicKeyInfo structure - * @dig: the digest algorithm of type #gnutls_digest_algorithm_t + * @dig: a digest algorithm of type #gnutls_digest_algorithm_t * * This function will set the digest algorithm of a - * SubjectPublicKeyInfo structure. + * SubjectPublicKeyInfo structure. This is relevant for + * RSA-PSS signatures which store the digest algorithm + * in the SubjectPublicKeyInfo. * * Since: 3.6.0 * @@ -125,7 +127,7 @@ void gnutls_x509_spki_set_digest_algorithm(gnutls_x509_spki_t spki, gnutls_digest_algorithm_t dig) { - spki->dig = dig; + spki->rsa_pss_dig = dig; } /** @@ -133,7 +135,9 @@ gnutls_x509_spki_set_digest_algorithm(gnutls_x509_spki_t spki, * @spki: the SubjectPublicKeyInfo structure * * This function will get the digest algorithm of a - * SubjectPublicKeyInfo structure. + * SubjectPublicKeyInfo structure. This is relevant for + * RSA-PSS signatures which store the digest algorithm + * in the SubjectPublicKeyInfo. * * Returns: a member of the #gnutls_digest_algorithm_t enumeration on * success, or a %GNUTLS_DIG_UNKNOWN on error. @@ -144,7 +148,7 @@ gnutls_x509_spki_set_digest_algorithm(gnutls_x509_spki_t spki, int gnutls_x509_spki_get_digest_algorithm(gnutls_x509_spki_t spki) { - return spki->dig; + return spki->rsa_pss_dig; } /** diff --git a/lib/x509/verify.c b/lib/x509/verify.c index 002fac6f2a..0b8760254a 100644 --- a/lib/x509/verify.c +++ b/lib/x509/verify.c @@ -1295,7 +1295,7 @@ _gnutls_x509_validate_sign_params(gnutls_pk_algorithm_t pk_algorithm, } } else { /* Check if the underlying hash algorithms are same. */ - if (sig_params->dig != params.dig) { + if (sig_params->rsa_pss_dig != params.rsa_pss_dig) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } @@ -1330,6 +1330,7 @@ _gnutls_x509_verify_data(gnutls_sign_algorithm_t sign, int ret; gnutls_x509_spki_st sign_params; const mac_entry_st * me; + const gnutls_sign_entry_st *se; /* Read the MPI parameters from the issuer's certificate. */ @@ -1341,6 +1342,10 @@ _gnutls_x509_verify_data(gnutls_sign_algorithm_t sign, issuer_pk = gnutls_x509_crt_get_pk_algorithm(issuer, NULL); + se = _gnutls_sign_to_entry(sign); + if (se == NULL) + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM); + if (cert != NULL) { ret = _gnutls_x509_read_sign_params(cert->cert, "signatureAlgorithm", @@ -1363,18 +1368,20 @@ _gnutls_x509_verify_data(gnutls_sign_algorithm_t sign, } else { memcpy(&sign_params, ¶ms.sign, sizeof(gnutls_x509_spki_st)); - sign_params.pk = gnutls_sign_get_pk_algorithm(sign); - sign_params.dig = gnutls_sign_get_hash_algorithm(sign); + + sign_params.pk = se->pk; + if (sign_params.pk == GNUTLS_PK_RSA_PSS) + sign_params.rsa_pss_dig = se->hash; } - me = hash_to_entry(sign_params.dig); + me = hash_to_entry(se->hash); if (unlikely(me == NULL)) { gnutls_assert(); ret = GNUTLS_E_CERTIFICATE_ERROR; goto cleanup; } - ret = pubkey_verify_data(sign_params.pk, me, data, signature, ¶ms, + ret = pubkey_verify_data(se->pk, me, data, signature, ¶ms, &sign_params); if (ret < 0) { gnutls_assert(); diff --git a/lib/x509/x509.c b/lib/x509/x509.c index f779cd97b4..073e7fcdbb 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -1605,13 +1605,13 @@ gnutls_x509_crt_get_pk_algorithm2(gnutls_x509_crt_t cert, spki->pk = result; - result = _gnutls_x509_crt_read_sign_params(cert, ¶ms); + result = _gnutls_x509_crt_read_spki_params(cert, ¶ms); if (result < 0) { gnutls_assert(); return result; } - spki->dig = params.dig; + spki->rsa_pss_dig = params.rsa_pss_dig; spki->salt_size = params.salt_size; return spki->pk; diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index 6160a50e0c..2d7e881997 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2003-2012 Free Software Foundation, Inc. + * Copyright (C) 2017 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -159,7 +160,7 @@ int _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name, unsigned int flags, gnutls_x509_crt_t issuer, gnutls_privkey_t issuer_key); -int _gnutls_x509_crt_get_sign_params(gnutls_x509_crt_t issuer, +int _gnutls_x509_crt_get_spki_params(gnutls_x509_crt_t issuer, const gnutls_x509_spki_st *key_params, gnutls_x509_spki_st *params); @@ -256,7 +257,7 @@ _gnutls_x509_read_ecc_params(uint8_t * der, int dersize, int _gnutls_asn1_encode_privkey(gnutls_pk_algorithm_t pk, ASN1_TYPE * c2, gnutls_pk_params_st * params, unsigned compat); -int _gnutls_x509_privkey_get_sign_params(gnutls_x509_privkey_t key, +int _gnutls_x509_privkey_get_spki_params(gnutls_x509_privkey_t key, gnutls_x509_spki_st * params); int _gnutls_x509_read_rsa_pss_params(uint8_t * der, int dersize, @@ -324,11 +325,6 @@ int _gnutls_x509_crq_get_mpis(gnutls_x509_crq_t cert, int _gnutls_x509_crt_get_mpis(gnutls_x509_crt_t cert, gnutls_pk_params_st * params); -int _gnutls_x509_crt_read_sign_params(gnutls_x509_crt_t crt, - gnutls_x509_spki_st *params); -int _gnutls_x509_crq_read_sign_params(gnutls_x509_crq_t crt, - gnutls_x509_spki_st *params); - int _gnutls_x509_read_pubkey_params(gnutls_pk_algorithm_t, uint8_t * der, int dersize, gnutls_pk_params_st * params); @@ -381,8 +377,35 @@ int _gnutls_x509_write_key_int(ASN1_TYPE node, const char *value, bigint_t mpi, int _gnutls_x509_read_sign_params(ASN1_TYPE src, const char *src_name, gnutls_x509_spki_st *params); int _gnutls_x509_write_sign_params(ASN1_TYPE dst, const char *dst_name, + const gnutls_sign_entry_st *se, gnutls_x509_spki_st *params); + +#define _gnutls_x509_read_spki_params _gnutls_x509_read_sign_params +int _gnutls_x509_write_spki_params(ASN1_TYPE dst, const char *dst_name, gnutls_x509_spki_st *params); +inline static int +_gnutls_x509_crt_read_spki_params(gnutls_x509_crt_t crt, + gnutls_x509_spki_st *params) +{ + return _gnutls_x509_read_spki_params(crt->cert, + "tbsCertificate." + "subjectPublicKeyInfo." + "algorithm", + params); +} + +inline static int +_gnutls_x509_crq_read_spki_params(gnutls_x509_crq_t crt, + gnutls_x509_spki_st *params) +{ + return _gnutls_x509_read_spki_params(crt->crq, + "certificationRequestInfo." + "subjectPKInfo." + "algorithm", + params); +} + + /* pkcs12.h */ #include <gnutls/pkcs12.h> diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c index da12905c71..cd72204b7b 100644 --- a/lib/x509/x509_write.c +++ b/lib/x509/x509_write.c @@ -2043,7 +2043,7 @@ gnutls_x509_crt_set_pk_algorithm(gnutls_x509_crt_t crt, if (crt_pk == GNUTLS_PK_RSA) { const mac_entry_st *me; - me = hash_to_entry(spki->dig); + me = hash_to_entry(spki->rsa_pss_dig); if (unlikely(me == NULL)) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; @@ -2051,7 +2051,7 @@ gnutls_x509_crt_set_pk_algorithm(gnutls_x509_crt_t crt, memset(¶ms, 0, sizeof(gnutls_x509_spki_st)); params.pk = spki->pk; - params.dig = spki->dig; + params.rsa_pss_dig = spki->rsa_pss_dig; /* If salt size is zero, find the optimal salt size. */ if (spki->salt_size == 0) { @@ -2061,13 +2061,13 @@ gnutls_x509_crt_set_pk_algorithm(gnutls_x509_crt_t crt, } else params.salt_size = spki->salt_size; } else if (crt_pk == GNUTLS_PK_RSA_PSS) { - result = _gnutls_x509_crt_read_sign_params(crt, ¶ms); + result = _gnutls_x509_crt_read_spki_params(crt, ¶ms); if (result < 0) { gnutls_assert(); return result; } - if (params.dig != spki->dig || + if (params.rsa_pss_dig != spki->rsa_pss_dig || params.salt_size > spki->salt_size) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; @@ -2078,7 +2078,7 @@ gnutls_x509_crt_set_pk_algorithm(gnutls_x509_crt_t crt, MODIFIED(crt); - result = _gnutls_x509_write_sign_params(crt->cert, + result = _gnutls_x509_write_spki_params(crt->cert, "tbsCertificate." "subjectPublicKeyInfo.algorithm", ¶ms); |