From bc86e1d2e1b14c28dc1f9890f589ddc349995287 Mon Sep 17 00:00:00 2001 From: perubeanie Date: Fri, 9 Feb 2024 17:05:55 +0100 Subject: [PATCH] Set shared did methods --- credential.jwt | 1 - ssl/ssl_local.h | 4 +- ssl/ssl_ssi.c | 118 ++++++++++++++++++++++++++++++++++- ssl/statem/extensions.c | 3 +- ssl/statem/extensions_clnt.c | 53 ++++++++++++++-- ssl/statem/extensions_srvr.c | 23 +++++-- ssl/statem/statem_clnt.c | 9 +-- ssl/statem/statem_lib.c | 3 +- ssl/statem/statem_local.h | 3 + 9 files changed, 197 insertions(+), 20 deletions(-) delete mode 100644 credential.jwt diff --git a/credential.jwt b/credential.jwt deleted file mode 100644 index a8e8225cc4f91..0000000000000 --- a/credential.jwt +++ /dev/null @@ -1 +0,0 @@ -1.2.840.30000.1.1 eyJraWQiOiJkaWQ6aW90YTpybXM6MHhjOGVkZTE3NDEyZjdlYWEzNTFhN2NmYjUxYzgzZTJiNmI4MDE0MzEzMGQyYzFmYWJlN2ZjZDgxZGM2MjdmMGM1I2M2Ty1tamdIVWc4dEltQmpiUGNWdUZIcjZydTNhb0J6TEhxT0l5MElSdU0iLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6aW90YTpybXM6MHhjOGVkZTE3NDEyZjdlYWEzNTFhN2NmYjUxYzgzZTJiNmI4MDE0MzEzMGQyYzFmYWJlN2ZjZDgxZGM2MjdmMGM1IiwibmJmIjoxNzA2NTQ1ODM5LCJqdGkiOiJodHRwczovL2V4YW1wbGUuZWR1L2NyZWRlbnRpYWxzLzM3MzIiLCJzdWIiOiJkaWQ6aW90YTpybXM6MHg3ZWQyNTgwMzExMmRmNDMwZWZhZDQ0Y2IzM2ZkNTFmMTJmNzdhMTMxYTg2ZWM2ZDdjZjhhNTZkZGJhZDE2Y2NmIiwidmMiOnsiQGNvbnRleHQiOiJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJXZWJDcmVkZW50aWFsIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7Im5hbWUiOiJ3d3cuc2VydmVyLmNvbSJ9fX0.w0W1eoT5JQR3PmVqbsUJKdl2Wam4sXWr4FAxHB7DF30cXjqUpQ6KUYGoLarrwfweiCVp12604Jtyk1gr9AS_DQ \ No newline at end of file diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 16162a48963c4..48fef0a1b5b1b 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -1644,6 +1644,8 @@ struct ssl_connection_st { size_t didmethods_len; /* our list */ uint16_t *didmethods; + /* used by the client to know if it actually sent did methods */ + uint8_t didmethods_sent; size_t peer_didmethods_len; /* peer's list */ @@ -1839,7 +1841,7 @@ struct ssl_connection_st { * DID methods shared by client and server: cached because these * are used most often. */ - const uint16_t *shared_didmethods; + const uint16_t **shared_didmethods; size_t shared_didmethodslen; #endif diff --git a/ssl/ssl_ssi.c b/ssl/ssl_ssi.c index e401d619cb4e4..7260710fcdbdc 100644 --- a/ssl/ssl_ssi.c +++ b/ssl/ssl_ssi.c @@ -177,12 +177,106 @@ int ssl_setup_didmethods(SSL_CTX *ctx) { } #endif +#ifndef OPENSSL_NO_VCAUTHTLS +static int tls13_shared_didmethods(SSL_CONNECTION *s, + const uint16_t **shdidmethods, + const uint16_t *pref, size_t preflen, + const uint16_t *allow, size_t allowlen) { + const uint16_t *ptmp, *atmp; + size_t i, j, nmatch = 0; + + for(i = 0, ptmp = pref; i < preflen; i++, ptmp++) { + for (j = 0, atmp = allow; j < allowlen; j++, atmp++) { + if (*ptmp == *atmp) { + nmatch++; + if (shdidmethods) + *shdidmethods++ = ptmp; + break; + } + } + } + return nmatch; +} +#endif + +#ifndef OPENSSL_NO_VCAUTHTLS +static int tls13_check_shared_didmethods(SSL_CONNECTION *s, + const uint16_t *pref, size_t preflen, + const uint16_t *allow, size_t allowlen) { + const uint16_t *ptmp, *atmp; + size_t i, j; + + for(i = 0, ptmp = pref; i < preflen; i++, ptmp++) { + for (j = 0, atmp = allow; j < allowlen; j++, atmp++) { + if (*ptmp == *atmp) + break; + } + if(j == allowlen) + return 0; + } + + return 1; +} +#endif + +#ifndef OPENSSL_NO_VCAUTHTLS +static int tls13_set_shared_didmethods(SSL_CONNECTION *s) +{ + const uint16_t *pref, *allow; + const uint16_t **shdidmethods = NULL; + size_t preflen, allowlen; + size_t nmatch; + + OPENSSL_free(s->shared_didmethods); + s->shared_didmethods = NULL; + s->shared_didmethodslen = 0; + + pref = s->ext.peer_didmethods; + preflen = s->ext.peer_didmethods_len; + allow = s->ext.didmethods; + allowlen = s->ext.didmethods_len; + + /* On client side check that each did method sent by the server belong to the client list */ + if(!s->server) + if(!tls13_check_shared_didmethods(s, pref, preflen, allow, allowlen)) + return 0; + + nmatch = tls13_shared_didmethods(s, NULL, pref, preflen, allow, allowlen); + if (nmatch) { + if ((shdidmethods = OPENSSL_malloc(nmatch * sizeof(*shdidmethods))) == NULL) + return 0; + nmatch = tls13_shared_didmethods(s, shdidmethods, pref, preflen, allow, allowlen); + } else { + shdidmethods = NULL; + return 0; /* Maybe should be omitted */ + } + s->shared_didmethods = shdidmethods; + s->shared_didmethodslen = nmatch; + return 1; +} +#endif + #ifndef OPENSSL_NO_VCAUTHTLS int set_server_didmethods(SSL_CONNECTION *s) { - /* The server checks if the client sent the did_methods extension and set the - did_methods they have in common */ + if(s->ext.client_cert_type != TLSEXT_cert_type_vc || !send_certificate_request(s)) + return 1; + + /* The server must have a list of did methods to send */ + if(send_certificate_request(s) && s->ext.didmethods == NULL) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_R_TLSV13_ALERT_MISSING_EXTENSION); + return 0; + } + /* Some day MUST also be checked that the server's DID belongs to the list sent by the client */ + + /* If they both authenticate with VC the server must send a list of + did methods the two have in common. */ + if(s->ext.server_cert_type == TLSEXT_cert_type_vc) + return tls13_set_shared_didmethods(s); + + /* The server will send the full list of did methods */ return 1; } #endif @@ -190,6 +284,26 @@ int set_server_didmethods(SSL_CONNECTION *s) { #ifndef OPENSSL_NO_VCAUTHTLS int process_didmethods(SSL_CONNECTION *s) { + /* If client certificate type is set to VC the list sent by the server can't be empty */ + if(s->ext.peer_didmethods == NULL) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_R_TLSV13_ALERT_MISSING_EXTENSION /* This should be changed to something more appropriate */); + return 0; + } + + /* If the client sent the did methods extension checks that the list sent by the server + is a subset of its list */ + if(s->ext.didmethods_sent) { + if(!tls13_set_shared_didmethods(s)) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_R_TLSV13_ALERT_MISSING_EXTENSION /* This should be changed to something more appropriate */); + return 0; + } + } + + /* Otherwise accepts the whole list sent by the server */ + /* Some day MUST also be checked that the client's DID belongs to the list sent by the server */ + return 1; } #endif \ No newline at end of file diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 7147b74339adc..783c9e9d6a6d0 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -339,7 +339,8 @@ static const EXTENSION_DEFINITION ext_defs[] = { TLSEXT_TYPE_did_methods, SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST | SSL_EXT_TLS1_3_ONLY, - NULL, tls_parse_ctos_did_methods, tls_parse_ctos_did_methods, tls_construct_stoc_did_methods, tls_construct_ctos_did_methods, NULL + NULL, tls_parse_ctos_did_methods, tls_parse_stoc_did_methods, + tls_construct_stoc_did_methods, tls_construct_ctos_did_methods, NULL }, #else INVALID_EXTENSION, diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index f5aac248de90a..4204b7d916f00 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -2145,19 +2145,62 @@ EXT_RETURN tls_construct_ctos_did_methods(SSL_CONNECTION *sc, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { + int i; + sc->ext.didmethods_sent = 0; + if(sc->ext.didmethods == NULL) return EXT_RETURN_NOT_SENT; if(!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_did_methods) || !WPACKET_start_sub_packet_u16(pkt) - /* || !WPACKET_start_sub_packet_u16(pkt) */ - || !WPACKET_sub_memcpy_u16(pkt, sc->ext.didmethods, sc->ext.didmethods_len*2) - || !WPACKET_close(pkt) - /* || !WPACKET_close(pkt) */) { + || !WPACKET_start_sub_packet_u16(pkt)) { SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; + } + + for (i = 0; i < sc->ext.didmethods_len; i++) { + if(!WPACKET_put_bytes_u16(pkt, sc->ext.didmethods[i])) { + SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } } - + if (!WPACKET_close(pkt) + || !WPACKET_close(pkt)) { + SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + sc->ext.didmethods_sent = 1; return EXT_RETURN_SENT; } +#endif + +#ifndef OPENSSL_NO_VCAUTHTLS +int tls_parse_stoc_did_methods(SSL_CONNECTION *sc, PACKET *pkt, + unsigned int context, + X509 *x, size_t chainidx) +{ + PACKET did_methods; + + /* Ignore the extension */ + if(sc->ext.client_cert_type != TLSEXT_cert_type_vc) + return 1; + + if(!PACKET_as_length_prefixed_2(pkt, &did_methods) + || PACKET_remaining(&did_methods) == 0) { + SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); + return 0; + } + + OPENSSL_free(sc->ext.peer_didmethods); + sc->ext.peer_didmethods = NULL; + sc->ext.peer_didmethods_len = 0; + if (!tls1_save_u16(&did_methods, &sc->ext.peer_didmethods, + &sc->ext.peer_didmethods_len)) { + SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} #endif \ No newline at end of file diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index d0e33675bc5bc..b7cde5f6546bc 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -2121,6 +2121,10 @@ int tls_parse_ctos_did_methods(SSL_CONNECTION *sc, PACKET *pkt, { PACKET did_methods; + /* Ignore the extension */ + if(sc->ext.server_cert_type != TLSEXT_cert_type_vc) + return 1; + if(!PACKET_as_length_prefixed_2(pkt, &did_methods) || PACKET_remaining(&did_methods) == 0) { SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); @@ -2147,6 +2151,7 @@ EXT_RETURN tls_construct_stoc_did_methods (SSL_CONNECTION *sc, WPACKET *pkt, { const uint16_t *didmethods; size_t didmethodslen; + int i; if(sc->ext.client_cert_type != TLSEXT_cert_type_vc || sc->ext.didmethods == NULL) @@ -2154,7 +2159,7 @@ EXT_RETURN tls_construct_stoc_did_methods (SSL_CONNECTION *sc, WPACKET *pkt, if (sc->shared_didmethods != NULL) { - didmethods = sc->shared_didmethods; + didmethods = *sc->shared_didmethods; didmethodslen = sc->shared_didmethodslen; } else @@ -2165,9 +2170,19 @@ EXT_RETURN tls_construct_stoc_did_methods (SSL_CONNECTION *sc, WPACKET *pkt, if(!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_did_methods) || !WPACKET_start_sub_packet_u16(pkt) - /* || !WPACKET_start_sub_packet_u16(pkt) */ - || !WPACKET_sub_memcpy_u16(pkt, didmethods, didmethodslen*2) - /* || !WPACKET_close(pkt) */ + || !WPACKET_start_sub_packet_u16(pkt)) { + SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + for(i = 0; i < didmethodslen; i++) { + if(!WPACKET_put_bytes_u16(pkt, didmethods[i])) { + SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + } + + if(!WPACKET_close(pkt) || !WPACKET_close(pkt)) { SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 63ad2ad93fb0e..3997fd84d339b 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -2666,10 +2666,11 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL_CONNECTION *s, return MSG_PROCESS_ERROR; } #ifndef OPENSSL_NO_VCAUTHTLS - if (!process_didmethods(s)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_LENGTH); - return MSG_PROCESS_ERROR; - } + if(s->ext.client_cert_type == TLSEXT_cert_type_vc) + if (!process_didmethods(s)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_LENGTH); + return MSG_PROCESS_ERROR; + } #endif } else { PACKET ctypes; diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c index 7c0266c4d3484..c126c26e9a202 100644 --- a/ssl/statem/statem_lib.c +++ b/ssl/statem/statem_lib.c @@ -1138,10 +1138,9 @@ int tls_process_vc(SSL_CONNECTION *sc, PACKET *pkt, EVP_PKEY **peer_rpk) EVP_PKEY *pkey = NULL; int ret = 0; RAW_EXTENSION *rawexts = NULL; - PACKET extensions; PACKET context; unsigned long cert_len = 0, spki_len = 0; - const unsigned char *spki, *spkistart; + const unsigned char *spki; SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(sc); if (SSL_CONNECTION_IS_TLS13(sc)) { diff --git a/ssl/statem/statem_local.h b/ssl/statem/statem_local.h index 9782b7e614dca..37b8c07f640f4 100644 --- a/ssl/statem/statem_local.h +++ b/ssl/statem/statem_local.h @@ -585,6 +585,9 @@ __owur int tls_process_vc(SSL_CONNECTION *sc, PACKET *pkt, EVP_PKEY **peer_vc); __owur EXT_RETURN tls_construct_ctos_did_methods(SSL_CONNECTION *sc, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx); +__owur int tls_parse_stoc_did_methods(SSL_CONNECTION *sc, PACKET *pkt, + unsigned int context, + X509 *x, size_t chainidx); __owur int tls_parse_ctos_did_methods(SSL_CONNECTION *sc, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx);