+ /* Preserve the raw extensions PACKET for later use */
+ extensions = clienthello.extensions;
+ if (!tls_collect_extensions(&extensions, &clienthello.pre_proc_exts,
+ &clienthello.num_extensions, &al)) {
+ /* SSLerr already been called */
+ goto f_err;
+ }
+
+ /* Finished parsing the ClientHello, now we can start processing it */
+
+ /* Set up the client_random */
+ memcpy(s->s3->client_random, clienthello.random, SSL3_RANDOM_SIZE);
+
+ /* Choose the version */
+
+ if (clienthello.isv2) {
+ if (clienthello.legacy_version == SSL2_VERSION
+ || (clienthello.legacy_version & 0xff00)
+ != (SSL3_VERSION_MAJOR << 8)) {
+ /*
+ * This is real SSLv2 or something complete unknown. We don't
+ * support it.
+ */
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ goto err;
+ }
+ /* SSLv3/TLS */
+ s->client_version = clienthello.legacy_version;
+ }
+ /*
+ * Do SSL/TLS version negotiation if applicable. For DTLS we just check
+ * versions are potentially compatible. Version negotiation comes later.
+ */
+ if (!SSL_IS_DTLS(s)) {
+ protverr = ssl_choose_server_version(s, &clienthello);
+ } else if (s->method->version != DTLS_ANY_VERSION &&
+ DTLS_VERSION_LT((int)clienthello.legacy_version, s->version)) {
+ protverr = SSL_R_VERSION_TOO_LOW;
+ } else {
+ protverr = 0;
+ }
+
+ if (protverr) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, protverr);
+ if ((!s->enc_write_ctx && !s->write_hash)) {
+ /* like ssl3_get_record, send alert using remote version number */
+ s->version = s->client_version = clienthello.legacy_version;
+ }
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+
+ if (SSL_IS_DTLS(s)) {
+ /* Empty cookie was already handled above by returning early. */
+ if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
+ if (s->ctx->app_verify_cookie_cb != NULL) {
+ if (s->ctx->app_verify_cookie_cb(s, clienthello.dtls_cookie,
+ clienthello.dtls_cookie_len) == 0) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
+ SSL_R_COOKIE_MISMATCH);
+ goto f_err;
+ /* else cookie verification succeeded */
+ }
+ /* default verification */
+ } else if (s->d1->cookie_len != clienthello.dtls_cookie_len
+ || memcmp(clienthello.dtls_cookie, s->d1->cookie,
+ s->d1->cookie_len) != 0) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
+ goto f_err;
+ }
+ s->d1->cookie_verified = 1;
+ }
+ if (s->method->version == DTLS_ANY_VERSION) {
+ protverr = ssl_choose_server_version(s, &clienthello);
+ if (protverr != 0) {
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, protverr);
+ s->version = s->client_version;
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ }
+ }
+
+ s->hit = 0;
+
+ /* We need to do this before getting the session */
+ if (!tls_check_client_ems_support(s, &clienthello)) {
+ /* Only fails if the extension is malformed */
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+ goto f_err;
+ }
+
+ /*