X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=ssl%2Fstatem%2Fextensions.c;h=5a0fa25571f393e421898357e8eaa3bb5f0f6de2;hb=97ea1e7f42eea97b117af08b3c1d29f6443850ab;hp=464a5ef5eb4052befea48735c774ffc9bc7d698c;hpb=29bfd5b79a1ec2be8bea307ffb50810fce11915c;p=openssl.git diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 464a5ef5eb..5a0fa25571 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,8 +9,10 @@ #include #include "internal/nelem.h" +#include "internal/cryptlib.h" #include "../ssl_locl.h" #include "statem_locl.h" +#include "internal/cryptlib.h" static int final_renegotiate(SSL *s, unsigned int context, int sent); static int init_server_name(SSL *s, unsigned int context); @@ -159,8 +161,34 @@ static const EXTENSION_DEFINITION ext_defs[] = { final_ec_pt_formats }, { + /* + * "supported_groups" is spread across several specifications. + * It was originally specified as "elliptic_curves" in RFC 4492, + * and broadened to include named FFDH groups by RFC 7919. + * Both RFCs 4492 and 7919 do not include a provision for the server + * to indicate to the client the complete list of groups supported + * by the server, with the server instead just indicating the + * selected group for this connection in the ServerKeyExchange + * message. TLS 1.3 adds a scheme for the server to indicate + * to the client its list of supported groups in the + * EncryptedExtensions message, but none of the relevant + * specifications permit sending supported_groups in the ServerHello. + * Nonetheless (possibly due to the close proximity to the + * "ec_point_formats" extension, which is allowed in the ServerHello), + * there are several servers that send this extension in the + * ServerHello anyway. Up to and including the 1.1.0 release, + * we did not check for the presence of nonpermitted extensions, + * so to avoid a regression, we must permit this extension in the + * TLS 1.2 ServerHello as well. + * + * Note that there is no tls_parse_stoc_supported_groups function, + * so we do not perform any additional parsing, validation, or + * processing on the server's group list -- this is just a minimal + * change to preserve compatibility with these misbehaving servers. + */ TLSEXT_TYPE_supported_groups, - SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS + | SSL_EXT_TLS1_2_SERVER_HELLO, NULL, tls_parse_ctos_supported_groups, NULL, tls_construct_stoc_supported_groups, tls_construct_ctos_supported_groups, NULL @@ -261,11 +289,14 @@ static const EXTENSION_DEFINITION ext_defs[] = { }, { TLSEXT_TYPE_supported_versions, - SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY - | SSL_EXT_TLS1_3_ONLY, + SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO + | SSL_EXT_TLS1_3_SERVER_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST + | SSL_EXT_TLS_IMPLEMENTATION_ONLY, NULL, /* Processed inline as part of version selection */ - NULL, NULL, NULL, tls_construct_ctos_supported_versions, NULL + NULL, tls_parse_stoc_supported_versions, + tls_construct_stoc_supported_versions, + tls_construct_ctos_supported_versions, NULL }, { TLSEXT_TYPE_psk_kex_modes, @@ -290,11 +321,12 @@ static const EXTENSION_DEFINITION ext_defs[] = { }, #endif { + /* Must be after key_share */ TLSEXT_TYPE_cookie, SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY, - NULL, NULL, tls_parse_stoc_cookie, NULL, tls_construct_ctos_cookie, - NULL + NULL, tls_parse_ctos_cookie, tls_parse_stoc_cookie, + tls_construct_stoc_cookie, tls_construct_ctos_cookie, NULL }, { /* @@ -357,6 +389,44 @@ static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx) return 1; } +int tls_validate_all_contexts(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts) +{ + size_t i, num_exts, builtin_num = OSSL_NELEM(ext_defs), offset; + RAW_EXTENSION *thisext; + unsigned int context; + ENDPOINT role = ENDPOINT_BOTH; + + if ((thisctx & SSL_EXT_CLIENT_HELLO) != 0) + role = ENDPOINT_SERVER; + else if ((thisctx & SSL_EXT_TLS1_2_SERVER_HELLO) != 0) + role = ENDPOINT_CLIENT; + + /* Calculate the number of extensions in the extensions list */ + num_exts = builtin_num + s->cert->custext.meths_count; + + for (thisext = exts, i = 0; i < num_exts; i++, thisext++) { + if (!thisext->present) + continue; + + if (i < builtin_num) { + context = ext_defs[i].context; + } else { + custom_ext_method *meth = NULL; + + meth = custom_ext_find(&s->cert->custext, role, thisext->type, + &offset); + if (!ossl_assert(meth != NULL)) + return 0; + context = meth->context; + } + + if (!validate_context(s, context, thisctx)) + return 0; + } + + return 1; +} + /* * Verify whether we are allowed to use the extension |type| in the current * |context|. Returns 1 to indicate the extension is allowed or unknown or 0 to @@ -1005,7 +1075,7 @@ static int final_alpn(SSL *s, unsigned int context, int sent) * we also have to do this before we decide whether to accept early_data. * In TLSv1.3 we've already negotiated our cipher so we do this call now. * For < TLSv1.3 we defer it until after cipher negotiation. - * + * * On failure SSLfatal() already called. */ return tls_handle_alpn(s); @@ -1169,85 +1239,136 @@ static int final_key_share(SSL *s, unsigned int context, int sent) return 0; } /* - * If + * IF * we are a server - * AND - * we have no key_share * THEN - * If - * we didn't already send a HelloRetryRequest - * AND - * the client sent a key_share extension - * AND - * (we are not resuming - * OR the kex_mode allows key_share resumes) - * AND - * a shared group exists - * THEN - * send a HelloRetryRequest - * ELSE If - * we are not resuming - * OR - * the kex_mode doesn't allow non key_share resumes + * IF + * we have a suitable key_share * THEN - * fail; + * IF + * we are stateless AND we have no cookie + * THEN + * send a HelloRetryRequest + * ELSE + * IF + * we didn't already send a HelloRetryRequest + * AND + * the client sent a key_share extension + * AND + * (we are not resuming + * OR the kex_mode allows key_share resumes) + * AND + * a shared group exists + * THEN + * send a HelloRetryRequest + * ELSE IF + * we are not resuming + * OR + * the kex_mode doesn't allow non key_share resumes + * THEN + * fail + * ELSE IF + * we are stateless AND we have no cookie + * THEN + * send a HelloRetryRequest */ - if (s->server && s->s3->peer_tmp == NULL) { - /* No suitable share */ - if (s->hello_retry_request == 0 && sent - && (!s->hit - || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) - != 0)) { - const uint16_t *pgroups, *clntgroups; - size_t num_groups, clnt_num_groups, i; - unsigned int group_id = 0; - - /* Check if a shared group exists */ - - /* Get the clients list of supported groups. */ - tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups); - tls1_get_supported_groups(s, &pgroups, &num_groups); - - /* Find the first group we allow that is also in client's list */ - for (i = 0; i < num_groups; i++) { - group_id = pgroups[i]; - - if (check_in_list(s, group_id, clntgroups, clnt_num_groups, 1)) - break; + if (s->server) { + if (s->s3->peer_tmp != NULL) { + /* We have a suitable key_share */ + if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0 + && !s->ext.cookieok) { + if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) { + /* + * If we are stateless then we wouldn't know about any + * previously sent HRR - so how can this be anything other + * than 0? + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->hello_retry_request = SSL_HRR_PENDING; + return 1; + } + } else { + /* No suitable key_share */ + if (s->hello_retry_request == SSL_HRR_NONE && sent + && (!s->hit + || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) + != 0)) { + const uint16_t *pgroups, *clntgroups; + size_t num_groups, clnt_num_groups, i; + unsigned int group_id = 0; + + /* Check if a shared group exists */ + + /* Get the clients list of supported groups. */ + tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups); + tls1_get_supported_groups(s, &pgroups, &num_groups); + + /* + * Find the first group we allow that is also in client's list + */ + for (i = 0; i < num_groups; i++) { + group_id = pgroups[i]; + + if (check_in_list(s, group_id, clntgroups, clnt_num_groups, + 1)) + break; + } + + if (i < num_groups) { + /* A shared group exists so send a HelloRetryRequest */ + s->s3->group_id = group_id; + s->hello_retry_request = SSL_HRR_PENDING; + return 1; + } + } + if (!s->hit + || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0) { + /* Nothing left we can do - just fail */ + SSLfatal(s, sent ? SSL_AD_HANDSHAKE_FAILURE + : SSL_AD_MISSING_EXTENSION, + SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE); + return 0; } - if (i < num_groups) { - /* A shared group exists so send a HelloRetryRequest */ - s->s3->group_id = group_id; - s->hello_retry_request = 1; + if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0 + && !s->ext.cookieok) { + if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) { + /* + * If we are stateless then we wouldn't know about any + * previously sent HRR - so how can this be anything other + * than 0? + */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE, + ERR_R_INTERNAL_ERROR); + return 0; + } + s->hello_retry_request = SSL_HRR_PENDING; return 1; } } - if (!s->hit - || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0) { - /* Nothing left we can do - just fail */ - SSLfatal(s, - sent ? SSL_AD_HANDSHAKE_FAILURE : SSL_AD_MISSING_EXTENSION, - SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE); + + /* + * We have a key_share so don't send any more HelloRetryRequest + * messages + */ + if (s->hello_retry_request == SSL_HRR_PENDING) + s->hello_retry_request = SSL_HRR_COMPLETE; + } else { + /* + * For a client side resumption with no key_share we need to generate + * the handshake secret (otherwise this is done during key_share + * processing). + */ + if (!sent && !tls13_generate_handshake_secret(s, NULL, 0)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE, + ERR_R_INTERNAL_ERROR); return 0; } } - /* We have a key_share so don't send any more HelloRetryRequest messages */ - if (s->server) - s->hello_retry_request = 0; - - /* - * For a client side resumption with no key_share we need to generate - * the handshake secret (otherwise this is done during key_share - * processing). - */ - if (!sent && !s->server && !tls13_generate_handshake_secret(s, NULL, 0)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE, - ERR_R_INTERNAL_ERROR); - return 0; - } - return 1; } #endif @@ -1364,7 +1485,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, * following a HelloRetryRequest then this includes the hash of the first * ClientHello and the HelloRetryRequest itself. */ - if (s->hello_retry_request) { + if (s->hello_retry_request == SSL_HRR_PENDING) { size_t hdatalen; void *hdata; @@ -1475,7 +1596,7 @@ static int final_early_data(SSL *s, unsigned int context, int sent) || s->session->ext.tick_identity != 0 || s->early_data_state != SSL_EARLY_DATA_ACCEPTING || !s->ext.early_data_ok - || s->hello_retry_request) { + || s->hello_retry_request != SSL_HRR_NONE) { s->ext.early_data = SSL_EARLY_DATA_REJECTED; } else { s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;