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.
This commit is contained in:
Scott Deboy
2013-06-18 14:34:38 -07:00
committed by Ben Laurie
parent cda01d55ba
commit 36086186a9
25 changed files with 920 additions and 810 deletions

View File

@@ -1445,26 +1445,6 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
ret += el;
}
/* Add TLS extension Server_Authz_DataFormats to the ClientHello */
/* 2 bytes for extension type */
/* 2 bytes for extension length */
/* 1 byte for the list length */
/* 1 byte for the list (we only support audit proofs) */
if (s->ctx->tlsext_authz_server_audit_proof_cb != NULL)
{
const unsigned short ext_len = 2;
const unsigned char list_len = 1;
if (limit < ret + 6)
return NULL;
s2n(TLSEXT_TYPE_server_authz, ret);
/* Extension length: 2 bytes */
s2n(ext_len, ret);
*(ret++) = list_len;
*(ret++) = TLSEXT_AUTHZDATAFORMAT_audit_proof;
}
/* Add custom TLS Extensions to ClientHello */
if (s->ctx->custom_cli_ext_records_count)
{
@@ -1693,79 +1673,6 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
}
#endif
/* If the client supports authz then see whether we have any to offer
* to it. */
if (s->s3->tlsext_authz_client_types_len)
{
size_t authz_length;
/* By now we already know the new cipher, so we can look ahead
* to see whether the cert we are going to send
* has any authz data attached to it. */
const unsigned char* authz = ssl_get_authz_data(s, &authz_length);
const unsigned char* const orig_authz = authz;
size_t i;
unsigned authz_count = 0;
/* The authz data contains a number of the following structures:
* uint8_t authz_type
* uint16_t length
* uint8_t data[length]
*
* First we walk over it to find the number of authz elements. */
for (i = 0; i < authz_length; i++)
{
unsigned short length;
unsigned char type;
type = *(authz++);
if (memchr(s->s3->tlsext_authz_client_types,
type,
s->s3->tlsext_authz_client_types_len) != NULL)
authz_count++;
n2s(authz, length);
/* n2s increments authz by 2 */
i += 2;
authz += length;
i += length;
}
if (authz_count)
{
/* Add TLS extension server_authz to the ServerHello message
* 2 bytes for extension type
* 2 bytes for extension length
* 1 byte for the list length
* n bytes for the list */
const unsigned short ext_len = 1 + authz_count;
if ((long)(limit - ret - 4 - ext_len) < 0) return NULL;
s2n(TLSEXT_TYPE_server_authz, ret);
s2n(ext_len, ret);
*(ret++) = authz_count;
s->s3->tlsext_authz_promised_to_client = 1;
}
authz = orig_authz;
for (i = 0; i < authz_length; i++)
{
unsigned short length;
unsigned char type;
authz_count++;
type = *(authz++);
if (memchr(s->s3->tlsext_authz_client_types,
type,
s->s3->tlsext_authz_client_types_len) != NULL)
*(ret++) = type;
n2s(authz, length);
/* n2s increments authz by 2 */
i += 2;
authz += length;
i += length;
}
}
/* If custom types were sent in ClientHello, add ServerHello responses */
if (s->s3->tlsext_custom_types_count)
{
@@ -2511,66 +2418,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
al))
return 0;
}
else if (type == TLSEXT_TYPE_server_authz)
{
unsigned char *sdata = data;
unsigned char server_authz_dataformatlist_length;
if (size == 0)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
server_authz_dataformatlist_length = *(sdata++);
if (server_authz_dataformatlist_length != size - 1)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
/* Successful session resumption uses the same authz
* information as the original session so we ignore this
* in the case of a session resumption. */
if (!s->hit)
{
if (s->s3->tlsext_authz_client_types != NULL)
OPENSSL_free(s->s3->tlsext_authz_client_types);
s->s3->tlsext_authz_client_types =
OPENSSL_malloc(server_authz_dataformatlist_length);
if (!s->s3->tlsext_authz_client_types)
{
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
s->s3->tlsext_authz_client_types_len =
server_authz_dataformatlist_length;
memcpy(s->s3->tlsext_authz_client_types,
sdata,
server_authz_dataformatlist_length);
/* Sort the types in order to check for duplicates. */
qsort(s->s3->tlsext_authz_client_types,
server_authz_dataformatlist_length,
1 /* element size */,
byte_compare);
for (i = 0; i < server_authz_dataformatlist_length; i++)
{
if (i > 0 &&
s->s3->tlsext_authz_client_types[i] ==
s->s3->tlsext_authz_client_types[i-1])
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
}
}
}
/* If this ClientHello extension was unhandled and this is
* a nonresumed connection, check whether the extension is a
* custom TLS Extension (has a custom_srv_ext_record), and if
@@ -2936,46 +2783,6 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
al))
return 0;
}
else if (type == TLSEXT_TYPE_server_authz)
{
/* We only support audit proofs. It's an error to send
* an authz hello extension if the client
* didn't request a proof. */
unsigned char *sdata = data;
unsigned char server_authz_dataformatlist_length;
if (!s->ctx->tlsext_authz_server_audit_proof_cb)
{
*al = TLS1_AD_UNSUPPORTED_EXTENSION;
return 0;
}
if (!size)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
server_authz_dataformatlist_length = *(sdata++);
if (server_authz_dataformatlist_length != size - 1)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
/* We only support audit proofs, so a legal ServerHello
* authz list contains exactly one entry. */
if (server_authz_dataformatlist_length != 1 ||
sdata[0] != TLSEXT_AUTHZDATAFORMAT_audit_proof)
{
*al = TLS1_AD_UNSUPPORTED_EXTENSION;
return 0;
}
s->s3->tlsext_authz_server_promised = 1;
}
/* If this extension type was not otherwise handled, but
* matches a custom_cli_ext_record, then send it to the c
* callback */