libressl-portable/tests/tls_ext_alpn.c
2023-09-03 18:11:42 -07:00

443 lines
14 KiB
C

/* $OpenBSD: tls_ext_alpn.c,v 1.9 2022/11/26 16:08:57 tb Exp $ */
/*
* Copyright (c) 2015 Doug Hogan <doug@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Test TLS extension Application-Layer Protocol Negotiation (RFC 7301).
*/
#include <stdio.h>
#include <openssl/ssl.h>
#include "ssl_local.h"
#include "ssl_tlsext.h"
#include "tests.h"
/*
* In the ProtocolNameList, ProtocolNames must not include empty strings and
* byte strings must not be truncated.
*
* This uses some of the IANA approved protocol names from:
* http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
*/
/* Valid for client and server since it only has one name. */
static uint8_t proto_single[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0f, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x0b, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x09, /* len of all names */
/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
0x08, /* len */
0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31
};
/* Valid for client, but NOT server. Server must have exactly one name. */
static uint8_t proto_multiple1[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x19, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x15, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x13, /* len of all names */
/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
0x08, /* len */
0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
/* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */
0x09, /* len */
0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e
};
/* Valid for client, but NOT server. Server must have exactly one name. */
static uint8_t proto_multiple2[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x1c, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x18, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x16, /* len of all names */
/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
0x08, /* len */
0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
/* opaque ProtocolName<1..2^8-1> -- 'h2' */
0x02, /* len */
0x68, 0x32,
/* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */
0x09, /* len */
0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e
};
/* Valid for client, but NOT server. Server must have exactly one name. */
static uint8_t proto_multiple3[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x20, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x1c, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x1a, /* len of all names */
/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
0x08, /* len */
0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
/* opaque ProtocolName<1..2^8-1> -- 'h2' */
0x02, /* len */
0x68, 0x32,
/* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */
0x09, /* len */
0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e,
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
0x03, /* len */
0x68, 0x32, 0x63
};
static uint8_t proto_empty[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions. */
0x00, 0x00, /* none present. */
};
/* Invalid for both client and server. Length is wrong. */
static uint8_t proto_invalid_len1[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x06, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x04, /* len of all names */
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
0x04, /* XXX len too large */
0x68, 0x32, 0x63
};
static uint8_t proto_invalid_len2[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x06, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x04, /* len of all names */
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
0x02, /* XXX len too small */
0x68, 0x32, 0x63
};
static uint8_t proto_invalid_len3[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x06, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x03, /* XXX len too small */
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
0x03, /* len */
0x68, 0x32, 0x63
};
static uint8_t proto_invalid_len4[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x06, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x06, /* XXX len too large */
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
0x03, /* len */
0x68, 0x32, 0x63
};
static uint8_t proto_invalid_len5[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x01, 0x08, /* XXX len too large */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x04, /* len */
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
0x03, /* len */
0x68, 0x32, 0x63
};
static uint8_t proto_invalid_len6[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x05, /* XXX len too small */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x04, /* len */
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
0x03, /* len */
0x68, 0x32, 0x63
};
static uint8_t proto_invalid_len7[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x06, /* XXX len too small */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x06, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x04, /* len */
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
0x03, /* len */
0x68, 0x32, 0x63
};
static uint8_t proto_invalid_len8[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0b, /* XXX len too large */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x06, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x04, /* len */
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
0x03, /* len */
0x68, 0x32, 0x63
};
/* Invalid for client and server since it is missing data. */
static uint8_t proto_invalid_missing1[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x06, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x04, /* len of all names */
/* opaque ProtocolName<1..2^8-1> -- 'h2c' */
/* XXX missing */
};
static uint8_t proto_invalid_missing2[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x00, /* XXX missing name list */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
};
static uint8_t proto_invalid_missing3[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x02, /* XXX size is sufficient but missing data for name list */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
};
static uint8_t proto_invalid_missing4[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x0a, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
/* XXX missing */
};
static uint8_t proto_invalid_missing5[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x1c, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x18, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x16, /* len of all names */
/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
0x08, /* len */
0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31,
/* opaque ProtocolName<1..2^8-1> -- 'h2' */
0x02, /* len */
0x68, 0x32,
/* XXX missing name */
};
static uint8_t proto_invalid_missing6[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x07, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x03, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x01, /* XXX len must be at least 2 */
/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
0x00, /* XXX len cannot be 0 */
};
static uint8_t proto_invalid_missing7[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x07, /* len */
/* ExtensionType extension_type */
0x00, 0x10, /* ALPN */
/* opaque extension_data<0..2^16-1> */
0x00, 0x03, /* len */
/* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */
0x00, 0x02, /* XXX len is at least 2 but not correct. */
/* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */
0x00, /* XXX len cannot be 0 */
};
static uint8_t proto_invalid_missing8[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x00, 0x01, /* len */
/* ExtensionType extension_type */
0x00, /* XXX need a 2 byte type */
};
static uint8_t proto_invalid_missing9[] = {
/* Extension extensions<0..2^16-1> -- All TLS extensions */
0x0a, /* XXX need a 2 byte len */
};
#define CHECK_BOTH(c_val, s_val, proto) do { \
{ \
CBS cbs; \
int al; \
\
CBS_init(&cbs, proto, sizeof(proto)); \
CHECK(c_val == tlsext_server_parse(s, SSL_TLSEXT_MSG_CH, &cbs, &al)); \
CBS_init(&cbs, proto, sizeof(proto)); \
CHECK(s_val == tlsext_client_parse(s, SSL_TLSEXT_MSG_SH, &cbs, &al)); \
} \
} while (0)
static int dummy_alpn_cb(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in, unsigned int inlen,
void *arg);
static int
check_valid_alpn(SSL *s)
{
const uint8_t str[] = {
0x08, /* len */
0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 /* http/1.1 */
};
/* Setup in order to test ALPN. */
CHECK(! SSL_set_alpn_protos(s, str, 9));
SSL_CTX_set_alpn_select_cb(s->ctx, dummy_alpn_cb, NULL);
/* Prerequisites to test these. */
CHECK(s->alpn_client_proto_list != NULL);
CHECK(s->ctx->alpn_select_cb != NULL);
//CHECK(s->s3->tmp.finish_md_len == 0);
CHECK_BOTH(1, 1, proto_single);
CHECK_BOTH(1, 1, proto_empty);
/* Multiple protocol names are only valid for client */
CHECK_BOTH(1, 0, proto_multiple1);
CHECK_BOTH(1, 0, proto_multiple2);
CHECK_BOTH(1, 0, proto_multiple3);
return 1;
}
/*
* Some of the IANA approved IDs from:
* http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
*/
static int
check_invalid_alpn(SSL *s)
{
const uint8_t str[] = {
0x08, /* len */
0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 /* http/1.1 */
};
/* Setup in order to test ALPN. */
CHECK(! SSL_set_alpn_protos(s, str, 9));
SSL_CTX_set_alpn_select_cb(s->ctx, dummy_alpn_cb, NULL);
/* Prerequisites to test these. */
CHECK(s->alpn_client_proto_list != NULL);
CHECK(s->ctx->alpn_select_cb != NULL);
//CHECK(s->s3->tmp.finish_md_len == 0);
/* None of these are valid for client or server */
CHECK_BOTH(0, 0, proto_invalid_len1);
CHECK_BOTH(0, 0, proto_invalid_len2);
CHECK_BOTH(0, 0, proto_invalid_len3);
CHECK_BOTH(0, 0, proto_invalid_len4);
CHECK_BOTH(0, 0, proto_invalid_len5);
CHECK_BOTH(0, 0, proto_invalid_len6);
CHECK_BOTH(0, 0, proto_invalid_len7);
CHECK_BOTH(0, 0, proto_invalid_len8);
CHECK_BOTH(0, 0, proto_invalid_missing1);
CHECK_BOTH(0, 0, proto_invalid_missing2);
CHECK_BOTH(0, 0, proto_invalid_missing3);
CHECK_BOTH(0, 0, proto_invalid_missing4);
CHECK_BOTH(0, 0, proto_invalid_missing5);
CHECK_BOTH(0, 0, proto_invalid_missing6);
CHECK_BOTH(0, 0, proto_invalid_missing7);
CHECK_BOTH(0, 0, proto_invalid_missing8);
CHECK_BOTH(0, 0, proto_invalid_missing9);
return 1;
}
int
dummy_alpn_cb(SSL *ssl __attribute__((unused)), const unsigned char **out,
unsigned char *outlen, const unsigned char *in, unsigned int inlen,
void *arg __attribute__((unused)))
{
*out = in;
*outlen = (unsigned char)inlen;
return 0;
}
int
main(void)
{
SSL_CTX *ctx = NULL;
SSL *s = NULL;
int rv = 1;
SSL_library_init();
CHECK_GOTO((ctx = SSL_CTX_new(TLSv1_2_client_method())) != NULL);
CHECK_GOTO((s = SSL_new(ctx)) != NULL);
if (!check_valid_alpn(s))
goto err;
if (!check_invalid_alpn(s))
goto err;
rv = 0;
err:
SSL_CTX_free(ctx);
SSL_free(s);
if (!rv)
printf("PASS %s\n", __FILE__);
return rv;
}