summaryrefslogtreecommitdiffstats
path: root/ssl/s3_srvr.c
diff options
context:
space:
mode:
authorBen Laurie <ben@openssl.org>2012-05-29 17:27:48 +0000
committerBen Laurie <ben@openssl.org>2012-05-29 17:27:48 +0000
commit8a02a46a5cb92790c79bfbf04c043e234e2af6bf (patch)
treeb1f3963b25a9be2887d673228df7d811a1572d59 /ssl/s3_srvr.c
parent0de5a0feeef1e43aa080189c25af691448a2d860 (diff)
RFC 5878 support.
Diffstat (limited to 'ssl/s3_srvr.c')
-rw-r--r--ssl/s3_srvr.c116
1 files changed, 114 insertions, 2 deletions
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 2132514efd..d8b61f2c65 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -401,9 +401,30 @@ int ssl3_accept(SSL *s)
s->state=SSL3_ST_SW_CHANGE_A;
#endif
else
- s->state=SSL3_ST_SW_CERT_A;
- s->init_num=0;
+#ifndef OPENSSL_NO_TLSEXT
+ s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_A;
+#else
+ s->state = SSL3_ST_SW_CERT_A;
+#endif
+ s->init_num = 0;
+ break;
+
+#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;
+
+ s->state = SSL3_ST_SW_CERT_A;
+ s->init_num = 0;
break;
+#endif
case SSL3_ST_SW_CERT_A:
case SSL3_ST_SW_CERT_B:
@@ -3619,4 +3640,95 @@ int ssl3_get_next_proto(SSL *s)
return 1;
}
# endif
+
+int tls1_send_server_supplemental_data(SSL *s)
+ {
+ 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);
+
+ orig_authz = authz = ssl_get_authz_data(s, &authz_length);
+ if (authz == NULL)
+ {
+ /* This should never occur. */
+ return 0;
+ }
+
+ /* 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;
+
+ type = *(authz++);
+ n2s(authz, len);
+
+ if (memchr(s->s3->tlsext_authz_client_types,
+ type,
+ s->s3->tlsext_authz_client_types_len) != NULL)
+ length += 1 /* authz type */ + 2 /* length */ + len;
+
+ authz += len;
+ i += len;
+ }
+
+ length += 1 /* handshake type */ +
+ 3 /* handshake length */ +
+ 3 /* supplemental data length */ +
+ 2 /* supplemental entry type */ +
+ 2 /* supplemental entry length */;
+
+ if (!BUF_MEM_grow_clean(s->init_buf, length))
+ {
+ 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;
+ /* 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++)
+ {
+ unsigned short len;
+ unsigned char type;
+
+ type = *(authz++);
+ n2s(authz, len);
+
+ if (memchr(s->s3->tlsext_authz_client_types,
+ type,
+ s->s3->tlsext_authz_client_types_len) != NULL)
+ {
+ *(p++) = type;
+ s2n(len, p);
+ memcpy(p, authz, len);
+ p += len;
+ }
+
+ authz += len;
+ i += 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);
+ }
#endif