diff options
author | Adam Langley <agl@google.com> | 2014-12-19 04:42:32 +0300 |
---|---|---|
committer | Adam Langley <agl@google.com> | 2014-12-19 04:43:03 +0300 |
commit | fcf25833bc4d057377da1ea755f57b2f5126e555 (patch) | |
tree | f9c9c70afa73cc9935c836debb23f6f897266f1b /ssl/s3_srvr.c | |
parent | 4685e87746bbb6a47772feda773ce9f098948479 (diff) |
Reformat the rest of ssl/.
Change-Id: I7dc264f7e29b3ba8be4c717583467edf71bf8dd9
Diffstat (limited to 'ssl/s3_srvr.c')
-rw-r--r-- | ssl/s3_srvr.c | 5431 |
1 files changed, 2608 insertions, 2823 deletions
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 170777b5..88f462b2 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -172,2857 +172,2642 @@ #include "../crypto/internal.h" #include "../crypto/dh/internal.h" + /* INITIAL_SNIFF_BUFFER_SIZE is the number of bytes read in the initial sniff * buffer. */ #define INITIAL_SNIFF_BUFFER_SIZE 8 -int ssl3_accept(SSL *s) - { - BUF_MEM *buf = NULL; - unsigned long alg_a; - void (*cb)(const SSL *ssl,int type,int val)=NULL; - int ret= -1; - int new_state,state,skip=0; - - assert(s->handshake_func == ssl3_accept); - assert(s->server); - assert(!SSL_IS_DTLS(s)); - - ERR_clear_error(); - ERR_clear_system_error(); - - if (s->info_callback != NULL) - cb=s->info_callback; - else if (s->ctx->info_callback != NULL) - cb=s->ctx->info_callback; - - s->in_handshake++; - - if (s->cert == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_NO_CERTIFICATE_SET); - return(-1); - } - - for (;;) - { - state=s->state; - - switch (s->state) - { - case SSL_ST_RENEGOTIATE: - /* This state is the renegotiate entry point. It sends a - * HelloRequest and nothing else. */ - s->renegotiate = 1; - - if (cb != NULL) - cb(s, SSL_CB_HANDSHAKE_START, 1); - - if (s->init_buf == NULL) - { - buf = BUF_MEM_new(); - if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) - { - ret = -1; - goto end; - } - s->init_buf = buf; - buf = NULL; - } - s->init_num = 0; - - if (!ssl3_setup_buffers(s)) - { - ret = -1; - goto end; - } - - if (!s->s3->send_connection_binding && - !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) - { - /* Server attempting to renegotiate with - * client that doesn't support secure - * renegotiation. - */ - OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); - ret = -1; - goto end; - } - - s->ctx->stats.sess_accept_renegotiate++; - s->state = SSL3_ST_SW_HELLO_REQ_A; - break; - - case SSL3_ST_SW_HELLO_REQ_A: - case SSL3_ST_SW_HELLO_REQ_B: - - s->shutdown=0; - ret=ssl3_send_hello_request(s); - if (ret <= 0) goto end; - s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C; - s->state=SSL3_ST_SW_FLUSH; - s->init_num=0; - - if (!ssl3_init_finished_mac(s)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); - ret = -1; - goto end; - } - break; - - case SSL3_ST_SW_HELLO_REQ_C: - s->state=SSL_ST_OK; - break; - - case SSL_ST_ACCEPT: - case SSL_ST_BEFORE|SSL_ST_ACCEPT: - /* This state is the entry point for the handshake - * itself (initial and renegotiation). */ - if (cb != NULL) - cb(s, SSL_CB_HANDSHAKE_START, 1); - - if (s->init_buf == NULL) - { - buf = BUF_MEM_new(); - if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) - { - ret = -1; - goto end; - } - s->init_buf = buf; - buf = NULL; - } - s->init_num = 0; - - if (!ssl3_init_finished_mac(s)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); - ret = -1; - goto end; - } - - if (!s->s3->have_version) - { - /* This is the initial handshake. The record - * layer has not been initialized yet. Sniff for - * a V2ClientHello before reading a ClientHello - * normally. */ - assert(s->s3->rbuf.buf == NULL); - assert(s->s3->wbuf.buf == NULL); - s->state = SSL3_ST_SR_INITIAL_BYTES; - } - else - { - /* Enable a write buffer. This groups handshake - * messages within a flight into a single - * write. */ - if (!ssl3_setup_buffers(s) || - !ssl_init_wbio_buffer(s, 1)) - { - ret = -1; - goto end; - } - s->state = SSL3_ST_SR_CLNT_HELLO_A; - } - s->ctx->stats.sess_accept++; - break; - - case SSL3_ST_SR_INITIAL_BYTES: - ret = ssl3_get_initial_bytes(s); - if (ret <= 0) - goto end; - /* ssl3_get_initial_bytes sets s->state to one of - * SSL3_ST_SR_V2_CLIENT_HELLO or SSL3_ST_SR_CLNT_HELLO_A - * on success. */ - break; - - case SSL3_ST_SR_V2_CLIENT_HELLO: - ret = ssl3_get_v2_client_hello(s); - if (ret <= 0) - goto end; - s->state = SSL3_ST_SR_CLNT_HELLO_A; - break; - - case SSL3_ST_SR_CLNT_HELLO_A: - case SSL3_ST_SR_CLNT_HELLO_B: - case SSL3_ST_SR_CLNT_HELLO_C: - case SSL3_ST_SR_CLNT_HELLO_D: - s->shutdown=0; - ret=ssl3_get_client_hello(s); - if (ret == PENDING_SESSION) { - s->rwstate = SSL_PENDING_SESSION; - goto end; - } - if (ret == CERTIFICATE_SELECTION_PENDING) - { - s->rwstate = SSL_CERTIFICATE_SELECTION_PENDING; - goto end; - } - if (ret <= 0) goto end; - s->renegotiate = 2; - s->state=SSL3_ST_SW_SRVR_HELLO_A; - s->init_num=0; - break; - - case SSL3_ST_SW_SRVR_HELLO_A: - case SSL3_ST_SW_SRVR_HELLO_B: - ret=ssl3_send_server_hello(s); - if (ret <= 0) goto end; - if (s->hit) - { - if (s->tlsext_ticket_expected) - s->state=SSL3_ST_SW_SESSION_TICKET_A; - else - s->state=SSL3_ST_SW_CHANGE_A; - } - else - s->state = SSL3_ST_SW_CERT_A; - s->init_num = 0; - break; - - case SSL3_ST_SW_CERT_A: - case SSL3_ST_SW_CERT_B: - if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) - { - ret=ssl3_send_server_certificate(s); - if (ret <= 0) goto end; - if (s->s3->tmp.certificate_status_expected) - s->state=SSL3_ST_SW_CERT_STATUS_A; - else - s->state=SSL3_ST_SW_KEY_EXCH_A; - } - else - { - skip = 1; - s->state=SSL3_ST_SW_KEY_EXCH_A; - } - s->init_num=0; - break; - - case SSL3_ST_SW_KEY_EXCH_A: - case SSL3_ST_SW_KEY_EXCH_B: - alg_a = s->s3->tmp.new_cipher->algorithm_auth; - - /* Send a ServerKeyExchange message if: - * - The key exchange is ephemeral or anonymous - * Diffie-Hellman. - * - There is a PSK identity hint. - * - * TODO(davidben): This logic is currently duplicated - * in d1_srvr.c. Fix this. In the meantime, keep them - * in sync. - */ - if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) || - ((alg_a & SSL_aPSK) && s->psk_identity_hint)) - { - ret=ssl3_send_server_key_exchange(s); - if (ret <= 0) goto end; - } - else - skip=1; - - s->state=SSL3_ST_SW_CERT_REQ_A; - s->init_num=0; - break; - - case SSL3_ST_SW_CERT_REQ_A: - case SSL3_ST_SW_CERT_REQ_B: - if (/* don't request cert unless asked for it: */ - !(s->verify_mode & SSL_VERIFY_PEER) || - /* Don't request a certificate if an obc was presented */ - ((s->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) && - s->s3->tlsext_channel_id_valid) || - /* if SSL_VERIFY_CLIENT_ONCE is set, - * don't request cert during re-negotiation: */ - ((s->session->peer != NULL) && - (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || - /* never request cert in anonymous ciphersuites - * (see section "Certificate request" in SSL 3 drafts - * and in RFC 2246): */ - ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && - /* ... except when the application insists on verification - * (against the specs, but s3_clnt.c accepts this for SSL 3) */ - !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || - /* With normal PSK Certificates and - * Certificate Requests are omitted */ - (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) - { - /* no cert request */ - skip=1; - s->s3->tmp.cert_request=0; - s->state=SSL3_ST_SW_SRVR_DONE_A; - if (s->s3->handshake_buffer) - if (!ssl3_digest_cached_records(s, free_handshake_buffer)) - return -1; - } - else - { - s->s3->tmp.cert_request=1; - ret=ssl3_send_certificate_request(s); - if (ret <= 0) goto end; +int ssl3_accept(SSL *s) { + BUF_MEM *buf = NULL; + unsigned long alg_a; + void (*cb)(const SSL *ssl, int type, int val) = NULL; + int ret = -1; + int new_state, state, skip = 0; + + assert(s->handshake_func == ssl3_accept); + assert(s->server); + assert(!SSL_IS_DTLS(s)); + + ERR_clear_error(); + ERR_clear_system_error(); + + if (s->info_callback != NULL) { + cb = s->info_callback; + } else if (s->ctx->info_callback != NULL) { + cb = s->ctx->info_callback; + } + + s->in_handshake++; + + if (s->cert == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_NO_CERTIFICATE_SET); + return -1; + } + + for (;;) { + state = s->state; + + switch (s->state) { + case SSL_ST_RENEGOTIATE: + /* This state is the renegotiate entry point. It sends a HelloRequest + * and nothing else. */ + s->renegotiate = 1; + + if (cb != NULL) { + cb(s, SSL_CB_HANDSHAKE_START, 1); + } + + if (s->init_buf == NULL) { + buf = BUF_MEM_new(); + if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { + ret = -1; + goto end; + } + s->init_buf = buf; + buf = NULL; + } + s->init_num = 0; + + if (!ssl3_setup_buffers(s)) { + ret = -1; + goto end; + } + + if (!s->s3->send_connection_binding && + !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { + /* Server attempting to renegotiate with client that doesn't support + * secure renegotiation. */ + OPENSSL_PUT_ERROR(SSL, ssl3_accept, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + ret = -1; + goto end; + } + + s->ctx->stats.sess_accept_renegotiate++; + s->state = SSL3_ST_SW_HELLO_REQ_A; + break; + + case SSL3_ST_SW_HELLO_REQ_A: + case SSL3_ST_SW_HELLO_REQ_B: + s->shutdown = 0; + ret = ssl3_send_hello_request(s); + if (ret <= 0) { + goto end; + } + s->s3->tmp.next_state = SSL3_ST_SW_HELLO_REQ_C; + s->state = SSL3_ST_SW_FLUSH; + s->init_num = 0; + + if (!ssl3_init_finished_mac(s)) { + OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + break; + + case SSL3_ST_SW_HELLO_REQ_C: + s->state = SSL_ST_OK; + break; + + case SSL_ST_ACCEPT: + case SSL_ST_BEFORE | SSL_ST_ACCEPT: + /* This state is the entry point for the handshake itself (initial and + * renegotiation). */ + if (cb != NULL) { + cb(s, SSL_CB_HANDSHAKE_START, 1); + } + + if (s->init_buf == NULL) { + buf = BUF_MEM_new(); + if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { + ret = -1; + goto end; + } + s->init_buf = buf; + buf = NULL; + } + s->init_num = 0; + + if (!ssl3_init_finished_mac(s)) { + OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + + if (!s->s3->have_version) { + /* This is the initial handshake. The record layer has not been + * initialized yet. Sniff for a V2ClientHello before reading a + * ClientHello normally. */ + assert(s->s3->rbuf.buf == NULL); + assert(s->s3->wbuf.buf == NULL); + s->state = SSL3_ST_SR_INITIAL_BYTES; + } else { + /* Enable a write buffer. This groups handshake messages within a + * flight into a single write. */ + if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) { + ret = -1; + goto end; + } + s->state = SSL3_ST_SR_CLNT_HELLO_A; + } + s->ctx->stats.sess_accept++; + break; + + case SSL3_ST_SR_INITIAL_BYTES: + ret = ssl3_get_initial_bytes(s); + if (ret <= 0) { + goto end; + } + /* ssl3_get_initial_bytes sets s->state to one of + * SSL3_ST_SR_V2_CLIENT_HELLO or SSL3_ST_SR_CLNT_HELLO_A on success. */ + break; + + case SSL3_ST_SR_V2_CLIENT_HELLO: + ret = ssl3_get_v2_client_hello(s); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SR_CLNT_HELLO_A; + break; + + case SSL3_ST_SR_CLNT_HELLO_A: + case SSL3_ST_SR_CLNT_HELLO_B: + case SSL3_ST_SR_CLNT_HELLO_C: + case SSL3_ST_SR_CLNT_HELLO_D: + s->shutdown = 0; + ret = ssl3_get_client_hello(s); + if (ret == PENDING_SESSION) { + s->rwstate = SSL_PENDING_SESSION; + goto end; + } + if (ret == CERTIFICATE_SELECTION_PENDING) { + s->rwstate = SSL_CERTIFICATE_SELECTION_PENDING; + goto end; + } + if (ret <= 0) { + goto end; + } + s->renegotiate = 2; + s->state = SSL3_ST_SW_SRVR_HELLO_A; + s->init_num = 0; + break; + + case SSL3_ST_SW_SRVR_HELLO_A: + case SSL3_ST_SW_SRVR_HELLO_B: + ret = ssl3_send_server_hello(s); + if (ret <= 0) { + goto end; + } + if (s->hit) { + if (s->tlsext_ticket_expected) { + s->state = SSL3_ST_SW_SESSION_TICKET_A; + } else { + s->state = SSL3_ST_SW_CHANGE_A; + } + } else { + s->state = SSL3_ST_SW_CERT_A; + } + s->init_num = 0; + break; + + case SSL3_ST_SW_CERT_A: + case SSL3_ST_SW_CERT_B: + if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { + ret = ssl3_send_server_certificate(s); + if (ret <= 0) { + goto end; + } + if (s->s3->tmp.certificate_status_expected) { + s->state = SSL3_ST_SW_CERT_STATUS_A; + } else { + s->state = SSL3_ST_SW_KEY_EXCH_A; + } + } else { + skip = 1; + s->state = SSL3_ST_SW_KEY_EXCH_A; + } + s->init_num = 0; + break; + + case SSL3_ST_SW_KEY_EXCH_A: + case SSL3_ST_SW_KEY_EXCH_B: + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + + /* Send a ServerKeyExchange message if: + * - The key exchange is ephemeral or anonymous + * Diffie-Hellman. + * - There is a PSK identity hint. + * + * TODO(davidben): This logic is currently duplicated in d1_srvr.c. Fix + * this. In the meantime, keep them in sync. */ + if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) || + ((alg_a & SSL_aPSK) && s->psk_identity_hint)) { + ret = ssl3_send_server_key_exchange(s); + if (ret <= 0) + goto end; + } else { + skip = 1; + } + + s->state = SSL3_ST_SW_CERT_REQ_A; + s->init_num = 0; + break; + + case SSL3_ST_SW_CERT_REQ_A: + case SSL3_ST_SW_CERT_REQ_B: + if (/* don't request cert unless asked for it: */ + !(s->verify_mode & SSL_VERIFY_PEER) || + /* Don't request a certificate if an obc was presented */ + ((s->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) && + s->s3->tlsext_channel_id_valid) || + /* if SSL_VERIFY_CLIENT_ONCE is set, + * don't request cert during re-negotiation: */ + ((s->session->peer != NULL) && + (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || + /* never request cert in anonymous ciphersuites + * (see section "Certificate request" in SSL 3 drafts + * and in RFC 2246): */ + ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && + /* ... except when the application insists on verification + * (against the specs, but s3_clnt.c accepts this for SSL 3) */ + !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || + /* With normal PSK Certificates and + * Certificate Requests are omitted */ + (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + /* no cert request */ + skip = 1; + s->s3->tmp.cert_request = 0; + s->state = SSL3_ST_SW_SRVR_DONE_A; + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + return -1; + } + } else { + s->s3->tmp.cert_request = 1; + ret = ssl3_send_certificate_request(s); + if (ret <= 0) { + goto end; + } #ifndef NETSCAPE_HANG_BUG - s->state=SSL3_ST_SW_SRVR_DONE_A; + s->state = SSL3_ST_SW_SRVR_DONE_A; #else - /* ServerHelloDone was already sent in the - * previous record. */ - s->state=SSL3_ST_SW_FLUSH; - s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; -#endif - s->init_num=0; - } - break; - - case SSL3_ST_SW_SRVR_DONE_A: - case SSL3_ST_SW_SRVR_DONE_B: - ret=ssl3_send_server_done(s); - if (ret <= 0) goto end; - s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; - s->state=SSL3_ST_SW_FLUSH; - s->init_num=0; - break; - - case SSL3_ST_SW_FLUSH: - - /* This code originally checked to see if - * any data was pending using BIO_CTRL_INFO - * and then flushed. This caused problems - * as documented in PR#1939. The proposed - * fix doesn't completely resolve this issue - * as buggy implementations of BIO_CTRL_PENDING - * still exist. So instead we just flush - * unconditionally. - */ - - s->rwstate=SSL_WRITING; - if (BIO_flush(s->wbio) <= 0) - { - ret= -1; - goto end; - } - s->rwstate=SSL_NOTHING; - - s->state=s->s3->tmp.next_state; - break; - - case SSL3_ST_SR_CERT_A: - case SSL3_ST_SR_CERT_B: - if (s->s3->tmp.cert_request) - { - ret=ssl3_get_client_certificate(s); - if (ret <= 0) goto end; - } - s->init_num=0; - s->state=SSL3_ST_SR_KEY_EXCH_A; - break; - - case SSL3_ST_SR_KEY_EXCH_A: - case SSL3_ST_SR_KEY_EXCH_B: - ret=ssl3_get_client_key_exchange(s); - if (ret <= 0) - goto end; - s->state=SSL3_ST_SR_CERT_VRFY_A; - s->init_num=0; - break; - - case SSL3_ST_SR_CERT_VRFY_A: - case SSL3_ST_SR_CERT_VRFY_B: - ret=ssl3_get_cert_verify(s); - if (ret <= 0) goto end; - - s->state = SSL3_ST_SR_CHANGE; - s->init_num=0; - break; - - case SSL3_ST_SR_CHANGE: { - char next_proto_neg = 0; - char channel_id = 0; - next_proto_neg = s->s3->next_proto_neg_seen; - channel_id = s->s3->tlsext_channel_id_valid; - - /* At this point, the next message must be entirely - * behind a ChangeCipherSpec. */ - if (!ssl3_expect_change_cipher_spec(s)) - { - ret = -1; - goto end; - } - if (next_proto_neg) - s->state = SSL3_ST_SR_NEXT_PROTO_A; - else if (channel_id) - s->state = SSL3_ST_SR_CHANNEL_ID_A; - else - s->state = SSL3_ST_SR_FINISHED_A; - break; - } - - case SSL3_ST_SR_NEXT_PROTO_A: - case SSL3_ST_SR_NEXT_PROTO_B: - ret=ssl3_get_next_proto(s); - if (ret <= 0) goto end; - s->init_num = 0; - if (s->s3->tlsext_channel_id_valid) - s->state=SSL3_ST_SR_CHANNEL_ID_A; - else - s->state=SSL3_ST_SR_FINISHED_A; - break; - - case SSL3_ST_SR_CHANNEL_ID_A: - case SSL3_ST_SR_CHANNEL_ID_B: - ret=ssl3_get_channel_id(s); - if (ret <= 0) goto end; - s->init_num = 0; - s->state=SSL3_ST_SR_FINISHED_A; - break; - - case SSL3_ST_SR_FINISHED_A: - case SSL3_ST_SR_FINISHED_B: - ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, - SSL3_ST_SR_FINISHED_B); - if (ret <= 0) goto end; - if (s->hit) - s->state=SSL_ST_OK; - else if (s->tlsext_ticket_expected) - s->state=SSL3_ST_SW_SESSION_TICKET_A; - else - s->state=SSL3_ST_SW_CHANGE_A; - /* If this is a full handshake with ChannelID then - * record the hashshake hashes in |s->session| in case - * we need them to verify a ChannelID signature on a - * resumption of this session in the future. */ - if (!s->hit && s->s3->tlsext_channel_id_new) - { - ret = tls1_record_handshake_hashes_for_channel_id(s); - if (ret <= 0) goto end; - } - s->init_num=0; - break; - - case SSL3_ST_SW_SESSION_TICKET_A: - case SSL3_ST_SW_SESSION_TICKET_B: - ret=ssl3_send_new_session_ticket(s); - if (ret <= 0) goto end; - s->state=SSL3_ST_SW_CHANGE_A; - s->init_num=0; - break; - -#if 0 - // TODO(davidben): Implement OCSP stapling on the server. - case SSL3_ST_SW_CERT_STATUS_A: - case SSL3_ST_SW_CERT_STATUS_B: - ret=ssl3_send_cert_status(s); - if (ret <= 0) goto end; - s->state=SSL3_ST_SW_KEY_EXCH_A; - s->init_num=0; - break; + /* ServerHelloDone was already sent in the + * previous record. */ + s->state = SSL3_ST_SW_FLUSH; + s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; #endif + s->init_num = 0; + } + break; + + case SSL3_ST_SW_SRVR_DONE_A: + case SSL3_ST_SW_SRVR_DONE_B: + ret = ssl3_send_server_done(s); + if (ret <= 0) { + goto end; + } + s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; + s->state = SSL3_ST_SW_FLUSH; + s->init_num = 0; + break; + + case SSL3_ST_SW_FLUSH: + /* This code originally checked to see if any data was pending using + * BIO_CTRL_INFO and then flushed. This caused problems as documented + * in PR#1939. The proposed fix doesn't completely resolve this issue + * as buggy implementations of BIO_CTRL_PENDING still exist. So instead + * we just flush unconditionally. */ + s->rwstate = SSL_WRITING; + if (BIO_flush(s->wbio) <= 0) { + ret = -1; + goto end; + } + s->rwstate = SSL_NOTHING; + + s->state = s->s3->tmp.next_state; + break; + + case SSL3_ST_SR_CERT_A: + case SSL3_ST_SR_CERT_B: + if (s->s3->tmp.cert_request) { + ret = ssl3_get_client_certificate(s); + if (ret <= 0) { + goto end; + } + } + s->init_num = 0; + s->state = SSL3_ST_SR_KEY_EXCH_A; + break; + + case SSL3_ST_SR_KEY_EXCH_A: + case SSL3_ST_SR_KEY_EXCH_B: + ret = ssl3_get_client_key_exchange(s); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SR_CERT_VRFY_A; + s->init_num = 0; + break; + + case SSL3_ST_SR_CERT_VRFY_A: + case SSL3_ST_SR_CERT_VRFY_B: + ret = ssl3_get_cert_verify(s); + if (ret <= 0) { + goto end; + } + + s->state = SSL3_ST_SR_CHANGE; + s->init_num = 0; + break; + + case SSL3_ST_SR_CHANGE: { + char next_proto_neg = 0; + char channel_id = 0; + next_proto_neg = s->s3->next_proto_neg_seen; + channel_id = s->s3->tlsext_channel_id_valid; + + /* At this point, the next message must be entirely behind a + * ChangeCipherSpec. */ + if (!ssl3_expect_change_cipher_spec(s)) { + ret = -1; + goto end; + } + if (next_proto_neg) { + s->state = SSL3_ST_SR_NEXT_PROTO_A; + } else if (channel_id) { + s->state = SSL3_ST_SR_CHANNEL_ID_A; + } else { + s->state = SSL3_ST_SR_FINISHED_A; + } + break; + } + + case SSL3_ST_SR_NEXT_PROTO_A: + case SSL3_ST_SR_NEXT_PROTO_B: + ret = ssl3_get_next_proto(s); + if (ret <= 0) { + goto end; + } + s->init_num = 0; + if (s->s3->tlsext_channel_id_valid) { + s->state = SSL3_ST_SR_CHANNEL_ID_A; + } else { + s->state = SSL3_ST_SR_FINISHED_A; + } + break; + + case SSL3_ST_SR_CHANNEL_ID_A: + case SSL3_ST_SR_CHANNEL_ID_B: + ret = ssl3_get_channel_id(s); + if (ret <= 0) { + goto end; + } + s->init_num = 0; + s->state = SSL3_ST_SR_FINISHED_A; + break; + + case SSL3_ST_SR_FINISHED_A: + case SSL3_ST_SR_FINISHED_B: + ret = + ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); + if (ret <= 0) { + goto end; + } + + if (s->hit) { + s->state = SSL_ST_OK; + } else if (s->tlsext_ticket_expected) { + s->state = SSL3_ST_SW_SESSION_TICKET_A; + } else { + s->state = SSL3_ST_SW_CHANGE_A; + } + /* If this is a full handshake with ChannelID then record the hashshake + * hashes in |s->session| in case we need them to verify a ChannelID + * signature on a resumption of this session in the future. */ + if (!s->hit && s->s3->tlsext_channel_id_new) { + ret = tls1_record_handshake_hashes_for_channel_id(s); + if (ret <= 0) { + goto end; + } + } + s->init_num = 0; + break; + + case SSL3_ST_SW_SESSION_TICKET_A: + case SSL3_ST_SW_SESSION_TICKET_B: + ret = ssl3_send_new_session_ticket(s); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SW_CHANGE_A; + s->init_num = 0; + break; + + case SSL3_ST_SW_CHANGE_A: + case SSL3_ST_SW_CHANGE_B: + s->session->cipher = s->s3->tmp.new_cipher; + if (!s->enc_method->setup_key_block(s)) { + ret = -1; + goto end; + } + + ret = ssl3_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A, + SSL3_ST_SW_CHANGE_B); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SW_FINISHED_A; + s->init_num = 0; + + if (!s->enc_method->change_cipher_state( + s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { + ret = -1; + goto end; + } + break; + + case SSL3_ST_SW_FINISHED_A: + case SSL3_ST_SW_FINISHED_B: + ret = + ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A, SSL3_ST_SW_FINISHED_B, + s->enc_method->server_finished_label, + s->enc_method->server_finished_label_len); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SW_FLUSH; + if (s->hit) { + s->s3->tmp.next_state = SSL3_ST_SR_CHANGE; + } else { + s->s3->tmp.next_state = SSL_ST_OK; + } + s->init_num = 0; + break; + + case SSL_ST_OK: + /* clean a few things up */ + ssl3_cleanup_key_block(s); + + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; + + /* remove buffering on output */ + ssl_free_wbio_buffer(s); + + s->init_num = 0; + + /* If we aren't retaining peer certificates then we can discard it + * now. */ + if (s->session->peer && s->ctx->retain_only_sha256_of_client_certs) { + X509_free(s->session->peer); + s->session->peer = NULL; + } + + if (s->renegotiate == 2) { + /* skipped if we just sent a HelloRequest */ + s->renegotiate = 0; + s->new_session = 0; + + ssl_update_cache(s, SSL_SESS_CACHE_SERVER); + + s->ctx->stats.sess_accept_good++; + + if (cb != NULL) { + cb(s, SSL_CB_HANDSHAKE_DONE, 1); + } + } + + ret = 1; + goto end; + + default: + OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_UNKNOWN_STATE); + ret = -1; + goto end; + } + + if (!s->s3->tmp.reuse_message && !skip && cb != NULL && s->state != state) { + new_state = s->state; + s->state = state; + cb(s, SSL_CB_ACCEPT_LOOP, 1); + s->state = new_state; + } + skip = 0; + } - case SSL3_ST_SW_CHANGE_A: - case SSL3_ST_SW_CHANGE_B: - - s->session->cipher=s->s3->tmp.new_cipher; - if (!s->enc_method->setup_key_block(s)) - { ret= -1; goto end; } - - ret=ssl3_send_change_cipher_spec(s, - SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B); - - if (ret <= 0) goto end; - s->state=SSL3_ST_SW_FINISHED_A; - s->init_num=0; - - if (!s->enc_method->change_cipher_state(s, - SSL3_CHANGE_CIPHER_SERVER_WRITE)) - { - ret= -1; - goto end; - } - - break; - - case SSL3_ST_SW_FINISHED_A: - case SSL3_ST_SW_FINISHED_B: - ret=ssl3_send_finished(s, - SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, - s->enc_method->server_finished_label, - s->enc_method->server_finished_label_len); - if (ret <= 0) goto end; - s->state = SSL3_ST_SW_FLUSH; - if (s->hit) - s->s3->tmp.next_state = SSL3_ST_SR_CHANGE; - else - s->s3->tmp.next_state = SSL_ST_OK; - s->init_num=0; - break; - - case SSL_ST_OK: - /* clean a few things up */ - ssl3_cleanup_key_block(s); - - BUF_MEM_free(s->init_buf); - s->init_buf=NULL; - - /* remove buffering on output */ - ssl_free_wbio_buffer(s); - - s->init_num=0; - - /* If we aren't retaining peer certificates then we can - * discard it now. */ - if (s->session->peer && s->ctx->retain_only_sha256_of_client_certs) - { - X509_free(s->session->peer); - s->session->peer = NULL; - } - - if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ - { - s->renegotiate=0; - s->new_session=0; - - ssl_update_cache(s,SSL_SESS_CACHE_SERVER); - - s->ctx->stats.sess_accept_good++; - /* s->server=1; */ - - if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); - } - - ret = 1; - goto end; - /* break; */ - - default: - OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_UNKNOWN_STATE); - ret= -1; - goto end; - /* break; */ - } - - if (!s->s3->tmp.reuse_message && !skip) - { - if ((cb != NULL) && (s->state != state)) - { - new_state=s->state; - s->state=state; - cb(s,SSL_CB_ACCEPT_LOOP,1); - s->state=new_state; - } - } - skip=0; - } end: - /* BIO_flush(s->wbio); */ - - s->in_handshake--; - if (buf != NULL) - BUF_MEM_free(buf); - if (cb != NULL) - cb(s,SSL_CB_ACCEPT_EXIT,ret); - return(ret); - } - -static int ssl3_read_sniff_buffer(SSL *s, size_t n) - { - if (s->s3->sniff_buffer == NULL) - { - s->s3->sniff_buffer = BUF_MEM_new(); - } - if (s->s3->sniff_buffer == NULL || - !BUF_MEM_grow(s->s3->sniff_buffer, n)) - { - return -1; - } - - while (s->s3->sniff_buffer_len < n) - { - int ret; - - s->rwstate = SSL_READING; - ret = BIO_read(s->rbio, - s->s3->sniff_buffer->data + s->s3->sniff_buffer_len, - n - s->s3->sniff_buffer_len); - if (ret <= 0) - return ret; - s->rwstate = SSL_NOTHING; - s->s3->sniff_buffer_len += ret; - } - return 1; - } - -int ssl3_get_initial_bytes(SSL *s) - { - int ret; - const uint8_t *p; - - /* Read the first 8 bytes. To recognize a ClientHello or V2ClientHello - * only needs the first 6 bytes, but 8 is needed to recognize CONNECT - * below. */ - ret = ssl3_read_sniff_buffer(s, INITIAL_SNIFF_BUFFER_SIZE); - if (ret <= 0) - return ret; - assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE); - p = (const uint8_t *)s->s3->sniff_buffer->data; - - /* Some dedicated error codes for protocol mixups should the application - * wish to interpret them differently. (These do not overlap with - * ClientHello or V2ClientHello.) */ - if (strncmp("GET ", (const char *)p, 4) == 0 || - strncmp("POST ", (const char *)p, 5) == 0 || - strncmp("HEAD ", (const char *)p, 5) == 0 || - strncmp("PUT ", (const char *)p, 4) == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTP_REQUEST); - return -1; - } - if (strncmp("CONNECT ", (const char *)p, 8) == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTPS_PROXY_REQUEST); - return -1; - } - - /* Determine if this is a ClientHello or V2ClientHello. */ - - if ((p[0] & 0x80) && p[2] == SSL2_MT_CLIENT_HELLO && - p[3] >= SSL3_VERSION_MAJOR) - { - /* This is a V2ClientHello. */ - s->state = SSL3_ST_SR_V2_CLIENT_HELLO; - return 1; - } - if (p[0] == SSL3_RT_HANDSHAKE && p[1] >= SSL3_VERSION_MAJOR && - p[5] == SSL3_MT_CLIENT_HELLO) - { - /* This is a ClientHello. Initialize the record layer with the - * already consumed data and continue the handshake. */ - if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) - { - return -1; - } - assert(s->rstate == SSL_ST_READ_HEADER); - memcpy(s->s3->rbuf.buf, p, s->s3->sniff_buffer_len); - s->s3->rbuf.offset = 0; - s->s3->rbuf.left = s->s3->sniff_buffer_len; - s->packet_length = 0; - - BUF_MEM_free(s->s3->sniff_buffer); - s->s3->sniff_buffer = NULL; - s->s3->sniff_buffer_len = 0; - - s->state = SSL3_ST_SR_CLNT_HELLO_A; - return 1; - } - - OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_UNKNOWN_PROTOCOL); - return -1; - } - -int ssl3_get_v2_client_hello(SSL *s) - { - const uint8_t *p; - int ret; - CBS v2_client_hello, cipher_specs, session_id, challenge; - size_t msg_length, rand_len, len; - uint8_t msg_type; - uint16_t version, cipher_spec_length, session_id_length, challenge_length; - CBB client_hello, hello_body, cipher_suites; - uint8_t random[SSL3_RANDOM_SIZE]; - - /* Read the remainder of the V2ClientHello. We have previously read 8 - * bytes in ssl3_get_initial_bytes. */ - assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE); - p = (const uint8_t *)s->s3->sniff_buffer->data; - msg_length = ((p[0] & 0x7f) << 8) | p[1]; - if (msg_length > (1024 * 4)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_RECORD_TOO_LARGE); - return -1; - } - if (msg_length < INITIAL_SNIFF_BUFFER_SIZE - 2) - { - /* Reject lengths that are too short early. We have already read - * 8 bytes, so we should not attempt to process an (invalid) - * V2ClientHello which would be shorter than that. */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_RECORD_LENGTH_MISMATCH); - return -1; - } - - ret = ssl3_read_sniff_buffer(s, msg_length + 2); - if (ret <= 0) - return ret; - assert(s->s3->sniff_buffer_len == msg_length + 2); - CBS_init(&v2_client_hello, - (const uint8_t *)s->s3->sniff_buffer->data + 2, msg_length); - - /* The V2ClientHello without the length is incorporated into the - * Finished hash. */ - ssl3_finish_mac(s, CBS_data(&v2_client_hello), CBS_len(&v2_client_hello)); - if (s->msg_callback) - s->msg_callback(0, SSL2_VERSION, 0, CBS_data(&v2_client_hello), - CBS_len(&v2_client_hello), s, s->msg_callback_arg); - - if (!CBS_get_u8(&v2_client_hello, &msg_type) || - !CBS_get_u16(&v2_client_hello, &version) || - !CBS_get_u16(&v2_client_hello, &cipher_spec_length) || - !CBS_get_u16(&v2_client_hello, &session_id_length) || - !CBS_get_u16(&v2_client_hello, &challenge_length) || - !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) || - !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) || - !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) || - CBS_len(&v2_client_hello) != 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR); - return -1; - } - - /* msg_type has already been checked. */ - assert(msg_type == SSL2_MT_CLIENT_HELLO); - - /* The client_random is the V2ClientHello challenge. Truncate or - * left-pad with zeros as needed. */ - memset(random, 0, SSL3_RANDOM_SIZE); - rand_len = CBS_len(&challenge); - if (rand_len > SSL3_RANDOM_SIZE) - rand_len = SSL3_RANDOM_SIZE; - memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge), rand_len); - - /* Write out an equivalent SSLv3 ClientHello. */ - if (!CBB_init_fixed(&client_hello, (uint8_t *)s->init_buf->data, s->init_buf->max)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_MALLOC_FAILURE); - return -1; - } - if (!CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) || - !CBB_add_u24_length_prefixed(&client_hello, &hello_body) || - !CBB_add_u16(&hello_body, version) || - !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) || - /* No session id. */ - !CBB_add_u8(&hello_body, 0) || - !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) - { - CBB_cleanup(&client_hello); - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - - /* Copy the cipher suites. */ - while (CBS_len(&cipher_specs) > 0) - { - uint32_t cipher_spec; - if (!CBS_get_u24(&cipher_specs, &cipher_spec)) - { - CBB_cleanup(&client_hello); - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR); - return -1; - } - - /* Skip SSLv2 ciphers. */ - if ((cipher_spec & 0xff0000) != 0) - continue; - if (!CBB_add_u16(&cipher_suites, cipher_spec)) - { - CBB_cleanup(&client_hello); - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - } - - /* Add the null compression scheme and finish. */ - if (!CBB_add_u8(&hello_body, 1) || - !CBB_add_u8(&hello_body, 0) || - !CBB_finish(&client_hello, NULL, &len)) - { - CBB_cleanup(&client_hello); - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - - /* Mark the message for "re"-use by the version-specific - * method. */ - s->s3->tmp.reuse_message = 1; - s->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO; - /* The handshake message header is 4 bytes. */ - s->s3->tmp.message_size = len - 4; - - /* Initialize the record layer. */ - if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) - { - return -1; - } - - /* Drop the sniff buffer. */ - BUF_MEM_free(s->s3->sniff_buffer); - s->s3->sniff_buffer = NULL; - s->s3->sniff_buffer_len = 0; - - return 1; - } - -int ssl3_send_hello_request(SSL *s) - { - - if (s->state == SSL3_ST_SW_HELLO_REQ_A) - { - ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0); - s->state=SSL3_ST_SW_HELLO_REQ_B; - } - - /* SSL3_ST_SW_HELLO_REQ_B */ - return ssl_do_write(s); - } - -int ssl3_get_client_hello(SSL *s) - { - int i,ok,al=SSL_AD_INTERNAL_ERROR,ret= -1; - long n; - const SSL_CIPHER *c; - STACK_OF(SSL_CIPHER) *ciphers=NULL; - struct ssl_early_callback_ctx early_ctx; - CBS client_hello; - uint16_t client_version; - CBS client_random, session_id, cipher_suites, compression_methods; - - /* We do this so that we will respond with our native type. - * If we are TLSv1 and we get SSLv3, we will respond with TLSv1, - * This down switching should be handled by a different method. - * If we are SSLv3, we will respond with SSLv3, even if prompted with - * TLSv1. - */ - switch (s->state) { - case SSL3_ST_SR_CLNT_HELLO_A: - case SSL3_ST_SR_CLNT_HELLO_B: - n=s->method->ssl_get_message(s, - SSL3_ST_SR_CLNT_HELLO_A, - SSL3_ST_SR_CLNT_HELLO_B, - SSL3_MT_CLIENT_HELLO, - SSL3_RT_MAX_PLAIN_LENGTH, - SSL_GET_MESSAGE_HASH_MESSAGE, - &ok); - - if (!ok) return((int)n); - - /* If we require cookies and this ClientHello doesn't - * contain one, just return since we do not want to - * allocate any memory yet. So check cookie length... - */ - if (SSL_IS_DTLS(s) && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) - { - uint8_t cookie_length; - - CBS_init(&client_hello, s->init_msg, n); - if (!CBS_skip(&client_hello, 2 + SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&client_hello, &session_id) || - !CBS_get_u8(&client_hello, &cookie_length)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); - goto f_err; - } - - if (cookie_length == 0) - return 1; - } - s->state = SSL3_ST_SR_CLNT_HELLO_C; - /* fallthrough */ - case SSL3_ST_SR_CLNT_HELLO_C: - case SSL3_ST_SR_CLNT_HELLO_D: - /* We have previously parsed the ClientHello message, - * and can't call ssl_get_message again without hashing - * the message into the Finished digest again. */ - n = s->init_num; - - memset(&early_ctx, 0, sizeof(early_ctx)); - early_ctx.ssl = s; - early_ctx.client_hello = s->init_msg; - early_ctx.client_hello_len = n; - if (!ssl_early_callback_init(&early_ctx)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CLIENTHELLO_PARSE_FAILED); - goto f_err; - } - - if (s->state == SSL3_ST_SR_CLNT_HELLO_C && - s->ctx->select_certificate_cb != NULL) - { - s->state = SSL3_ST_SR_CLNT_HELLO_D; - switch (s->ctx->select_certificate_cb(&early_ctx)) - { - case 0: - return CERTIFICATE_SELECTION_PENDING; - case -1: - /* Connection rejected. */ - al = SSL_AD_ACCESS_DENIED; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CONNECTION_REJECTED); - goto f_err; - default: - /* fallthrough */; - } - } - s->state = SSL3_ST_SR_CLNT_HELLO_D; - break; - default: - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNKNOWN_STATE); - return -1; - } - - CBS_init(&client_hello, s->init_msg, n); - if (!CBS_get_u16(&client_hello, &client_version) || - !CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&client_hello, &session_id) || - CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); - goto f_err; - } - - /* use version from inside client hello, not from record header - * (may differ: see RFC 2246, Appendix E, second paragraph) */ - s->client_version = client_version; - - /* Load the client random. */ - memcpy(s->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE); - - if (SSL_IS_DTLS(s)) - { - CBS cookie; - - if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) || - CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); - goto f_err; - } - - /* Verify the cookie if appropriate option is set. */ - if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && - CBS_len(&cookie) > 0) - { - if (s->ctx->app_verify_cookie_cb != NULL) - { - if (s->ctx->app_verify_cookie_cb(s, - CBS_data(&cookie), CBS_len(&cookie)) == 0) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH); - goto f_err; - } - /* else cookie verification succeeded */ - } - else if (!CBS_mem_equal(&cookie, s->d1->cookie, s->d1->cookie_len)) - { - /* default verification */ - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH); - goto f_err; - } - /* Set to -2 so if successful we return 2 and - * don't send HelloVerifyRequest. */ - ret = -2; - } - } - - if (!s->s3->have_version) - { - /* Select version to use */ - uint16_t version = ssl3_get_mutual_version(s, client_version); - if (version == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNSUPPORTED_PROTOCOL); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - s->version = version; - s->enc_method = ssl3_get_enc_method(version); - assert(s->enc_method != NULL); - /* At this point, the connection's version is known and - * s->version is fixed. Begin enforcing the record-layer - * version. */ - s->s3->have_version = 1; - } - else if (SSL_IS_DTLS(s) ? (s->client_version > s->version) - : (s->client_version < s->version)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER); - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - - s->hit=0; - /* Versions before 0.9.7 always allow clients to resume sessions in renegotiation. - * 0.9.7 and later allow this by default, but optionally ignore resumption requests - * with flag SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather - * than a change to default behavior so that applications relying on this for security - * won't even compile against older library versions). - * - * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to request - * renegotiation but not a new session (s->new_session remains unset): for servers, - * this essentially just means that the SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION - * setting will be ignored. - */ - if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) - { - if (!ssl_get_new_session(s,1)) - goto err; - } - else - { - i = ssl_get_prev_session(s, &early_ctx); - if (i == PENDING_SESSION) - { - ret = PENDING_SESSION; - goto err; - } - else if (i == -1) - { - goto err; - } - - /* Only resume if the session's version matches the negotiated - * version: most clients do not accept a mismatch. */ - if (i == 1 && s->version == s->session->ssl_version) - { - s->hit = 1; - } - else - { - /* No session was found or it was unacceptable. */ - if (!ssl_get_new_session(s, 1)) - goto err; - } - } - - if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || - !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || - CBS_len(&compression_methods) == 0) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); - goto f_err; - } - - /* TODO(davidben): Per spec, cipher_suites can never be empty - * (specified at the ClientHello structure level). This logic - * allows it to be empty if resuming a session. Can we always - * require non-empty? If a client sends empty cipher_suites - * because it's resuming a session, it could always fail to - * resume a session, so it's unlikely to actually work. */ - if (CBS_len(&cipher_suites) == 0 && CBS_len(&session_id) != 0) - { - /* We need a cipher if we are not resuming a session. */ - al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_SPECIFIED); - goto f_err; - } - - ciphers = ssl_bytes_to_cipher_list(s, &cipher_suites); - if (ciphers == NULL) - { - goto err; - } - - /* If it is a hit, check that the cipher is in the list */ - if (s->hit && CBS_len(&cipher_suites) > 0) - { - size_t j; - int found_cipher = 0; - unsigned long id = s->session->cipher->id; - - for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) - { - c = sk_SSL_CIPHER_value(ciphers, j); - if (c->id == id) - { - found_cipher = 1; - break; - } - } - if (!found_cipher) - { - /* we need to have the cipher in the cipher - * list if we are asked to reuse it */ - al=SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_REQUIRED_CIPHER_MISSING); - goto f_err; - } - } - - /* Only null compression is supported. */ - if (memchr(CBS_data(&compression_methods), 0, - CBS_len(&compression_methods)) == NULL) - { - al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_COMPRESSION_SPECIFIED); - goto f_err; - } - - /* TLS extensions*/ - if (s->version >= SSL3_VERSION) - { - if (!ssl_parse_clienthello_tlsext(s, &client_hello)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_PARSE_TLSEXT); - goto err; - } - } - - /* There should be nothing left over in the record. */ - if (CBS_len(&client_hello) != 0) - { - /* wrong packet length */ - al=SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_BAD_PACKET_LENGTH); - goto f_err; - } - - /* Given ciphers and SSL_get_ciphers, we must pick a cipher */ - if (!s->hit) - { - if (ciphers == NULL) - { - al=SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_PASSED); - goto f_err; - } - /* Let cert callback update server certificates if required */ - if (s->cert->cert_cb) - { - int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); - if (rv == 0) - { - al=SSL_AD_INTERNAL_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CERT_CB_ERROR); - goto f_err; - } - if (rv < 0) - { - s->rwstate=SSL_X509_LOOKUP; - goto err; - } - s->rwstate = SSL_NOTHING; - } - c=ssl3_choose_cipher(s, ciphers, ssl_get_cipher_preferences(s)); - - if (c == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_SHARED_CIPHER); - goto f_err; - } - s->s3->tmp.new_cipher=c; - } - else - { - /* Session-id reuse */ - s->s3->tmp.new_cipher=s->session->cipher; - } - - if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) - { - if (!ssl3_digest_cached_records(s, free_handshake_buffer)) - goto f_err; - } - - /* we now have the following setup. - * client_random - * cipher_list - our prefered list of ciphers - * ciphers - the clients prefered list of ciphers - * compression - basically ignored right now - * ssl version is set - sslv3 - * s->session - The ssl session has been setup. - * s->hit - session reuse flag - * s->tmp.new_cipher - the new cipher to use. - */ - - if (ret < 0) ret=-ret; - if (0) - { -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); - } + s->in_handshake--; + if (buf != NULL) { + BUF_MEM_free(buf); + } + if (cb != NULL) { + cb(s, SSL_CB_ACCEPT_EXIT, ret); + } + return ret; +} + +static int ssl3_read_sniff_buffer(SSL *s, size_t n) { + if (s->s3->sniff_buffer == NULL) { + s->s3->sniff_buffer = BUF_MEM_new(); + } + if (s->s3->sniff_buffer == NULL || !BUF_MEM_grow(s->s3->sniff_buffer, n)) { + return -1; + } + + while (s->s3->sniff_buffer_len < n) { + int ret; + + s->rwstate = SSL_READING; + ret = BIO_read(s->rbio, s->s3->sniff_buffer->data + s->s3->sniff_buffer_len, + n - s->s3->sniff_buffer_len); + if (ret <= 0) { + return ret; + } + s->rwstate = SSL_NOTHING; + s->s3->sniff_buffer_len += ret; + } + + return 1; +} + +int ssl3_get_initial_bytes(SSL *s) { + int ret; + const uint8_t *p; + + /* Read the first 8 bytes. To recognize a ClientHello or V2ClientHello only + * needs the first 6 bytes, but 8 is needed to recognize CONNECT below. */ + ret = ssl3_read_sniff_buffer(s, INITIAL_SNIFF_BUFFER_SIZE); + if (ret <= 0) { + return ret; + } + assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE); + p = (const uint8_t *)s->s3->sniff_buffer->data; + + /* Some dedicated error codes for protocol mixups should the application wish + * to interpret them differently. (These do not overlap with ClientHello or + * V2ClientHello.) */ + if (strncmp("GET ", (const char *)p, 4) == 0 || + strncmp("POST ", (const char *)p, 5) == 0 || + strncmp("HEAD ", (const char *)p, 5) == 0 || + strncmp("PUT ", (const char *)p, 4) == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTP_REQUEST); + return -1; + } + if (strncmp("CONNECT ", (const char *)p, 8) == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTPS_PROXY_REQUEST); + return -1; + } + + /* Determine if this is a ClientHello or V2ClientHello. */ + if ((p[0] & 0x80) && p[2] == SSL2_MT_CLIENT_HELLO && + p[3] >= SSL3_VERSION_MAJOR) { + /* This is a V2ClientHello. */ + s->state = SSL3_ST_SR_V2_CLIENT_HELLO; + return 1; + } + if (p[0] == SSL3_RT_HANDSHAKE && p[1] >= SSL3_VERSION_MAJOR && + p[5] == SSL3_MT_CLIENT_HELLO) { + /* This is a ClientHello. Initialize the record layer with the already + * consumed data and continue the handshake. */ + if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) { + return -1; + } + assert(s->rstate == SSL_ST_READ_HEADER); + memcpy(s->s3->rbuf.buf, p, s->s3->sniff_buffer_len); + s->s3->rbuf.offset = 0; + s->s3->rbuf.left = s->s3->sniff_buffer_len; + s->packet_length = 0; + + BUF_MEM_free(s->s3->sniff_buffer); + s->s3->sniff_buffer = NULL; + s->s3->sniff_buffer_len = 0; + + s->state = SSL3_ST_SR_CLNT_HELLO_A; + return 1; + } + + OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_UNKNOWN_PROTOCOL); + return -1; +} + +int ssl3_get_v2_client_hello(SSL *s) { + const uint8_t *p; + int ret; + CBS v2_client_hello, cipher_specs, session_id, challenge; + size_t msg_length, rand_len, len; + uint8_t msg_type; + uint16_t version, cipher_spec_length, session_id_length, challenge_length; + CBB client_hello, hello_body, cipher_suites; + uint8_t random[SSL3_RANDOM_SIZE]; + + /* Read the remainder of the V2ClientHello. We have previously read 8 bytes + * in ssl3_get_initial_bytes. */ + assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE); + p = (const uint8_t *)s->s3->sniff_buffer->data; + msg_length = ((p[0] & 0x7f) << 8) | p[1]; + if (msg_length > (1024 * 4)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_RECORD_TOO_LARGE); + return -1; + } + if (msg_length < INITIAL_SNIFF_BUFFER_SIZE - 2) { + /* Reject lengths that are too short early. We have already read 8 bytes, + * so we should not attempt to process an (invalid) V2ClientHello which + * would be shorter than that. */ + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, + SSL_R_RECORD_LENGTH_MISMATCH); + return -1; + } + + ret = ssl3_read_sniff_buffer(s, msg_length + 2); + if (ret <= 0) { + return ret; + } + assert(s->s3->sniff_buffer_len == msg_length + 2); + CBS_init(&v2_client_hello, (const uint8_t *)s->s3->sniff_buffer->data + 2, + msg_length); + + /* The V2ClientHello without the length is incorporated into the Finished + * hash. */ + ssl3_finish_mac(s, CBS_data(&v2_client_hello), CBS_len(&v2_client_hello)); + if (s->msg_callback) { + s->msg_callback(0, SSL2_VERSION, 0, CBS_data(&v2_client_hello), + CBS_len(&v2_client_hello), s, s->msg_callback_arg); + } + + if (!CBS_get_u8(&v2_client_hello, &msg_type) || + !CBS_get_u16(&v2_client_hello, &version) || + !CBS_get_u16(&v2_client_hello, &cipher_spec_length) || + !CBS_get_u16(&v2_client_hello, &session_id_length) || + !CBS_get_u16(&v2_client_hello, &challenge_length) || + !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) || + !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) || + !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) || + CBS_len(&v2_client_hello) != 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR); + return -1; + } + + /* msg_type has already been checked. */ + assert(msg_type == SSL2_MT_CLIENT_HELLO); + + /* The client_random is the V2ClientHello challenge. Truncate or + * left-pad with zeros as needed. */ + memset(random, 0, SSL3_RANDOM_SIZE); + rand_len = CBS_len(&challenge); + if (rand_len > SSL3_RANDOM_SIZE) { + rand_len = SSL3_RANDOM_SIZE; + } + memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge), + rand_len); + + /* Write out an equivalent SSLv3 ClientHello. */ + if (!CBB_init_fixed(&client_hello, (uint8_t *)s->init_buf->data, + s->init_buf->max)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_MALLOC_FAILURE); + return -1; + } + if (!CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) || + !CBB_add_u24_length_prefixed(&client_hello, &hello_body) || + !CBB_add_u16(&hello_body, version) || + !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) || + /* No session id. */ + !CBB_add_u8(&hello_body, 0) || + !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Copy the cipher suites. */ + while (CBS_len(&cipher_specs) > 0) { + uint32_t cipher_spec; + if (!CBS_get_u24(&cipher_specs, &cipher_spec)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR); + return -1; + } + + /* Skip SSLv2 ciphers. */ + if ((cipher_spec & 0xff0000) != 0) { + continue; + } + if (!CBB_add_u16(&cipher_suites, cipher_spec)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); + return -1; + } + } + + /* Add the null compression scheme and finish. */ + if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) || + !CBB_finish(&client_hello, NULL, &len)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Mark the message for "re"-use by the version-specific method. */ + s->s3->tmp.reuse_message = 1; + s->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO; + /* The handshake message header is 4 bytes. */ + s->s3->tmp.message_size = len - 4; + + /* Initialize the record layer. */ + if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) { + return -1; + } + + /* Drop the sniff buffer. */ + BUF_MEM_free(s->s3->sniff_buffer); + s->s3->sniff_buffer = NULL; + s->s3->sniff_buffer_len = 0; + + return 1; +} + +int ssl3_send_hello_request(SSL *s) { + if (s->state == SSL3_ST_SW_HELLO_REQ_A) { + ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0); + s->state = SSL3_ST_SW_HELLO_REQ_B; + } + + /* SSL3_ST_SW_HELLO_REQ_B */ + return ssl_do_write(s); +} + +int ssl3_get_client_hello(SSL *s) { + int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1; + long n; + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + struct ssl_early_callback_ctx early_ctx; + CBS client_hello; + uint16_t client_version; + CBS client_random, session_id, cipher_suites, compression_methods; + + /* We do this so that we will respond with our native type. If we are TLSv1 + * and we get SSLv3, we will respond with TLSv1, This down switching should + * be handled by a different method. If we are SSLv3, we will respond with + * SSLv3, even if prompted with TLSv1. */ + switch (s->state) { + case SSL3_ST_SR_CLNT_HELLO_A: + case SSL3_ST_SR_CLNT_HELLO_B: + n = s->method->ssl_get_message( + s, SSL3_ST_SR_CLNT_HELLO_A, SSL3_ST_SR_CLNT_HELLO_B, + SSL3_MT_CLIENT_HELLO, SSL3_RT_MAX_PLAIN_LENGTH, + SSL_GET_MESSAGE_HASH_MESSAGE, &ok); + + if (!ok) { + return n; + } + + /* If we require cookies and this ClientHello doesn't contain one, just + * return since we do not want to allocate any memory yet. So check + * cookie length... */ + if (SSL_IS_DTLS(s) && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) { + uint8_t cookie_length; + + CBS_init(&client_hello, s->init_msg, n); + if (!CBS_skip(&client_hello, 2 + SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&client_hello, &session_id) || + !CBS_get_u8(&client_hello, &cookie_length)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); + goto f_err; + } + + if (cookie_length == 0) { + return 1; + } + } + s->state = SSL3_ST_SR_CLNT_HELLO_C; + /* fallthrough */ + case SSL3_ST_SR_CLNT_HELLO_C: + case SSL3_ST_SR_CLNT_HELLO_D: + /* We have previously parsed the ClientHello message, and can't call + * ssl_get_message again without hashing the message into the Finished + * digest again. */ + n = s->init_num; + + memset(&early_ctx, 0, sizeof(early_ctx)); + early_ctx.ssl = s; + early_ctx.client_hello = s->init_msg; + early_ctx.client_hello_len = n; + if (!ssl_early_callback_init(&early_ctx)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, + SSL_R_CLIENTHELLO_PARSE_FAILED); + goto f_err; + } + + if (s->state == SSL3_ST_SR_CLNT_HELLO_C && + s->ctx->select_certificate_cb != NULL) { + s->state = SSL3_ST_SR_CLNT_HELLO_D; + switch (s->ctx->select_certificate_cb(&early_ctx)) { + case 0: + return CERTIFICATE_SELECTION_PENDING; + + case -1: + /* Connection rejected. */ + al = SSL_AD_ACCESS_DENIED; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, + SSL_R_CONNECTION_REJECTED); + goto f_err; + + default: + /* fallthrough */; + } + } + s->state = SSL3_ST_SR_CLNT_HELLO_D; + break; + + default: + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNKNOWN_STATE); + return -1; + } + + CBS_init(&client_hello, s->init_msg, n); + if (!CBS_get_u16(&client_hello, &client_version) || + !CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&client_hello, &session_id) || + CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); + goto f_err; + } + + /* use version from inside client hello, not from record header (may differ: + * see RFC 2246, Appendix E, second paragraph) */ + s->client_version = client_version; + + /* Load the client random. */ + memcpy(s->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE); + + if (SSL_IS_DTLS(s)) { + CBS cookie; + + if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) || + CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); + goto f_err; + } + + /* Verify the cookie if appropriate option is set. */ + if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && CBS_len(&cookie) > 0) { + if (s->ctx->app_verify_cookie_cb != NULL) { + if (s->ctx->app_verify_cookie_cb(s, CBS_data(&cookie), + CBS_len(&cookie)) == 0) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH); + goto f_err; + } + /* else cookie verification succeeded */ + } else if (!CBS_mem_equal(&cookie, s->d1->cookie, s->d1->cookie_len)) { + /* default verification */ + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH); + goto f_err; + } + /* Set to -2 so if successful we return 2 and don't send + * HelloVerifyRequest. */ + ret = -2; + } + } + + if (!s->s3->have_version) { + /* Select version to use */ + uint16_t version = ssl3_get_mutual_version(s, client_version); + if (version == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNSUPPORTED_PROTOCOL); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->version = version; + s->enc_method = ssl3_get_enc_method(version); + assert(s->enc_method != NULL); + /* At this point, the connection's version is known and |s->version| is + * fixed. Begin enforcing the record-layer version. */ + s->s3->have_version = 1; + } else if (SSL_IS_DTLS(s) ? (s->client_version > s->version) + : (s->client_version < s->version)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + + s->hit = 0; + /* Versions before 0.9.7 always allow clients to resume sessions in + * renegotiation. 0.9.7 and later allow this by default, but optionally + * ignore resumption requests with flag + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather than + * a change to default behavior so that applications relying on this for + * security won't even compile against older library versions). + * + * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to + * request renegotiation but not a new session (s->new_session remains + * unset): for servers, this essentially just means that the + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be ignored. */ + if (s->new_session && + (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)) { + if (!ssl_get_new_session(s, 1)) { + goto err; + } + } else { + i = ssl_get_prev_session(s, &early_ctx); + if (i == PENDING_SESSION) { + ret = PENDING_SESSION; + goto err; + } else if (i == -1) { + goto err; + } + + /* Only resume if the session's version matches the negotiated version: + * most clients do not accept a mismatch. */ + if (i == 1 && s->version == s->session->ssl_version) { + s->hit = 1; + } else { + /* No session was found or it was unacceptable. */ + if (!ssl_get_new_session(s, 1)) { + goto err; + } + } + } + + if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || + !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || + CBS_len(&compression_methods) == 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); + goto f_err; + } + + /* TODO(davidben): Per spec, cipher_suites can never be empty (specified at + * the ClientHello structure level). This logic allows it to be empty if + * resuming a session. Can we always require non-empty? If a client sends + * empty cipher_suites because it's resuming a session, it could always fail + * to resume a session, so it's unlikely to actually work. */ + if (CBS_len(&cipher_suites) == 0 && CBS_len(&session_id) != 0) { + /* We need a cipher if we are not resuming a session. */ + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_SPECIFIED); + goto f_err; + } + + ciphers = ssl_bytes_to_cipher_list(s, &cipher_suites); + if (ciphers == NULL) { + goto err; + } + + /* If it is a hit, check that the cipher is in the list. */ + if (s->hit && CBS_len(&cipher_suites) > 0) { + size_t j; + int found_cipher = 0; + unsigned long id = s->session->cipher->id; + + for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { + c = sk_SSL_CIPHER_value(ciphers, j); + if (c->id == id) { + found_cipher = 1; + break; + } + } + + if (!found_cipher) { + /* we need to have the cipher in the cipher list if we are asked to reuse + * it */ + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, + SSL_R_REQUIRED_CIPHER_MISSING); + goto f_err; + } + } + + /* Only null compression is supported. */ + if (memchr(CBS_data(&compression_methods), 0, + CBS_len(&compression_methods)) == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, + SSL_R_NO_COMPRESSION_SPECIFIED); + goto f_err; + } + + /* TLS extensions. */ + if (s->version >= SSL3_VERSION && + !ssl_parse_clienthello_tlsext(s, &client_hello)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_PARSE_TLSEXT); + goto err; + } + + /* There should be nothing left over in the record. */ + if (CBS_len(&client_hello) != 0) { + /* wrong packet length */ + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_BAD_PACKET_LENGTH); + goto f_err; + } + + /* Given ciphers and SSL_get_ciphers, we must pick a cipher */ + if (!s->hit) { + if (ciphers == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_PASSED); + goto f_err; + } + + /* Let cert callback update server certificates if required */ + if (s->cert->cert_cb) { + int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (rv == 0) { + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CERT_CB_ERROR); + goto f_err; + } + if (rv < 0) { + s->rwstate = SSL_X509_LOOKUP; + goto err; + } + s->rwstate = SSL_NOTHING; + } + c = ssl3_choose_cipher(s, ciphers, ssl_get_cipher_preferences(s)); + + if (c == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_SHARED_CIPHER); + goto f_err; + } + s->s3->tmp.new_cipher = c; + } else { + /* Session-id reuse */ + s->s3->tmp.new_cipher = s->session->cipher; + } + + if ((!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + goto f_err; + } + + /* we now have the following setup; + * client_random + * cipher_list - our prefered list of ciphers + * ciphers - the clients prefered list of ciphers + * compression - basically ignored right now + * ssl version is set - sslv3 + * s->session - The ssl session has been setup. + * s->hit - session reuse flag + * s->tmp.new_cipher - the new cipher to use. */ + + if (ret < 0) { + ret = -ret; + } + + if (0) { + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + err: - if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers); - return ret; - } - -int ssl3_send_server_hello(SSL *s) - { - unsigned char *buf; - unsigned char *p,*d; - int sl; - unsigned long l; - - if (s->state == SSL3_ST_SW_SRVR_HELLO_A) - { - /* We only accept ChannelIDs on connections with ECDHE in order - * to avoid a known attack while we fix ChannelID itself. */ - if (s->s3->tlsext_channel_id_valid && - (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kEECDH) == 0) - s->s3->tlsext_channel_id_valid = 0; - - /* If this is a resumption and the original handshake didn't - * support ChannelID then we didn't record the original - * handshake hashes in the session and so cannot resume with - * ChannelIDs. */ - if (s->hit && - s->s3->tlsext_channel_id_new && - s->session->original_handshake_hash_len == 0) - s->s3->tlsext_channel_id_valid = 0; - - buf=(unsigned char *)s->init_buf->data; - /* Do the message type and length last */ - d=p= ssl_handshake_start(s); - - *(p++)=s->version>>8; - *(p++)=s->version&0xff; - - /* Random stuff */ - if (!ssl_fill_hello_random(s, 1, s->s3->server_random, SSL3_RANDOM_SIZE)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); - p+=SSL3_RANDOM_SIZE; - - /* There are several cases for the session ID to send - * back in the server hello: - * - For session reuse from the session cache, - * we send back the old session ID. - * - If stateless session reuse (using a session ticket) - * is successful, we send back the client's "session ID" - * (which doesn't actually identify the session). - * - If it is a new session, we send back the new - * session ID. - * - However, if we want the new session to be single-use, - * we send back a 0-length session ID. - * s->hit is non-zero in either case of session reuse, - * so the following won't overwrite an ID that we're supposed - * to send back. - */ - if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) - && !s->hit) - s->session->session_id_length=0; - - sl=s->session->session_id_length; - if (sl > (int)sizeof(s->session->session_id)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - *(p++)=sl; - memcpy(p,s->session->session_id,sl); - p+=sl; - - /* put the cipher */ - s2n(ssl3_get_cipher_value(s->s3->tmp.new_cipher), p); - - /* put the compression method */ - *(p++)=0; - if (ssl_prepare_serverhello_tlsext(s) <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, SSL_R_SERVERHELLO_TLSEXT); - return -1; - } - if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - /* do the header */ - l=(p-d); - ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l); - s->state=SSL3_ST_SW_SRVR_HELLO_B; - } - - /* SSL3_ST_SW_SRVR_HELLO_B */ - return ssl_do_write(s); - } - -int ssl3_send_server_done(SSL *s) - { - - if (s->state == SSL3_ST_SW_SRVR_DONE_A) - { - ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0); - s->state = SSL3_ST_SW_SRVR_DONE_B; - } - - /* SSL3_ST_SW_SRVR_DONE_B */ - return ssl_do_write(s); - } - -int ssl3_send_server_key_exchange(SSL *s) - { - DH *dh=NULL,*dhp; - EC_KEY *ecdh=NULL, *ecdhp; - unsigned char *encodedPoint = NULL; - int encodedlen = 0; - int curve_id = 0; - BN_CTX *bn_ctx = NULL; - const char* psk_identity_hint = NULL; - size_t psk_identity_hint_len = 0; - EVP_PKEY *pkey; - unsigned char *p,*d; - int al,i; - unsigned long alg_k; - unsigned long alg_a; - int n; - CERT *cert; - BIGNUM *r[4]; - int nr[4],kn; - BUF_MEM *buf; - EVP_MD_CTX md_ctx; - - EVP_MD_CTX_init(&md_ctx); - if (s->state == SSL3_ST_SW_KEY_EXCH_A) - { - alg_k=s->s3->tmp.new_cipher->algorithm_mkey; - alg_a=s->s3->tmp.new_cipher->algorithm_auth; - cert=s->cert; - - buf=s->init_buf; - - r[0]=r[1]=r[2]=r[3]=NULL; - n=0; - if (alg_a & SSL_aPSK) - { - /* size for PSK identity hint */ - psk_identity_hint = s->psk_identity_hint; - if (psk_identity_hint) - psk_identity_hint_len = strlen(psk_identity_hint); - else - psk_identity_hint_len = 0; - n+=2+psk_identity_hint_len; - } - if (alg_k & SSL_kEDH) - { - dhp=cert->dh_tmp; - if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) - dhp=s->cert->dh_tmp_cb(s, 0, 1024); - if (dhp == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, SSL_R_MISSING_TMP_DH_KEY); - goto f_err; - } - - if (s->s3->tmp.dh != NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_INTERNAL_ERROR); - goto err; - } - - if ((dh=DHparams_dup(dhp)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); - goto err; - } - - s->s3->tmp.dh=dh; - if ((dhp->pub_key == NULL || - dhp->priv_key == NULL || - (s->options & SSL_OP_SINGLE_DH_USE))) - { - if(!DH_generate_key(dh)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); - goto err; - } - } - else - { - dh->pub_key=BN_dup(dhp->pub_key); - dh->priv_key=BN_dup(dhp->priv_key); - if ((dh->pub_key == NULL) || - (dh->priv_key == NULL)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); - goto err; - } - } - r[0]=dh->p; - r[1]=dh->g; - r[2]=dh->pub_key; - } - else - if (alg_k & SSL_kEECDH) - { - const EC_GROUP *group; - - ecdhp=cert->ecdh_tmp; - if (s->cert->ecdh_tmp_auto) - { - /* Get NID of appropriate shared curve */ - int nid = tls1_get_shared_curve(s); - if (nid != NID_undef) - ecdhp = EC_KEY_new_by_curve_name(nid); - } - else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb) - { - ecdhp = s->cert->ecdh_tmp_cb(s, 0, 1024); - } - if (ecdhp == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, SSL_R_MISSING_TMP_ECDH_KEY); - goto f_err; - } - - if (s->s3->tmp.ecdh != NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_INTERNAL_ERROR); - goto err; - } - - /* Duplicate the ECDH structure. */ - if (ecdhp == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } - if (s->cert->ecdh_tmp_auto) - ecdh = ecdhp; - else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } - - s->s3->tmp.ecdh=ecdh; - if ((EC_KEY_get0_public_key(ecdh) == NULL) || - (EC_KEY_get0_private_key(ecdh) == NULL) || - (s->options & SSL_OP_SINGLE_ECDH_USE)) - { - if(!EC_KEY_generate_key(ecdh)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } - } - - if (((group = EC_KEY_get0_group(ecdh)) == NULL) || - (EC_KEY_get0_public_key(ecdh) == NULL) || - (EC_KEY_get0_private_key(ecdh) == NULL)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } - - /* XXX: For now, we only support ephemeral ECDH - * keys over named (not generic) curves. For - * supported named curves, curve_id is non-zero. - */ - if ((curve_id = - tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group))) - == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); - goto err; - } - - /* Encode the public key. - * First check the size of encoding and - * allocate memory accordingly. - */ - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - NULL, 0, NULL); - - encodedPoint = (unsigned char *) - OPENSSL_malloc(encodedlen*sizeof(unsigned char)); - bn_ctx = BN_CTX_new(); - if ((encodedPoint == NULL) || (bn_ctx == NULL)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - - - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - encodedPoint, encodedlen, bn_ctx); - - if (encodedlen == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } - - BN_CTX_free(bn_ctx); bn_ctx=NULL; - - /* XXX: For now, we only support named (not - * generic) curves in ECDH ephemeral key exchanges. - * In this situation, we need four additional bytes - * to encode the entire ServerECDHParams - * structure. - */ - n += 4 + encodedlen; - - /* We'll generate the serverKeyExchange message - * explicitly so we can set these to NULLs - */ - r[0]=NULL; - r[1]=NULL; - r[2]=NULL; - r[3]=NULL; - } - else - if (!(alg_k & SSL_kPSK)) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); - goto f_err; - } - for (i=0; i < 4 && r[i] != NULL; i++) - { - nr[i]=BN_num_bytes(r[i]); - n+=2+nr[i]; - } - - if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) - { - if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher)) - == NULL) - { - al=SSL_AD_DECODE_ERROR; - goto f_err; - } - kn=EVP_PKEY_size(pkey); - } - else - { - pkey=NULL; - kn=0; - } - - if (!BUF_MEM_grow_clean(buf,n+SSL_HM_HEADER_LENGTH(s)+kn)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_BUF); - goto err; - } - d = p = ssl_handshake_start(s); - - for (i=0; i < 4 && r[i] != NULL; i++) - { - s2n(nr[i],p); - BN_bn2bin(r[i],p); - p+=nr[i]; - } - -/* Note: ECDHE PSK ciphersuites use SSL_kEECDH and SSL_aPSK. - * When one of them is used, the server key exchange record needs to have both - * the psk_identity_hint and the ServerECDHParams. */ - if (alg_a & SSL_aPSK) - { - /* copy PSK identity hint (if provided) */ - s2n(psk_identity_hint_len, p); - if (psk_identity_hint_len > 0) - { - memcpy(p, psk_identity_hint, psk_identity_hint_len); - p+=psk_identity_hint_len; - } - } - - if (alg_k & SSL_kEECDH) - { - /* XXX: For now, we only support named (not generic) curves. - * In this situation, the serverKeyExchange message has: - * [1 byte CurveType], [2 byte CurveName] - * [1 byte length of encoded point], followed by - * the actual encoded point itself - */ - *p = NAMED_CURVE_TYPE; - p += 1; - *p = 0; - p += 1; - *p = curve_id; - p += 1; - *p = encodedlen; - p += 1; - memcpy((unsigned char*)p, - (unsigned char *)encodedPoint, - encodedlen); - OPENSSL_free(encodedPoint); - encodedPoint = NULL; - p += encodedlen; - } - - /* not anonymous */ - if (pkey != NULL) - { - /* n is the length of the params, they start at &(d[4]) - * and p points to the space at the end. */ - const EVP_MD *md; - size_t sig_len = EVP_PKEY_size(pkey); - - /* Determine signature algorithm. */ - if (SSL_USE_SIGALGS(s)) - { - md = tls1_choose_signing_digest(s, pkey); - if (!tls12_get_sigandhash(p, pkey, md)) - { - /* Should never happen */ - al=SSL_AD_INTERNAL_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_INTERNAL_ERROR); - goto f_err; - } - p+=2; - } - else if (pkey->type == EVP_PKEY_RSA) - { - md = EVP_md5_sha1(); - } - else - { - md = EVP_sha1(); - } - - if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey) || - !EVP_DigestSignUpdate(&md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) || - !EVP_DigestSignUpdate(&md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) || - !EVP_DigestSignUpdate(&md_ctx, d, n) || - !EVP_DigestSignFinal(&md_ctx, &p[2], &sig_len)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_EVP); - goto err; - } - s2n(sig_len, p); - n += sig_len + 2; - if (SSL_USE_SIGALGS(s)) - n += 2; - } - - ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n); - } - - s->state = SSL3_ST_SW_KEY_EXCH_B; - EVP_MD_CTX_cleanup(&md_ctx); - return ssl_do_write(s); + if (ciphers != NULL) { + sk_SSL_CIPHER_free(ciphers); + } + return ret; +} + +int ssl3_send_server_hello(SSL *s) { + uint8_t *buf; + uint8_t *p, *d; + int sl; + unsigned long l; + + if (s->state == SSL3_ST_SW_SRVR_HELLO_A) { + /* We only accept ChannelIDs on connections with ECDHE in order to avoid a + * known attack while we fix ChannelID itself. */ + if (s->s3->tlsext_channel_id_valid && + (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kEECDH) == 0) { + s->s3->tlsext_channel_id_valid = 0; + } + + /* If this is a resumption and the original handshake didn't support + * ChannelID then we didn't record the original handshake hashes in the + * session and so cannot resume with ChannelIDs. */ + if (s->hit && s->s3->tlsext_channel_id_new && + s->session->original_handshake_hash_len == 0) { + s->s3->tlsext_channel_id_valid = 0; + } + + buf = (uint8_t *)s->init_buf->data; + /* Do the message type and length last */ + d = p = ssl_handshake_start(s); + + *(p++) = s->version >> 8; + *(p++) = s->version & 0xff; + + /* Random stuff */ + if (!ssl_fill_hello_random(s, 1, s->s3->server_random, SSL3_RANDOM_SIZE)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); + return -1; + } + memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); + p += SSL3_RANDOM_SIZE; + + /* There are several cases for the session ID to send + * back in the server hello: + * - For session reuse from the session cache, we send back the old session + * ID. + * - If stateless session reuse (using a session ticket) is successful, we + * send back the client's "session ID" (which doesn't actually identify + * the session). + * - If it is a new session, we send back the new session ID. + * - However, if we want the new session to be single-use, we send back a + * 0-length session ID. + * s->hit is non-zero in either case of session reuse, so the following + * won't overwrite an ID that we're supposed to send back. */ + if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) && !s->hit) { + s->session->session_id_length = 0; + } + + sl = s->session->session_id_length; + if (sl > (int)sizeof(s->session->session_id)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); + return -1; + } + *(p++) = sl; + memcpy(p, s->session->session_id, sl); + p += sl; + + /* put the cipher */ + s2n(ssl3_get_cipher_value(s->s3->tmp.new_cipher), p); + + /* put the compression method */ + *(p++) = 0; + if (ssl_prepare_serverhello_tlsext(s) <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, SSL_R_SERVERHELLO_TLSEXT); + return -1; + } + p = ssl_add_serverhello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH); + if (p == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* do the header */ + l = (p - d); + ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l); + s->state = SSL3_ST_SW_SRVR_HELLO_B; + } + + /* SSL3_ST_SW_SRVR_HELLO_B */ + return ssl_do_write(s); +} + +int ssl3_send_server_done(SSL *s) { + if (s->state == SSL3_ST_SW_SRVR_DONE_A) { + ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0); + s->state = SSL3_ST_SW_SRVR_DONE_B; + } + + /* SSL3_ST_SW_SRVR_DONE_B */ + return ssl_do_write(s); +} + +int ssl3_send_server_key_exchange(SSL *s) { + DH *dh = NULL, *dhp; + EC_KEY *ecdh = NULL, *ecdhp; + uint8_t *encodedPoint = NULL; + int encodedlen = 0; + int curve_id = 0; + BN_CTX *bn_ctx = NULL; + const char *psk_identity_hint = NULL; + size_t psk_identity_hint_len = 0; + EVP_PKEY *pkey; + uint8_t *p, *d; + int al, i; + unsigned long alg_k; + unsigned long alg_a; + int n; + CERT *cert; + BIGNUM *r[4]; + int nr[4], kn; + BUF_MEM *buf; + EVP_MD_CTX md_ctx; + + EVP_MD_CTX_init(&md_ctx); + if (s->state == SSL3_ST_SW_KEY_EXCH_A) { + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + cert = s->cert; + + buf = s->init_buf; + + r[0] = r[1] = r[2] = r[3] = NULL; + n = 0; + if (alg_a & SSL_aPSK) { + /* size for PSK identity hint */ + psk_identity_hint = s->psk_identity_hint; + if (psk_identity_hint) { + psk_identity_hint_len = strlen(psk_identity_hint); + } else { + psk_identity_hint_len = 0; + } + n += 2 + psk_identity_hint_len; + } + + if (alg_k & SSL_kEDH) { + dhp = cert->dh_tmp; + if (dhp == NULL && s->cert->dh_tmp_cb != NULL) { + dhp = s->cert->dh_tmp_cb(s, 0, 1024); + } + if (dhp == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + SSL_R_MISSING_TMP_DH_KEY); + goto f_err; + } + + if (s->s3->tmp.dh != NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + ERR_R_INTERNAL_ERROR); + goto err; + } + + dh = DHparams_dup(dhp); + if (dh == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); + goto err; + } + + s->s3->tmp.dh = dh; + if (dhp->pub_key == NULL || dhp->priv_key == NULL || + (s->options & SSL_OP_SINGLE_DH_USE)) { + if (!DH_generate_key(dh)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); + goto err; + } + } else { + dh->pub_key = BN_dup(dhp->pub_key); + dh->priv_key = BN_dup(dhp->priv_key); + if (dh->pub_key == NULL || dh->priv_key == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); + goto err; + } + } + + r[0] = dh->p; + r[1] = dh->g; + r[2] = dh->pub_key; + } else if (alg_k & SSL_kEECDH) { + const EC_GROUP *group; + + ecdhp = cert->ecdh_tmp; + if (s->cert->ecdh_tmp_auto) { + /* Get NID of appropriate shared curve */ + int nid = tls1_get_shared_curve(s); + if (nid != NID_undef) { + ecdhp = EC_KEY_new_by_curve_name(nid); + } + } else if (ecdhp == NULL && s->cert->ecdh_tmp_cb) { + ecdhp = s->cert->ecdh_tmp_cb(s, 0, 1024); + } + if (ecdhp == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + SSL_R_MISSING_TMP_ECDH_KEY); + goto f_err; + } + + if (s->s3->tmp.ecdh != NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Duplicate the ECDH structure. */ + if (ecdhp == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + + if (s->cert->ecdh_tmp_auto) { + ecdh = ecdhp; + } else { + ecdh = EC_KEY_dup(ecdhp); + if (ecdh == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + } + + s->s3->tmp.ecdh = ecdh; + if (EC_KEY_get0_public_key(ecdh) == NULL || + EC_KEY_get0_private_key(ecdh) == NULL || + (s->options & SSL_OP_SINGLE_ECDH_USE)) { + if (!EC_KEY_generate_key(ecdh)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + } + + group = EC_KEY_get0_group(ecdh); + if (group == NULL || + EC_KEY_get0_public_key(ecdh) == NULL || + EC_KEY_get0_private_key(ecdh) == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + + /* We only support ephemeral ECDH keys over named (not generic) curves. + * For supported named curves, curve_id is non-zero. */ + curve_id = tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group)); + if (curve_id == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + goto err; + } + + /* Encode the public key. First check the size of encoding and allocate + * memory accordingly. */ + encodedlen = + EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), + POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); + + encodedPoint = (uint8_t *)OPENSSL_malloc(encodedlen * sizeof(uint8_t)); + bn_ctx = BN_CTX_new(); + if (encodedPoint == NULL || bn_ctx == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + + encodedlen = EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), + POINT_CONVERSION_UNCOMPRESSED, + encodedPoint, encodedlen, bn_ctx); + + if (encodedlen == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + + BN_CTX_free(bn_ctx); + bn_ctx = NULL; + + /* We only support named (not generic) curves in ECDH ephemeral key + * exchanges. In this situation, we need four additional bytes to encode + * the entire ServerECDHParams structure. */ + n += 4 + encodedlen; + + /* We'll generate the serverKeyExchange message explicitly so we can set + * these to NULLs */ + r[0] = NULL; + r[1] = NULL; + r[2] = NULL; + r[3] = NULL; + } else if (!(alg_k & SSL_kPSK)) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); + goto f_err; + } + + for (i = 0; i < 4 && r[i] != NULL; i++) { + nr[i] = BN_num_bytes(r[i]); + n += 2 + nr[i]; + } + + if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { + pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher); + if (pkey == NULL) { + al = SSL_AD_DECODE_ERROR; + goto f_err; + } + kn = EVP_PKEY_size(pkey); + } else { + pkey = NULL; + kn = 0; + } + + if (!BUF_MEM_grow_clean(buf, n + SSL_HM_HEADER_LENGTH(s) + kn)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_BUF); + goto err; + } + d = p = ssl_handshake_start(s); + + for (i = 0; i < 4 && r[i] != NULL; i++) { + s2n(nr[i], p); + BN_bn2bin(r[i], p); + p += nr[i]; + } + + /* Note: ECDHE PSK ciphersuites use SSL_kEECDH and SSL_aPSK. When one of + * them is used, the server key exchange record needs to have both the + * psk_identity_hint and the ServerECDHParams. */ + if (alg_a & SSL_aPSK) { + /* copy PSK identity hint (if provided) */ + s2n(psk_identity_hint_len, p); + if (psk_identity_hint_len > 0) { + memcpy(p, psk_identity_hint, psk_identity_hint_len); + p += psk_identity_hint_len; + } + } + + if (alg_k & SSL_kEECDH) { + /* We only support named (not generic) curves. In this situation, the + * serverKeyExchange message has: + * [1 byte CurveType], [2 byte CurveName] + * [1 byte length of encoded point], followed by + * the actual encoded point itself. */ + *p = NAMED_CURVE_TYPE; + p += 1; + *p = 0; + p += 1; + *p = curve_id; + p += 1; + *p = encodedlen; + p += 1; + memcpy((uint8_t *)p, (uint8_t *)encodedPoint, encodedlen); + OPENSSL_free(encodedPoint); + encodedPoint = NULL; + p += encodedlen; + } + + /* not anonymous */ + if (pkey != NULL) { + /* n is the length of the params, they start at &(d[4]) and p points to + * the space at the end. */ + const EVP_MD *md; + size_t sig_len = EVP_PKEY_size(pkey); + + /* Determine signature algorithm. */ + if (SSL_USE_SIGALGS(s)) { + md = tls1_choose_signing_digest(s, pkey); + if (!tls12_get_sigandhash(p, pkey, md)) { + /* Should never happen */ + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + ERR_R_INTERNAL_ERROR); + goto f_err; + } + p += 2; + } else if (pkey->type == EVP_PKEY_RSA) { + md = EVP_md5_sha1(); + } else { + md = EVP_sha1(); + } + + if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey) || + !EVP_DigestSignUpdate(&md_ctx, s->s3->client_random, + SSL3_RANDOM_SIZE) || + !EVP_DigestSignUpdate(&md_ctx, s->s3->server_random, + SSL3_RANDOM_SIZE) || + !EVP_DigestSignUpdate(&md_ctx, d, n) || + !EVP_DigestSignFinal(&md_ctx, &p[2], &sig_len)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_EVP); + goto err; + } + + s2n(sig_len, p); + n += sig_len + 2; + if (SSL_USE_SIGALGS(s)) { + n += 2; + } + } + + ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n); + } + + s->state = SSL3_ST_SW_KEY_EXCH_B; + EVP_MD_CTX_cleanup(&md_ctx); + return ssl_do_write(s); + f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); + ssl3_send_alert(s, SSL3_AL_FATAL, al); err: - if (encodedPoint != NULL) OPENSSL_free(encodedPoint); - BN_CTX_free(bn_ctx); - EVP_MD_CTX_cleanup(&md_ctx); - return(-1); - } - -int ssl3_send_certificate_request(SSL *s) - { - unsigned char *p,*d; - size_t i; - int j,nl,off,n; - STACK_OF(X509_NAME) *sk=NULL; - X509_NAME *name; - BUF_MEM *buf; - - if (s->state == SSL3_ST_SW_CERT_REQ_A) - { - buf=s->init_buf; - - d=p=ssl_handshake_start(s); - - /* get the list of acceptable cert types */ - p++; - n=ssl3_get_req_cert_type(s,p); - d[0]=n; - p+=n; - n++; - - if (SSL_USE_SIGALGS(s)) - { - const unsigned char *psigs; - nl = tls12_get_psigalgs(s, &psigs); - s2n(nl, p); - memcpy(p, psigs, nl); - p += nl; - n += nl + 2; - } - - off=n; - p+=2; - n+=2; - - sk=SSL_get_client_CA_list(s); - nl=0; - if (sk != NULL) - { - for (i=0; i<sk_X509_NAME_num(sk); i++) - { - name=sk_X509_NAME_value(sk,i); - j=i2d_X509_NAME(name,NULL); - if (!BUF_MEM_grow_clean(buf,SSL_HM_HEADER_LENGTH(s)+n+j+2)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB); - goto err; - } - p = ssl_handshake_start(s) + n; - s2n(j,p); - i2d_X509_NAME(name,&p); - n+=2+j; - nl+=2+j; - } - } - /* else no CA names */ - p = ssl_handshake_start(s) + off; - s2n(nl,p); - - ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n); + if (encodedPoint != NULL) { + OPENSSL_free(encodedPoint); + } + BN_CTX_free(bn_ctx); + EVP_MD_CTX_cleanup(&md_ctx); + return -1; +} + +int ssl3_send_certificate_request(SSL *s) { + uint8_t *p, *d; + size_t i; + int j, nl, off, n; + STACK_OF(X509_NAME) *sk = NULL; + X509_NAME *name; + BUF_MEM *buf; + + if (s->state == SSL3_ST_SW_CERT_REQ_A) { + buf = s->init_buf; + + d = p = ssl_handshake_start(s); + + /* get the list of acceptable cert types */ + p++; + n = ssl3_get_req_cert_type(s, p); + d[0] = n; + p += n; + n++; + + if (SSL_USE_SIGALGS(s)) { + const uint8_t *psigs; + nl = tls12_get_psigalgs(s, &psigs); + s2n(nl, p); + memcpy(p, psigs, nl); + p += nl; + n += nl + 2; + } + + off = n; + p += 2; + n += 2; + + sk = SSL_get_client_CA_list(s); + nl = 0; + if (sk != NULL) { + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + name = sk_X509_NAME_value(sk, i); + j = i2d_X509_NAME(name, NULL); + if (!BUF_MEM_grow_clean(buf, SSL_HM_HEADER_LENGTH(s) + n + j + 2)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB); + goto err; + } + p = ssl_handshake_start(s) + n; + s2n(j, p); + i2d_X509_NAME(name, &p); + n += 2 + j; + nl += 2 + j; + } + } + + /* else no CA names */ + p = ssl_handshake_start(s) + off; + s2n(nl, p); + + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n); #ifdef NETSCAPE_HANG_BUG - if (!SSL_IS_DTLS(s)) - { - /* Prepare a ServerHelloDone in the same record. This is - * to workaround a hang in Netscape. */ - if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB); - goto err; - } - p=(unsigned char *)s->init_buf->data + s->init_num; - /* do the header */ - *(p++)=SSL3_MT_SERVER_DONE; - *(p++)=0; - *(p++)=0; - *(p++)=0; - s->init_num += 4; - ssl3_finish_mac(s, p - 4, 4); - } + if (!SSL_IS_DTLS(s)) { + /* Prepare a ServerHelloDone in the same record. This is to workaround a + * hang in Netscape. */ + if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB); + goto err; + } + p = (uint8_t *)s->init_buf->data + s->init_num; + /* do the header */ + *(p++) = SSL3_MT_SERVER_DONE; + *(p++) = 0; + *(p++) = 0; + *(p++) = 0; + s->init_num += 4; + ssl3_finish_mac(s, p - 4, 4); + } #endif - s->state = SSL3_ST_SW_CERT_REQ_B; - } + s->state = SSL3_ST_SW_CERT_REQ_B; + } + + /* SSL3_ST_SW_CERT_REQ_B */ + return ssl_do_write(s); - /* SSL3_ST_SW_CERT_REQ_B */ - return ssl_do_write(s); err: - return(-1); - } - -int ssl3_get_client_key_exchange(SSL *s) - { - int al,ok; - long n; - CBS client_key_exchange; - unsigned long alg_k; - unsigned long alg_a; - uint8_t *premaster_secret = NULL; - size_t premaster_secret_len = 0; - RSA *rsa=NULL; - uint8_t *decrypt_buf = NULL; - EVP_PKEY *pkey=NULL; - BIGNUM *pub=NULL; - DH *dh_srvr; - - EC_KEY *srvr_ecdh = NULL; - EVP_PKEY *clnt_pub_pkey = NULL; - EC_POINT *clnt_ecpoint = NULL; - BN_CTX *bn_ctx = NULL; - unsigned int psk_len = 0; - unsigned char psk[PSK_MAX_PSK_LEN]; - - n=s->method->ssl_get_message(s, - SSL3_ST_SR_KEY_EXCH_A, - SSL3_ST_SR_KEY_EXCH_B, - SSL3_MT_CLIENT_KEY_EXCHANGE, - 2048, /* ??? */ - SSL_GET_MESSAGE_HASH_MESSAGE, - &ok); - - if (!ok) return((int)n); - CBS_init(&client_key_exchange, s->init_msg, n); - - alg_k=s->s3->tmp.new_cipher->algorithm_mkey; - alg_a=s->s3->tmp.new_cipher->algorithm_auth; - - /* If using a PSK key exchange, prepare the pre-shared key. */ - if (alg_a & SSL_aPSK) - { - CBS psk_identity; - - /* If using PSK, the ClientKeyExchange contains a - * psk_identity. If PSK, then this is the only field - * in the message. */ - if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) || - ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR); - al = SSL_AD_DECODE_ERROR; - goto f_err; - } - - if (s->psk_server_callback == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_PSK_NO_SERVER_CB); - al = SSL_AD_INTERNAL_ERROR; - goto f_err; - } - - if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN || - CBS_contains_zero_byte(&psk_identity)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DATA_LENGTH_TOO_LONG); - al = SSL_AD_ILLEGAL_PARAMETER; - goto f_err; - } - - if (!CBS_strdup(&psk_identity, &s->session->psk_identity)) - { - al = SSL_AD_INTERNAL_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto f_err; - } - - /* Look up the key for the identity. */ - psk_len = s->psk_server_callback(s, s->session->psk_identity, psk, sizeof(psk)); - if (psk_len > PSK_MAX_PSK_LEN) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_INTERNAL_ERROR); - al = SSL_AD_INTERNAL_ERROR; - goto f_err; - } - else if (psk_len == 0) - { - /* PSK related to the given identity not found */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_PSK_IDENTITY_NOT_FOUND); - al = SSL_AD_UNKNOWN_PSK_IDENTITY; - goto f_err; - } - } - - /* Depending on the key exchange method, compute |premaster_secret| and - * |premaster_secret_len|. */ - if (alg_k & SSL_kRSA) - { - CBS encrypted_premaster_secret; - uint8_t rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; - uint8_t good; - size_t rsa_size, decrypt_len, premaster_index, j; - - pkey=s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey; - if ( (pkey == NULL) || - (pkey->type != EVP_PKEY_RSA) || - (pkey->pkey.rsa == NULL)) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_MISSING_RSA_CERTIFICATE); - goto f_err; - } - rsa=pkey->pkey.rsa; - - /* TLS and [incidentally] DTLS{0xFEFF} */ - if (s->version > SSL3_VERSION) - { - CBS copy = client_key_exchange; - if (!CBS_get_u16_length_prefixed(&client_key_exchange, - &encrypted_premaster_secret) || - CBS_len(&client_key_exchange) != 0) - { - if (!(s->options & SSL_OP_TLS_D5_BUG)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); - goto f_err; - } - else - encrypted_premaster_secret = copy; - } - } - else - encrypted_premaster_secret = client_key_exchange; - - /* Reject overly short RSA keys because we want to be sure that - * the buffer size makes it safe to iterate over the entire size - * of a premaster secret (SSL_MAX_MASTER_KEY_LENGTH). The actual - * expected size is larger due to RSA padding, but the bound is - * sufficient to be safe. */ - rsa_size = RSA_size(rsa); - if (rsa_size < SSL_MAX_MASTER_KEY_LENGTH) - { - al = SSL_AD_DECRYPT_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECRYPTION_FAILED); - goto f_err; - } - - /* We must not leak whether a decryption failure occurs because - * of Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see - * RFC 2246, section 7.4.7.1). The code follows that advice of - * the TLS RFC and generates a random premaster secret for the - * case that the decrypt fails. See - * https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */ - if (!RAND_bytes(rand_premaster_secret, - sizeof(rand_premaster_secret))) - goto err; - - /* Allocate a buffer large enough for an RSA decryption. */ - decrypt_buf = OPENSSL_malloc(rsa_size); - if (decrypt_buf == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* Decrypt with no padding. PKCS#1 padding will be removed as - * part of the timing-sensitive code below. */ - if (!RSA_decrypt(rsa, &decrypt_len, decrypt_buf, rsa_size, - CBS_data(&encrypted_premaster_secret), - CBS_len(&encrypted_premaster_secret), - RSA_NO_PADDING)) - { - goto err; - } - if (decrypt_len != rsa_size) - { - /* This should never happen, but do a check so we do not - * read uninitialized memory. */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_INTERNAL_ERROR); - goto err; - } - - /* Remove the PKCS#1 padding and adjust |decrypt_len| as - * appropriate. |good| will be 0xff if the premaster is - * acceptable and zero otherwise. */ - good = constant_time_eq_int_8( - RSA_message_index_PKCS1_type_2(decrypt_buf, decrypt_len, &premaster_index), 1); - decrypt_len = decrypt_len - premaster_index; - - /* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH. */ - good &= constant_time_eq_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH); - - /* Copy over the unpadded premaster. Whatever the value of - * |decrypt_good_mask|, copy as if the premaster were the right - * length. It is important the memory access pattern be - * constant. */ - premaster_secret = BUF_memdup( - decrypt_buf + (rsa_size - SSL_MAX_MASTER_KEY_LENGTH), - SSL_MAX_MASTER_KEY_LENGTH); - if (premaster_secret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - OPENSSL_free(decrypt_buf); - decrypt_buf = NULL; - - /* If the version in the decrypted pre-master secret is correct - * then version_good will be 0xff, otherwise it'll be zero. The - * Klima-Pokorny-Rosa extension of Bleichenbacher's attack - * (http://eprint.iacr.org/2003/052/) exploits the version - * number check as a "bad version oracle". Thus version checks - * are done in constant time and are treated like any other - * decryption error. */ - good &= constant_time_eq_8(premaster_secret[0], (unsigned)(s->client_version>>8)); - good &= constant_time_eq_8(premaster_secret[1], (unsigned)(s->client_version&0xff)); - - /* Now copy rand_premaster_secret over premaster_secret using - * decrypt_good_mask. */ - for (j = 0; j < sizeof(rand_premaster_secret); j++) - { - premaster_secret[j] = constant_time_select_8(good, premaster_secret[j], rand_premaster_secret[j]); - } - - premaster_secret_len = sizeof(rand_premaster_secret); - } - else if (alg_k & SSL_kEDH) - { - CBS dh_Yc; - int dh_len; - - if (!CBS_get_u16_length_prefixed(&client_key_exchange, &dh_Yc) || - CBS_len(&dh_Yc) == 0 || - CBS_len(&client_key_exchange) != 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); - al = SSL_R_DECODE_ERROR; - goto f_err; - } - - if (s->s3->tmp.dh == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_MISSING_TMP_DH_KEY); - goto f_err; - } - dh_srvr=s->s3->tmp.dh; - - pub = BN_bin2bn(CBS_data(&dh_Yc), CBS_len(&dh_Yc), NULL); - if (pub == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_BN_LIB); - goto err; - } - - /* Allocate a buffer for the premaster secret. */ - premaster_secret = OPENSSL_malloc(DH_size(dh_srvr)); - if (premaster_secret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - - dh_len = DH_compute_key(premaster_secret, pub, dh_srvr); - if (dh_len <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_DH_LIB); - BN_clear_free(pub); - goto err; - } - - DH_free(s->s3->tmp.dh); - s->s3->tmp.dh=NULL; - BN_clear_free(pub); - pub=NULL; - - premaster_secret_len = dh_len; - } - - else if (alg_k & SSL_kEECDH) - { - int field_size = 0, ecdh_len; - const EC_KEY *tkey; - const EC_GROUP *group; - const BIGNUM *priv_key; - CBS ecdh_Yc; - - /* initialize structures for server's ECDH key pair */ - if ((srvr_ecdh = EC_KEY_new()) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* Use the ephermeral values we saved when generating the - * ServerKeyExchange msg. */ - tkey = s->s3->tmp.ecdh; - - group = EC_KEY_get0_group(tkey); - priv_key = EC_KEY_get0_private_key(tkey); - - if (!EC_KEY_set_group(srvr_ecdh, group) || - !EC_KEY_set_private_key(srvr_ecdh, priv_key)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB); - goto err; - } - - /* Let's get client's public key */ - if ((clnt_ecpoint = EC_POINT_new(group)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* Get client's public key from encoded point - * in the ClientKeyExchange message. - */ - if (!CBS_get_u8_length_prefixed(&client_key_exchange, &ecdh_Yc) || - CBS_len(&client_key_exchange) != 0) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR); - goto f_err; - } - - if ((bn_ctx = BN_CTX_new()) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!EC_POINT_oct2point(group, clnt_ecpoint, - CBS_data(&ecdh_Yc), CBS_len(&ecdh_Yc), bn_ctx)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB); - goto err; - } - - /* Allocate a buffer for both the secret and the PSK. */ - field_size = EC_GROUP_get_degree(group); - if (field_size <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB); - goto err; - } - - ecdh_len = (field_size + 7) / 8; - premaster_secret = OPENSSL_malloc(ecdh_len); - if (premaster_secret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* Compute the shared pre-master secret */ - ecdh_len = ECDH_compute_key(premaster_secret, - ecdh_len, clnt_ecpoint, srvr_ecdh, NULL); - if (ecdh_len <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB); - goto err; - } - - EVP_PKEY_free(clnt_pub_pkey); - clnt_pub_pkey = NULL; - EC_POINT_free(clnt_ecpoint); - clnt_ecpoint = NULL; - EC_KEY_free(srvr_ecdh); - srvr_ecdh = NULL; - BN_CTX_free(bn_ctx); - bn_ctx = NULL; - EC_KEY_free(s->s3->tmp.ecdh); - s->s3->tmp.ecdh = NULL; - - premaster_secret_len = ecdh_len; - } - else if (alg_k & SSL_kPSK) - { - /* For plain PSK, other_secret is a block of 0s with the same - * length as the pre-shared key. */ - premaster_secret_len = psk_len; - premaster_secret = OPENSSL_malloc(premaster_secret_len); - if (premaster_secret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - memset(premaster_secret, 0, premaster_secret_len); - } - else - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_UNKNOWN_CIPHER_TYPE); - goto f_err; - } - - /* For a PSK cipher suite, the actual pre-master secret is combined with - * the pre-shared key. */ - if (alg_a & SSL_aPSK) - { - CBB new_premaster, child; - uint8_t *new_data; - size_t new_len; - - if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!CBB_add_u16_length_prefixed(&new_premaster, &child) || - !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) || - !CBB_add_u16_length_prefixed(&new_premaster, &child) || - !CBB_add_bytes(&child, psk, psk_len) || - !CBB_finish(&new_premaster, &new_data, &new_len)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_INTERNAL_ERROR); - CBB_cleanup(&new_premaster); - goto err; - } - - OPENSSL_cleanse(premaster_secret, premaster_secret_len); - OPENSSL_free(premaster_secret); - premaster_secret = new_data; - premaster_secret_len = new_len; - } - - /* Compute the master secret */ - s->session->master_key_length = s->enc_method - ->generate_master_secret(s, - s->session->master_key, premaster_secret, premaster_secret_len); - if (s->session->master_key_length == 0) - goto err; - s->session->extended_master_secret = s->s3->tmp.extended_master_secret; - - OPENSSL_cleanse(premaster_secret, premaster_secret_len); - OPENSSL_free(premaster_secret); - return 1; + return -1; +} + +int ssl3_get_client_key_exchange(SSL *s) { + int al, ok; + long n; + CBS client_key_exchange; + unsigned long alg_k; + unsigned long alg_a; + uint8_t *premaster_secret = NULL; + size_t premaster_secret_len = 0; + RSA *rsa = NULL; + uint8_t *decrypt_buf = NULL; + EVP_PKEY *pkey = NULL; + BIGNUM *pub = NULL; + DH *dh_srvr; + + EC_KEY *srvr_ecdh = NULL; + EVP_PKEY *clnt_pub_pkey = NULL; + EC_POINT *clnt_ecpoint = NULL; + BN_CTX *bn_ctx = NULL; + unsigned int psk_len = 0; + uint8_t psk[PSK_MAX_PSK_LEN]; + + n = s->method->ssl_get_message(s, SSL3_ST_SR_KEY_EXCH_A, + SSL3_ST_SR_KEY_EXCH_B, + SSL3_MT_CLIENT_KEY_EXCHANGE, 2048, /* ??? */ + SSL_GET_MESSAGE_HASH_MESSAGE, &ok); + + if (!ok) { + return n; + } + + CBS_init(&client_key_exchange, s->init_msg, n); + + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + + /* If using a PSK key exchange, prepare the pre-shared key. */ + if (alg_a & SSL_aPSK) { + CBS psk_identity; + + /* If using PSK, the ClientKeyExchange contains a psk_identity. If PSK, + * then this is the only field in the message. */ + if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) || + ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR); + al = SSL_AD_DECODE_ERROR; + goto f_err; + } + + if (s->psk_server_callback == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_PSK_NO_SERVER_CB); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } + + if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN || + CBS_contains_zero_byte(&psk_identity)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_DATA_LENGTH_TOO_LONG); + al = SSL_AD_ILLEGAL_PARAMETER; + goto f_err; + } + + if (!CBS_strdup(&psk_identity, &s->session->psk_identity)) { + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto f_err; + } + + /* Look up the key for the identity. */ + psk_len = + s->psk_server_callback(s, s->session->psk_identity, psk, sizeof(psk)); + if (psk_len > PSK_MAX_PSK_LEN) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } else if (psk_len == 0) { + /* PSK related to the given identity not found */ + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_PSK_IDENTITY_NOT_FOUND); + al = SSL_AD_UNKNOWN_PSK_IDENTITY; + goto f_err; + } + } + + /* Depending on the key exchange method, compute |premaster_secret| and + * |premaster_secret_len|. */ + if (alg_k & SSL_kRSA) { + CBS encrypted_premaster_secret; + uint8_t rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; + uint8_t good; + size_t rsa_size, decrypt_len, premaster_index, j; + + pkey = s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey; + if (pkey == NULL || pkey->type != EVP_PKEY_RSA || pkey->pkey.rsa == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_MISSING_RSA_CERTIFICATE); + goto f_err; + } + rsa = pkey->pkey.rsa; + + /* TLS and [incidentally] DTLS{0xFEFF} */ + if (s->version > SSL3_VERSION) { + CBS copy = client_key_exchange; + if (!CBS_get_u16_length_prefixed(&client_key_exchange, + &encrypted_premaster_secret) || + CBS_len(&client_key_exchange) != 0) { + if (!(s->options & SSL_OP_TLS_D5_BUG)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); + goto f_err; + } else { + encrypted_premaster_secret = copy; + } + } + } else { + encrypted_premaster_secret = client_key_exchange; + } + + /* Reject overly short RSA keys because we want to be sure that the buffer + * size makes it safe to iterate over the entire size of a premaster secret + * (SSL_MAX_MASTER_KEY_LENGTH). The actual expected size is larger due to + * RSA padding, but the bound is sufficient to be safe. */ + rsa_size = RSA_size(rsa); + if (rsa_size < SSL_MAX_MASTER_KEY_LENGTH) { + al = SSL_AD_DECRYPT_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_DECRYPTION_FAILED); + goto f_err; + } + + /* We must not leak whether a decryption failure occurs because of + * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, + * section 7.4.7.1). The code follows that advice of the TLS RFC and + * generates a random premaster secret for the case that the decrypt fails. + * See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */ + if (!RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret))) { + goto err; + } + + /* Allocate a buffer large enough for an RSA decryption. */ + decrypt_buf = OPENSSL_malloc(rsa_size); + if (decrypt_buf == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Decrypt with no padding. PKCS#1 padding will be removed as part of the + * timing-sensitive code below. */ + if (!RSA_decrypt(rsa, &decrypt_len, decrypt_buf, rsa_size, + CBS_data(&encrypted_premaster_secret), + CBS_len(&encrypted_premaster_secret), RSA_NO_PADDING)) { + goto err; + } + if (decrypt_len != rsa_size) { + /* This should never happen, but do a check so we do not read + * uninitialized memory. */ + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Remove the PKCS#1 padding and adjust |decrypt_len| as appropriate. + * |good| will be 0xff if the premaster is acceptable and zero otherwise. + * */ + good = + constant_time_eq_int_8(RSA_message_index_PKCS1_type_2( + decrypt_buf, decrypt_len, &premaster_index), + 1); + decrypt_len = decrypt_len - premaster_index; + + /* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH. */ + good &= constant_time_eq_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH); + + /* Copy over the unpadded premaster. Whatever the value of + * |decrypt_good_mask|, copy as if the premaster were the right length. It + * is important the memory access pattern be constant. */ + premaster_secret = + BUF_memdup(decrypt_buf + (rsa_size - SSL_MAX_MASTER_KEY_LENGTH), + SSL_MAX_MASTER_KEY_LENGTH); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + OPENSSL_free(decrypt_buf); + decrypt_buf = NULL; + + /* If the version in the decrypted pre-master secret is correct then + * version_good will be 0xff, otherwise it'll be zero. The + * Klima-Pokorny-Rosa extension of Bleichenbacher's attack + * (http://eprint.iacr.org/2003/052/) exploits the version number check as + * a "bad version oracle". Thus version checks are done in constant time + * and are treated like any other decryption error. */ + good &= constant_time_eq_8(premaster_secret[0], + (unsigned)(s->client_version >> 8)); + good &= constant_time_eq_8(premaster_secret[1], + (unsigned)(s->client_version & 0xff)); + + /* Now copy rand_premaster_secret over premaster_secret using + * decrypt_good_mask. */ + for (j = 0; j < sizeof(rand_premaster_secret); j++) { + premaster_secret[j] = constant_time_select_8(good, premaster_secret[j], + rand_premaster_secret[j]); + } + + premaster_secret_len = sizeof(rand_premaster_secret); + } else if (alg_k & SSL_kEDH) { + CBS dh_Yc; + int dh_len; + + if (!CBS_get_u16_length_prefixed(&client_key_exchange, &dh_Yc) || + CBS_len(&dh_Yc) == 0 || CBS_len(&client_key_exchange) != 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); + al = SSL_R_DECODE_ERROR; + goto f_err; + } + + if (s->s3->tmp.dh == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_MISSING_TMP_DH_KEY); + goto f_err; + } + dh_srvr = s->s3->tmp.dh; + + pub = BN_bin2bn(CBS_data(&dh_Yc), CBS_len(&dh_Yc), NULL); + if (pub == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_BN_LIB); + goto err; + } + + /* Allocate a buffer for the premaster secret. */ + premaster_secret = OPENSSL_malloc(DH_size(dh_srvr)); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + + dh_len = DH_compute_key(premaster_secret, pub, dh_srvr); + if (dh_len <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_DH_LIB); + BN_clear_free(pub); + goto err; + } + + DH_free(s->s3->tmp.dh); + s->s3->tmp.dh = NULL; + BN_clear_free(pub); + pub = NULL; + + premaster_secret_len = dh_len; + } else if (alg_k & SSL_kEECDH) { + int field_size = 0, ecdh_len; + const EC_KEY *tkey; + const EC_GROUP *group; + const BIGNUM *priv_key; + CBS ecdh_Yc; + + /* initialize structures for server's ECDH key pair */ + srvr_ecdh = EC_KEY_new(); + if (srvr_ecdh == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Use the ephermeral values we saved when generating the ServerKeyExchange + * msg. */ + tkey = s->s3->tmp.ecdh; + + group = EC_KEY_get0_group(tkey); + priv_key = EC_KEY_get0_private_key(tkey); + + if (!EC_KEY_set_group(srvr_ecdh, group) || + !EC_KEY_set_private_key(srvr_ecdh, priv_key)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB); + goto err; + } + + /* Let's get client's public key */ + clnt_ecpoint = EC_POINT_new(group); + if (clnt_ecpoint == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Get client's public key from encoded point in the ClientKeyExchange + * message. */ + if (!CBS_get_u8_length_prefixed(&client_key_exchange, &ecdh_Yc) || + CBS_len(&client_key_exchange) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR); + goto f_err; + } + + bn_ctx = BN_CTX_new(); + if (bn_ctx == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!EC_POINT_oct2point(group, clnt_ecpoint, CBS_data(&ecdh_Yc), + CBS_len(&ecdh_Yc), bn_ctx)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB); + goto err; + } + + /* Allocate a buffer for both the secret and the PSK. */ + field_size = EC_GROUP_get_degree(group); + if (field_size <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + + ecdh_len = (field_size + 7) / 8; + premaster_secret = OPENSSL_malloc(ecdh_len); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Compute the shared pre-master secret */ + ecdh_len = ECDH_compute_key(premaster_secret, ecdh_len, clnt_ecpoint, + srvr_ecdh, NULL); + if (ecdh_len <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + + EVP_PKEY_free(clnt_pub_pkey); + clnt_pub_pkey = NULL; + EC_POINT_free(clnt_ecpoint); + clnt_ecpoint = NULL; + EC_KEY_free(srvr_ecdh); + srvr_ecdh = NULL; + BN_CTX_free(bn_ctx); + bn_ctx = NULL; + EC_KEY_free(s->s3->tmp.ecdh); + s->s3->tmp.ecdh = NULL; + + premaster_secret_len = ecdh_len; + } else if (alg_k & SSL_kPSK) { + /* For plain PSK, other_secret is a block of 0s with the same length as the + * pre-shared key. */ + premaster_secret_len = psk_len; + premaster_secret = OPENSSL_malloc(premaster_secret_len); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + memset(premaster_secret, 0, premaster_secret_len); + } else { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_UNKNOWN_CIPHER_TYPE); + goto f_err; + } + + /* For a PSK cipher suite, the actual pre-master secret is combined with the + * pre-shared key. */ + if (alg_a & SSL_aPSK) { + CBB new_premaster, child; + uint8_t *new_data; + size_t new_len; + + if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (!CBB_add_u16_length_prefixed(&new_premaster, &child) || + !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) || + !CBB_add_u16_length_prefixed(&new_premaster, &child) || + !CBB_add_bytes(&child, psk, psk_len) || + !CBB_finish(&new_premaster, &new_data, &new_len)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_INTERNAL_ERROR); + CBB_cleanup(&new_premaster); + goto err; + } + + OPENSSL_cleanse(premaster_secret, premaster_secret_len); + OPENSSL_free(premaster_secret); + premaster_secret = new_data; + premaster_secret_len = new_len; + } + + /* Compute the master secret */ + s->session->master_key_length = s->enc_method->generate_master_secret( + s, s->session->master_key, premaster_secret, premaster_secret_len); + if (s->session->master_key_length == 0) { + goto err; + } + s->session->extended_master_secret = s->s3->tmp.extended_master_secret; + + OPENSSL_cleanse(premaster_secret, premaster_secret_len); + OPENSSL_free(premaster_secret); + return 1; + f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); + ssl3_send_alert(s, SSL3_AL_FATAL, al); err: - if (premaster_secret) - { - if (premaster_secret_len) - OPENSSL_cleanse(premaster_secret, premaster_secret_len); - OPENSSL_free(premaster_secret); - } - if (decrypt_buf) - OPENSSL_free(decrypt_buf); - EVP_PKEY_free(clnt_pub_pkey); - EC_POINT_free(clnt_ecpoint); - if (srvr_ecdh != NULL) - EC_KEY_free(srvr_ecdh); - BN_CTX_free(bn_ctx); - return(-1); - } - -int ssl3_get_cert_verify(SSL *s) - { - int al,ok,ret=0; - long n; - CBS certificate_verify, signature; - X509 *peer = s->session->peer; - EVP_PKEY *pkey = NULL; - const EVP_MD *md = NULL; - uint8_t digest[EVP_MAX_MD_SIZE]; - size_t digest_length; - EVP_PKEY_CTX *pctx = NULL; - - /* Only RSA and ECDSA client certificates are supported, so a - * CertificateVerify is required if and only if there's a - * client certificate. */ - if (peer == NULL) - { - if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer)) - return -1; - return 1; - } - - n=s->method->ssl_get_message(s, - SSL3_ST_SR_CERT_VRFY_A, - SSL3_ST_SR_CERT_VRFY_B, - SSL3_MT_CERTIFICATE_VERIFY, - SSL3_RT_MAX_PLAIN_LENGTH, - SSL_GET_MESSAGE_DONT_HASH_MESSAGE, - &ok); - - if (!ok) - return (int)n; - - /* Filter out unsupported certificate types. */ - pkey = X509_get_pubkey(peer); - if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) || - (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC)) - { - al = SSL_AD_UNSUPPORTED_CERTIFICATE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); - goto f_err; - } - - CBS_init(&certificate_verify, s->init_msg, n); - - /* Determine the digest type if needbe. */ - if (SSL_USE_SIGALGS(s)) - { - if (!tls12_check_peer_sigalg(&md, &al, s, &certificate_verify, pkey)) - goto f_err; - } - - /* Compute the digest. */ - if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey)) - goto err; - - /* The handshake buffer is no longer necessary, and we may hash the - * current message.*/ - if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer)) - goto err; - ssl3_hash_current_message(s); - - /* Parse and verify the signature. */ - if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) || - CBS_len(&certificate_verify) != 0) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_DECODE_ERROR); - goto f_err; - } - - pctx = EVP_PKEY_CTX_new(pkey, NULL); - if (pctx == NULL) - goto err; - if (!EVP_PKEY_verify_init(pctx) || - !EVP_PKEY_CTX_set_signature_md(pctx, md) || - !EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature), - digest, digest_length)) - { - al = SSL_AD_DECRYPT_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_BAD_SIGNATURE); - goto f_err; - } - - ret = 1; - if (0) - { -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); - } + if (premaster_secret) { + if (premaster_secret_len) { + OPENSSL_cleanse(premaster_secret, premaster_secret_len); + } + OPENSSL_free(premaster_secret); + } + if (decrypt_buf) { + OPENSSL_free(decrypt_buf); + } + EVP_PKEY_free(clnt_pub_pkey); + EC_POINT_free(clnt_ecpoint); + if (srvr_ecdh != NULL) { + EC_KEY_free(srvr_ecdh); + } + BN_CTX_free(bn_ctx); + + return -1; +} + +int ssl3_get_cert_verify(SSL *s) { + int al, ok, ret = 0; + long n; + CBS certificate_verify, signature; + X509 *peer = s->session->peer; + EVP_PKEY *pkey = NULL; + const EVP_MD *md = NULL; + uint8_t digest[EVP_MAX_MD_SIZE]; + size_t digest_length; + EVP_PKEY_CTX *pctx = NULL; + + /* Only RSA and ECDSA client certificates are supported, so a + * CertificateVerify is required if and only if there's a client certificate. + * */ + if (peer == NULL) { + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + return -1; + } + return 1; + } + + n = s->method->ssl_get_message( + s, SSL3_ST_SR_CERT_VRFY_A, SSL3_ST_SR_CERT_VRFY_B, + SSL3_MT_CERTIFICATE_VERIFY, SSL3_RT_MAX_PLAIN_LENGTH, + SSL_GET_MESSAGE_DONT_HASH_MESSAGE, &ok); + + if (!ok) { + return n; + } + + /* Filter out unsupported certificate types. */ + pkey = X509_get_pubkey(peer); + if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) || + (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC)) { + al = SSL_AD_UNSUPPORTED_CERTIFICATE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, + SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); + goto f_err; + } + + CBS_init(&certificate_verify, s->init_msg, n); + + /* Determine the digest type if needbe. */ + if (SSL_USE_SIGALGS(s) && + !tls12_check_peer_sigalg(&md, &al, s, &certificate_verify, pkey)) { + goto f_err; + } + + /* Compute the digest. */ + if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey)) { + goto err; + } + + /* The handshake buffer is no longer necessary, and we may hash the current + * message.*/ + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + goto err; + } + ssl3_hash_current_message(s); + + /* Parse and verify the signature. */ + if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) || + CBS_len(&certificate_verify) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_DECODE_ERROR); + goto f_err; + } + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + goto err; + } + if (!EVP_PKEY_verify_init(pctx) || + !EVP_PKEY_CTX_set_signature_md(pctx, md) || + !EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature), digest, + digest_length)) { + al = SSL_AD_DECRYPT_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_BAD_SIGNATURE); + goto f_err; + } + + ret = 1; + + if (0) { + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + err: - EVP_PKEY_CTX_free(pctx); - EVP_PKEY_free(pkey); - return(ret); - } - -int ssl3_get_client_certificate(SSL *s) - { - int i,ok,al,ret= -1; - X509 *x=NULL; - unsigned long n; - STACK_OF(X509) *sk=NULL; - SHA256_CTX sha256; - CBS certificate_msg, certificate_list; - int is_first_certificate = 1; - - n=s->method->ssl_get_message(s, - SSL3_ST_SR_CERT_A, - SSL3_ST_SR_CERT_B, - -1, - s->max_cert_list, - SSL_GET_MESSAGE_HASH_MESSAGE, - &ok); - - if (!ok) return((int)n); - - if (s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) - { - if ( (s->verify_mode & SSL_VERIFY_PEER) && - (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); - al=SSL_AD_HANDSHAKE_FAILURE; - goto f_err; - } - /* If tls asked for a client cert, the client must return a 0 list */ - if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); - al=SSL_AD_UNEXPECTED_MESSAGE; - goto f_err; - } - s->s3->tmp.reuse_message=1; - return(1); - } - - if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_WRONG_MESSAGE_TYPE); - goto f_err; - } - - CBS_init(&certificate_msg, s->init_msg, n); - - if ((sk=sk_X509_new_null()) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) || - CBS_len(&certificate_msg) != 0) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR); - goto f_err; - } - - while (CBS_len(&certificate_list) > 0) - { - CBS certificate; - const uint8_t *data; - - if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR); - goto f_err; - } - if (is_first_certificate && s->ctx->retain_only_sha256_of_client_certs) - { - /* If this is the first certificate, and we don't want - * to keep peer certificates in memory, then we hash it - * right away. */ - SHA256_Init(&sha256); - SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate)); - SHA256_Final(s->session->peer_sha256, &sha256); - s->session->peer_sha256_valid = 1; - } - is_first_certificate = 0; - data = CBS_data(&certificate); - x = d2i_X509(NULL, &data, CBS_len(&certificate)); - if (x == NULL) - { - al = SSL_AD_BAD_CERTIFICATE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_ASN1_LIB); - goto f_err; - } - if (data != CBS_data(&certificate) + CBS_len(&certificate)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_CERT_LENGTH_MISMATCH); - goto f_err; - } - if (!sk_X509_push(sk, x)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); - goto err; - } - x = NULL; - } - - if (sk_X509_num(sk) <= 0) - { - /* TLS does not mind 0 certs returned */ - if (s->version == SSL3_VERSION) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_NO_CERTIFICATES_RETURNED); - goto f_err; - } - /* Fail for TLS only if we required a certificate */ - else if ((s->verify_mode & SSL_VERIFY_PEER) && - (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); - al=SSL_AD_HANDSHAKE_FAILURE; - goto f_err; - } - /* No client certificate so digest cached records */ - if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer)) - { - al=SSL_AD_INTERNAL_ERROR; - goto f_err; - } - } - else - { - i=ssl_verify_cert_chain(s,sk); - if (i <= 0) - { - al=ssl_verify_alarm_type(s->verify_result); - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_CERTIFICATE_VERIFY_FAILED); - goto f_err; - } - } - - if (s->session->peer != NULL) /* This should not be needed */ - X509_free(s->session->peer); - s->session->peer=sk_X509_shift(sk); - s->session->verify_result = s->verify_result; - - /* With the current implementation, sess_cert will always be NULL - * when we arrive here. */ - if (s->session->sess_cert == NULL) - { - s->session->sess_cert = ssl_sess_cert_new(); - if (s->session->sess_cert == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); - goto err; - } - } - if (s->session->sess_cert->cert_chain != NULL) - sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free); - s->session->sess_cert->cert_chain=sk; - /* Inconsistency alert: cert_chain does *not* include the - * peer's own certificate, while we do include it in s3_clnt.c */ - - sk=NULL; - - ret=1; - if (0) - { -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); - } + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(pkey); + + return ret; +} + +int ssl3_get_client_certificate(SSL *s) { + int i, ok, al, ret = -1; + X509 *x = NULL; + unsigned long n; + STACK_OF(X509) *sk = NULL; + SHA256_CTX sha256; + CBS certificate_msg, certificate_list; + int is_first_certificate = 1; + + n = s->method->ssl_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, -1, + s->max_cert_list, SSL_GET_MESSAGE_HASH_MESSAGE, + &ok); + + if (!ok) { + return n; + } + + if (s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) { + if ((s->verify_mode & SSL_VERIFY_PEER) && + (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } + + /* If tls asked for a client cert, the client must return a 0 list */ + if (s->version > SSL3_VERSION && s->s3->tmp.cert_request) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); + al = SSL_AD_UNEXPECTED_MESSAGE; + goto f_err; + } + s->s3->tmp.reuse_message = 1; + + return 1; + } + + if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_WRONG_MESSAGE_TYPE); + goto f_err; + } + + CBS_init(&certificate_msg, s->init_msg, n); + + sk = sk_X509_new_null(); + if (sk == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) || + CBS_len(&certificate_msg) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR); + goto f_err; + } + + while (CBS_len(&certificate_list) > 0) { + CBS certificate; + const uint8_t *data; + + if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR); + goto f_err; + } + + if (is_first_certificate && s->ctx->retain_only_sha256_of_client_certs) { + /* If this is the first certificate, and we don't want to keep peer + * certificates in memory, then we hash it right away. */ + SHA256_Init(&sha256); + SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate)); + SHA256_Final(s->session->peer_sha256, &sha256); + s->session->peer_sha256_valid = 1; + } + is_first_certificate = 0; + + data = CBS_data(&certificate); + x = d2i_X509(NULL, &data, CBS_len(&certificate)); + if (x == NULL) { + al = SSL_AD_BAD_CERTIFICATE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_ASN1_LIB); + goto f_err; + } + if (data != CBS_data(&certificate) + CBS_len(&certificate)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } + if (!sk_X509_push(sk, x)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); + goto err; + } + x = NULL; + } + + if (sk_X509_num(sk) <= 0) { + /* TLS does not mind 0 certs returned */ + if (s->version == SSL3_VERSION) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_NO_CERTIFICATES_RETURNED); + goto f_err; + } + /* Fail for TLS only if we required a certificate */ + else if ((s->verify_mode & SSL_VERIFY_PEER) && + (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } + /* No client certificate so digest cached records */ + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } + } else { + i = ssl_verify_cert_chain(s, sk); + if (i <= 0) { + al = ssl_verify_alarm_type(s->verify_result); + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_CERTIFICATE_VERIFY_FAILED); + goto f_err; + } + } + + if (s->session->peer != NULL) { + /* This should not be needed */ + X509_free(s->session->peer); + } + + s->session->peer = sk_X509_shift(sk); + s->session->verify_result = s->verify_result; + + /* With the current implementation, sess_cert will always be NULL when we + * arrive here. */ + if (s->session->sess_cert == NULL) { + s->session->sess_cert = ssl_sess_cert_new(); + if (s->session->sess_cert == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if (s->session->sess_cert->cert_chain != NULL) { + sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free); + } + s->session->sess_cert->cert_chain = sk; + /* Inconsistency alert: cert_chain does *not* include the peer's own + * certificate, while we do include it in s3_clnt.c */ + + sk = NULL; + + ret = 1; + + if (0) { + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + err: - if (x != NULL) X509_free(x); - if (sk != NULL) sk_X509_pop_free(sk,X509_free); - return(ret); - } - -int ssl3_send_server_certificate(SSL *s) - { - CERT_PKEY *cpk; - - if (s->state == SSL3_ST_SW_CERT_A) - { - cpk=ssl_get_server_send_pkey(s); - if (cpk == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_certificate, ERR_R_INTERNAL_ERROR); - return(0); - } - - ssl3_output_cert_chain(s,cpk); - s->state=SSL3_ST_SW_CERT_B; - } - - /* SSL3_ST_SW_CERT_B */ - return ssl_do_write(s); - } + if (x != NULL) { + X509_free(x); + } + if (sk != NULL) { + sk_X509_pop_free(sk, X509_free); + } + return ret; +} + +int ssl3_send_server_certificate(SSL *s) { + CERT_PKEY *cpk; + + if (s->state == SSL3_ST_SW_CERT_A) { + cpk = ssl_get_server_send_pkey(s); + if (cpk == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_certificate, + ERR_R_INTERNAL_ERROR); + return 0; + } + + ssl3_output_cert_chain(s, cpk); + s->state = SSL3_ST_SW_CERT_B; + } + + /* SSL3_ST_SW_CERT_B */ + return ssl_do_write(s); +} /* send a new session ticket (not necessarily for a new session) */ -int ssl3_send_new_session_ticket(SSL *s) - { - if (s->state == SSL3_ST_SW_SESSION_TICKET_A) - { - uint8_t *session; - size_t session_len; - uint8_t *p, *macstart; - int len; - unsigned int hlen; - EVP_CIPHER_CTX ctx; - HMAC_CTX hctx; - SSL_CTX *tctx = s->initial_ctx; - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char key_name[16]; - /* The maximum overhead of encrypting the session is 16 (key - * name) + IV + one block of encryption overhead + HMAC. */ - const size_t max_ticket_overhead = 16 + EVP_MAX_IV_LENGTH + - EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE; - - /* Serialize the SSL_SESSION to be encoded into the ticket. */ - if (!SSL_SESSION_to_bytes_for_ticket(s->session, &session, - &session_len)) - { - return -1; - } - - /* If the session is too long, emit a dummy value rather than - * abort the connection. */ - if (session_len > 0xFFFF - max_ticket_overhead) - { - const char kTicketPlaceholder[] = "TICKET TOO LARGE"; - size_t placeholder_len = strlen(kTicketPlaceholder); - - OPENSSL_free(session); - - p = ssl_handshake_start(s); - /* Emit ticket_lifetime_hint. */ - l2n(0, p); - /* Emit ticket. */ - s2n(placeholder_len, p); - memcpy(p, kTicketPlaceholder, placeholder_len); - p += placeholder_len; - - len = p - ssl_handshake_start(s); - ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); - s->state = SSL3_ST_SW_SESSION_TICKET_B; - return ssl_do_write(s); - } - - /* Grow buffer if need be: the length calculation is as - * follows: handshake_header_length + - * 4 (ticket lifetime hint) + 2 (ticket length) + - * max_ticket_overhead + * session_length */ - if (!BUF_MEM_grow(s->init_buf, - SSL_HM_HEADER_LENGTH(s) + 6 + - max_ticket_overhead + session_len)) - { - OPENSSL_free(session); - return -1; - } - p = ssl_handshake_start(s); - EVP_CIPHER_CTX_init(&ctx); - HMAC_CTX_init(&hctx); - /* Initialize HMAC and cipher contexts. If callback present - * it does all the work otherwise use generated values - * from parent ctx. - */ - if (tctx->tlsext_ticket_key_cb) - { - if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, - &hctx, 1) < 0) - { - OPENSSL_free(session); - EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&hctx); - return -1; - } - } - else - { - if (!RAND_bytes(iv, 16) || - !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, iv) || - !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), NULL)) - { - OPENSSL_free(session); - EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&hctx); - return -1; - } - memcpy(key_name, tctx->tlsext_tick_key_name, 16); - } - - /* Ticket lifetime hint (advisory only): - * We leave this unspecified for resumed session (for simplicity), - * and guess that tickets for new sessions will live as long - * as their sessions. */ - l2n(s->hit ? 0 : s->session->timeout, p); - - /* Skip ticket length for now */ - p += 2; - /* Output key name */ - macstart = p; - memcpy(p, key_name, 16); - p += 16; - /* output IV */ - memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); - p += EVP_CIPHER_CTX_iv_length(&ctx); - /* Encrypt session data */ - EVP_EncryptUpdate(&ctx, p, &len, session, session_len); - p += len; - EVP_EncryptFinal_ex(&ctx, p, &len); - p += len; - EVP_CIPHER_CTX_cleanup(&ctx); - - HMAC_Update(&hctx, macstart, p - macstart); - HMAC_Final(&hctx, p, &hlen); - HMAC_CTX_cleanup(&hctx); - - p += hlen; - /* Now write out lengths: p points to end of data written */ - /* Total length */ - len = p - ssl_handshake_start(s); - /* Skip ticket lifetime hint */ - p = ssl_handshake_start(s) + 4; - s2n(len - 6, p); - ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); - s->state=SSL3_ST_SW_SESSION_TICKET_B; - OPENSSL_free(session); - } - - /* SSL3_ST_SW_SESSION_TICKET_B */ - return ssl_do_write(s); - } - -#if 0 -int ssl3_send_cert_status(SSL *s) - { - if (s->state == SSL3_ST_SW_CERT_STATUS_A) - { - unsigned char *p; - /* Grow buffer if need be: the length calculation is as - * follows 1 (message type) + 3 (message length) + - * 1 (ocsp response type) + 3 (ocsp response length) - * + (ocsp response) - */ - if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen)) - return -1; - - p=(unsigned char *)s->init_buf->data; - - /* do the header */ - *(p++)=SSL3_MT_CERTIFICATE_STATUS; - /* message length */ - l2n3(s->tlsext_ocsp_resplen + 4, p); - /* status type */ - *(p++)= s->tlsext_status_type; - /* length of OCSP response */ - l2n3(s->tlsext_ocsp_resplen, p); - /* actual response */ - memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen); - /* number of bytes to write */ - s->init_num = 8 + s->tlsext_ocsp_resplen; - s->state=SSL3_ST_SW_CERT_STATUS_B; - s->init_off = 0; - } - - /* SSL3_ST_SW_CERT_STATUS_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); - } -#endif +int ssl3_send_new_session_ticket(SSL *s) { + if (s->state == SSL3_ST_SW_SESSION_TICKET_A) { + uint8_t *session; + size_t session_len; + uint8_t *p, *macstart; + int len; + unsigned int hlen; + EVP_CIPHER_CTX ctx; + HMAC_CTX hctx; + SSL_CTX *tctx = s->initial_ctx; + uint8_t iv[EVP_MAX_IV_LENGTH]; + uint8_t key_name[16]; + /* The maximum overhead of encrypting the session is 16 (key name) + IV + + * one block of encryption overhead + HMAC. */ + const size_t max_ticket_overhead = + 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE; + + /* Serialize the SSL_SESSION to be encoded into the ticket. */ + if (!SSL_SESSION_to_bytes_for_ticket(s->session, &session, &session_len)) { + return -1; + } + + /* If the session is too long, emit a dummy value rather than abort the + * connection. */ + if (session_len > 0xFFFF - max_ticket_overhead) { + static const char kTicketPlaceholder[] = "TICKET TOO LARGE"; + const size_t placeholder_len = strlen(kTicketPlaceholder); + + OPENSSL_free(session); + + p = ssl_handshake_start(s); + /* Emit ticket_lifetime_hint. */ + l2n(0, p); + /* Emit ticket. */ + s2n(placeholder_len, p); + memcpy(p, kTicketPlaceholder, placeholder_len); + p += placeholder_len; + + len = p - ssl_handshake_start(s); + ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); + s->state = SSL3_ST_SW_SESSION_TICKET_B; + return ssl_do_write(s); + } + + /* Grow buffer if need be: the length calculation is as follows: + * handshake_header_length + 4 (ticket lifetime hint) + 2 (ticket length) + + * max_ticket_overhead + * session_length */ + if (!BUF_MEM_grow(s->init_buf, SSL_HM_HEADER_LENGTH(s) + 6 + + max_ticket_overhead + session_len)) { + OPENSSL_free(session); + return -1; + } + p = ssl_handshake_start(s); + EVP_CIPHER_CTX_init(&ctx); + HMAC_CTX_init(&hctx); + /* Initialize HMAC and cipher contexts. If callback present it does all the + * work otherwise use generated values from parent ctx. */ + if (tctx->tlsext_ticket_key_cb) { + if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, &hctx, 1) < 0) { + OPENSSL_free(session); + EVP_CIPHER_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&hctx); + return -1; + } + } else { + if (!RAND_bytes(iv, 16) || + !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + tctx->tlsext_tick_aes_key, iv) || + !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), + NULL)) { + OPENSSL_free(session); + EVP_CIPHER_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&hctx); + return -1; + } + memcpy(key_name, tctx->tlsext_tick_key_name, 16); + } + + /* Ticket lifetime hint (advisory only): We leave this unspecified for + * resumed session (for simplicity), and guess that tickets for new + * sessions will live as long as their sessions. */ + l2n(s->hit ? 0 : s->session->timeout, p); + + /* Skip ticket length for now */ + p += 2; + /* Output key name */ + macstart = p; + memcpy(p, key_name, 16); + p += 16; + /* output IV */ + memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); + p += EVP_CIPHER_CTX_iv_length(&ctx); + /* Encrypt session data */ + EVP_EncryptUpdate(&ctx, p, &len, session, session_len); + p += len; + EVP_EncryptFinal_ex(&ctx, p, &len); + p += len; + EVP_CIPHER_CTX_cleanup(&ctx); + + HMAC_Update(&hctx, macstart, p - macstart); + HMAC_Final(&hctx, p, &hlen); + HMAC_CTX_cleanup(&hctx); + + p += hlen; + /* Now write out lengths: p points to end of data written */ + /* Total length */ + len = p - ssl_handshake_start(s); + /* Skip ticket lifetime hint */ + p = ssl_handshake_start(s) + 4; + s2n(len - 6, p); + ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); + s->state = SSL3_ST_SW_SESSION_TICKET_B; + OPENSSL_free(session); + } + + /* SSL3_ST_SW_SESSION_TICKET_B */ + return ssl_do_write(s); +} /* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It * sets the next_proto member in s if found */ -int ssl3_get_next_proto(SSL *s) - { - int ok; - long n; - CBS next_protocol, selected_protocol, padding; - - /* Clients cannot send a NextProtocol message if we didn't see the - * extension in their ClientHello */ - if (!s->s3->next_proto_neg_seen) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION); - return -1; - } - - n=s->method->ssl_get_message(s, - SSL3_ST_SR_NEXT_PROTO_A, - SSL3_ST_SR_NEXT_PROTO_B, - SSL3_MT_NEXT_PROTO, - 514, /* See the payload format below */ - SSL_GET_MESSAGE_HASH_MESSAGE, - &ok); - - if (!ok) - return((int)n); - - /* s->state doesn't reflect whether ChangeCipherSpec has been received - * in this handshake, but s->s3->change_cipher_spec does (will be reset - * by ssl3_get_finished). - * TODO(davidben): Is this check now redundant with - * SSL3_FLAGS_EXPECT_CCS? */ - if (!s->s3->change_cipher_spec) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto, SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS); - return -1; - } - - CBS_init(&next_protocol, s->init_msg, n); - - /* The payload looks like: - * uint8 proto_len; - * uint8 proto[proto_len]; - * uint8 padding_len; - * uint8 padding[padding_len]; - */ - if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) || - !CBS_get_u8_length_prefixed(&next_protocol, &padding) || - CBS_len(&next_protocol) != 0) - return 0; - - if (!CBS_stow(&selected_protocol, - &s->next_proto_negotiated, - &s->next_proto_negotiated_len)) - return 0; - - return 1; - } +int ssl3_get_next_proto(SSL *s) { + int ok; + long n; + CBS next_protocol, selected_protocol, padding; + + /* Clients cannot send a NextProtocol message if we didn't see the extension + * in their ClientHello */ + if (!s->s3->next_proto_neg_seen) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto, + SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION); + return -1; + } + + n = s->method->ssl_get_message(s, SSL3_ST_SR_NEXT_PROTO_A, + SSL3_ST_SR_NEXT_PROTO_B, SSL3_MT_NEXT_PROTO, + 514, /* See the payload format below */ + SSL_GET_MESSAGE_HASH_MESSAGE, &ok); + + if (!ok) { + return n; + } + + /* s->state doesn't reflect whether ChangeCipherSpec has been received in + * this handshake, but s->s3->change_cipher_spec does (will be reset by + * ssl3_get_finished). + * + * TODO(davidben): Is this check now redundant with + * SSL3_FLAGS_EXPECT_CCS? */ + if (!s->s3->change_cipher_spec) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto, + SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS); + return -1; + } + + CBS_init(&next_protocol, s->init_msg, n); + + /* The payload looks like: + * uint8 proto_len; + * uint8 proto[proto_len]; + * uint8 padding_len; + * uint8 padding[padding_len]; */ + if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) || + !CBS_get_u8_length_prefixed(&next_protocol, &padding) || + CBS_len(&next_protocol) != 0 || + !CBS_stow(&selected_protocol, &s->next_proto_negotiated, + &s->next_proto_negotiated_len)) { + return 0; + } + + return 1; +} /* ssl3_get_channel_id reads and verifies a ClientID handshake message. */ -int ssl3_get_channel_id(SSL *s) - { - int ret = -1, ok; - long n; - EVP_MD_CTX md_ctx; - uint8_t channel_id_hash[SHA256_DIGEST_LENGTH]; - unsigned int channel_id_hash_len; - const uint8_t *p; - uint16_t extension_type, expected_extension_type; - EC_GROUP* p256 = NULL; - EC_KEY* key = NULL; - EC_POINT* point = NULL; - ECDSA_SIG sig; - BIGNUM x, y; - CBS encrypted_extensions, extension; - - n = s->method->ssl_get_message(s, - SSL3_ST_SR_CHANNEL_ID_A, - SSL3_ST_SR_CHANNEL_ID_B, - SSL3_MT_ENCRYPTED_EXTENSIONS, - 2 + 2 + TLSEXT_CHANNEL_ID_SIZE, - SSL_GET_MESSAGE_DONT_HASH_MESSAGE, - &ok); - - if (!ok) - return((int)n); - - /* Before incorporating the EncryptedExtensions message to the - * handshake hash, compute the hash that should have been signed. */ - channel_id_hash_len = sizeof(channel_id_hash); - EVP_MD_CTX_init(&md_ctx); - if (!EVP_DigestInit_ex(&md_ctx, EVP_sha256(), NULL) || - !tls1_channel_id_hash(&md_ctx, s) || - !EVP_DigestFinal(&md_ctx, channel_id_hash, &channel_id_hash_len)) - { - EVP_MD_CTX_cleanup(&md_ctx); - return -1; - } - EVP_MD_CTX_cleanup(&md_ctx); - assert(channel_id_hash_len == SHA256_DIGEST_LENGTH); - - ssl3_hash_current_message(s); - - /* s->state doesn't reflect whether ChangeCipherSpec has been received - * in this handshake, but s->s3->change_cipher_spec does (will be reset - * by ssl3_get_finished). - * TODO(davidben): Is this check now redundant with - * SSL3_FLAGS_EXPECT_CCS? */ - if (!s->s3->change_cipher_spec) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_GOT_CHANNEL_ID_BEFORE_A_CCS); - return -1; - } - - CBS_init(&encrypted_extensions, s->init_msg, n); - - /* EncryptedExtensions could include multiple extensions, but - * the only extension that could be negotiated is ChannelID, - * so there can only be one entry. - * - * The payload looks like: - * uint16 extension_type - * uint16 extension_len; - * uint8 x[32]; - * uint8 y[32]; - * uint8 r[32]; - * uint8 s[32]; - */ - expected_extension_type = TLSEXT_TYPE_channel_id; - if (s->s3->tlsext_channel_id_new) - expected_extension_type = TLSEXT_TYPE_channel_id_new; - - if (!CBS_get_u16(&encrypted_extensions, &extension_type) || - !CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) || - CBS_len(&encrypted_extensions) != 0 || - extension_type != expected_extension_type || - CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_INVALID_MESSAGE); - return -1; - } - - p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); - if (!p256) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_NO_P256_SUPPORT); - return -1; - } - - BN_init(&x); - BN_init(&y); - sig.r = BN_new(); - sig.s = BN_new(); - - p = CBS_data(&extension); - if (BN_bin2bn(p + 0, 32, &x) == NULL || - BN_bin2bn(p + 32, 32, &y) == NULL || - BN_bin2bn(p + 64, 32, sig.r) == NULL || - BN_bin2bn(p + 96, 32, sig.s) == NULL) - goto err; - - point = EC_POINT_new(p256); - if (!point || - !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) - goto err; - - key = EC_KEY_new(); - if (!key || - !EC_KEY_set_group(key, p256) || - !EC_KEY_set_public_key(key, point)) - goto err; - - /* We stored the handshake hash in |tlsext_channel_id| the first time - * that we were called. */ - if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_CHANNEL_ID_SIGNATURE_INVALID); - s->s3->tlsext_channel_id_valid = 0; - goto err; - } - - memcpy(s->s3->tlsext_channel_id, p, 64); - ret = 1; +int ssl3_get_channel_id(SSL *s) { + int ret = -1, ok; + long n; + EVP_MD_CTX md_ctx; + uint8_t channel_id_hash[SHA256_DIGEST_LENGTH]; + unsigned int channel_id_hash_len; + const uint8_t *p; + uint16_t extension_type, expected_extension_type; + EC_GROUP *p256 = NULL; + EC_KEY *key = NULL; + EC_POINT *point = NULL; + ECDSA_SIG sig; + BIGNUM x, y; + CBS encrypted_extensions, extension; + + n = s->method->ssl_get_message( + s, SSL3_ST_SR_CHANNEL_ID_A, SSL3_ST_SR_CHANNEL_ID_B, + SSL3_MT_ENCRYPTED_EXTENSIONS, 2 + 2 + TLSEXT_CHANNEL_ID_SIZE, + SSL_GET_MESSAGE_DONT_HASH_MESSAGE, &ok); + + if (!ok) { + return n; + } + + /* Before incorporating the EncryptedExtensions message to the handshake + * hash, compute the hash that should have been signed. */ + channel_id_hash_len = sizeof(channel_id_hash); + EVP_MD_CTX_init(&md_ctx); + if (!EVP_DigestInit_ex(&md_ctx, EVP_sha256(), NULL) || + !tls1_channel_id_hash(&md_ctx, s) || + !EVP_DigestFinal(&md_ctx, channel_id_hash, &channel_id_hash_len)) { + EVP_MD_CTX_cleanup(&md_ctx); + return -1; + } + EVP_MD_CTX_cleanup(&md_ctx); + assert(channel_id_hash_len == SHA256_DIGEST_LENGTH); + + ssl3_hash_current_message(s); + + /* s->state doesn't reflect whether ChangeCipherSpec has been received in + * this handshake, but s->s3->change_cipher_spec does (will be reset by + * ssl3_get_finished). + * + * TODO(davidben): Is this check now redundant with SSL3_FLAGS_EXPECT_CCS? */ + if (!s->s3->change_cipher_spec) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, + SSL_R_GOT_CHANNEL_ID_BEFORE_A_CCS); + return -1; + } + + CBS_init(&encrypted_extensions, s->init_msg, n); + + /* EncryptedExtensions could include multiple extensions, but the only + * extension that could be negotiated is ChannelID, so there can only be one + * entry. + * + * The payload looks like: + * uint16 extension_type + * uint16 extension_len; + * uint8 x[32]; + * uint8 y[32]; + * uint8 r[32]; + * uint8 s[32]; */ + expected_extension_type = TLSEXT_TYPE_channel_id; + if (s->s3->tlsext_channel_id_new) { + expected_extension_type = TLSEXT_TYPE_channel_id_new; + } + + if (!CBS_get_u16(&encrypted_extensions, &extension_type) || + !CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) || + CBS_len(&encrypted_extensions) != 0 || + extension_type != expected_extension_type || + CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_INVALID_MESSAGE); + return -1; + } + + p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + if (!p256) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_NO_P256_SUPPORT); + return -1; + } + + BN_init(&x); + BN_init(&y); + sig.r = BN_new(); + sig.s = BN_new(); + + p = CBS_data(&extension); + if (BN_bin2bn(p + 0, 32, &x) == NULL || + BN_bin2bn(p + 32, 32, &y) == NULL || + BN_bin2bn(p + 64, 32, sig.r) == NULL || + BN_bin2bn(p + 96, 32, sig.s) == NULL) { + goto err; + } + + point = EC_POINT_new(p256); + if (!point || !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) { + goto err; + } + + key = EC_KEY_new(); + if (!key || !EC_KEY_set_group(key, p256) || + !EC_KEY_set_public_key(key, point)) { + goto err; + } + + /* We stored the handshake hash in |tlsext_channel_id| the first time that we + * were called. */ + if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, + SSL_R_CHANNEL_ID_SIGNATURE_INVALID); + s->s3->tlsext_channel_id_valid = 0; + goto err; + } + + memcpy(s->s3->tlsext_channel_id, p, 64); + ret = 1; err: - BN_free(&x); - BN_free(&y); - BN_free(sig.r); - BN_free(sig.s); - if (key) - EC_KEY_free(key); - if (point) - EC_POINT_free(point); - if (p256) - EC_GROUP_free(p256); - return ret; - } - + BN_free(&x); + BN_free(&y); + BN_free(sig.r); + BN_free(sig.s); + if (key) { + EC_KEY_free(key); + } + if (point) { + EC_POINT_free(point); + } + if (p256) { + EC_GROUP_free(p256); + } + return ret; +} |