-/* $OpenBSD: ssl_locl.h,v 1.201 2017/10/12 16:06:32 jsing Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.202 2018/01/27 15:30:05 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
__BEGIN_HIDDEN_DECLS
+#define CTASSERT(x) extern char _ctassert[(x) ? 1 : -1 ] \
+ __attribute__((__unused__))
+
#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
int tls1_check_curve(SSL *s, const uint16_t curve_id);
int tls1_get_shared_curve(SSL *s);
-int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data,
- unsigned char *d, int n, int *al);
int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data,
size_t n, int *al);
int ssl_check_clienthello_tlsext_early(SSL *s);
-/* $OpenBSD: ssl_srvr.c,v 1.26 2017/10/12 15:52:50 jsing Exp $ */
+/* $OpenBSD: ssl_srvr.c,v 1.27 2018/01/27 15:30:05 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
int i, j, ok, al, ret = -1, cookie_valid = 0;
long n;
unsigned long id;
- unsigned char *p, *d;
SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *ciphers = NULL;
unsigned long alg_k;
if (n < 0)
goto err;
- d = p = (unsigned char *)s->internal->init_msg;
- end = d + n;
+ end = (unsigned char *)s->internal->init_msg + n;
CBS_init(&cbs, s->internal->init_msg, n);
goto f_err;
}
- p = (unsigned char *)CBS_data(&cbs);
-
- /* TLS extensions*/
- if (!ssl_parse_clienthello_tlsext(s, &p, d, n, &al)) {
- /* 'al' set by ssl_parse_clienthello_tlsext */
+ if (!tlsext_clienthello_parse(s, &cbs, &al)) {
SSLerror(s, SSL_R_PARSE_TLSEXT);
goto f_err;
}
+
+ if (!S3I(s)->renegotiate_seen && s->internal->renegotiate) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ goto f_err;
+ }
+
if (ssl_check_clienthello_tlsext_early(s) <= 0) {
SSLerror(s, SSL_R_CLIENTHELLO_TLSEXT);
goto err;
-/* $OpenBSD: ssl_tlsext.c,v 1.19 2018/01/27 15:17:13 jsing Exp $ */
+/* $OpenBSD: ssl_tlsext.c,v 1.20 2018/01/27 15:30:05 jsing Exp $ */
/*
* Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
#define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions))
+/* Ensure that extensions fit in a uint32_t bitmask. */
+CTASSERT(N_TLS_EXTENSIONS <= (sizeof(uint32_t) * 8));
+
+static struct tls_extension *
+tls_extension_find(uint16_t type, size_t *tls_extensions_idx)
+{
+ size_t i;
+
+ for (i = 0; i < N_TLS_EXTENSIONS; i++) {
+ if (tls_extensions[i].type == type) {
+ *tls_extensions_idx = i;
+ return &tls_extensions[i];
+ }
+ }
+
+ return NULL;
+}
+
+static void
+tlsext_clienthello_reset_state(SSL *s)
+{
+ s->internal->servername_done = 0;
+ s->tlsext_status_type = -1;
+ S3I(s)->renegotiate_seen = 0;
+ free(S3I(s)->alpn_selected);
+ S3I(s)->alpn_selected = NULL;
+ s->internal->srtp_profile = NULL;
+}
+
int
tlsext_clienthello_build(SSL *s, CBB *cbb)
{
}
int
-tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t type, int *alert)
+tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert)
{
+ CBS extensions, extension_data;
struct tls_extension *tlsext;
- size_t i;
+ uint32_t extensions_seen = 0;
+ uint16_t type;
+ size_t idx;
- for (i = 0; i < N_TLS_EXTENSIONS; i++) {
- tlsext = &tls_extensions[i];
+ /* XXX - this possibly should be done by the caller... */
+ tlsext_clienthello_reset_state(s);
- if (tlsext->type != type)
+ /* An empty extensions block is valid. */
+ if (CBS_len(cbs) == 0)
+ return 1;
+
+ *alert = SSL_AD_DECODE_ERROR;
+
+ if (!CBS_get_u16_length_prefixed(cbs, &extensions))
+ return 0;
+
+ while (CBS_len(&extensions) > 0) {
+ if (!CBS_get_u16(&extensions, &type))
+ return 0;
+ if (!CBS_get_u16_length_prefixed(&extensions, &extension_data))
+ return 0;
+
+ if (s->internal->tlsext_debug_cb != NULL)
+ s->internal->tlsext_debug_cb(s, 0, type,
+ (unsigned char *)CBS_data(&extension_data),
+ CBS_len(&extension_data),
+ s->internal->tlsext_debug_arg);
+
+ /* Unknown extensions are ignored. */
+ if ((tlsext = tls_extension_find(type, &idx)) == NULL)
continue;
- if (!tlsext->clienthello_parse(s, cbs, alert))
+
+ /* Check for duplicate extensions. */
+ if ((extensions_seen & (1 << idx)) != 0)
return 0;
- if (CBS_len(cbs) != 0) {
- *alert = SSL_AD_DECODE_ERROR;
+ extensions_seen |= (1 << idx);
+
+ if (!tlsext->clienthello_parse(s, &extension_data, alert))
return 0;
- }
- return 1;
+ if (CBS_len(&extension_data) != 0)
+ return 0;
}
- /* Not found. */
- return 2;
+ return 1;
}
int
-/* $OpenBSD: ssl_tlsext.h,v 1.10 2017/08/27 02:58:04 doug Exp $ */
+/* $OpenBSD: ssl_tlsext.h,v 1.11 2018/01/27 15:30:05 jsing Exp $ */
/*
* Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
#endif
int tlsext_clienthello_build(SSL *s, CBB *cbb);
-int tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type,
- int *alert);
+int tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert);
int tlsext_serverhello_build(SSL *s, CBB *cbb);
int tlsext_serverhello_parse_one(SSL *s, CBS *cbs, uint16_t tlsext_type,
-/* $OpenBSD: t1_lib.c,v 1.139 2017/10/11 17:35:00 jsing Exp $ */
+/* $OpenBSD: t1_lib.c,v 1.140 2018/01/27 15:30:05 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
*sigalgs_len = sizeof(tls12_sigalgs);
}
-int
-ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
- int n, int *al)
-{
- unsigned short type;
- unsigned short size;
- unsigned short len;
- unsigned char *data = *p;
- unsigned char *end = d + n;
- CBS cbs;
-
- s->internal->servername_done = 0;
- s->tlsext_status_type = -1;
- S3I(s)->renegotiate_seen = 0;
- free(S3I(s)->alpn_selected);
- S3I(s)->alpn_selected = NULL;
- s->internal->srtp_profile = NULL;
-
- if (data == end)
- goto ri_check;
-
- if (end - data < 2)
- goto err;
- n2s(data, len);
-
- if (end - data != len)
- goto err;
-
- while (end - data >= 4) {
- n2s(data, type);
- n2s(data, size);
-
- if (end - data < size)
- goto err;
-
- if (s->internal->tlsext_debug_cb)
- s->internal->tlsext_debug_cb(s, 0, type, data, size,
- s->internal->tlsext_debug_arg);
-
- CBS_init(&cbs, data, size);
- if (!tlsext_clienthello_parse_one(s, &cbs, type, al))
- return 0;
-
- data += size;
- }
-
- /* Spurious data on the end */
- if (data != end)
- goto err;
-
- *p = data;
-
-ri_check:
-
- /* Need RI if renegotiating */
-
- if (!S3I(s)->renegotiate_seen && s->internal->renegotiate) {
- *al = SSL_AD_HANDSHAKE_FAILURE;
- SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
- return 0;
- }
-
- return 1;
-
-err:
- *al = SSL_AD_DECODE_ERROR;
- return 0;
-}
-
int
ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, size_t n, int *al)
{