aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2017-02-22 17:26:44 +0000
committerDr. Stephen Henson <steve@openssl.org>2017-02-27 18:23:18 +0000
commit03f44b974b1c85804b54af7c3ffb5241d5ffd952 (patch)
treea5da2267b5cc1e615edb973040fed6c2cfc89aca
parent013bc448672cbc3c9cd154709400c676c2955229 (diff)
downloadopenssl-03f44b974b1c85804b54af7c3ffb5241d5ffd952.tar.gz
Initial incomplete TLS 1.3 certificate request support.
This adds partial support for TLS 1.3 certificate request message. The request context and extensions are currently ignored on receive and set to zero length on send. Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2728)
-rw-r--r--include/openssl/ssl.h1
-rw-r--r--ssl/ssl_err.c1
-rw-r--r--ssl/statem/statem_clnt.c64
-rw-r--r--ssl/statem/statem_srvr.c30
4 files changed, 74 insertions, 22 deletions
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 51dbca4ee9..24360d7280 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 444de8ebc5..70764b370b 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 6e162fb305..5957718c23 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 9c422e4752..26c37c73d0 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;