diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2019-10-23 15:04:58 +0000 |
---|---|---|
committer | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2019-10-23 15:04:58 +0000 |
commit | 69390cc8a09fcb4167a995e570c7d2163264f4c2 (patch) | |
tree | 9673bf07e1c35b565062acc66e3e317c561fcdb9 | |
parent | d4eaf6da6d7c3a1f11a43d9fcb11904e7dc7df3d (diff) | |
parent | 3f4470b193b7de1c85ee6f4868faf08d3b0671dc (diff) | |
download | gnutls-69390cc8a09fcb4167a995e570c7d2163264f4c2.tar.gz |
Merge branch 'new-crt-vrfy' into 'master'
Split CertVerify code. Switch sign_entry_st to use flags
See merge request gnutls/gnutls!1103
-rw-r--r-- | lib/algorithms.h | 4 | ||||
-rw-r--r-- | lib/algorithms/sign.c | 22 | ||||
-rw-r--r-- | lib/ext/signature.c | 2 | ||||
-rw-r--r-- | lib/tls-sig.c | 184 | ||||
-rw-r--r-- | lib/tls13-sig.c | 4 |
5 files changed, 126 insertions, 90 deletions
diff --git a/lib/algorithms.h b/lib/algorithms.h index 7f27b2270d..84271e53b8 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -337,6 +337,7 @@ unsigned _gnutls_digest_is_insecure(gnutls_digest_algorithm_t dig); int _gnutls_version_mark_disabled(const char *name); gnutls_protocol_t _gnutls_protocol_get_id_if_supported(const char *name); +#define GNUTLS_SIGN_FLAG_TLS13_OK 1 /* if it is ok to use under TLS1.3 */ struct gnutls_sign_entry_st { const char *name; const char *oid; @@ -353,8 +354,7 @@ struct gnutls_sign_entry_st { gnutls_pk_algorithm_t priv_pk; gnutls_pk_algorithm_t cert_pk; - /* non-zero if it is ok to use under TLS1.3 */ - unsigned tls13_ok; + unsigned flags; /* if this signature algorithm is restricted to a curve * under TLS 1.3. */ diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c index 05bd88e3b8..6e4393b5dc 100644 --- a/lib/algorithms/sign.c +++ b/lib/algorithms/sign.c @@ -68,7 +68,7 @@ gnutls_sign_entry_st sign_algorithms[] = { .pk = GNUTLS_PK_RSA_PSS, .priv_pk = GNUTLS_PK_RSA, /* PKCS#11 doesn't separate RSA from RSA-PSS privkeys */ .hash = GNUTLS_DIG_SHA256, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{8, 9}, SIG_SEM_DEFAULT}}, {.name = "RSA-PSS-RSAE-SHA256", .oid = PK_PKIX1_RSA_PSS_OID, @@ -77,7 +77,7 @@ gnutls_sign_entry_st sign_algorithms[] = { .cert_pk = GNUTLS_PK_RSA, .priv_pk = GNUTLS_PK_RSA, .hash = GNUTLS_DIG_SHA256, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{8, 4}, SIG_SEM_DEFAULT}}, {.name = "RSA-PSS-SHA384", .oid = PK_PKIX1_RSA_PSS_OID, @@ -85,7 +85,7 @@ gnutls_sign_entry_st sign_algorithms[] = { .pk = GNUTLS_PK_RSA_PSS, .priv_pk = GNUTLS_PK_RSA, .hash = GNUTLS_DIG_SHA384, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{8, 0x0A}, SIG_SEM_DEFAULT}}, {.name = "RSA-PSS-RSAE-SHA384", .oid = PK_PKIX1_RSA_PSS_OID, @@ -94,7 +94,7 @@ gnutls_sign_entry_st sign_algorithms[] = { .cert_pk = GNUTLS_PK_RSA, .priv_pk = GNUTLS_PK_RSA, .hash = GNUTLS_DIG_SHA384, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{8, 5}, SIG_SEM_DEFAULT}}, {.name = "RSA-PSS-SHA512", .oid = PK_PKIX1_RSA_PSS_OID, @@ -102,7 +102,7 @@ gnutls_sign_entry_st sign_algorithms[] = { .pk = GNUTLS_PK_RSA_PSS, .priv_pk = GNUTLS_PK_RSA, .hash = GNUTLS_DIG_SHA512, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{8, 0x0B}, SIG_SEM_DEFAULT}}, {.name = "RSA-PSS-RSAE-SHA512", .oid = PK_PKIX1_RSA_PSS_OID, @@ -111,7 +111,7 @@ gnutls_sign_entry_st sign_algorithms[] = { .cert_pk = GNUTLS_PK_RSA, .priv_pk = GNUTLS_PK_RSA, .hash = GNUTLS_DIG_SHA512, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{8, 6}, SIG_SEM_DEFAULT}}, /* Ed25519: The hash algorithm here is set to be SHA512, although that is @@ -122,7 +122,7 @@ gnutls_sign_entry_st sign_algorithms[] = { .id = GNUTLS_SIGN_EDDSA_ED25519, .pk = GNUTLS_PK_EDDSA_ED25519, .hash = GNUTLS_DIG_SHA512, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{8, 7}, SIG_SEM_DEFAULT}}, /* ECDSA */ @@ -159,21 +159,21 @@ gnutls_sign_entry_st sign_algorithms[] = { .pk = GNUTLS_PK_ECDSA, .curve = GNUTLS_ECC_CURVE_SECP256R1, .hash = GNUTLS_DIG_SHA256, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{4, 3}, SIG_SEM_TLS13}}, {.name = "ECDSA-SECP384R1-SHA384", .id = GNUTLS_SIGN_ECDSA_SECP384R1_SHA384, .pk = GNUTLS_PK_ECDSA, .curve = GNUTLS_ECC_CURVE_SECP384R1, .hash = GNUTLS_DIG_SHA384, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{5, 3}, SIG_SEM_TLS13}}, {.name = "ECDSA-SECP521R1-SHA512", .id = GNUTLS_SIGN_ECDSA_SECP521R1_SHA512, .pk = GNUTLS_PK_ECDSA, .curve = GNUTLS_ECC_CURVE_SECP521R1, .hash = GNUTLS_DIG_SHA512, - .tls13_ok = 1, + .flags = GNUTLS_SIGN_FLAG_TLS13_OK, .aid = {{6, 3}, SIG_SEM_TLS13}}, /* ECDSA-SHA3 */ @@ -763,7 +763,7 @@ const gnutls_sign_entry_st * _gnutls13_sign_get_compatible_with_privkey(gnutls_privkey_t privkey) { GNUTLS_SIGN_LOOP( - if (p->tls13_ok && + if ((p->flags & GNUTLS_SIGN_FLAG_TLS13_OK) && _gnutls_privkey_compatible_with_sig(privkey, p->id)) { return p; } diff --git a/lib/ext/signature.c b/lib/ext/signature.c index 28d88c5bfc..8dba4c6ca7 100644 --- a/lib/ext/signature.c +++ b/lib/ext/signature.c @@ -361,7 +361,7 @@ _gnutls_session_sign_algo_enabled(gnutls_session_t session, const gnutls_sign_entry_st *se; se = _gnutls_sign_to_entry(sig); - if (se == NULL || (se->tls13_ok == 0)) { + if (se == NULL || (se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0) { gnutls_assert(); goto disallowed; } diff --git a/lib/tls-sig.c b/lib/tls-sig.c index 66897502a5..aebd0b1e3f 100644 --- a/lib/tls-sig.c +++ b/lib/tls-sig.c @@ -470,6 +470,54 @@ _gnutls_handshake_verify_crt_vrfy3(gnutls_session_t session, } #endif +static int +_gnutls_handshake_verify_crt_vrfy10(gnutls_session_t session, + unsigned verify_flags, + gnutls_pcert_st * cert, + gnutls_datum_t * signature, + gnutls_sign_algorithm_t sign_algo) +{ + int ret; + uint8_t concat[MAX_SIG_SIZE]; + digest_hd_st td_sha; + gnutls_datum_t dconcat; + gnutls_pk_algorithm_t pk_algo; + const mac_entry_st *me; + + /* TLS 1.0 and TLS 1.1 */ + pk_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL); + if (pk_algo == GNUTLS_PK_RSA) { + me = hash_to_entry(GNUTLS_DIG_MD5_SHA1); + verify_flags |= GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA; + sign_algo = GNUTLS_SIGN_UNKNOWN; + } else { + me = hash_to_entry(GNUTLS_DIG_SHA1); + sign_algo = gnutls_pk_to_sign(pk_algo, GNUTLS_DIG_SHA1); + } + ret = _gnutls_hash_init(&td_sha, me); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + _gnutls_hash(&td_sha, + session->internals.handshake_hash_buffer.data, + session->internals.handshake_hash_buffer_prev_len); + + _gnutls_hash_deinit(&td_sha, concat); + + dconcat.data = concat; + dconcat.size = _gnutls_hash_get_algo_len(me); + + ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo, + GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1|verify_flags, + &dconcat, signature); + if (ret < 0) + gnutls_assert(); + + return ret; +} + /* Verifies a TLS signature (like the one in the client certificate * verify message). */ @@ -481,12 +529,7 @@ _gnutls_handshake_verify_crt_vrfy(gnutls_session_t session, gnutls_sign_algorithm_t sign_algo) { int ret; - uint8_t concat[MAX_SIG_SIZE]; - digest_hd_st td_sha; - gnutls_datum_t dconcat; const version_entry_st *ver = get_version(session); - gnutls_pk_algorithm_t pk_algo; - const mac_entry_st *me; unsigned key_usage; if (cert == NULL) { @@ -526,37 +569,11 @@ _gnutls_handshake_verify_crt_vrfy(gnutls_session_t session, #endif /* TLS 1.0 and TLS 1.1 */ - pk_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL); - if (pk_algo == GNUTLS_PK_RSA) { - me = hash_to_entry(GNUTLS_DIG_MD5_SHA1); - verify_flags |= GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA; - sign_algo = GNUTLS_SIGN_UNKNOWN; - } else { - me = hash_to_entry(GNUTLS_DIG_SHA1); - sign_algo = gnutls_pk_to_sign(pk_algo, GNUTLS_DIG_SHA1); - } - ret = _gnutls_hash_init(&td_sha, me); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - _gnutls_hash(&td_sha, - session->internals.handshake_hash_buffer.data, - session->internals.handshake_hash_buffer_prev_len); - - _gnutls_hash_deinit(&td_sha, concat); - - dconcat.data = concat; - dconcat.size = _gnutls_hash_get_algo_len(me); - - ret = gnutls_pubkey_verify_hash2(cert->pubkey, sign_algo, - GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1|verify_flags, - &dconcat, signature); - if (ret < 0) - gnutls_assert(); - - return ret; + return _gnutls_handshake_verify_crt_vrfy10(session, + verify_flags, + cert, + signature, + sign_algo); } /* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2. @@ -603,6 +620,7 @@ _gnutls_handshake_sign_crt_vrfy12(gnutls_session_t session, static int _gnutls_handshake_sign_crt_vrfy3(gnutls_session_t session, gnutls_pcert_st * cert, + const version_entry_st *ver, gnutls_privkey_t pkey, gnutls_datum_t * signature) { @@ -613,6 +631,13 @@ _gnutls_handshake_sign_crt_vrfy3(gnutls_session_t session, gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm(pkey, NULL); + /* ensure 1024 bit DSA keys are used */ + ret = + _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, + GNUTLS_SIGN_UNKNOWN); + if (ret < 0) + return gnutls_assert_val(ret); + ret = _gnutls_generate_master(session, 1); if (ret < 0) { gnutls_assert(); @@ -676,45 +701,20 @@ _gnutls_handshake_sign_crt_vrfy3(gnutls_session_t session, } #endif -/* Generates a signature of all the previous sent packets in the - * handshake procedure. - * 20040227: now it works for SSL 3.0 as well - * 20091031: works for TLS 1.2 too! - * - * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success. - * For TLS1.2 returns the signature algorithm used on success, or a negative error code; - * - * Returns the used signature algorithm, or a negative error code. - */ -int -_gnutls_handshake_sign_crt_vrfy(gnutls_session_t session, - gnutls_pcert_st * cert, - gnutls_privkey_t pkey, - gnutls_datum_t * signature) +static int +_gnutls_handshake_sign_crt_vrfy10(gnutls_session_t session, + gnutls_pcert_st * cert, + const version_entry_st *ver, + gnutls_privkey_t pkey, + gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; uint8_t concat[MAX_SIG_SIZE]; digest_hd_st td_sha; - const version_entry_st *ver = get_version(session); gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm(pkey, NULL); const mac_entry_st *me; - unsigned key_usage = 0; - - if (unlikely(ver == NULL)) - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); - - gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage); - - ret = _gnutls_check_key_usage_for_sig(session, key_usage, 1); - if (ret < 0) - return gnutls_assert_val(ret); - - /* TLS 1.2 */ - if (_gnutls_version_has_selectable_sighash(ver)) - return _gnutls_handshake_sign_crt_vrfy12(session, cert, - pkey, signature); /* ensure 1024 bit DSA keys are used */ ret = @@ -723,13 +723,6 @@ _gnutls_handshake_sign_crt_vrfy(gnutls_session_t session, if (ret < 0) return gnutls_assert_val(ret); - /* TLS 1.1 or earlier */ -#ifdef ENABLE_SSL3 - if (ver->id == GNUTLS_SSL3) - return _gnutls_handshake_sign_crt_vrfy3(session, cert, - pkey, signature); -#endif - if (pk == GNUTLS_PK_RSA) me = hash_to_entry(GNUTLS_DIG_MD5_SHA1); else @@ -760,4 +753,47 @@ _gnutls_handshake_sign_crt_vrfy(gnutls_session_t session, return GNUTLS_SIGN_UNKNOWN; } +/* Generates a signature of all the previous sent packets in the + * handshake procedure. + * 20040227: now it works for SSL 3.0 as well + * 20091031: works for TLS 1.2 too! + * + * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success. + * For TLS1.2 returns the signature algorithm used on success, or a negative error code; + * + * Returns the used signature algorithm, or a negative error code. + */ +int +_gnutls_handshake_sign_crt_vrfy(gnutls_session_t session, + gnutls_pcert_st * cert, + gnutls_privkey_t pkey, + gnutls_datum_t * signature) +{ + int ret; + const version_entry_st *ver = get_version(session); + unsigned key_usage = 0; + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage); + ret = _gnutls_check_key_usage_for_sig(session, key_usage, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + /* TLS 1.2 */ + if (_gnutls_version_has_selectable_sighash(ver)) + return _gnutls_handshake_sign_crt_vrfy12(session, cert, + pkey, signature); + + /* TLS 1.1 or earlier */ +#ifdef ENABLE_SSL3 + if (ver->id == GNUTLS_SSL3) + return _gnutls_handshake_sign_crt_vrfy3(session, cert, ver, + pkey, signature); +#endif + + return _gnutls_handshake_sign_crt_vrfy10(session, cert, ver, + pkey, signature); +} diff --git a/lib/tls13-sig.c b/lib/tls13-sig.c index 61f9d58209..e15d8305e2 100644 --- a/lib/tls13-sig.c +++ b/lib/tls13-sig.c @@ -74,7 +74,7 @@ _gnutls13_handshake_verify_data(gnutls_session_t session, if (ret < 0) return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); - if (se->tls13_ok == 0) /* explicitly prohibited */ + if ((se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0) /* explicitly prohibited */ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage); @@ -152,7 +152,7 @@ _gnutls13_handshake_sign_data(gnutls_session_t session, gnutls_buffer_st buf; uint8_t tmp[MAX_HASH_SIZE]; - if (unlikely(se == NULL || se->tls13_ok == 0)) + if (unlikely(se == NULL || (se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0)) return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); if (unlikely(sign_supports_priv_pk_algorithm(se, pkey->pk_algorithm) == 0)) |