* [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
* [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
* [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
* 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 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
* 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
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 read-only IMAP folder(s) and NNTP newsgroup(s).