summaryrefslogtreecommitdiffstats
path: root/ssl/s3_clnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/s3_clnt.c')
-rw-r--r--ssl/s3_clnt.c239
1 files changed, 142 insertions, 97 deletions
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 21e09b9394..13006b7e05 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -307,13 +307,6 @@ int ssl3_connect(SSL *s)
}
else
{
-#ifndef OPENSSL_NO_TLSEXT
- /* The server hello indicated that
- * an audit proof would follow. */
- if (s->s3->tlsext_authz_server_promised)
- s->state=SSL3_ST_CR_SUPPLEMENTAL_DATA_A;
- else
-#endif
s->state=SSL3_ST_CR_CERT_A;
}
s->init_num=0;
@@ -332,6 +325,12 @@ int ssl3_connect(SSL *s)
#ifndef OPENSSL_NO_TLSEXT
ret=ssl3_check_finished(s);
if (ret <= 0) goto end;
+ if (ret == 3)
+ {
+ s->state=SSL3_ST_CR_SUPPLEMENTAL_DATA_A;
+ s->init_num=0;
+ break;
+ }
if (ret == 2)
{
s->hit = 1;
@@ -410,10 +409,14 @@ int ssl3_connect(SSL *s)
}
}
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ s->state=SSL3_ST_CW_SUPPLEMENTAL_DATA_A;
+#else
if (s->s3->tmp.cert_req)
s->state=SSL3_ST_CW_CERT_A;
else
s->state=SSL3_ST_CW_KEY_EXCH_A;
+#endif
s->init_num=0;
break;
@@ -520,6 +523,19 @@ int ssl3_connect(SSL *s)
break;
#endif
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL3_ST_CW_SUPPLEMENTAL_DATA_A:
+ case SSL3_ST_CW_SUPPLEMENTAL_DATA_B:
+ ret = tls1_send_client_supplemental_data(s, &skip);
+ if (ret <= 0) goto end;
+ if (s->s3->tmp.cert_req)
+ s->state=SSL3_ST_CW_CERT_A;
+ else
+ s->state=SSL3_ST_CW_KEY_EXCH_A;
+ s->init_num=0;
+ break;
+#endif
+
case SSL3_ST_CW_FINISHED_A:
case SSL3_ST_CW_FINISHED_B:
ret=ssl3_send_finished(s,
@@ -1357,21 +1373,6 @@ int ssl3_get_server_certificate(SSL *s)
s->session->verify_result = s->verify_result;
x=NULL;
-#ifndef OPENSSL_NO_TLSEXT
- /* Check the audit proof. */
- if (s->ctx->tlsext_authz_server_audit_proof_cb)
- {
- ret = s->ctx->tlsext_authz_server_audit_proof_cb(s,
- s->ctx->tlsext_authz_server_audit_proof_cb_arg);
- if (ret <= 0)
- {
- al = SSL_AD_BAD_CERTIFICATE;
- SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_INVALID_AUDIT_PROOF);
- goto f_err;
- }
- }
-
-#endif
ret=1;
if (0)
{
@@ -3563,11 +3564,9 @@ int ssl3_check_finished(SSL *s)
{
int ok;
long n;
- /* If we have no ticket it cannot be a resumed session. */
- if (!s->session->tlsext_tick)
- return 1;
- /* this function is called when we really expect a Certificate
- * message, so permit appropriate message length */
+/* Read the message to see if it is supplemental data, regardless if there is a session ticket
+ this function is called when we really expect a Certificate
+ message, so permit appropriate message length */
n=s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_A,
SSL3_ST_CR_CERT_B,
@@ -3576,6 +3575,14 @@ int ssl3_check_finished(SSL *s)
&ok);
if (!ok) return((int)n);
s->s3->tmp.reuse_message = 1;
+
+ if (s->s3->tmp.message_type == SSL3_MT_SUPPLEMENTAL_DATA)
+ {
+ return 3;
+ }
+ /* If we have no ticket it cannot be a resumed session. */
+ if (!s->session->tlsext_tick)
+ return 1;
if ((s->s3->tmp.message_type == SSL3_MT_FINISHED)
|| (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET))
return 2;
@@ -3603,15 +3610,99 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
}
#ifndef OPENSSL_NO_TLSEXT
+int tls1_send_client_supplemental_data(SSL *s, int *skip)
+ {
+ if (s->ctx->cli_supp_data_records_count)
+ {
+ unsigned char *p = NULL;
+ unsigned char *size_loc = NULL;
+ cli_supp_data_record *record = NULL;
+ size_t length = 0;
+ size_t i = 0;
+
+ for (i = 0; i < s->ctx->cli_supp_data_records_count; i++)
+ {
+ const unsigned char *out = NULL;
+ unsigned short outlen = 0;
+ int cb_retval = 0;
+ record = &s->ctx->cli_supp_data_records[i];
+
+ /* NULL callback or -1 omits supp data entry*/
+ if (!record->fn2)
+ continue;
+ cb_retval = record->fn2(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_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length)
+ {
+ SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ //if first entry, write handshake message type
+ if (length == 0)
+ {
+ if (!BUF_MEM_grow_clean(s->init_buf, 4))
+ {
+ SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ p = (unsigned char *)s->init_buf->data;
+ *(p++) = SSL3_MT_SUPPLEMENTAL_DATA;
+ //update message length when all callbacks complete
+ size_loc = p;
+ //skip over handshake length field (3 bytes) and supp_data length field (3 bytes)
+ p += 3 + 3;
+ length += 1 +3 +3;
+ }
+ if (!BUF_MEM_grow(s->init_buf, outlen + 4))
+ {
+ SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ s2n(record->supp_data_type, p);
+ s2n(outlen, p);
+ memcpy(p, out, outlen);
+ 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_CW_SUPPLEMENTAL_DATA_B;
+ s->init_num = length;
+ s->init_off = 0;
+ return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+ }
+ }
+
+ //no supp data message sent
+ *skip = 1;
+ s->init_num = 0;
+ s->init_off = 0;
+ return 1;
+ }
+
int tls1_get_server_supplemental_data(SSL *s)
{
- int al;
+ int al = 0;
int ok;
- unsigned long supp_data_len, authz_data_len;
long n;
- unsigned short supp_data_type, authz_data_type, proof_len;
- const unsigned char *p;
- unsigned char *new_proof;
+ 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;
+ int cb_retval = 0;
n=s->method->ssl_get_message(s,
SSL3_ST_CR_SUPPLEMENTAL_DATA_A,
@@ -3624,7 +3715,7 @@ int tls1_get_server_supplemental_data(SSL *s)
if (!ok) return((int)n);
p = (unsigned char *)s->init_msg;
-
+ d = p;
/* The message cannot be empty */
if (n < 3)
{
@@ -3632,72 +3723,26 @@ int tls1_get_server_supplemental_data(SSL *s)
SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
- /* Length of supplemental data */
- n2l3(p,supp_data_len);
- n -= 3;
- /* We must have at least one supplemental data entry
- * with type (1 byte) and length (2 bytes). */
- if (supp_data_len != (unsigned long) n || n < 4)
+ n2l3(p, supp_data_len);
+ while (p<d+supp_data_len)
{
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
- /* Supplemental data type: must be authz_data */
- n2s(p,supp_data_type);
- n -= 2;
- if (supp_data_type != TLSEXT_SUPPLEMENTALDATATYPE_authz_data)
- {
- al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_UNKNOWN_SUPPLEMENTAL_DATA_TYPE);
- goto f_err;
- }
- /* Authz data length */
- n2s(p, authz_data_len);
- n -= 2;
- if (authz_data_len != (unsigned long) n || n < 1)
- {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
- /* Authz data type: must be audit_proof */
- authz_data_type = *(p++);
- n -= 1;
- if (authz_data_type != TLSEXT_AUTHZDATAFORMAT_audit_proof)
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_UNKNOWN_AUTHZ_DATA_TYPE);
- goto f_err;
- }
- /* We have a proof: read its length */
- if (n < 2)
- {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
- n2s(p, proof_len);
- n -= 2;
- if (proof_len != (unsigned long) n)
- {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
- /* Store the proof */
- new_proof = OPENSSL_realloc(s->session->audit_proof,
- proof_len);
- if (new_proof == NULL)
- {
- SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,ERR_R_MALLOC_FAILURE);
- return 0;
+ 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->cli_supp_data_records_count; i++)
+ {
+ if (s->ctx->cli_supp_data_records[i].supp_data_type == supp_data_entry_type && s->ctx->cli_supp_data_records[i].fn1)
+ {
+ cb_retval = s->ctx->cli_supp_data_records[i].fn1(s, supp_data_entry_type, p, supp_data_entry_len, &al, s->ctx->cli_supp_data_records[i].arg);
+ if (cb_retval == 0)
+ {
+ SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA, ERR_R_SSL_LIB);
+ goto f_err;
+ }
+ }
+ }
+ p+=supp_data_entry_len;
}
- s->session->audit_proof_length = proof_len;
- s->session->audit_proof = new_proof;
- memcpy(s->session->audit_proof, p, proof_len);
-
- /* Got the proof, but can't verify it yet. */
return 1;
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);