* [PATCH 1/9] cert/key: Add support for EC based certificates @ 2022-07-18 16:02 Denis Kenzior 2022-07-18 16:02 ` [PATCH 2/9] unit: Add basic EC-DSA verification test Denis Kenzior ` (7 more replies) 0 siblings, 8 replies; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 16:02 UTC (permalink / raw) To: ell; +Cc: Denis Kenzior Mostly for use with Elliptic Curve (EC) Digital Signature Algorithm (DSA) based certificates. Other combinations of EC + signature algorithms are also possible. This requires your kernel to be built with CRYPTO_ECDSA support. --- NOTE: At the time this patch was created, kernel had to be patched with the following fix in order for ECDSA support to function properly from userspace: https://lore.kernel.org/linux-crypto/20220715182810.30505-1-denkenz@gmail.com/ ell/cert.c | 18 ++++++++++++++++-- ell/cert.h | 1 + ell/key.c | 1 + ell/key.h | 1 + 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ell/cert.c b/ell/cert.c index 141ea1cec038..a158142445ec 100644 --- a/ell/cert.c +++ b/ell/cert.c @@ -77,7 +77,15 @@ static const struct pkcs1_encryption_oid { } pkcs1_encryption_oids[] = { { /* rsaEncryption */ L_CERT_KEY_RSA, - { 9, { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 } }, + { .asn1_len = 9, .asn1 = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 } + }, + }, + { /* ecPublicKey */ + L_CERT_KEY_ECC, + { .asn1_len = 7, .asn1 = { + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 } + }, }, }; @@ -261,8 +269,14 @@ LIB_EXPORT struct l_key *l_cert_get_pubkey(struct l_cert *cert) return NULL; /* Use kernel's ASN.1 certificate parser to find the key data for us */ - if (cert->pubkey_type == L_CERT_KEY_RSA) + switch (cert->pubkey_type) { + case L_CERT_KEY_RSA: return l_key_new(L_KEY_RSA, cert->asn1, cert->asn1_len); + case L_CERT_KEY_ECC: + return l_key_new(L_KEY_ECC, cert->asn1, cert->asn1_len); + case L_CERT_KEY_UNKNOWN: + break; + } return NULL; } diff --git a/ell/cert.h b/ell/cert.h index 605e427c3d05..f637588e6d66 100644 --- a/ell/cert.h +++ b/ell/cert.h @@ -36,6 +36,7 @@ struct l_certchain; enum l_cert_key_type { L_CERT_KEY_RSA, + L_CERT_KEY_ECC, L_CERT_KEY_UNKNOWN, }; diff --git a/ell/key.c b/ell/key.c index b28bf4dbf085..73f38581f736 100644 --- a/ell/key.c +++ b/ell/key.c @@ -108,6 +108,7 @@ struct l_keyring { static const char * const key_type_names[] = { [L_KEY_RAW] = "user", [L_KEY_RSA] = "asymmetric", + [L_KEY_ECC] = "asymmetric", }; static long kernel_add_key(const char *type, const char *description, diff --git a/ell/key.h b/ell/key.h index d25d09385b6f..f26f7ecb26c3 100644 --- a/ell/key.h +++ b/ell/key.h @@ -45,6 +45,7 @@ enum l_key_feature { enum l_key_type { L_KEY_RAW = 0, L_KEY_RSA, + L_KEY_ECC, }; enum l_keyring_restriction { -- 2.35.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/9] unit: Add basic EC-DSA verification test 2022-07-18 16:02 [PATCH 1/9] cert/key: Add support for EC based certificates Denis Kenzior @ 2022-07-18 16:02 ` Denis Kenzior 2022-07-18 16:02 ` [PATCH 3/9] key: ECDSA data is given in x962 format Denis Kenzior ` (6 subsequent siblings) 7 siblings, 0 replies; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 16:02 UTC (permalink / raw) To: ell; +Cc: Denis Kenzior --- .gitignore | 2 ++ Makefile.am | 39 ++++++++++++++++++++++++++++++++++++++- unit/test-tls.c | 22 +++++++++++++++++++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 346243a8f9c7..76f10aecfdd3 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,8 @@ unit/cert-*.csr unit/cert-*.srl unit/cert-*.crt unit/cert-*.p12 +unit/ec-cert-*.pem +unit/ec-cert-*.csr unit/key-*.dat unit/key-*.h unit/*.log diff --git a/Makefile.am b/Makefile.am index 2bf728bbde7a..e5d7143af236 100644 --- a/Makefile.am +++ b/Makefile.am @@ -219,6 +219,7 @@ cert_tests = unit/test-pem \ cert_files = unit/cert-chain.pem \ unit/cert-entity-int.pem \ unit/cert-server.pem \ + unit/ec-cert-server.pem \ unit/cert-server-key-pkcs8.pem \ unit/cert-client.pem \ unit/cert-client.crt \ @@ -246,6 +247,7 @@ cert_files = unit/cert-chain.pem \ cert_checks = unit/cert-intca \ unit/cert-entity-int \ unit/cert-server \ + unit/ec-cert-server \ unit/cert-client \ unit/cert-no-keyid @@ -417,15 +419,30 @@ false_redirect_openssl = 2>/dev/null unit/cert-ca-key.pem: $(AM_V_GEN)openssl genrsa -out $@ 2048 $($(AM_V_P)_redirect_openssl) +unit/ec-cert-ca-key.pem: + $(AM_V_GEN)openssl ecparam -out $@ -name secp384r1 \ + -genkey $($(AM_V_P)_redirect_openssl) + + unit/cert-ca.pem: unit/cert-ca-key.pem unit/gencerts.cnf $(AM_V_GEN)openssl req -x509 -new -nodes -extensions ca_ext \ -config $(srcdir)/unit/gencerts.cnf \ -subj '/O=International Union of Example Organizations/CN=Certificate issuer guy/emailAddress=ca@mail.example' \ -key $< -sha256 -days 10000 -out $@ +unit/ec-cert-ca.pem: unit/ec-cert-ca-key.pem unit/gencerts.cnf + $(AM_V_GEN)openssl req -x509 -new -nodes -extensions ca_ext \ + -config $(srcdir)/unit/gencerts.cnf \ + -subj '/O=International Union of Example Organizations/CN=Certificate issuer guy/emailAddress=ca@mail.example' \ + -key $< -sha256 -days 10000 -out $@ + unit/cert-server-key.pem: $(AM_V_GEN)openssl genrsa -out $@ $($(AM_V_P)_redirect_openssl) +unit/ec-cert-server-key.pem: + $(AM_V_GEN)openssl ecparam -out $@ -name secp384r1 \ + -genkey $($(AM_V_P)_redirect_openssl) + unit/cert-server-key-pkcs8.pem: unit/cert-server-key.pem $(AM_V_GEN)openssl pkcs8 -topk8 -nocrypt -in $< -out $@ @@ -435,6 +452,12 @@ unit/cert-server.csr: unit/cert-server-key.pem unit/gencerts.cnf -subj '/O=Foo Example Organization/CN=Foo Example Organization/emailAddress=foo@mail.example' \ -key $< -out $@ +unit/ec-cert-server.csr: unit/ec-cert-server-key.pem unit/gencerts.cnf + $(AM_V_GEN)openssl req -new -extensions cert_ext \ + -config $(srcdir)/unit/gencerts.cnf \ + -subj '/O=Foo Example Organization/CN=Foo Example Organization/emailAddress=foo@mail.example' \ + -key $< -out $@ + unit/cert-server.pem: unit/cert-server.csr unit/cert-ca.pem unit/gencerts.cnf $(AM_V_GEN)openssl x509 -req -extensions server_ext \ -extfile $(srcdir)/unit/gencerts.cnf \ @@ -443,9 +466,22 @@ unit/cert-server.pem: unit/cert-server.csr unit/cert-ca.pem unit/gencerts.cnf -CAserial $(builddir)/unit/cert-ca.srl \ -CAcreateserial -sha256 -days 10000 -out $@ $($(AM_V_P)_redirect_openssl) +unit/ec-cert-server.pem: unit/ec-cert-server.csr unit/ec-cert-ca.pem \ + unit/gencerts.cnf + $(AM_V_GEN)openssl x509 -req -extensions server_ext \ + -extfile $(srcdir)/unit/gencerts.cnf \ + -in $< -CA $(builddir)/unit/ec-cert-ca.pem \ + -CAkey $(builddir)/unit/ec-cert-ca-key.pem \ + -CAserial $(builddir)/unit/cert-ca.srl \ + -CAcreateserial -sha256 -days 10000 \ + -out $@ $($(AM_V_P)_redirect_openssl) + unit/cert-server: unit/cert-server.pem unit/cert-ca.pem $(AM_V_GEN)openssl verify -CAfile $(builddir)/unit/cert-ca.pem $< +unit/ec-cert-server: unit/ce-cert-server.pem unit/ce-cert-ca.pem + $(AM_V_GEN)openssl verify -CAfile $(builddir)/unit/ce-cert-ca.pem $< + unit/cert-client-key-pkcs1.pem: $(AM_V_GEN)openssl genrsa -out $@ $($(AM_V_P)_redirect_openssl) @@ -623,7 +659,8 @@ check-local: $(cert_checks) endif clean-local: - -rm -f unit/cert-*.pem unit/cert-*.csr unit/cert-*.srl unit/key-*.dat + -rm -f unit/ec-cert*.pem unit/ec-cert-*.csr \ + unit/cert-*.pem unit/cert-*.csr unit/cert-*.srl unit/key-*.dat maintainer-clean-local: -rm -rf build-aux diff --git a/unit/test-tls.c b/unit/test-tls.c index 7937962cf8a0..aee5b2e36b78 100644 --- a/unit/test-tls.c +++ b/unit/test-tls.c @@ -325,6 +325,24 @@ static void test_certificates(const void *data) l_queue_destroy(twocas, (l_queue_destroy_func_t) l_cert_free); } +static void test_ec_certificates(const void *data) +{ + struct l_queue *cacert; + struct l_certchain *chain; + + cacert = l_pem_load_certificate_list(CERTDIR "ec-cert-ca.pem"); + assert(cacert && !l_queue_isempty(cacert)); + + chain = l_pem_load_certificate_chain(CERTDIR "ec-cert-server.pem"); + assert(chain); + + assert(l_certchain_verify(chain, cacert, NULL)); + assert(l_certchain_verify(chain, NULL, NULL)); + + l_certchain_free(chain); + l_queue_destroy(cacert, (l_queue_destroy_func_t) l_cert_free); +} + struct tls_conn_test { const char *server_cert_path; const char *server_key_path; @@ -948,8 +966,10 @@ int main(int argc, char *argv[]) l_test_add("TLS 1.2 PRF with SHA512", test_tls12_prf, &tls12_prf_sha512_0); - if (l_key_is_supported(L_KEY_FEATURE_RESTRICT)) + if (l_key_is_supported(L_KEY_FEATURE_RESTRICT)) { l_test_add("Certificate chains", test_certificates, NULL); + l_test_add("ECDSA Certificates", test_ec_certificates, NULL); + } if (!l_getrandom_is_supported()) { printf("getrandom missing, skipping TLS connection tests...\n"); -- 2.35.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/9] key: ECDSA data is given in x962 format 2022-07-18 16:02 [PATCH 1/9] cert/key: Add support for EC based certificates Denis Kenzior 2022-07-18 16:02 ` [PATCH 2/9] unit: Add basic EC-DSA verification test Denis Kenzior @ 2022-07-18 16:02 ` Denis Kenzior 2022-07-18 16:02 ` [PATCH 4/9] tls: Support peer certificates that use ECDSA Denis Kenzior ` (5 subsequent siblings) 7 siblings, 0 replies; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 16:02 UTC (permalink / raw) To: ell; +Cc: Denis Kenzior When using the verify operation with ECDSA based public keys, the new format type must be used. --- ell/key.c | 12 +++++------- ell/key.h | 1 + 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ell/key.c b/ell/key.c index 73f38581f736..24374a5d836d 100644 --- a/ell/key.c +++ b/ell/key.c @@ -383,18 +383,16 @@ LIB_EXPORT ssize_t l_key_get_payload_size(struct l_key *key) static const char *lookup_cipher(enum l_key_cipher_type cipher) { - const char* ret = NULL; - switch (cipher) { case L_KEY_RSA_PKCS1_V1_5: - ret = "pkcs1"; - break; + return "pkcs1"; case L_KEY_RSA_RAW: - ret = "raw"; - break; + return "raw"; + case L_KEY_ECDSA_X962: + return "x962"; } - return ret; + return NULL; } static const char *lookup_checksum(enum l_checksum_type checksum) diff --git a/ell/key.h b/ell/key.h index f26f7ecb26c3..68971052ffde 100644 --- a/ell/key.h +++ b/ell/key.h @@ -56,6 +56,7 @@ enum l_keyring_restriction { enum l_key_cipher_type { L_KEY_RSA_PKCS1_V1_5, L_KEY_RSA_RAW, + L_KEY_ECDSA_X962, }; struct l_key *l_key_new(enum l_key_type type, const void *payload, -- 2.35.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/9] tls: Support peer certificates that use ECDSA 2022-07-18 16:02 [PATCH 1/9] cert/key: Add support for EC based certificates Denis Kenzior 2022-07-18 16:02 ` [PATCH 2/9] unit: Add basic EC-DSA verification test Denis Kenzior 2022-07-18 16:02 ` [PATCH 3/9] key: ECDSA data is given in x962 format Denis Kenzior @ 2022-07-18 16:02 ` Denis Kenzior 2022-07-18 17:44 ` Mat Martineau 2022-07-18 16:02 ` [PATCH 5/9] tls: Add helper for DigitallySigned validation Denis Kenzior ` (4 subsequent siblings) 7 siblings, 1 reply; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 16:02 UTC (permalink / raw) To: ell; +Cc: Denis Kenzior --- ell/tls.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/ell/tls.c b/ell/tls.c index b2f7411f3b36..75b9d45c6523 100644 --- a/ell/tls.c +++ b/ell/tls.c @@ -1899,6 +1899,8 @@ static void tls_handle_certificate(struct l_tls *tls, bool dummy; const char *error_str; char *subject_str; + enum l_key_cipher_type format_type; + enum l_checksum_type checksum_type; if (len < 3) goto decode_error; @@ -2028,9 +2030,23 @@ static void tls_handle_certificate(struct l_tls *tls, return; } - if (!l_key_get_info(tls->peer_pubkey, L_KEY_RSA_PKCS1_V1_5, - L_CHECKSUM_NONE, &tls->peer_pubkey_size, - &dummy)) { + switch (l_cert_get_pubkey_type(tls->peer_cert)) { + case L_CERT_KEY_RSA: + format_type = L_KEY_RSA_PKCS1_V1_5; + checksum_type = L_CHECKSUM_NONE; + break; + case L_CERT_KEY_ECC: + format_type = L_KEY_ECDSA_X962; + checksum_type = L_CHECKSUM_SHA1; + break; + case L_CERT_KEY_UNKNOWN: + TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, + "Unknown public key type"); + return; + } + + if (!l_key_get_info(tls->peer_pubkey, format_type, checksum_type, + &tls->peer_pubkey_size, &dummy)) { TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, "Can't l_key_get_info for peer public key"); -- 2.35.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 4/9] tls: Support peer certificates that use ECDSA 2022-07-18 16:02 ` [PATCH 4/9] tls: Support peer certificates that use ECDSA Denis Kenzior @ 2022-07-18 17:44 ` Mat Martineau 2022-07-18 17:59 ` Denis Kenzior 0 siblings, 1 reply; 12+ messages in thread From: Mat Martineau @ 2022-07-18 17:44 UTC (permalink / raw) To: Denis Kenzior; +Cc: ell On Mon, 18 Jul 2022, Denis Kenzior wrote: > --- > ell/tls.c | 22 +++++++++++++++++++--- > 1 file changed, 19 insertions(+), 3 deletions(-) > > diff --git a/ell/tls.c b/ell/tls.c > index b2f7411f3b36..75b9d45c6523 100644 > --- a/ell/tls.c > +++ b/ell/tls.c > @@ -1899,6 +1899,8 @@ static void tls_handle_certificate(struct l_tls *tls, > bool dummy; > const char *error_str; > char *subject_str; > + enum l_key_cipher_type format_type; > + enum l_checksum_type checksum_type; > > if (len < 3) > goto decode_error; > @@ -2028,9 +2030,23 @@ static void tls_handle_certificate(struct l_tls *tls, > return; > } > > - if (!l_key_get_info(tls->peer_pubkey, L_KEY_RSA_PKCS1_V1_5, > - L_CHECKSUM_NONE, &tls->peer_pubkey_size, > - &dummy)) { > + switch (l_cert_get_pubkey_type(tls->peer_cert)) { > + case L_CERT_KEY_RSA: > + format_type = L_KEY_RSA_PKCS1_V1_5; > + checksum_type = L_CHECKSUM_NONE; > + break; > + case L_CERT_KEY_ECC: > + format_type = L_KEY_ECDSA_X962; > + checksum_type = L_CHECKSUM_SHA1; > + break; > + case L_CERT_KEY_UNKNOWN: Hi Denis, I needed to add default: here to get it to build. Details below. > + TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, > + "Unknown public key type"); > + return; > + } > + > + if (!l_key_get_info(tls->peer_pubkey, format_type, checksum_type, > + &tls->peer_pubkey_size, &dummy)) { The ell (standalone, bootstrap-configure) build fails here with gcc12/Fedora36: ell/tls.c:2061:14: error: 'checksum_type' may be used uninitialized [-Werror=maybe-uninitialized] ell/tls.c:2061:14: error: 'format_type' may be used uninitialized [-Werror=maybe-uninitialized] Apparently gcc12 can't track that -Werror=switch-enum is in use in combination with -Werror=maybe-uninitialized, and doesn't understand that the switch statement above does guarantee initialization. > TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, > "Can't l_key_get_info for peer public key"); > > -- > 2.35.1 > > > -- Mat Martineau Intel ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 4/9] tls: Support peer certificates that use ECDSA 2022-07-18 17:44 ` Mat Martineau @ 2022-07-18 17:59 ` Denis Kenzior 0 siblings, 0 replies; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 17:59 UTC (permalink / raw) To: Mat Martineau; +Cc: ell Hi Mat, > default: Indeed. > here to get it to build. Details below. > >> + TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, >> + "Unknown public key type"); >> + return; >> + } >> + >> + if (!l_key_get_info(tls->peer_pubkey, format_type, checksum_type, >> + &tls->peer_pubkey_size, &dummy)) { > > The ell (standalone, bootstrap-configure) build fails here with gcc12/Fedora36: > > ell/tls.c:2061:14: error: 'checksum_type' may be used uninitialized > [-Werror=maybe-uninitialized] > ell/tls.c:2061:14: error: 'format_type' may be used uninitialized > [-Werror=maybe-uninitialized] > > Apparently gcc12 can't track that -Werror=switch-enum is in use in combination > with -Werror=maybe-uninitialized, and doesn't understand that the switch > statement above does guarantee initialization. > GCC seems a bit silly here. Not sure adding 'default:' is any better since we use these warnings defensively in case a new enumeration is added and not handled. Anyhow, I fixed this slightly differently in v2 out shortly. Thanks for testing. Regards, -Denis ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 5/9] tls: Add helper for DigitallySigned validation 2022-07-18 16:02 [PATCH 1/9] cert/key: Add support for EC based certificates Denis Kenzior ` (2 preceding siblings ...) 2022-07-18 16:02 ` [PATCH 4/9] tls: Support peer certificates that use ECDSA Denis Kenzior @ 2022-07-18 16:02 ` Denis Kenzior 2022-07-18 16:02 ` [PATCH 6/9] tls: Add helper to find hash function by id Denis Kenzior ` (3 subsequent siblings) 7 siblings, 0 replies; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 16:02 UTC (permalink / raw) To: ell; +Cc: Denis Kenzior To support additional signature algorithms, move the logic that validates DigitallySigned structure to a helper function. --- ell/tls-suites.c | 87 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 27 deletions(-) diff --git a/ell/tls-suites.c b/ell/tls-suites.c index 1c1ca078b3d8..d5d2ec8f741f 100644 --- a/ell/tls-suites.c +++ b/ell/tls-suites.c @@ -40,6 +40,57 @@ #include "ecdh.h" #include "missing.h" +enum signature_algorithm { + SIGNATURE_ALGORITHM_ANONYMOUS = 0, + SIGNATURE_ALGORITHM_RSA = 1, + SIGNATURE_ALGORITHM_DSA = 2, + SIGNATURE_ALGORITHM_ECDSA = 3, +}; + +/* + * Sanitize DigitallySigned struct input, making sure the lengths + * are valid and correspond to what we expect. + * + * Returns: start of the opaque portion + */ +static const uint8_t *validate_digitally_signed(struct l_tls *tls, + const uint8_t *in, size_t in_len, + enum signature_algorithm expected_alg, + uint16_t *opaque_len) +{ + size_t offset = 2; + uint16_t len; + + if (tls->negotiated_version < L_TLS_V12) + offset = 0; + + if (in_len < offset + 2) + goto size_error; + + len = l_get_be16(in + offset); + if (len != in_len - offset - 2) + goto size_error; + + if (tls->negotiated_version >= L_TLS_V12) { + if (in[1] != expected_alg) { + TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, + "Unknown signature algorithm %i", + in[1]); + + return NULL; + } + } + + *opaque_len = len; + return in + offset + 2; + +size_error: + TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0, "Signature msg too " + "short (%zi) or signature length doesn't match", + in_len); + return NULL; +} + static bool tls_rsa_validate_cert_key(struct l_cert *cert) { return l_cert_get_pubkey_type(cert) == L_CERT_KEY_RSA; @@ -112,29 +163,20 @@ static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t in_len, enum l_checksum_type sign_checksum_type; uint8_t expected[HANDSHAKE_HASH_MAX_SIZE + 36]; size_t expected_len; - unsigned int offset; + const uint8_t *opaque; + uint16_t opaque_len; bool success; - /* 2 bytes for SignatureAndHashAlgorithm if version >= 1.2 */ - offset = 2; - if (tls->negotiated_version < L_TLS_V12) - offset = 0; - - if (in_len < offset + 2 || - (size_t) l_get_be16(in + offset) + offset + 2 != - in_len) { - TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0, "Signature msg too " - "short (%zi) or signature length doesn't match", - in_len); - + opaque = validate_digitally_signed(tls, in, in_len, + SIGNATURE_ALGORITHM_RSA, &opaque_len); + if (!opaque) return false; - } /* Only the default hash type supported */ - if (in_len != offset + 2 + tls->peer_pubkey_size) { + if (opaque_len != tls->peer_pubkey_size) { TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0, - "Signature length %zi not equal %zi", in_len, - offset + 2 + tls->peer_pubkey_size); + "Signature length %hu not equal %zi", + opaque_len, tls->peer_pubkey_size); return false; } @@ -142,15 +184,6 @@ static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t in_len, if (tls->negotiated_version >= L_TLS_V12) { enum handshake_hash_type hash; - /* Only RSA supported */ - if (in[1] != 1 /* RSA_sign */) { - TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, - "Unknown signature algorithm %i", - in[1]); - - return false; - } - for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++) if (tls_handshake_hash_data[hash].tls_id == in[0]) break; @@ -203,7 +236,7 @@ static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t in_len, } success = l_key_verify(tls->peer_pubkey, L_KEY_RSA_PKCS1_V1_5, - sign_checksum_type, expected, in + offset + 2, + sign_checksum_type, expected, opaque, expected_len, tls->peer_pubkey_size); if (!success) -- 2.35.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 6/9] tls: Add helper to find hash function by id 2022-07-18 16:02 [PATCH 1/9] cert/key: Add support for EC based certificates Denis Kenzior ` (3 preceding siblings ...) 2022-07-18 16:02 ` [PATCH 5/9] tls: Add helper for DigitallySigned validation Denis Kenzior @ 2022-07-18 16:02 ` Denis Kenzior 2022-07-18 16:02 ` [PATCH 7/9] tls-suites: Add ECDSA suites from RFC 8422 Denis Kenzior ` (2 subsequent siblings) 7 siblings, 0 replies; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 16:02 UTC (permalink / raw) To: ell; +Cc: Denis Kenzior Instead of open-coding a loop to map the hash id from SignatureAndHashAlgorithm structure to a supported hash function. --- ell/tls-suites.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/ell/tls-suites.c b/ell/tls-suites.c index d5d2ec8f741f..bc6a756422b3 100644 --- a/ell/tls-suites.c +++ b/ell/tls-suites.c @@ -47,6 +47,17 @@ enum signature_algorithm { SIGNATURE_ALGORITHM_ECDSA = 3, }; +static enum handshake_hash_type find_hash_by_id(uint8_t id) +{ + enum handshake_hash_type hash; + + for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++) + if (tls_handshake_hash_data[hash].tls_id == id) + break; + + return hash; +} + /* * Sanitize DigitallySigned struct input, making sure the lengths * are valid and correspond to what we expect. @@ -182,11 +193,7 @@ static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t in_len, } if (tls->negotiated_version >= L_TLS_V12) { - enum handshake_hash_type hash; - - for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++) - if (tls_handshake_hash_data[hash].tls_id == in[0]) - break; + enum handshake_hash_type hash = find_hash_by_id(in[0]); if (hash == __HANDSHAKE_HASH_COUNT) { TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, -- 2.35.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 7/9] tls-suites: Add ECDSA suites from RFC 8422 2022-07-18 16:02 [PATCH 1/9] cert/key: Add support for EC based certificates Denis Kenzior ` (4 preceding siblings ...) 2022-07-18 16:02 ` [PATCH 6/9] tls: Add helper to find hash function by id Denis Kenzior @ 2022-07-18 16:02 ` Denis Kenzior 2022-07-18 17:53 ` Mat Martineau 2022-07-18 16:02 ` [PATCH 8/9] useful: Add maxsize() Denis Kenzior 2022-07-18 16:02 ` [PATCH 9/9] tls: Do not set verify_data_length unless needed Denis Kenzior 7 siblings, 1 reply; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 16:02 UTC (permalink / raw) To: ell; +Cc: Denis Kenzior --- ell/tls-suites.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/ell/tls-suites.c b/ell/tls-suites.c index bc6a756422b3..34141ab7fa56 100644 --- a/ell/tls-suites.c +++ b/ell/tls-suites.c @@ -262,6 +262,81 @@ static struct tls_signature_algorithm tls_rsa_signature = { .verify = tls_rsa_verify, }; +static bool tls_ecdsa_validate_cert_key(struct l_cert *cert) +{ + return l_cert_get_pubkey_type(cert) == L_CERT_KEY_ECC; +} + +static bool tls_ecdsa_verify(struct l_tls *tls, + const uint8_t *in, size_t in_len, + tls_get_hash_t get_hash, + const uint8_t *data, size_t data_len) +{ + /* RFC 8422, Section 5.10: "SHA-1 is used in TLS 1.1 and earlier" */ + enum handshake_hash_type hash = HANDSHAKE_HASH_SHA1; + enum l_checksum_type sign_checksum_type; + const uint8_t *opaque; + uint16_t opaque_len; + uint8_t expected[HANDSHAKE_HASH_MAX_SIZE]; + size_t expected_len; + bool success; + + opaque = validate_digitally_signed(tls, in, in_len, + SIGNATURE_ALGORITHM_ECDSA, &opaque_len); + if (!opaque) + return false; + + if (tls->negotiated_version >= L_TLS_V12) { + hash = find_hash_by_id(in[0]); + if (hash == __HANDSHAKE_HASH_COUNT) { + TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, + "Unknown hash type %i", in[0]); + return false; + } + + /* Hash should match the curve, refer to RFC 5480, Section 4 */ + switch (tls->peer_pubkey_size) { + case 32: + if (hash != HANDSHAKE_HASH_SHA256 && + hash != HANDSHAKE_HASH_SHA384) + goto bad_hash; + + break; + case 48: + if (hash != HANDSHAKE_HASH_SHA384) + goto bad_hash; + + break; + bad_hash: + default: + TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, + "Invalid hash %i", + in[0]); + } + } + + get_hash(tls, hash, data, data_len, expected, &expected_len); + sign_checksum_type = tls_handshake_hash_data[hash].l_id; + + success = l_key_verify(tls->peer_pubkey, L_KEY_ECDSA_X962, + sign_checksum_type, expected, opaque, + expected_len, opaque_len); + + if (!success) + TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, + "Peer signature verification failed"); + else + TLS_DEBUG("Peer signature verified"); + + return success; +} + +static struct tls_signature_algorithm tls_ecdsa_signature = { + .id = 3, /* SignatureAlgorithm.ecdsa */ + .validate_cert_key_type = tls_ecdsa_validate_cert_key, + .verify = tls_ecdsa_verify, +}; + static bool tls_send_rsa_client_key_xchg(struct l_tls *tls) { uint8_t buf[1024 + 32]; @@ -1350,11 +1425,52 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { .prf_hmac = L_CHECKSUM_SHA384, .signature = &tls_rsa_signature, .key_xchg = &tls_ecdhe, +}, tls_ecdhe_ecdsa_with_3des_ede_cbc_sha = { + .id = { 0xc0, 0x08 }, + .name = "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", + .verify_data_length = 12, + .encryption = &tls_3des_ede, + .mac = &tls_sha, + .signature = &tls_ecdsa_signature, + .key_xchg = &tls_ecdhe, +}, tls_ecdhe_ecdsa_with_aes_128_cbc_sha = { + .id = { 0xc0, 0x09 }, + .name = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + .verify_data_length = 12, + .encryption = &tls_aes128, + .mac = &tls_sha, + .signature = &tls_ecdsa_signature, + .key_xchg = &tls_ecdhe, +}, tls_ecdhe_ecdsa_with_aes_256_cbc_sha = { + .id = { 0xc0, 0x0a }, + .name = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", + .verify_data_length = 12, + .encryption = &tls_aes256, + .mac = &tls_sha, + .signature = &tls_ecdsa_signature, + .key_xchg = &tls_ecdhe, +}, tls_ecdhe_ecdsa_with_aes_128_gcm_sha256 = { + .id = { 0xc0, 0x2b }, + .name = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + .verify_data_length = 12, + .encryption = &tls_aes128_gcm, + .signature = &tls_ecdsa_signature, + .key_xchg = &tls_ecdhe, +}, tls_ecdhe_ecdsa_with_aes_256_gcm_sha384 = { + .id = { 0xc0, 0x2c }, + .name = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + .verify_data_length = 12, + .encryption = &tls_aes256_gcm, + .prf_hmac = L_CHECKSUM_SHA384, + .signature = &tls_ecdsa_signature, + .key_xchg = &tls_ecdhe, }; struct tls_cipher_suite *tls_cipher_suite_pref[] = { &tls_ecdhe_rsa_with_aes_256_cbc_sha, + &tls_ecdhe_ecdsa_with_aes_256_cbc_sha, &tls_ecdhe_rsa_with_aes_128_cbc_sha, + &tls_ecdhe_ecdsa_with_aes_128_cbc_sha, &tls_dhe_rsa_with_aes_256_cbc_sha, &tls_dhe_rsa_with_aes_128_cbc_sha, &tls_rsa_with_aes_256_cbc_sha, @@ -1367,11 +1483,14 @@ struct tls_cipher_suite *tls_cipher_suite_pref[] = { &tls_rsa_with_aes_128_cbc_sha256, &tls_ecdhe_rsa_with_aes_256_gcm_sha384, &tls_ecdhe_rsa_with_aes_128_gcm_sha256, + &tls_ecdhe_ecdsa_with_aes_256_gcm_sha384, + &tls_ecdhe_ecdsa_with_aes_128_gcm_sha256, &tls_dhe_rsa_with_aes_256_gcm_sha384, &tls_dhe_rsa_with_aes_128_gcm_sha256, &tls_rsa_with_aes_256_gcm_sha384, &tls_rsa_with_aes_128_gcm_sha256, &tls_ecdhe_rsa_with_3des_ede_cbc_sha, + &tls_ecdhe_ecdsa_with_3des_ede_cbc_sha, &tls_dhe_rsa_with_3des_ede_cbc_sha, &tls_rsa_with_3des_ede_cbc_sha, NULL, -- 2.35.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 7/9] tls-suites: Add ECDSA suites from RFC 8422 2022-07-18 16:02 ` [PATCH 7/9] tls-suites: Add ECDSA suites from RFC 8422 Denis Kenzior @ 2022-07-18 17:53 ` Mat Martineau 0 siblings, 0 replies; 12+ messages in thread From: Mat Martineau @ 2022-07-18 17:53 UTC (permalink / raw) To: Denis Kenzior; +Cc: ell On Mon, 18 Jul 2022, Denis Kenzior wrote: > --- > ell/tls-suites.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 119 insertions(+) > > diff --git a/ell/tls-suites.c b/ell/tls-suites.c > index bc6a756422b3..34141ab7fa56 100644 > --- a/ell/tls-suites.c > +++ b/ell/tls-suites.c > @@ -262,6 +262,81 @@ static struct tls_signature_algorithm tls_rsa_signature = { > .verify = tls_rsa_verify, > }; > > +static bool tls_ecdsa_validate_cert_key(struct l_cert *cert) > +{ > + return l_cert_get_pubkey_type(cert) == L_CERT_KEY_ECC; > +} > + > +static bool tls_ecdsa_verify(struct l_tls *tls, > + const uint8_t *in, size_t in_len, > + tls_get_hash_t get_hash, > + const uint8_t *data, size_t data_len) > +{ > + /* RFC 8422, Section 5.10: "SHA-1 is used in TLS 1.1 and earlier" */ > + enum handshake_hash_type hash = HANDSHAKE_HASH_SHA1; > + enum l_checksum_type sign_checksum_type; > + const uint8_t *opaque; > + uint16_t opaque_len; > + uint8_t expected[HANDSHAKE_HASH_MAX_SIZE]; > + size_t expected_len; > + bool success; > + > + opaque = validate_digitally_signed(tls, in, in_len, > + SIGNATURE_ALGORITHM_ECDSA, &opaque_len); > + if (!opaque) > + return false; > + > + if (tls->negotiated_version >= L_TLS_V12) { > + hash = find_hash_by_id(in[0]); > + if (hash == __HANDSHAKE_HASH_COUNT) { > + TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, > + "Unknown hash type %i", in[0]); > + return false; > + } > + > + /* Hash should match the curve, refer to RFC 5480, Section 4 */ > + switch (tls->peer_pubkey_size) { > + case 32: > + if (hash != HANDSHAKE_HASH_SHA256 && > + hash != HANDSHAKE_HASH_SHA384) > + goto bad_hash; > + > + break; > + case 48: > + if (hash != HANDSHAKE_HASH_SHA384) > + goto bad_hash; > + > + break; > + bad_hash: > + default: > + TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, > + "Invalid hash %i", > + in[0]); > + } > + } > + > + get_hash(tls, hash, data, data_len, expected, &expected_len); > + sign_checksum_type = tls_handshake_hash_data[hash].l_id; > + > + success = l_key_verify(tls->peer_pubkey, L_KEY_ECDSA_X962, > + sign_checksum_type, expected, opaque, > + expected_len, opaque_len); > + > + if (!success) > + TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, > + "Peer signature verification failed"); > + else > + TLS_DEBUG("Peer signature verified"); > + > + return success; > +} > + > +static struct tls_signature_algorithm tls_ecdsa_signature = { > + .id = 3, /* SignatureAlgorithm.ecdsa */ > + .validate_cert_key_type = tls_ecdsa_validate_cert_key, > + .verify = tls_ecdsa_verify, > +}; > + > static bool tls_send_rsa_client_key_xchg(struct l_tls *tls) > { > uint8_t buf[1024 + 32]; > @@ -1350,11 +1425,52 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { > .prf_hmac = L_CHECKSUM_SHA384, > .signature = &tls_rsa_signature, > .key_xchg = &tls_ecdhe, > +}, tls_ecdhe_ecdsa_with_3des_ede_cbc_sha = { > + .id = { 0xc0, 0x08 }, > + .name = "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", > + .verify_data_length = 12, > + .encryption = &tls_3des_ede, > + .mac = &tls_sha, > + .signature = &tls_ecdsa_signature, > + .key_xchg = &tls_ecdhe, > +}, tls_ecdhe_ecdsa_with_aes_128_cbc_sha = { > + .id = { 0xc0, 0x09 }, > + .name = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", > + .verify_data_length = 12, > + .encryption = &tls_aes128, > + .mac = &tls_sha, > + .signature = &tls_ecdsa_signature, > + .key_xchg = &tls_ecdhe, > +}, tls_ecdhe_ecdsa_with_aes_256_cbc_sha = { > + .id = { 0xc0, 0x0a }, > + .name = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", > + .verify_data_length = 12, > + .encryption = &tls_aes256, > + .mac = &tls_sha, > + .signature = &tls_ecdsa_signature, > + .key_xchg = &tls_ecdhe, > +}, tls_ecdhe_ecdsa_with_aes_128_gcm_sha256 = { > + .id = { 0xc0, 0x2b }, > + .name = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", > + .verify_data_length = 12, > + .encryption = &tls_aes128_gcm, > + .signature = &tls_ecdsa_signature, > + .key_xchg = &tls_ecdhe, > +}, tls_ecdhe_ecdsa_with_aes_256_gcm_sha384 = { > + .id = { 0xc0, 0x2c }, > + .name = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", > + .verify_data_length = 12, > + .encryption = &tls_aes256_gcm, > + .prf_hmac = L_CHECKSUM_SHA384, > + .signature = &tls_ecdsa_signature, > + .key_xchg = &tls_ecdhe, > }; These new suites fail in unit/test-tls with the 5.18.11-200.fc36.x86_64 kernel (latest Fedora 36): TEST: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA test-tls: unit/test-tls.c:661: test_tls_with_ver: Assertion `!!l_tls_start(s[1].tls) == !test->expect_client_start_fail' failed. I started commenting out each failed test, also verified the failure with TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA and TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384. Didn't try the last couple cases (GCM_SHA256 and 3DES). > > struct tls_cipher_suite *tls_cipher_suite_pref[] = { > &tls_ecdhe_rsa_with_aes_256_cbc_sha, > + &tls_ecdhe_ecdsa_with_aes_256_cbc_sha, > &tls_ecdhe_rsa_with_aes_128_cbc_sha, > + &tls_ecdhe_ecdsa_with_aes_128_cbc_sha, > &tls_dhe_rsa_with_aes_256_cbc_sha, > &tls_dhe_rsa_with_aes_128_cbc_sha, > &tls_rsa_with_aes_256_cbc_sha, > @@ -1367,11 +1483,14 @@ struct tls_cipher_suite *tls_cipher_suite_pref[] = { > &tls_rsa_with_aes_128_cbc_sha256, > &tls_ecdhe_rsa_with_aes_256_gcm_sha384, > &tls_ecdhe_rsa_with_aes_128_gcm_sha256, > + &tls_ecdhe_ecdsa_with_aes_256_gcm_sha384, > + &tls_ecdhe_ecdsa_with_aes_128_gcm_sha256, > &tls_dhe_rsa_with_aes_256_gcm_sha384, > &tls_dhe_rsa_with_aes_128_gcm_sha256, > &tls_rsa_with_aes_256_gcm_sha384, > &tls_rsa_with_aes_128_gcm_sha256, > &tls_ecdhe_rsa_with_3des_ede_cbc_sha, > + &tls_ecdhe_ecdsa_with_3des_ede_cbc_sha, > &tls_dhe_rsa_with_3des_ede_cbc_sha, > &tls_rsa_with_3des_ede_cbc_sha, > NULL, > -- > 2.35.1 > > > -- Mat Martineau Intel ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 8/9] useful: Add maxsize() 2022-07-18 16:02 [PATCH 1/9] cert/key: Add support for EC based certificates Denis Kenzior ` (5 preceding siblings ...) 2022-07-18 16:02 ` [PATCH 7/9] tls-suites: Add ECDSA suites from RFC 8422 Denis Kenzior @ 2022-07-18 16:02 ` Denis Kenzior 2022-07-18 16:02 ` [PATCH 9/9] tls: Do not set verify_data_length unless needed Denis Kenzior 7 siblings, 0 replies; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 16:02 UTC (permalink / raw) To: ell; +Cc: Denis Kenzior Similar to minsize(), but for finding the maximum of two sizes --- ell/useful.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ell/useful.h b/ell/useful.h index 791fa2006494..efd91d78b3f2 100644 --- a/ell/useful.h +++ b/ell/useful.h @@ -38,6 +38,14 @@ static inline size_t minsize(size_t a, size_t b) return b; } +static inline size_t maxsize(size_t a, size_t b) +{ + if (a >= b) + return a; + + return b; +} + static inline void set_bit(void *addr, unsigned int bit) { unsigned char *field = addr; -- 2.35.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 9/9] tls: Do not set verify_data_length unless needed 2022-07-18 16:02 [PATCH 1/9] cert/key: Add support for EC based certificates Denis Kenzior ` (6 preceding siblings ...) 2022-07-18 16:02 ` [PATCH 8/9] useful: Add maxsize() Denis Kenzior @ 2022-07-18 16:02 ` Denis Kenzior 7 siblings, 0 replies; 12+ messages in thread From: Denis Kenzior @ 2022-07-18 16:02 UTC (permalink / raw) To: ell; +Cc: Denis Kenzior All current TLS cipher suites use a verify_data_length of 12. In fact, according to RFC 5246, most cipher suites are expected to be 12 bytes unless specified otherwise. Use this fact to simplify the cipher suite definition: initialization of verify_data_length is no longer necessary unless the length is greater than 12 bytes. While here, also update struct tls_cipher_suite to use a size_t member for verify_data_length instead of an int. --- ell/tls-private.h | 2 +- ell/tls-suites.c | 26 -------------------------- ell/tls.c | 29 +++++++++++++++++++++-------- 3 files changed, 22 insertions(+), 35 deletions(-) diff --git a/ell/tls-private.h b/ell/tls-private.h index 8ceeb68df40b..8941e90d03ca 100644 --- a/ell/tls-private.h +++ b/ell/tls-private.h @@ -112,7 +112,7 @@ struct tls_mac_algorithm { struct tls_cipher_suite { uint8_t id[2]; const char *name; - int verify_data_length; + size_t verify_data_length; struct tls_bulk_encryption_algorithm *encryption; struct tls_signature_algorithm *signature; diff --git a/ell/tls-suites.c b/ell/tls-suites.c index 34141ab7fa56..ee4e7ee6c310 100644 --- a/ell/tls-suites.c +++ b/ell/tls-suites.c @@ -1262,7 +1262,6 @@ static struct tls_mac_algorithm tls_sha = { static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { .id = { 0x00, 0x0a }, .name = "TLS_RSA_WITH_3DES_EDE_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_3des_ede, .mac = &tls_sha, .signature = &tls_rsa_signature, @@ -1270,7 +1269,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_dhe_rsa_with_3des_ede_cbc_sha = { .id = { 0x00, 0x16 }, .name = "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_3des_ede, .mac = &tls_sha, .signature = &tls_rsa_signature, @@ -1278,7 +1276,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_rsa_with_aes_128_cbc_sha = { .id = { 0x00, 0x2f }, .name = "TLS_RSA_WITH_AES_128_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_aes128, .mac = &tls_sha, .signature = &tls_rsa_signature, @@ -1286,7 +1283,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_dhe_rsa_with_aes_128_cbc_sha = { .id = { 0x00, 0x33 }, .name = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_aes128, .mac = &tls_sha, .signature = &tls_rsa_signature, @@ -1294,7 +1290,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_rsa_with_aes_256_cbc_sha = { .id = { 0x00, 0x35 }, .name = "TLS_RSA_WITH_AES_256_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_aes256, .mac = &tls_sha, .signature = &tls_rsa_signature, @@ -1302,7 +1297,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_dhe_rsa_with_aes_256_cbc_sha = { .id = { 0x00, 0x39 }, .name = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_aes256, .mac = &tls_sha, .signature = &tls_rsa_signature, @@ -1310,7 +1304,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_rsa_with_aes_128_cbc_sha256 = { .id = { 0x00, 0x3c }, .name = "TLS_RSA_WITH_AES_128_CBC_SHA256", - .verify_data_length = 12, .encryption = &tls_aes128, .mac = &tls_sha256, .signature = &tls_rsa_signature, @@ -1318,7 +1311,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_rsa_with_aes_256_cbc_sha256 = { .id = { 0x00, 0x3d }, .name = "TLS_RSA_WITH_AES_256_CBC_SHA256", - .verify_data_length = 12, .encryption = &tls_aes256, .mac = &tls_sha256, .signature = &tls_rsa_signature, @@ -1326,7 +1318,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_dhe_rsa_with_aes_128_cbc_sha256 = { .id = { 0x00, 0x67 }, .name = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", - .verify_data_length = 12, .encryption = &tls_aes128, .mac = &tls_sha256, .signature = &tls_rsa_signature, @@ -1334,7 +1325,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_dhe_rsa_with_aes_256_cbc_sha256 = { .id = { 0x00, 0x6b }, .name = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", - .verify_data_length = 12, .encryption = &tls_aes256, .mac = &tls_sha256, .signature = &tls_rsa_signature, @@ -1342,14 +1332,12 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_rsa_with_aes_128_gcm_sha256 = { .id = { 0x00, 0x9c }, .name = "TLS_RSA_WITH_AES_128_GCM_SHA256", - .verify_data_length = 12, .encryption = &tls_aes128_gcm, .signature = &tls_rsa_signature, .key_xchg = &tls_rsa_key_xchg, }, tls_rsa_with_aes_256_gcm_sha384 = { .id = { 0x00, 0x9d }, .name = "TLS_RSA_WITH_AES_256_GCM_SHA384", - .verify_data_length = 12, .encryption = &tls_aes256_gcm, .prf_hmac = L_CHECKSUM_SHA384, .signature = &tls_rsa_signature, @@ -1357,14 +1345,12 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_dhe_rsa_with_aes_128_gcm_sha256 = { .id = { 0x00, 0x9e }, .name = "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", - .verify_data_length = 12, .encryption = &tls_aes128_gcm, .signature = &tls_rsa_signature, .key_xchg = &tls_dhe, }, tls_dhe_rsa_with_aes_256_gcm_sha384 = { .id = { 0x00, 0x9f }, .name = "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", - .verify_data_length = 12, .encryption = &tls_aes256_gcm, .prf_hmac = L_CHECKSUM_SHA384, .signature = &tls_rsa_signature, @@ -1372,7 +1358,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_rsa_with_3des_ede_cbc_sha = { .id = { 0xc0, 0x12 }, .name = "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_3des_ede, .mac = &tls_sha, .signature = &tls_rsa_signature, @@ -1380,7 +1365,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_rsa_with_aes_128_cbc_sha = { .id = { 0xc0, 0x13 }, .name = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_aes128, .mac = &tls_sha, .signature = &tls_rsa_signature, @@ -1388,7 +1372,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_rsa_with_aes_256_cbc_sha = { .id = { 0xc0, 0x14 }, .name = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_aes256, .mac = &tls_sha, .signature = &tls_rsa_signature, @@ -1396,7 +1379,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_rsa_with_aes_128_cbc_sha256 = { .id = { 0xc0, 0x27 }, .name = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", - .verify_data_length = 12, .encryption = &tls_aes128, .mac = &tls_sha256, .signature = &tls_rsa_signature, @@ -1404,7 +1386,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_rsa_with_aes_256_cbc_sha384 = { .id = { 0xc0, 0x28 }, .name = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", - .verify_data_length = 12, .encryption = &tls_aes256, .mac = &tls_sha384, .prf_hmac = L_CHECKSUM_SHA384, @@ -1413,14 +1394,12 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_rsa_with_aes_128_gcm_sha256 = { .id = { 0xc0, 0x2f }, .name = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - .verify_data_length = 12, .encryption = &tls_aes128_gcm, .signature = &tls_rsa_signature, .key_xchg = &tls_ecdhe, }, tls_ecdhe_rsa_with_aes_256_gcm_sha384 = { .id = { 0xc0, 0x30 }, .name = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", - .verify_data_length = 12, .encryption = &tls_aes256_gcm, .prf_hmac = L_CHECKSUM_SHA384, .signature = &tls_rsa_signature, @@ -1428,7 +1407,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_ecdsa_with_3des_ede_cbc_sha = { .id = { 0xc0, 0x08 }, .name = "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_3des_ede, .mac = &tls_sha, .signature = &tls_ecdsa_signature, @@ -1436,7 +1414,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_ecdsa_with_aes_128_cbc_sha = { .id = { 0xc0, 0x09 }, .name = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_aes128, .mac = &tls_sha, .signature = &tls_ecdsa_signature, @@ -1444,7 +1421,6 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_ecdsa_with_aes_256_cbc_sha = { .id = { 0xc0, 0x0a }, .name = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", - .verify_data_length = 12, .encryption = &tls_aes256, .mac = &tls_sha, .signature = &tls_ecdsa_signature, @@ -1452,14 +1428,12 @@ static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = { }, tls_ecdhe_ecdsa_with_aes_128_gcm_sha256 = { .id = { 0xc0, 0x2b }, .name = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - .verify_data_length = 12, .encryption = &tls_aes128_gcm, .signature = &tls_ecdsa_signature, .key_xchg = &tls_ecdhe, }, tls_ecdhe_ecdsa_with_aes_256_gcm_sha384 = { .id = { 0xc0, 0x2c }, .name = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", - .verify_data_length = 12, .encryption = &tls_aes256_gcm, .prf_hmac = L_CHECKSUM_SHA384, .signature = &tls_ecdsa_signature, diff --git a/ell/tls.c b/ell/tls.c index 75b9d45c6523..0bf647919478 100644 --- a/ell/tls.c +++ b/ell/tls.c @@ -1370,11 +1370,25 @@ static void tls_send_change_cipher_spec(struct l_tls *tls) tls_tx_record(tls, TLS_CT_CHANGE_CIPHER_SPEC, &buf, 1); } +static size_t tls_verify_data_length(struct l_tls *tls, unsigned int index) +{ + /* + * RFC 5246, Section 7.4.9: + * + * In previous versions of TLS, the verify_data was always 12 octets + * long. In the current version of TLS, it depends on the cipher + * suite. Any cipher suite which does not explicitly specify + * verify_data_length has a verify_data_length equal to 12. + */ + return maxsize(tls->cipher_suite[index]->verify_data_length, 12); +} + static void tls_send_finished(struct l_tls *tls) { uint8_t buf[512]; uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE; uint8_t seed[HANDSHAKE_HASH_MAX_SIZE * 2]; + size_t vdl = tls_verify_data_length(tls, 1); size_t seed_len; if (tls->negotiated_version >= L_TLS_V12) { @@ -1391,8 +1405,8 @@ static void tls_send_finished(struct l_tls *tls) tls->server ? "server finished" : "client finished", seed, seed_len, - ptr, tls->cipher_suite[1]->verify_data_length); - ptr += tls->cipher_suite[1]->verify_data_length; + ptr, vdl); + ptr += vdl; tls_tx_handshake(tls, TLS_FINISHED, buf, ptr - buf); } @@ -1400,14 +1414,14 @@ static void tls_send_finished(struct l_tls *tls) static bool tls_verify_finished(struct l_tls *tls, const uint8_t *received, size_t len) { - uint8_t expected[tls->cipher_suite[0]->verify_data_length]; + size_t vdl = tls_verify_data_length(tls, 0); + uint8_t expected[vdl]; uint8_t *seed; size_t seed_len; - if (len != (size_t) tls->cipher_suite[0]->verify_data_length) { + if (len != vdl) { TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0, - "TLS_FINISHED length not %i", - tls->cipher_suite[0]->verify_data_length); + "TLS_FINISHED length not %zu", vdl); return false; } @@ -1428,8 +1442,7 @@ static bool tls_verify_finished(struct l_tls *tls, const uint8_t *received, tls->server ? "client finished" : "server finished", seed, seed_len, - expected, - tls->cipher_suite[0]->verify_data_length); + expected, vdl); if (memcmp(received, expected, len)) { TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0, -- 2.35.1 ^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2022-07-18 18:04 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-07-18 16:02 [PATCH 1/9] cert/key: Add support for EC based certificates Denis Kenzior 2022-07-18 16:02 ` [PATCH 2/9] unit: Add basic EC-DSA verification test Denis Kenzior 2022-07-18 16:02 ` [PATCH 3/9] key: ECDSA data is given in x962 format Denis Kenzior 2022-07-18 16:02 ` [PATCH 4/9] tls: Support peer certificates that use ECDSA Denis Kenzior 2022-07-18 17:44 ` Mat Martineau 2022-07-18 17:59 ` Denis Kenzior 2022-07-18 16:02 ` [PATCH 5/9] tls: Add helper for DigitallySigned validation Denis Kenzior 2022-07-18 16:02 ` [PATCH 6/9] tls: Add helper to find hash function by id Denis Kenzior 2022-07-18 16:02 ` [PATCH 7/9] tls-suites: Add ECDSA suites from RFC 8422 Denis Kenzior 2022-07-18 17:53 ` Mat Martineau 2022-07-18 16:02 ` [PATCH 8/9] useful: Add maxsize() Denis Kenzior 2022-07-18 16:02 ` [PATCH 9/9] tls: Do not set verify_data_length unless needed Denis Kenzior
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).