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:
193
ssl/t1_lib.c
193
ssl/t1_lib.c
@@ -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 */
|
||||
|
Reference in New Issue
Block a user