int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len) { SSL3_BUFFER *buf = &ssl->s3->write_buffer; if (buf->buf != NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } size_t header_len = ssl_seal_prefix_len(ssl); /* TODO(davidben): This matches the original behavior in keeping the malloc * size consistent. Does this matter? |cap| could just be |max_len|. */ size_t cap = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; if (SSL_IS_DTLS(ssl)) { cap += DTLS1_RT_HEADER_LENGTH; } else { cap += SSL3_RT_HEADER_LENGTH; if (ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) { cap += SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; } } if (max_len > cap) { OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); return 0; } if (!setup_buffer(buf, header_len, cap)) { return 0; } *out_ptr = buf->buf + buf->offset; return 1; }
int ssl3_setup_read_buffer(SSL *s) { uint8_t *p; size_t len, align = 0, headerlen; if (SSL_IS_DTLS(s)) { headerlen = DTLS1_RT_HEADER_LENGTH; } else { headerlen = SSL3_RT_HEADER_LENGTH; } #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); #endif if (s->s3->rbuf.buf == NULL) { len = SSL3_RT_MAX_ENCRYPTED_LENGTH + headerlen + align; if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) { s->s3->init_extra = 1; len += SSL3_RT_MAX_EXTRA; } p = OPENSSL_malloc(len); if (p == NULL) { goto err; } s->s3->rbuf.buf = p; s->s3->rbuf.len = len; } s->packet = &s->s3->rbuf.buf[0]; return 1; err: OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; }
int ssl_read_buffer_extend_to(SSL *ssl, size_t len) { /* |ssl_read_buffer_extend_to| implicitly discards any consumed data. */ ssl_read_buffer_discard(ssl); if (!setup_read_buffer(ssl)) { return -1; } if (ssl->rbio == NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET); return -1; } ERR_clear_system_error(); int ret; if (SSL_IS_DTLS(ssl)) { /* |len| is ignored for a datagram transport. */ ret = dtls_read_buffer_next_packet(ssl); } else { ret = tls_read_buffer_extend_to(ssl, len); } if (ret <= 0) { /* If the buffer was empty originally and remained empty after attempting to * extend it, release the buffer until the next attempt. */ ssl_read_buffer_discard(ssl); } return ret; }
int ssl3_setup_write_buffer(SSL *s) { uint8_t *p; size_t len, align, headerlen; if (SSL_IS_DTLS(s)) headerlen = DTLS1_RT_HEADER_LENGTH + 1; else headerlen = SSL3_RT_HEADER_LENGTH; align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); if (s->s3->wbuf.buf == NULL) { len = s->max_send_fragment + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; if ((p = malloc(len)) == NULL) goto err; s->s3->wbuf.buf = p; s->s3->wbuf.len = len; } return 1; err: SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE); return 0; }
int ssl3_setup_read_buffer(SSL *s) { uint8_t *p; size_t len, align, headerlen; if (SSL_IS_DTLS(s)) headerlen = DTLS1_RT_HEADER_LENGTH; else headerlen = SSL3_RT_HEADER_LENGTH; align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); if (s->s3->rbuf.buf == NULL) { len = SSL3_RT_MAX_ENCRYPTED_LENGTH + headerlen + align; if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) { s->s3->init_extra = 1; len += SSL3_RT_MAX_EXTRA; } if ((p = malloc(len)) == NULL) goto err; s->s3->rbuf.buf = p; s->s3->rbuf.len = len; } s->packet = &(s->s3->rbuf.buf[0]); return 1; err: SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER, ERR_R_MALLOC_FAILURE); return 0; }
static int version_cmp(const SSL *s, int a, int b) { int dtls = SSL_IS_DTLS(s); if (a == b) return 0; if (!dtls) return a < b ? -1 : 1; return DTLS_VERSION_LT(a, b) ? -1 : 1; }
void ssl_read_buffer_consume(SSL *ssl, size_t len) { SSL3_BUFFER *buf = &ssl->s3->read_buffer; consume_buffer(buf, len); if (!SSL_IS_DTLS(ssl)) { /* The TLS stack never reads beyond the current record, so there will never * be unconsumed data. If read-ahead is ever reimplemented, * |ssl_read_buffer_discard| will require a |memcpy| to shift the excess * back to the front of the buffer, to ensure there is enough space for the * next record. */ assert(buf->len == 0); } }
int ssl_write_buffer_flush(SSL *ssl) { if (ssl->wbio == NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET); return -1; } ERR_clear_system_error(); if (SSL_IS_DTLS(ssl)) { return dtls_write_buffer_flush(ssl); } else { return tls_write_buffer_flush(ssl); } }
int ssl3_setup_write_buffer(SSL *s, unsigned int numwpipes, size_t len) { unsigned char *p; size_t align = 0, headerlen; SSL3_BUFFER *wb; unsigned int currpipe; s->rlayer.numwpipes = numwpipes; if (len == 0) { if (SSL_IS_DTLS(s)) headerlen = DTLS1_RT_HEADER_LENGTH + 1; else headerlen = SSL3_RT_HEADER_LENGTH; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); #endif len = s->max_send_fragment + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; #ifndef OPENSSL_NO_COMP if (ssl_allow_compression(s)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; } wb = RECORD_LAYER_get_wbuf(&s->rlayer); for (currpipe = 0; currpipe < numwpipes; currpipe++) { SSL3_BUFFER *thiswb = &wb[currpipe]; if (thiswb->buf == NULL) { p = OPENSSL_malloc(len); if (p == NULL) { s->rlayer.numwpipes = currpipe; goto err; } memset(thiswb, 0, sizeof(SSL3_BUFFER)); thiswb->buf = p; thiswb->len = len; } } return 1; err: SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE); return 0; }
/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, * respectively. It returns one on success and zero on failure. */ int tls1_enc(SSL *s, int send) { SSL3_RECORD *rec; const SSL_AEAD_CTX *aead; if (send) { rec = &s->s3->wrec; aead = s->aead_write_ctx; } else { rec = &s->s3->rrec; aead = s->aead_read_ctx; } if (aead == NULL) { /* Handle the initial NULL cipher. */ memmove(rec->data, rec->input, rec->length); rec->input = rec->data; return 1; } uint8_t ad[13], *seq, *in, *out, nonce[EVP_AEAD_MAX_NONCE_LENGTH]; unsigned nonce_used; size_t n, ad_len; seq = send ? s->s3->write_sequence : s->s3->read_sequence; if (SSL_IS_DTLS(s)) { uint8_t dtlsseq[9], *p = dtlsseq; s2n(send ? s->d1->w_epoch : s->d1->r_epoch, p); memcpy(p, &seq[2], 6); memcpy(ad, dtlsseq, 8); } else { int i; memcpy(ad, seq, 8); for (i = 7; i >= 0; i--) { ++seq[i]; if (seq[i] != 0) { break; } } } ad[8] = rec->type; ad_len = 9; if (!aead->omit_version_in_ad) { ad[ad_len++] = (uint8_t)(s->version >> 8); ad[ad_len++] = (uint8_t)(s->version); }
/* setup_read_buffer initializes the read buffer if not already initialized. It * returns one on success and zero on failure. */ static int setup_read_buffer(SSL *ssl) { SSL3_BUFFER *buf = &ssl->s3->read_buffer; if (buf->buf != NULL) { return 1; } size_t header_len = ssl_record_prefix_len(ssl); size_t cap = SSL3_RT_MAX_ENCRYPTED_LENGTH; if (SSL_IS_DTLS(ssl)) { cap += DTLS1_RT_HEADER_LENGTH; } else { cap += SSL3_RT_HEADER_LENGTH; } return setup_buffer(buf, header_len, cap); }
/* * ssl_set_client_hello_version - Work out what version we should be using for * the initial ClientHello.legacy_version field. * * @s: client SSL handle. * * Returns 0 on success or an SSL error reason number on failure. */ int ssl_set_client_hello_version(SSL *s) { int ver_min, ver_max, ret; ret = ssl_get_client_min_max_version(s, &ver_min, &ver_max); if (ret != 0) return ret; s->version = ver_max; /* TLS1.3 always uses TLS1.2 in the legacy_version field */ if (!SSL_IS_DTLS(s) && ver_max > TLS1_2_VERSION) ver_max = TLS1_2_VERSION; s->client_version = ver_max; return 0; }
int DTLSv1_handle_timeout(SSL *ssl) { if (!SSL_IS_DTLS(ssl)) { return -1; } /* if no timer is expired, don't do anything */ if (!dtls1_is_timer_expired(ssl)) { return 0; } dtls1_double_timeout(ssl); if (dtls1_check_timeout_num(ssl) < 0) { return -1; } dtls1_start_timer(ssl); return dtls1_retransmit_buffered_messages(ssl); }
int ssl3_setup_read_buffer(SSL *s) { unsigned char *p; size_t len, align = 0, headerlen; SSL3_BUFFER *b; b = RECORD_LAYER_get_rbuf(&s->rlayer); if (SSL_IS_DTLS(s)) headerlen = DTLS1_RT_HEADER_LENGTH; else headerlen = SSL3_RT_HEADER_LENGTH; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); #endif if (b->buf == NULL) { len = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align; if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) { s->s3->init_extra = 1; len += SSL3_RT_MAX_EXTRA; } #ifndef OPENSSL_NO_COMP if (ssl_allow_compression(s)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if ((p = OPENSSL_malloc(len)) == NULL) goto err; b->buf = p; b->len = len; } RECORD_LAYER_set_packet(&s->rlayer, &(b->buf[0])); return 1; err: SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER, ERR_R_MALLOC_FAILURE); return 0; }
int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) { if (!SSL_IS_DTLS(ssl)) { return 0; } /* If no timeout is set, just return NULL */ if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) { return 0; } /* Get current time */ struct timeval timenow; get_current_time(ssl, &timenow); /* If timer already expired, set remaining time to 0 */ if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec || (ssl->d1->next_timeout.tv_sec == timenow.tv_sec && ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) { memset(out, 0, sizeof(struct timeval)); return 1; } /* Calculate time left until timer expires */ memcpy(out, &ssl->d1->next_timeout, sizeof(struct timeval)); out->tv_sec -= timenow.tv_sec; out->tv_usec -= timenow.tv_usec; if (out->tv_usec < 0) { out->tv_sec--; out->tv_usec += 1000000; } /* If remaining time is less than 15 ms, set it to 0 to prevent issues * because of small devergences with socket timeouts. */ if (out->tv_sec == 0 && out->tv_usec < 15000) { memset(out, 0, sizeof(struct timeval)); } return 1; }
int ssl3_setup_write_buffer(SSL *s) { unsigned char *p; size_t len, align = 0, headerlen; SSL3_BUFFER *wb; wb = RECORD_LAYER_get_wbuf(&s->rlayer); if (SSL_IS_DTLS(s)) headerlen = DTLS1_RT_HEADER_LENGTH + 1; else headerlen = SSL3_RT_HEADER_LENGTH; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); #endif if (wb->buf == NULL) { len = s->max_send_fragment + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; #ifndef OPENSSL_NO_COMP if (ssl_allow_compression(s)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; if ((p = OPENSSL_malloc(len)) == NULL) goto err; wb->buf = p; wb->len = len; } return 1; err: SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE); return 0; }
int DTLSv1_handle_timeout(SSL *ssl) { /* Functions which use SSL_get_error must clear the error queue on entry. */ ERR_clear_error(); if (!SSL_IS_DTLS(ssl)) { return -1; } /* if no timer is expired, don't do anything */ if (!dtls1_is_timer_expired(ssl)) { return 0; } dtls1_double_timeout(ssl); if (dtls1_check_timeout_num(ssl) < 0) { return -1; } dtls1_start_timer(ssl); return dtls1_retransmit_buffered_messages(ssl); }
int ssl3_setup_read_buffer(SSL *s) { unsigned char *p; size_t len, align = 0, headerlen; if (SSL_IS_DTLS(s)) headerlen = DTLS1_RT_HEADER_LENGTH; else headerlen = SSL3_RT_HEADER_LENGTH; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); #endif if (s->s3->rbuf.buf == NULL) { len = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align; if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) { s->s3->init_extra = 1; len += SSL3_RT_MAX_EXTRA; } #ifndef OPENSSL_NO_COMP if (!(s->options & SSL_OP_NO_COMPRESSION)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if ((p = freelist_extract(s->ctx, 1, len)) == NULL) goto err; s->s3->rbuf.buf = p; s->s3->rbuf.len = len; } s->packet = &(s->s3->rbuf.buf[0]); return 1; err: SSLerr(SSL_F_SSL3_SETUP_READ_BUFFER, ERR_R_MALLOC_FAILURE); return 0; }
int ssl3_setup_write_buffer(SSL *s) { uint8_t *p; size_t len, align = 0, headerlen; if (SSL_IS_DTLS(s)) { headerlen = DTLS1_RT_HEADER_LENGTH + 1; } else { headerlen = SSL3_RT_HEADER_LENGTH; } #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); #endif if (s->s3->wbuf.buf == NULL) { len = s->max_send_fragment + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; /* Account for 1/n-1 record splitting. */ if (s->mode & SSL_MODE_CBC_RECORD_SPLITTING) { len += headerlen + align + 1 + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; } p = OPENSSL_malloc(len); if (p == NULL) { goto err; } s->s3->wbuf.buf = p; s->s3->wbuf.len = len; } return 1; err: OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; }
int ssl3_setup_write_buffer(SSL *s) { unsigned char *p; size_t len, align = 0, headerlen; if (SSL_IS_DTLS(s)) headerlen = DTLS1_RT_HEADER_LENGTH + 1; else headerlen = SSL3_RT_HEADER_LENGTH; #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); #endif if (s->s3->wbuf.buf == NULL) { len = s->max_send_fragment + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; #ifndef OPENSSL_NO_COMP if (!(s->options & SSL_OP_NO_COMPRESSION)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; if ((p = freelist_extract(s->ctx, 0, len)) == NULL) goto err; s->s3->wbuf.buf = p; s->s3->wbuf.len = len; } return 1; err: SSLerr(SSL_F_SSL3_SETUP_WRITE_BUFFER, ERR_R_MALLOC_FAILURE); return 0; }
/* Since the server cache lookup is done early on in the processing of the * ClientHello, and other operations depend on the result, we need to handle * any TLS session ticket extension at the same time. * * session_id: points at the session ID in the ClientHello. This code will * read past the end of this in order to parse out the session ticket * extension, if any. * len: the length of the session ID. * limit: a pointer to the first byte after the ClientHello. * ret: (output) on return, if a ticket was decrypted, then this is set to * point to the resulting session. * * If s->internal->tls_session_secret_cb is set then we are expecting a pre-shared key * ciphersuite, in which case we have no use for session tickets and one will * never be decrypted, nor will s->internal->tlsext_ticket_expected be set to 1. * * Returns: * -1: fatal error, either from parsing or decrypting the ticket. * 0: no ticket was found (or was ignored, based on settings). * 1: a zero length extension was found, indicating that the client supports * session tickets but doesn't currently have one to offer. * 2: either s->internal->tls_session_secret_cb was set, or a ticket was offered but * couldn't be decrypted because of a non-fatal error. * 3: a ticket was successfully decrypted and *ret was set. * * Side effects: * Sets s->internal->tlsext_ticket_expected to 1 if the server will have to issue * a new session ticket to the client because the client indicated support * (and s->internal->tls_session_secret_cb is NULL) but the client either doesn't have * a session ticket or we couldn't use the one it gave us, or if * s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket. * Otherwise, s->internal->tlsext_ticket_expected is set to 0. */ int tls1_process_ticket(SSL *s, const unsigned char *session, int session_len, const unsigned char *limit, SSL_SESSION **ret) { /* Point after session ID in client hello */ CBS session_id, cookie, cipher_list, compress_algo, extensions; *ret = NULL; s->internal->tlsext_ticket_expected = 0; /* If tickets disabled behave as if no ticket present * to permit stateful resumption. */ if (SSL_get_options(s) & SSL_OP_NO_TICKET) return 0; if (!limit) return 0; if (limit < session) return -1; CBS_init(&session_id, session, limit - session); /* Skip past the session id */ if (!CBS_skip(&session_id, session_len)) return -1; /* Skip past DTLS cookie */ if (SSL_IS_DTLS(s)) { if (!CBS_get_u8_length_prefixed(&session_id, &cookie)) return -1; } /* Skip past cipher list */ if (!CBS_get_u16_length_prefixed(&session_id, &cipher_list)) return -1; /* Skip past compression algorithm list */ if (!CBS_get_u8_length_prefixed(&session_id, &compress_algo)) return -1; /* Now at start of extensions */ if (CBS_len(&session_id) == 0) return 0; if (!CBS_get_u16_length_prefixed(&session_id, &extensions)) return -1; while (CBS_len(&extensions) > 0) { CBS ext_data; uint16_t ext_type; if (!CBS_get_u16(&extensions, &ext_type) || !CBS_get_u16_length_prefixed(&extensions, &ext_data)) return -1; if (ext_type == TLSEXT_TYPE_session_ticket) { int r; if (CBS_len(&ext_data) == 0) { /* The client will accept a ticket but doesn't * currently have one. */ s->internal->tlsext_ticket_expected = 1; return 1; } if (s->internal->tls_session_secret_cb) { /* Indicate that the ticket couldn't be * decrypted rather than generating the session * from ticket now, trigger abbreviated * handshake based on external mechanism to * calculate the master secret later. */ return 2; } r = tls_decrypt_ticket(s, CBS_data(&ext_data), CBS_len(&ext_data), session, session_len, ret); switch (r) { case 2: /* ticket couldn't be decrypted */ s->internal->tlsext_ticket_expected = 1; return 2; case 3: /* ticket was decrypted */ return r; case 4: /* ticket decrypted but need to renew */ s->internal->tlsext_ticket_expected = 1; return 3; default: /* fatal error */ return -1; } } } return 0; }
int dtls1_accept(SSL *s) { BUF_MEM *buf = NULL; void (*cb)(const SSL *ssl, int type, int value) = NULL; uint32_t alg_a; int ret = -1; int new_state, state, skip = 0; assert(s->handshake_func == dtls1_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++; for (;;) { state = s->state; switch (s->state) { case SSL_ST_ACCEPT: if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_START, 1); } if (s->init_buf == NULL) { buf = BUF_MEM_new(); if (buf == NULL || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { ret = -1; goto end; } s->init_buf = buf; buf = NULL; } s->init_num = 0; if (!ssl_init_wbio_buffer(s, 1)) { ret = -1; goto end; } if (!ssl3_init_handshake_buffer(s)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); ret = -1; 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 <= 0) { goto end; } dtls1_stop_timer(s); 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: dtls1_start_timer(s); 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)) { dtls1_start_timer(s); 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_CERT_STATUS_A: case SSL3_ST_SW_CERT_STATUS_B: ret = ssl3_send_certificate_status(s); if (ret <= 0) { goto end; } 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: case SSL3_ST_SW_KEY_EXCH_C: 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 s3_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)) { dtls1_start_timer(s); 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 (s->s3->tmp.cert_request) { dtls1_start_timer(s); ret = ssl3_send_certificate_request(s); if (ret <= 0) { goto end; } } else { skip = 1; } s->state = SSL3_ST_SW_SRVR_DONE_A; s->init_num = 0; break; case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); 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: 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: case SSL3_ST_SR_KEY_EXCH_C: 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: ret = s->method->ssl_read_change_cipher_spec(s); if (ret <= 0) { goto end; } if (!ssl3_do_change_cipher_spec(s)) { ret = -1; goto end; } 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; } dtls1_stop_timer(s); 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; } 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 = dtls1_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: ssl3_cleanup_key_block(s); /* remove buffering on output */ ssl_free_wbio_buffer(s); s->init_num = 0; s->s3->initial_handshake_complete = 1; ssl_update_cache(s, SSL_SESS_CACHE_SERVER); if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_DONE, 1); } ret = 1; /* done handshaking, next message is client hello */ s->d1->handshake_read_seq = 0; /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; default: OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE); ret = -1; goto end; } 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: s->in_handshake--; BUF_MEM_free(buf); if (cb != NULL) { cb(s, SSL_CB_ACCEPT_EXIT, ret); } return ret; }
static int tls1_change_cipher_state_aead(SSL *s, char is_read, const uint8_t *key, unsigned key_len, const uint8_t *iv, unsigned iv_len, const uint8_t *mac_secret, unsigned mac_secret_len) { const EVP_AEAD *aead = s->s3->tmp.new_aead; SSL_AEAD_CTX *aead_ctx; /* merged_key is used to merge the MAC, cipher, and IV keys for an AEAD which * simulates pre-AEAD cipher suites. */ uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH]; if (mac_secret_len > 0) { /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher * suites). */ if (mac_secret_len + key_len + iv_len > sizeof(merged_key)) { OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR); return 0; } memcpy(merged_key, mac_secret, mac_secret_len); memcpy(merged_key + mac_secret_len, key, key_len); memcpy(merged_key + mac_secret_len + key_len, iv, iv_len); key = merged_key; key_len += mac_secret_len; key_len += iv_len; } if (is_read) { if (!tls1_aead_ctx_init(&s->aead_read_ctx)) { return 0; } aead_ctx = s->aead_read_ctx; } else { if (SSL_IS_DTLS(s) && s->aead_write_ctx != NULL) { /* DTLS renegotiation is unsupported, so a CCS can only switch away from * the NULL cipher. This simplifies renegotiation. */ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR); return 0; } if (!tls1_aead_ctx_init(&s->aead_write_ctx)) { return 0; } aead_ctx = s->aead_write_ctx; } if (!EVP_AEAD_CTX_init_with_direction( &aead_ctx->ctx, aead, key, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH, is_read ? evp_aead_open : evp_aead_seal)) { OPENSSL_free(aead_ctx); if (is_read) { s->aead_read_ctx = NULL; } else { s->aead_write_ctx = NULL; } return 0; } if (mac_secret_len == 0) { /* For a real AEAD, the IV is the fixed part of the nonce. */ if (iv_len > sizeof(aead_ctx->fixed_nonce)) { OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR); return 0; } memcpy(aead_ctx->fixed_nonce, iv, iv_len); aead_ctx->fixed_nonce_len = iv_len; aead_ctx->variable_nonce_included_in_record = (s->s3->tmp.new_cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0; aead_ctx->random_variable_nonce = 0; aead_ctx->omit_length_in_ad = 0; } else { aead_ctx->fixed_nonce_len = 0; aead_ctx->variable_nonce_included_in_record = 1; aead_ctx->random_variable_nonce = 1; aead_ctx->omit_length_in_ad = 1; } aead_ctx->variable_nonce_len = s->s3->tmp.new_variable_iv_len; aead_ctx->omit_version_in_ad = (s->version == SSL3_VERSION); if (aead_ctx->variable_nonce_len + aead_ctx->fixed_nonce_len != EVP_AEAD_nonce_length(aead)) { OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR); return 0; } aead_ctx->tag_len = EVP_AEAD_max_overhead(aead); return 1; }
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst) { void (*cb) (const SSL *ssl, int type, int val) = NULL; #ifndef OPENSSL_NO_SCTP if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) { WORK_STATE ret; ret = dtls_wait_for_dry(s); if (ret != WORK_FINISHED_CONTINUE) return ret; } #endif /* clean a few things up */ ssl3_cleanup_key_block(s); if (!SSL_IS_DTLS(s)) { /* * We don't do this in DTLS because we may still need the init_buf * in case there are any unexpected retransmits */ BUF_MEM_free(s->init_buf); s->init_buf = NULL; } ssl_free_wbio_buffer(s); s->init_num = 0; if (!s->server || s->renegotiate == 2) { /* skipped if we just sent a HelloRequest */ s->renegotiate = 0; s->new_session = 0; if (s->server) { ssl_update_cache(s, SSL_SESS_CACHE_SERVER); s->ctx->stats.sess_accept_good++; s->handshake_func = ossl_statem_accept; } else { ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); if (s->hit) s->ctx->stats.sess_hit++; s->handshake_func = ossl_statem_connect; s->ctx->stats.sess_connect_good++; } if (s->info_callback != NULL) cb = s->info_callback; else if (s->ctx->info_callback != NULL) cb = s->ctx->info_callback; if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_DONE, 1); if (SSL_IS_DTLS(s)) { /* done with handshaking */ s->d1->handshake_read_seq = 0; s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; dtls1_clear_received_buffer(s); } } return WORK_FINISHED_STOP; }
int tls1_change_cipher_state(SSL *s, int which) { /* is_read is true if we have just read a ChangeCipherSpec message - i.e. we * need to update the read cipherspec. Otherwise we have just written one. */ const char is_read = (which & SSL3_CC_READ) != 0; /* use_client_keys is true if we wish to use the keys for the "client write" * direction. This is the case if we're a client sending a ChangeCipherSpec, * or a server reading a client's ChangeCipherSpec. */ const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE || which == SSL3_CHANGE_CIPHER_SERVER_READ; const uint8_t *client_write_mac_secret, *server_write_mac_secret, *mac_secret; const uint8_t *client_write_key, *server_write_key, *key; const uint8_t *client_write_iv, *server_write_iv, *iv; const EVP_AEAD *aead = s->s3->tmp.new_aead; size_t key_len, iv_len, mac_secret_len; const uint8_t *key_data; /* Reset sequence number to zero. */ if (!SSL_IS_DTLS(s)) { memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8); } mac_secret_len = s->s3->tmp.new_mac_secret_len; iv_len = s->s3->tmp.new_fixed_iv_len; if (aead == NULL) { OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR); return 0; } key_len = EVP_AEAD_key_length(aead); if (mac_secret_len > 0) { /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher * suites) the key length reported by |EVP_AEAD_key_length| will * include the MAC and IV key bytes. */ if (key_len < mac_secret_len + iv_len) { OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR); return 0; } key_len -= mac_secret_len + iv_len; } key_data = s->s3->tmp.key_block; client_write_mac_secret = key_data; key_data += mac_secret_len; server_write_mac_secret = key_data; key_data += mac_secret_len; client_write_key = key_data; key_data += key_len; server_write_key = key_data; key_data += key_len; client_write_iv = key_data; key_data += iv_len; server_write_iv = key_data; key_data += iv_len; if (use_client_keys) { mac_secret = client_write_mac_secret; key = client_write_key; iv = client_write_iv; } else { mac_secret = server_write_mac_secret; key = server_write_key; iv = server_write_iv; } if (key_data - s->s3->tmp.key_block != s->s3->tmp.key_block_length) { OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR); return 0; } return tls1_change_cipher_state_aead(s, is_read, key, key_len, iv, iv_len, mac_secret, mac_secret_len); }
MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt) { int al; long remain; remain = PACKET_remaining(pkt); /* * 'Change Cipher Spec' is just a single byte, which should already have * been consumed by ssl_get_message() so there should be no bytes left, * unless we're using DTLS1_BAD_VER, which has an extra 2 bytes */ if (SSL_IS_DTLS(s)) { if ((s->version == DTLS1_BAD_VER && remain != DTLS1_CCS_HEADER_LENGTH + 1) || (s->version != DTLS1_BAD_VER && remain != DTLS1_CCS_HEADER_LENGTH - 1)) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } } else { if (remain != 0) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_BAD_CHANGE_CIPHER_SPEC); goto f_err; } } /* Check we have a cipher to change to */ if (s->s3->tmp.new_cipher == NULL) { al = SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY); goto f_err; } s->s3->change_cipher_spec = 1; if (!ssl3_do_change_cipher_spec(s)) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR); goto f_err; } if (SSL_IS_DTLS(s)) { dtls1_reset_seq_numbers(s, SSL3_CC_READ); if (s->version == DTLS1_BAD_VER) s->d1->handshake_read_seq++; #ifndef OPENSSL_NO_SCTP /* * Remember that a CCS has been received, so that an old key of * SCTP-Auth can be deleted when a CCS is sent. Will be ignored if no * SCTP is used */ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL); #endif } return MSG_PROCESS_CONTINUE_READING; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); ossl_statem_set_error(s); return MSG_PROCESS_ERROR; }
int dtls1_connect(SSL *s) { BUF_MEM *buf = NULL; void (*cb)(const SSL *ssl, int type, int value) = NULL; int ret = -1; int new_state, state, skip = 0; assert(s->handshake_func == dtls1_connect); 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++; for (;;) { state = s->state; switch (s->state) { case SSL_ST_CONNECT: if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_START, 1); } if (s->init_buf == NULL) { buf = BUF_MEM_new(); if (buf == NULL || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { ret = -1; goto end; } s->init_buf = buf; buf = NULL; } if (!ssl_init_wbio_buffer(s, 0)) { ret = -1; goto end; } /* don't push the buffering BIO quite yet */ s->state = SSL3_ST_CW_CLNT_HELLO_A; s->init_num = 0; s->d1->send_cookie = 0; s->hit = 0; break; case SSL3_ST_CW_CLNT_HELLO_A: case SSL3_ST_CW_CLNT_HELLO_B: s->shutdown = 0; dtls1_start_timer(s); ret = ssl3_send_client_hello(s); if (ret <= 0) { goto end; } if (s->d1->send_cookie) { s->state = SSL3_ST_CW_FLUSH; s->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A; } else { s->state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; } s->init_num = 0; /* turn on buffering for the next lot of output */ if (s->bbio != s->wbio) { s->wbio = BIO_push(s->bbio, s->wbio); } break; case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: ret = dtls1_get_hello_verify(s); if (ret <= 0) { goto end; } if (s->d1->send_cookie) { /* start again, with a cookie */ dtls1_stop_timer(s); s->state = SSL3_ST_CW_CLNT_HELLO_A; } else { s->state = SSL3_ST_CR_SRVR_HELLO_A; } s->init_num = 0; break; case SSL3_ST_CR_SRVR_HELLO_A: case SSL3_ST_CR_SRVR_HELLO_B: ret = ssl3_get_server_hello(s); if (ret <= 0) { goto end; } if (s->hit) { s->state = SSL3_ST_CR_FINISHED_A; if (s->tlsext_ticket_expected) { /* receive renewed session ticket */ s->state = SSL3_ST_CR_SESSION_TICKET_A; } } else { s->state = SSL3_ST_CR_CERT_A; } s->init_num = 0; break; case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { ret = ssl3_get_server_certificate(s); if (ret <= 0) { goto end; } if (s->s3->tmp.certificate_status_expected) { s->state = SSL3_ST_CR_CERT_STATUS_A; } else { s->state = SSL3_ST_VERIFY_SERVER_CERT; } } else { skip = 1; s->state = SSL3_ST_CR_KEY_EXCH_A; } s->init_num = 0; break; case SSL3_ST_VERIFY_SERVER_CERT: ret = ssl3_verify_server_cert(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CR_KEY_EXCH_A; s->init_num = 0; break; case SSL3_ST_CR_KEY_EXCH_A: case SSL3_ST_CR_KEY_EXCH_B: ret = ssl3_get_server_key_exchange(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CR_CERT_REQ_A; s->init_num = 0; break; case SSL3_ST_CR_CERT_REQ_A: case SSL3_ST_CR_CERT_REQ_B: ret = ssl3_get_certificate_request(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CR_SRVR_DONE_A; s->init_num = 0; break; case SSL3_ST_CR_SRVR_DONE_A: case SSL3_ST_CR_SRVR_DONE_B: ret = ssl3_get_server_done(s); if (ret <= 0) { goto end; } dtls1_stop_timer(s); if (s->s3->tmp.cert_req) { s->s3->tmp.next_state = SSL3_ST_CW_CERT_A; } else { s->s3->tmp.next_state = SSL3_ST_CW_KEY_EXCH_A; } s->init_num = 0; s->state = s->s3->tmp.next_state; break; case SSL3_ST_CW_CERT_A: case SSL3_ST_CW_CERT_B: case SSL3_ST_CW_CERT_C: case SSL3_ST_CW_CERT_D: dtls1_start_timer(s); ret = ssl3_send_client_certificate(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CW_KEY_EXCH_A; s->init_num = 0; break; case SSL3_ST_CW_KEY_EXCH_A: case SSL3_ST_CW_KEY_EXCH_B: dtls1_start_timer(s); ret = ssl3_send_client_key_exchange(s); if (ret <= 0) { goto end; } /* For TLS, cert_req is set to 2, so a cert chain * of nothing is sent, but no verify packet is sent */ if (s->s3->tmp.cert_req == 1) { s->state = SSL3_ST_CW_CERT_VRFY_A; } else { s->state = SSL3_ST_CW_CHANGE_A; s->s3->change_cipher_spec = 0; } s->init_num = 0; break; case SSL3_ST_CW_CERT_VRFY_A: case SSL3_ST_CW_CERT_VRFY_B: case SSL3_ST_CW_CERT_VRFY_C: dtls1_start_timer(s); ret = ssl3_send_cert_verify(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CW_CHANGE_A; s->init_num = 0; s->s3->change_cipher_spec = 0; break; case SSL3_ST_CW_CHANGE_A: case SSL3_ST_CW_CHANGE_B: if (!s->hit) { dtls1_start_timer(s); } ret = dtls1_send_change_cipher_spec(s, SSL3_ST_CW_CHANGE_A, SSL3_ST_CW_CHANGE_B); if (ret <= 0) { goto end; } s->state = SSL3_ST_CW_FINISHED_A; s->init_num = 0; s->session->cipher = s->s3->tmp.new_cipher; if (!s->enc_method->setup_key_block(s) || !s->enc_method->change_cipher_state( s, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { ret = -1; goto end; } break; case SSL3_ST_CW_FINISHED_A: case SSL3_ST_CW_FINISHED_B: if (!s->hit) { dtls1_start_timer(s); } ret = ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B, s->enc_method->client_finished_label, s->enc_method->client_finished_label_len); if (ret <= 0) { goto end; } s->state = SSL3_ST_CW_FLUSH; if (s->hit) { s->s3->tmp.next_state = SSL_ST_OK; } else { /* Allow NewSessionTicket if ticket expected */ if (s->tlsext_ticket_expected) { s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A; } else { s->s3->tmp.next_state = SSL3_ST_CR_FINISHED_A; } } s->init_num = 0; break; case SSL3_ST_CR_SESSION_TICKET_A: case SSL3_ST_CR_SESSION_TICKET_B: ret = ssl3_get_new_session_ticket(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_CR_FINISHED_A; s->init_num = 0; break; case SSL3_ST_CR_CERT_STATUS_A: case SSL3_ST_CR_CERT_STATUS_B: ret = ssl3_get_cert_status(s); if (ret <= 0) { goto end; } s->state = SSL3_ST_VERIFY_SERVER_CERT; s->init_num = 0; break; case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: s->d1->change_cipher_spec_ok = 1; ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret <= 0) { goto end; } dtls1_stop_timer(s); if (s->hit) { s->state = SSL3_ST_CW_CHANGE_A; } else { s->state = SSL_ST_OK; } s->init_num = 0; break; case SSL3_ST_CW_FLUSH: 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 SSL_ST_OK: /* clean a few things up */ ssl3_cleanup_key_block(s); /* Remove write buffering now. */ ssl_free_wbio_buffer(s); s->init_num = 0; s->s3->initial_handshake_complete = 1; ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); ret = 1; if (cb != NULL) { cb(s, SSL_CB_HANDSHAKE_DONE, 1); } /* done with handshaking */ s->d1->handshake_read_seq = 0; s->d1->next_handshake_write_seq = 0; goto end; default: OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE); ret = -1; goto end; } /* did we do anything? */ if (!s->s3->tmp.reuse_message && !skip) { if ((cb != NULL) && (s->state != state)) { new_state = s->state; s->state = state; cb(s, SSL_CB_CONNECT_LOOP, 1); s->state = new_state; } } skip = 0; } end: s->in_handshake--; BUF_MEM_free(buf); if (cb != NULL) { cb(s, SSL_CB_CONNECT_EXIT, ret); } return ret; }
int tls1_change_cipher_state(SSL *s, int which) { static const unsigned char empty[]=""; unsigned char *p,*mac_secret; unsigned char *exp_label; unsigned char tmp1[EVP_MAX_KEY_LENGTH]; unsigned char tmp2[EVP_MAX_KEY_LENGTH]; unsigned char iv1[EVP_MAX_IV_LENGTH*2]; unsigned char iv2[EVP_MAX_IV_LENGTH*2]; unsigned char *ms,*key,*iv; int client_write; EVP_CIPHER_CTX *dd; const EVP_CIPHER *c; #ifndef OPENSSL_NO_COMP const SSL_COMP *comp; #endif const EVP_MD *m; int mac_type; int *mac_secret_size; EVP_MD_CTX *mac_ctx; EVP_PKEY *mac_key; int is_export,n,i,j,k,exp_label_len,cl; int reuse_dd = 0; is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); c=s->s3->tmp.new_sym_enc; m=s->s3->tmp.new_hash; mac_type = s->s3->tmp.new_mac_pkey_type; #ifndef OPENSSL_NO_COMP comp=s->s3->tmp.new_compression; #endif #ifdef KSSL_DEBUG printf("tls1_change_cipher_state(which= %d) w/\n", which); printf("\talg= %ld/%ld, comp= %p\n", s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, comp); printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c); printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n", c->nid,c->block_size,c->key_len,c->iv_len); printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length); { int i; for (i=0; i<s->s3->tmp.key_block_length; i++) printf("%02x", s->s3->tmp.key_block[i]); printf("\n"); } #endif /* KSSL_DEBUG */ if (which & SSL3_CC_READ) { if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; else s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; if (s->enc_read_ctx != NULL) reuse_dd = 1; else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) goto err; else /* make sure it's intialized in case we exit later with an error */ EVP_CIPHER_CTX_init(s->enc_read_ctx); dd= s->enc_read_ctx; mac_ctx=ssl_replace_hash(&s->read_hash,NULL); #ifndef OPENSSL_NO_COMP if (s->expand != NULL) { COMP_CTX_free(s->expand); s->expand=NULL; } if (comp != NULL) { s->expand=COMP_CTX_new(comp->method); if (s->expand == NULL) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); goto err2; } if (s->s3->rrec.comp == NULL) s->s3->rrec.comp=(unsigned char *) OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); if (s->s3->rrec.comp == NULL) goto err; } #endif /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ if (s->version != DTLS1_VERSION) memset(&(s->s3->read_sequence[0]),0,8); mac_secret= &(s->s3->read_mac_secret[0]); mac_secret_size=&(s->s3->read_mac_secret_size); } else { if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; else s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM; if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) reuse_dd = 1; else if ((s->enc_write_ctx=EVP_CIPHER_CTX_new()) == NULL) goto err; dd= s->enc_write_ctx; if (SSL_IS_DTLS(s)) { mac_ctx = EVP_MD_CTX_create(); if (!mac_ctx) goto err; s->write_hash = mac_ctx; } else mac_ctx = ssl_replace_hash(&s->write_hash,NULL); #ifndef OPENSSL_NO_COMP if (s->compress != NULL) { COMP_CTX_free(s->compress); s->compress=NULL; } if (comp != NULL) { s->compress=COMP_CTX_new(comp->method); if (s->compress == NULL) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); goto err2; } } #endif /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ if (s->version != DTLS1_VERSION) memset(&(s->s3->write_sequence[0]),0,8); mac_secret= &(s->s3->write_mac_secret[0]); mac_secret_size = &(s->s3->write_mac_secret_size); } if (reuse_dd) EVP_CIPHER_CTX_cleanup(dd); p=s->s3->tmp.key_block; i=*mac_secret_size=s->s3->tmp.new_mac_secret_size; cl=EVP_CIPHER_key_length(c); j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */ /* If GCM mode only part of IV comes from PRF */ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) k = EVP_GCM_TLS_FIXED_IV_LEN; else k=EVP_CIPHER_iv_length(c); if ( (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || (which == SSL3_CHANGE_CIPHER_SERVER_READ)) { ms= &(p[ 0]); n=i+i; key= &(p[ n]); n+=j+j; iv= &(p[ n]); n+=k+k; exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST; exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE; client_write=1; } else { n=i; ms= &(p[ n]); n+=i+j; key= &(p[ n]); n+=j+k; iv= &(p[ n]); n+=k; exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST; exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE; client_write=0; } if (n > s->s3->tmp.key_block_length) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR); goto err2; } memcpy(mac_secret,ms,i); if (!(EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER)) { mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, mac_secret,*mac_secret_size); EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key); EVP_PKEY_free(mac_key); } #ifdef TLS_DEBUG printf("which = %04X\nmac key=",which); { int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); } #endif if (is_export) { /* In here I set both the read and write key/iv to the * same value since only the correct one will be used :-). */ if (!tls1_PRF(ssl_get_algorithm2(s), exp_label,exp_label_len, s->s3->client_random,SSL3_RANDOM_SIZE, s->s3->server_random,SSL3_RANDOM_SIZE, NULL,0,NULL,0, key,j,tmp1,tmp2,EVP_CIPHER_key_length(c))) goto err2; key=tmp1; if (k > 0) { if (!tls1_PRF(ssl_get_algorithm2(s), TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE, s->s3->client_random,SSL3_RANDOM_SIZE, s->s3->server_random,SSL3_RANDOM_SIZE, NULL,0,NULL,0, empty,0,iv1,iv2,k*2)) goto err2; if (client_write) iv=iv1; else iv= &(iv1[k]); } } s->session->key_arg_length=0; #ifdef KSSL_DEBUG { int i; printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n"); printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]); printf("\n"); printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]); printf("\n"); } #endif /* KSSL_DEBUG */ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) { EVP_CipherInit_ex(dd,c,NULL,key,NULL,(which & SSL3_CC_WRITE)); EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv); } else EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */ if ((EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size) EVP_CIPHER_CTX_ctrl(dd,EVP_CTRL_AEAD_SET_MAC_KEY, *mac_secret_size,mac_secret); #ifdef TLS_DEBUG printf("which = %04X\nkey=",which); { int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); } printf("\niv="); { int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); } printf("\n"); #endif OPENSSL_cleanse(tmp1,sizeof(tmp1)); OPENSSL_cleanse(tmp2,sizeof(tmp1)); OPENSSL_cleanse(iv1,sizeof(iv1)); OPENSSL_cleanse(iv2,sizeof(iv2)); return(1); err: SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE); err2: return(0); }
int tls1_change_cipher_state(SSL *s, int which) { /* is_read is true if we have just read a ChangeCipherSpec message - i.e. we * need to update the read cipherspec. Otherwise we have just written one. */ const char is_read = (which & SSL3_CC_READ) != 0; /* use_client_keys is true if we wish to use the keys for the "client write" * direction. This is the case if we're a client sending a ChangeCipherSpec, * or a server reading a client's ChangeCipherSpec. */ const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE || which == SSL3_CHANGE_CIPHER_SERVER_READ; const uint8_t *client_write_mac_secret, *server_write_mac_secret, *mac_secret; const uint8_t *client_write_key, *server_write_key, *key; const uint8_t *client_write_iv, *server_write_iv, *iv; const EVP_AEAD *aead = s->s3->tmp.new_aead; size_t key_len, iv_len, mac_secret_len; const uint8_t *key_data; /* Reset sequence number to zero. */ if (!SSL_IS_DTLS(s)) { memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8); } mac_secret_len = s->s3->tmp.new_mac_secret_len; iv_len = s->s3->tmp.new_fixed_iv_len; if (aead == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } key_len = EVP_AEAD_key_length(aead); if (mac_secret_len > 0) { /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher * suites) the key length reported by |EVP_AEAD_key_length| will * include the MAC and IV key bytes. */ if (key_len < mac_secret_len + iv_len) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } key_len -= mac_secret_len + iv_len; } key_data = s->s3->tmp.key_block; client_write_mac_secret = key_data; key_data += mac_secret_len; server_write_mac_secret = key_data; key_data += mac_secret_len; client_write_key = key_data; key_data += key_len; server_write_key = key_data; key_data += key_len; client_write_iv = key_data; key_data += iv_len; server_write_iv = key_data; key_data += iv_len; if (use_client_keys) { mac_secret = client_write_mac_secret; key = client_write_key; iv = client_write_iv; } else { mac_secret = server_write_mac_secret; key = server_write_key; iv = server_write_iv; } if (key_data - s->s3->tmp.key_block != s->s3->tmp.key_block_length) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } if (is_read) { SSL_AEAD_CTX_free(s->aead_read_ctx); s->aead_read_ctx = SSL_AEAD_CTX_new( evp_aead_open, ssl3_version_from_wire(s, s->version), s->s3->tmp.new_cipher, key, key_len, mac_secret, mac_secret_len, iv, iv_len); return s->aead_read_ctx != NULL; } SSL_AEAD_CTX_free(s->aead_write_ctx); s->aead_write_ctx = SSL_AEAD_CTX_new( evp_aead_seal, ssl3_version_from_wire(s, s->version), s->s3->tmp.new_cipher, key, key_len, mac_secret, mac_secret_len, iv, iv_len); if (s->aead_write_ctx == NULL) { return 0; } s->s3->need_record_splitting = 0; if (!SSL_USE_EXPLICIT_IV(s) && (s->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0 && SSL_CIPHER_is_block_cipher(s->s3->tmp.new_cipher)) { /* Enable 1/n-1 record-splitting to randomize the IV. See * https://www.openssl.org/~bodo/tls-cbc.txt and the BEAST attack. */ s->s3->need_record_splitting = 1; } return 1; }
/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. * * Returns: * 0: (in non-constant time) if the record is publically invalid (i.e. too * short etc). * 1: if the record's padding is valid / the encryption was successful. * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, * an internal error occurred. */ int tls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; int bs,i,j,k,pad=0,ret,mac_size=0; const EVP_CIPHER *enc; if (send) { if (EVP_MD_CTX_md(s->write_hash)) { int n=EVP_MD_CTX_size(s->write_hash); OPENSSL_assert(n >= 0); } ds=s->enc_write_ctx; rec= &(s->s3->wrec); if (s->enc_write_ctx == NULL) enc=NULL; else { int ivlen; enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); /* For TLSv1.1 and later explicit IV */ if (SSL_USE_EXPLICIT_IV(s) && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) ivlen = EVP_CIPHER_iv_length(enc); else ivlen = 0; if (ivlen > 1) { if ( rec->data != rec->input) /* we can't write into the input stream: * Can this ever happen?? (steve) */ fprintf(stderr, "%s:%d: rec->data != rec->input\n", __FILE__, __LINE__); else if (RAND_bytes(rec->input, ivlen) <= 0) return -1; } } } else { if (EVP_MD_CTX_md(s->read_hash)) { int n=EVP_MD_CTX_size(s->read_hash); OPENSSL_assert(n >= 0); } ds=s->enc_read_ctx; rec= &(s->s3->rrec); if (s->enc_read_ctx == NULL) enc=NULL; else enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); } #ifdef KSSL_DEBUG printf("tls1_enc(%d)\n", send); #endif /* KSSL_DEBUG */ if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data,rec->input,rec->length); rec->input=rec->data; ret = 1; } else { l=rec->length; bs=EVP_CIPHER_block_size(ds->cipher); if (EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER) { unsigned char buf[13],*seq; seq = send?s->s3->write_sequence:s->s3->read_sequence; if (SSL_IS_DTLS(s)) { unsigned char dtlsseq[9],*p=dtlsseq; s2n(send?s->d1->w_epoch:s->d1->r_epoch,p); memcpy(p,&seq[2],6); memcpy(buf,dtlsseq,8); } else { memcpy(buf,seq,8); for (i=7; i>=0; i--) /* increment */ { ++seq[i]; if (seq[i] != 0) break; } } buf[8]=rec->type; buf[9]=(unsigned char)(s->version>>8); buf[10]=(unsigned char)(s->version); buf[11]=rec->length>>8; buf[12]=rec->length&0xff; pad=EVP_CIPHER_CTX_ctrl(ds,EVP_CTRL_AEAD_TLS1_AAD,13,buf); if (send) { l+=pad; rec->length+=pad; } } else if ((bs != 1) && send)