diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 51dbca4ee909fe6799646777e426874d4765c398..24360d7280f5828d847abd55548780e073bc3137 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -2503,6 +2503,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN 204 # define SSL_R_EXCESSIVE_MESSAGE_SIZE 152 # define SSL_R_EXTRA_DATA_IN_MESSAGE 153 +# define SSL_R_EXT_LENGTH_MISMATCH 162 # define SSL_R_FAILED_TO_INIT_ASYNC 405 # define SSL_R_FRAGMENTED_CLIENT_HELLO 401 # define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 444de8ebc5ef9fa217b015c1d2de423e59bb89c6..70764b370bdefbd78aebd9de2509e4a388913789 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -565,6 +565,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { "error setting tlsa base domain"}, {ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE), "excessive message size"}, {ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE), "extra data in message"}, + {ERR_REASON(SSL_R_EXT_LENGTH_MISMATCH), "ext length mismatch"}, {ERR_REASON(SSL_R_FAILED_TO_INIT_ASYNC), "failed to init async"}, {ERR_REASON(SSL_R_FRAGMENTED_CLIENT_HELLO), "fragmented client hello"}, {ERR_REASON(SSL_R_GOT_A_FIN_BEFORE_A_CCS), "got a fin before a ccs"}, diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 6e162fb305f4654ced8830e9889392e9917e0bc6..5957718c23c8675931101330cb8d1d1d49461306 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -2196,27 +2196,45 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt) MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) { int ret = MSG_PROCESS_ERROR; - unsigned int list_len, i, name_len; + unsigned int i, name_len; X509_NAME *xn = NULL; const unsigned char *namestart, *namebytes; STACK_OF(X509_NAME) *ca_sk = NULL; - PACKET ctypes; + PACKET cadns; if ((ca_sk = sk_X509_NAME_new(ca_dn_cmp)) == NULL) { SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE); goto err; } - /* get the certificate types */ - if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); - goto err; - } + if (SSL_IS_TLS13(s)) { + PACKET reqctx; + + /* Free and zero certificate types: it is not present in TLS 1.3 */ + OPENSSL_free(s->s3->tmp.ctype); + s->s3->tmp.ctype = NULL; + s->s3->tmp.ctype_len = 0; + /* TODO(TLS1.3) need to process request context, for now ignore */ + if (!PACKET_get_length_prefixed_1(pkt, &reqctx)) { + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_LENGTH_MISMATCH); + goto err; + } + } else { + PACKET ctypes; - if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) { - SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR); + /* get the certificate types */ + if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_LENGTH_MISMATCH); goto err; + } + + if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) { + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR); + goto err; + } } if (SSL_USE_SIGALGS(s)) { @@ -2246,16 +2264,15 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) } /* get the CA RDNs */ - if (!PACKET_get_net_2(pkt, &list_len) - || PACKET_remaining(pkt) != list_len) { + if (!PACKET_get_length_prefixed_2(pkt, &cadns)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); goto err; } - while (PACKET_remaining(pkt)) { - if (!PACKET_get_net_2(pkt, &name_len) - || !PACKET_get_bytes(pkt, &namebytes, name_len)) { + while (PACKET_remaining(&cadns)) { + if (!PACKET_get_net_2(&cadns, &name_len) + || !PACKET_get_bytes(&cadns, &namebytes, name_len)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); @@ -2283,6 +2300,23 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt) } xn = NULL; } + /* TODO(TLS1.3) need to parse and process extensions, for now ignore */ + if (SSL_IS_TLS13(s)) { + PACKET reqexts; + + if (!PACKET_get_length_prefixed_2(pkt, &reqexts)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, + SSL_R_EXT_LENGTH_MISMATCH); + goto err; + } + } + + if (PACKET_remaining(pkt) != 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH); + goto err; + } /* we should setup a certificate to return.... */ s->s3->tmp.cert_req = 1; diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 9c422e47527ba0e8fd17306ffb373ba322b8e001..26c37c73d029345c80302694cc8bcbef5e0c3e6e 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -2448,12 +2448,21 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt) int i; STACK_OF(X509_NAME) *sk = NULL; - /* get the list of acceptable cert types */ - if (!WPACKET_start_sub_packet_u8(pkt) - || !ssl3_get_req_cert_type(s, pkt) - || !WPACKET_close(pkt)) { - SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR); - goto err; + if (SSL_IS_TLS13(s)) { + /* TODO(TLS1.3) for now send empty request context */ + if (!WPACKET_put_bytes_u8(pkt, 0)) { + SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + goto err; + } + } else { + /* get the list of acceptable cert types */ + if (!WPACKET_start_sub_packet_u8(pkt) + || !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) { + SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, + ERR_R_INTERNAL_ERROR); + goto err; + } } if (SSL_USE_SIGALGS(s)) { @@ -2494,11 +2503,18 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt) } } /* else no CA names */ - if (!WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR); goto err; } + /* + * TODO(TLS1.3) implement configurable certificate_extensions + * For now just send zero length extensions. + */ + if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u16(pkt, 0)) { + SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR); + goto err; + } s->s3->tmp.cert_request = 1;