static const SSL_CIPHER *choose_tls13_cipher( const SSL *ssl, const SSL_CLIENT_HELLO *client_hello) { if (client_hello->cipher_suites_len % 2 != 0) { return NULL; } CBS cipher_suites; CBS_init(&cipher_suites, client_hello->cipher_suites, client_hello->cipher_suites_len); const int aes_is_fine = EVP_has_aes_hardware(); const uint16_t version = ssl3_protocol_version(ssl); const SSL_CIPHER *best = NULL; while (CBS_len(&cipher_suites) > 0) { uint16_t cipher_suite; if (!CBS_get_u16(&cipher_suites, &cipher_suite)) { return NULL; } /* Limit to TLS 1.3 ciphers we know about. */ const SSL_CIPHER *candidate = SSL_get_cipher_by_value(cipher_suite); if (candidate == NULL || SSL_CIPHER_get_min_version(candidate) > version || SSL_CIPHER_get_max_version(candidate) < version) { continue; } /* TLS 1.3 removes legacy ciphers, so honor the client order, but prefer * ChaCha20 if we do not have AES hardware. */ if (aes_is_fine) { return candidate; } if (candidate->algorithm_enc == SSL_CHACHA20POLY1305) { return candidate; } if (best == NULL) { best = candidate; } } return best; }
static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) { if (!tls13_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) { return ssl_hs_error; } CBS cbs, server_random, extensions; uint16_t server_wire_version; uint16_t cipher_suite; CBS_init(&cbs, ssl->init_msg, ssl->init_num); if (!CBS_get_u16(&cbs, &server_wire_version) || !CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE) || !CBS_get_u16(&cbs, &cipher_suite) || !CBS_get_u16_length_prefixed(&cbs, &extensions) || CBS_len(&cbs) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return ssl_hs_error; } if (server_wire_version != ssl->version) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER); return ssl_hs_error; } /* Parse out the extensions. */ int have_key_share = 0; CBS key_share; while (CBS_len(&extensions) != 0) { uint16_t type; CBS extension; if (!CBS_get_u16(&extensions, &type) || !CBS_get_u16_length_prefixed(&extensions, &extension)) { OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } switch (type) { case TLSEXT_TYPE_key_share: if (have_key_share) { OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } key_share = extension; have_key_share = 1; break; default: OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); return ssl_hs_error; } } assert(ssl->s3->have_version); memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE); ssl->hit = 0; if (!ssl_get_new_session(ssl, 0)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite); if (cipher == NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } /* Check if the cipher is disabled. */ if ((cipher->algorithm_mkey & ssl->cert->mask_k) || (cipher->algorithm_auth & ssl->cert->mask_a) || SSL_CIPHER_get_min_version(cipher) > ssl3_protocol_version(ssl) || SSL_CIPHER_get_max_version(cipher) < ssl3_protocol_version(ssl) || !sk_SSL_CIPHER_find(ssl_get_ciphers_by_id(ssl), NULL, cipher)) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } ssl->session->cipher = cipher; ssl->s3->tmp.new_cipher = cipher; /* The PRF hash is now known. Set up the key schedule. */ static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0}; size_t hash_len = EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl))); if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) { return ssl_hs_error; } /* Resolve PSK and incorporate it into the secret. */ if (cipher->algorithm_auth == SSL_aPSK) { /* TODO(davidben): Support PSK. */ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return ssl_hs_error; } else if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) { return ssl_hs_error; } /* Resolve ECDHE and incorporate it into the secret. */ if (cipher->algorithm_mkey == SSL_kECDHE) { if (!have_key_share) { OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION); return ssl_hs_error; } uint8_t *dhe_secret; size_t dhe_secret_len; uint8_t alert = SSL_AD_DECODE_ERROR; if (!ext_key_share_parse_serverhello(ssl, &dhe_secret, &dhe_secret_len, &alert, &key_share)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len); OPENSSL_free(dhe_secret); if (!ok) { return ssl_hs_error; } } else { if (have_key_share) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); return ssl_hs_error; } if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) { return ssl_hs_error; } } /* If there was no HelloRetryRequest, the version negotiation logic has * already hashed the message. */ if (ssl->s3->hs->retry_group != 0 && !ssl->method->hash_current_message(ssl)) { return ssl_hs_error; } if (!tls13_set_handshake_traffic(ssl)) { return ssl_hs_error; } hs->state = state_process_encrypted_extensions; return ssl_hs_read_message; }
const SSL_CIPHER *ssl3_choose_cipher( SSL *ssl, const struct ssl_early_callback_ctx *client_hello, const struct ssl_cipher_preference_list_st *server_pref) { const SSL_CIPHER *c, *ret = NULL; STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow; int ok; size_t cipher_index; uint32_t alg_k, alg_a, mask_k, mask_a; /* in_group_flags will either be NULL, or will point to an array of bytes * which indicate equal-preference groups in the |prio| stack. See the * comment about |in_group_flags| in the |ssl_cipher_preference_list_st| * struct. */ const uint8_t *in_group_flags; /* group_min contains the minimal index so far found in a group, or -1 if no * such value exists yet. */ int group_min = -1; STACK_OF(SSL_CIPHER) *clnt = ssl_parse_client_cipher_list(client_hello); if (clnt == NULL) { return NULL; } if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) { prio = srvr; in_group_flags = server_pref->in_group_flags; allow = clnt; } else { prio = clnt; in_group_flags = NULL; allow = srvr; } ssl_get_compatible_server_ciphers(ssl, &mask_k, &mask_a); for (size_t i = 0; i < sk_SSL_CIPHER_num(prio); i++) { c = sk_SSL_CIPHER_value(prio, i); ok = 1; /* Check the TLS version. */ if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) || SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl)) { ok = 0; } alg_k = c->algorithm_mkey; alg_a = c->algorithm_auth; ok = ok && (alg_k & mask_k) && (alg_a & mask_a); if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) { if (in_group_flags != NULL && in_group_flags[i] == 1) { /* This element of |prio| is in a group. Update the minimum index found * so far and continue looking. */ if (group_min == -1 || (size_t)group_min > cipher_index) { group_min = cipher_index; } } else { if (group_min != -1 && (size_t)group_min < cipher_index) { cipher_index = group_min; } ret = sk_SSL_CIPHER_value(allow, cipher_index); break; } } if (in_group_flags != NULL && in_group_flags[i] == 0 && group_min != -1) { /* We are about to leave a group, but we found a match in it, so that's * our answer. */ ret = sk_SSL_CIPHER_value(allow, group_min); break; } } sk_SSL_CIPHER_free(clnt); return ret; }