diff options
Diffstat (limited to 'src/lib/libssl/ssl_tlsext.c')
-rw-r--r-- | src/lib/libssl/ssl_tlsext.c | 82 |
1 files changed, 69 insertions, 13 deletions
diff --git a/src/lib/libssl/ssl_tlsext.c b/src/lib/libssl/ssl_tlsext.c index d0764af3c0..0e3ef7da15 100644 --- a/src/lib/libssl/ssl_tlsext.c +++ b/src/lib/libssl/ssl_tlsext.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_tlsext.c,v 1.19 2018/01/27 15:17:13 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_tlsext.c,v 1.20 2018/01/27 15:30:05 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> | 4 | * Copyright (c) 2017 Doug Hogan <doug@openbsd.org> |
@@ -1292,6 +1292,35 @@ static struct tls_extension tls_extensions[] = { | |||
1292 | 1292 | ||
1293 | #define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) | 1293 | #define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) |
1294 | 1294 | ||
1295 | /* Ensure that extensions fit in a uint32_t bitmask. */ | ||
1296 | CTASSERT(N_TLS_EXTENSIONS <= (sizeof(uint32_t) * 8)); | ||
1297 | |||
1298 | static struct tls_extension * | ||
1299 | tls_extension_find(uint16_t type, size_t *tls_extensions_idx) | ||
1300 | { | ||
1301 | size_t i; | ||
1302 | |||
1303 | for (i = 0; i < N_TLS_EXTENSIONS; i++) { | ||
1304 | if (tls_extensions[i].type == type) { | ||
1305 | *tls_extensions_idx = i; | ||
1306 | return &tls_extensions[i]; | ||
1307 | } | ||
1308 | } | ||
1309 | |||
1310 | return NULL; | ||
1311 | } | ||
1312 | |||
1313 | static void | ||
1314 | tlsext_clienthello_reset_state(SSL *s) | ||
1315 | { | ||
1316 | s->internal->servername_done = 0; | ||
1317 | s->tlsext_status_type = -1; | ||
1318 | S3I(s)->renegotiate_seen = 0; | ||
1319 | free(S3I(s)->alpn_selected); | ||
1320 | S3I(s)->alpn_selected = NULL; | ||
1321 | s->internal->srtp_profile = NULL; | ||
1322 | } | ||
1323 | |||
1295 | int | 1324 | int |
1296 | tlsext_clienthello_build(SSL *s, CBB *cbb) | 1325 | tlsext_clienthello_build(SSL *s, CBB *cbb) |
1297 | { | 1326 | { |
@@ -1329,28 +1358,55 @@ tlsext_clienthello_build(SSL *s, CBB *cbb) | |||
1329 | } | 1358 | } |
1330 | 1359 | ||
1331 | int | 1360 | int |
1332 | tlsext_clienthello_parse_one(SSL *s, CBS *cbs, uint16_t type, int *alert) | 1361 | tlsext_clienthello_parse(SSL *s, CBS *cbs, int *alert) |
1333 | { | 1362 | { |
1363 | CBS extensions, extension_data; | ||
1334 | struct tls_extension *tlsext; | 1364 | struct tls_extension *tlsext; |
1335 | size_t i; | 1365 | uint32_t extensions_seen = 0; |
1366 | uint16_t type; | ||
1367 | size_t idx; | ||
1336 | 1368 | ||
1337 | for (i = 0; i < N_TLS_EXTENSIONS; i++) { | 1369 | /* XXX - this possibly should be done by the caller... */ |
1338 | tlsext = &tls_extensions[i]; | 1370 | tlsext_clienthello_reset_state(s); |
1339 | 1371 | ||
1340 | if (tlsext->type != type) | 1372 | /* An empty extensions block is valid. */ |
1373 | if (CBS_len(cbs) == 0) | ||
1374 | return 1; | ||
1375 | |||
1376 | *alert = SSL_AD_DECODE_ERROR; | ||
1377 | |||
1378 | if (!CBS_get_u16_length_prefixed(cbs, &extensions)) | ||
1379 | return 0; | ||
1380 | |||
1381 | while (CBS_len(&extensions) > 0) { | ||
1382 | if (!CBS_get_u16(&extensions, &type)) | ||
1383 | return 0; | ||
1384 | if (!CBS_get_u16_length_prefixed(&extensions, &extension_data)) | ||
1385 | return 0; | ||
1386 | |||
1387 | if (s->internal->tlsext_debug_cb != NULL) | ||
1388 | s->internal->tlsext_debug_cb(s, 0, type, | ||
1389 | (unsigned char *)CBS_data(&extension_data), | ||
1390 | CBS_len(&extension_data), | ||
1391 | s->internal->tlsext_debug_arg); | ||
1392 | |||
1393 | /* Unknown extensions are ignored. */ | ||
1394 | if ((tlsext = tls_extension_find(type, &idx)) == NULL) | ||
1341 | continue; | 1395 | continue; |
1342 | if (!tlsext->clienthello_parse(s, cbs, alert)) | 1396 | |
1397 | /* Check for duplicate extensions. */ | ||
1398 | if ((extensions_seen & (1 << idx)) != 0) | ||
1343 | return 0; | 1399 | return 0; |
1344 | if (CBS_len(cbs) != 0) { | 1400 | extensions_seen |= (1 << idx); |
1345 | *alert = SSL_AD_DECODE_ERROR; | 1401 | |
1402 | if (!tlsext->clienthello_parse(s, &extension_data, alert)) | ||
1346 | return 0; | 1403 | return 0; |
1347 | } | ||
1348 | 1404 | ||
1349 | return 1; | 1405 | if (CBS_len(&extension_data) != 0) |
1406 | return 0; | ||
1350 | } | 1407 | } |
1351 | 1408 | ||
1352 | /* Not found. */ | 1409 | return 1; |
1353 | return 2; | ||
1354 | } | 1410 | } |
1355 | 1411 | ||
1356 | int | 1412 | int |