diff options
author | Scott Deboy <sdeboy@secondstryke.com> | 2013-06-18 14:34:38 -0700 |
---|---|---|
committer | Scott Deboy <sdeboy@secondstryke.com> | 2014-02-08 16:12:15 -0800 |
commit | 038bec784e528ce273169f178c35991fbc3bea92 (patch) | |
tree | be8a71c2c534db29ea7ee31f1207be9b976b0698 /ssl/s3_srvr.c | |
parent | f407eec799f1f5d271b809875f016f680935567b (diff) |
Add callbacks supporting generation and retrieval of supplemental data entries, facilitating RFC 5878 (TLS auth extensions)
Removed prior audit proof logic - audit proof support was implemented using the generic TLS extension API
Tests exercising the new supplemental data registration and callback api can be found in ssltest.c.
Implemented changes to s_server and s_client to exercise supplemental data callbacks via the -auth argument, as well as additional flags to exercise supplemental data being sent only during renegotiation.
(cherry picked from commit 36086186a9b90cdad0d2cd0a598a10f03f8f4bcc)
Conflicts:
Configure
apps/s_client.c
apps/s_server.c
ssl/ssl.h
ssl/ssl3.h
ssl/ssltest.c
Diffstat (limited to 'ssl/s3_srvr.c')
-rw-r--r-- | ssl/s3_srvr.c | 238 |
1 files changed, 151 insertions, 87 deletions
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 8902303afd..3699524eb3 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -413,14 +413,8 @@ int ssl3_accept(SSL *s) #ifndef OPENSSL_NO_TLSEXT case SSL3_ST_SW_SUPPLEMENTAL_DATA_A: case SSL3_ST_SW_SUPPLEMENTAL_DATA_B: - /* We promised to send an audit proof in the hello. */ - if (s->s3->tlsext_authz_promised_to_client) - { - ret = tls1_send_server_supplemental_data(s); - if (ret <= 0) goto end; - } - else - skip = 1; + ret = tls1_send_server_supplemental_data(s, &skip); + if (ret <= 0) goto end; s->state = SSL3_ST_SW_CERT_A; s->init_num = 0; @@ -595,7 +589,16 @@ int ssl3_accept(SSL *s) s->state=s->s3->tmp.next_state; break; - +#ifndef OPENSSL_NO_TLSEXT + case SSL3_ST_SR_SUPPLEMENTAL_DATA_A: + case SSL3_ST_SR_SUPPLEMENTAL_DATA_B: + ret=tls1_get_client_supplemental_data(s); + if (ret <= 0) goto end; + s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; + s->state=SSL3_ST_SW_FLUSH; + s->init_num=0; + break; +#endif case SSL3_ST_SR_CERT_A: case SSL3_ST_SR_CERT_B: /* Check for second client hello (MS SGC) */ @@ -604,6 +607,10 @@ int ssl3_accept(SSL *s) goto end; if (ret == 2) s->state = SSL3_ST_SR_CLNT_HELLO_C; +#ifndef OPENSSL_NO_TLSEXT + else if (ret == 3) + s->state = SSL3_ST_SR_SUPPLEMENTAL_DATA_A; +#endif else { if (s->s3->tmp.cert_request) { @@ -894,6 +901,12 @@ int ssl3_check_client_hello(SSL *s) &ok); if (!ok) return((int)n); s->s3->tmp.reuse_message = 1; +#ifndef OPENSSL_NO_TLSEXT + if (s->s3->tmp.message_type == SSL3_MT_SUPPLEMENTAL_DATA) + { + return 3; + } +#endif if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO) { /* We only allow the client to restart the handshake once per @@ -3639,98 +3652,149 @@ int ssl3_get_next_proto(SSL *s) } # endif -int tls1_send_server_supplemental_data(SSL *s) +int tls1_send_server_supplemental_data(SSL *s, int *skip) { - size_t length = 0; - const unsigned char *authz, *orig_authz; - unsigned char *p; - size_t authz_length, i; - - if (s->state != SSL3_ST_SW_SUPPLEMENTAL_DATA_A) - return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + if (s->ctx->srv_supp_data_records_count) + { + unsigned char *p = NULL; + unsigned char *size_loc = NULL; + srv_supp_data_record *record = NULL; + size_t length = 0; + size_t i = 0; + + for (i = 0; i < s->ctx->srv_supp_data_records_count; i++) + { + const unsigned char *out = NULL; + unsigned short outlen = 0; + int cb_retval = 0; + record = &s->ctx->srv_supp_data_records[i]; + + /* NULL callback or -1 omits supp data entry */ + if (!record->fn1) + continue; + cb_retval = record->fn1(s, record->supp_data_type, + &out, &outlen, + record->arg); + if (cb_retval == -1) + continue; /* skip this supp data entry */ + if (cb_retval == 0) + { + SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); + return 0; + } + if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length) + { + SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); + return 0; + } + //write supp data entry... + //if first entry, write handshake message type + //jump back to write length at end + if (length == 0) + { + //1 byte message type + 3 bytes for message length + if (!BUF_MEM_grow_clean(s->init_buf, 4)) + { + SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); + return 0; + } + p = (unsigned char *)s->init_buf->data; + *(p++) = SSL3_MT_SUPPLEMENTAL_DATA; + //hold on to length field to update later + size_loc = p; + //skip over handshake length field (3 bytes) and supp_data length field (3 bytes) + p += 3 + 3; + length += 1 +3 +3; + } + //2 byte supp data type + 2 byte length + outlen + if (!BUF_MEM_grow(s->init_buf, outlen + 4)) + { + SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); + return 0; + } + s2n(record->supp_data_type, p); + s2n(outlen, p); + memcpy(p, out, outlen); + //update length to supp data type (2 bytes) + supp data length (2 bytes) + supp data + length += (outlen + 4); + p += outlen; + } + if (length > 0) + { + //write handshake length + l2n3(length - 4, size_loc); + //supp_data length + l2n3(length - 7, size_loc); + s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_B; + s->init_num = length; + s->init_off = 0; - orig_authz = authz = ssl_get_authz_data(s, &authz_length); - if (authz == NULL) - { - /* This should never occur. */ - return 0; + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + } } - /* First we walk over the authz data to see how long the handshake - * message will be. */ - for (i = 0; i < authz_length; i++) - { - unsigned short len; - unsigned char type; + //no supp data message sent + *skip = 1; + s->init_num = 0; + s->init_off = 0; + return 1; + } - type = *(authz++); - n2s(authz, len); - /* n2s increments authz by 2*/ - i += 2; +int tls1_get_client_supplemental_data(SSL *s) + { + int al = 0; + int cb_retval = 0; + int ok; + long n; + const unsigned char *p, *d; + unsigned short supp_data_entry_type = 0; + unsigned long supp_data_entry_len = 0; + unsigned long supp_data_len = 0; + size_t i = 0; - if (memchr(s->s3->tlsext_authz_client_types, - type, - s->s3->tlsext_authz_client_types_len) != NULL) - length += 1 /* authz type */ + 2 /* length */ + len; + n=s->method->ssl_get_message(s, + SSL3_ST_SR_SUPPLEMENTAL_DATA_A, + SSL3_ST_SR_SUPPLEMENTAL_DATA_B, + SSL3_MT_SUPPLEMENTAL_DATA, + /* use default limit */ + TLSEXT_MAXLEN_supplemental_data, + &ok); - authz += len; - i += len; - } + if (!ok) return((int)n); - length += 1 /* handshake type */ + - 3 /* handshake length */ + - 3 /* supplemental data length */ + - 2 /* supplemental entry type */ + - 2 /* supplemental entry length */; + p = (unsigned char *)s->init_msg; + d = p; - if (!BUF_MEM_grow_clean(s->init_buf, length)) + /* The message cannot be empty */ + if (n < 3) { - SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); - return 0; + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_TLS1_GET_CLIENT_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH); + goto f_err; } - - p = (unsigned char *)s->init_buf->data; - *(p++) = SSL3_MT_SUPPLEMENTAL_DATA; - /* Handshake length */ - l2n3(length - 4, p); - /* Length of supplemental data */ - l2n3(length - 7, p); - /* Supplemental data type */ - s2n(TLSEXT_SUPPLEMENTALDATATYPE_authz_data, p); - /* Its length */ - s2n(length - 11, p); - - authz = orig_authz; - - /* Walk over the authz again and append the selected elements. */ - for (i = 0; i < authz_length; i++) + n2l3(p, supp_data_len); + while (p<d+supp_data_len) { - unsigned short len; - unsigned char type; - - type = *(authz++); - n2s(authz, len); - /* n2s increments authz by 2 */ - i += 2; - - if (memchr(s->s3->tlsext_authz_client_types, - type, - s->s3->tlsext_authz_client_types_len) != NULL) + n2s(p, supp_data_entry_type); + n2s(p, supp_data_entry_len); + //if there is a callback for this supp data type, send it + for (i=0; i < s->ctx->srv_supp_data_records_count; i++) { - *(p++) = type; - s2n(len, p); - memcpy(p, authz, len); - p += len; + if (s->ctx->srv_supp_data_records[i].supp_data_type == supp_data_entry_type && s->ctx->srv_supp_data_records[i].fn2) + { + cb_retval = s->ctx->srv_supp_data_records[i].fn2(s, supp_data_entry_type, p, supp_data_entry_len, &al, s->ctx->srv_supp_data_records[i].arg); + if (cb_retval == 0) + { + SSLerr(SSL_F_TLS1_GET_CLIENT_SUPPLEMENTAL_DATA, ERR_R_SSL_LIB); + goto f_err; + } + } } - - authz += len; - i += len; + p+=supp_data_entry_len; } - - s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_B; - s->init_num = length; - s->init_off = 0; - - return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + return 1; +f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); + return -1; } #endif |