/* * Parse the client's renegotiation binding and abort if it's not right */ int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { unsigned int ilen; const unsigned char *data; /* Parse the length byte */ if (!PACKET_get_1(pkt, &ilen) || !PACKET_get_bytes(pkt, &data, ilen)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, SSL_R_RENEGOTIATION_ENCODING_ERR); return 0; } /* Check that the extension matches */ if (ilen != s->s3->previous_client_finished_len) { SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, SSL_R_RENEGOTIATION_MISMATCH); return 0; } if (memcmp(data, s->s3->previous_client_finished, s->s3->previous_client_finished_len)) { SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE, SSL_R_RENEGOTIATION_MISMATCH); return 0; } s->s3->send_connection_binding = 1; return 1; }
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET srp_I; if (!PACKET_as_length_prefixed_1(pkt, &srp_I) || PACKET_contains_zero_byte(&srp_I)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SRP, SSL_R_BAD_EXTENSION); return 0; } /* * TODO(openssl-team): currently, we re-authenticate the user * upon resumption. Instead, we MUST ignore the login. */ if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SRP, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len) { int ret; if (s->s3->handshake_dgst == NULL) { /* Note: this writes to a memory BIO so a failure is a fatal error */ if (len > INT_MAX) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC, SSL_R_OVERFLOW_ERROR); return 0; } ret = BIO_write(s->s3->handshake_buffer, (void *)buf, (int)len); if (ret <= 0 || ret != (int)len) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC, ERR_R_INTERNAL_ERROR); return 0; } } else { ret = EVP_DigestUpdate(s->s3->handshake_dgst, buf, len); if (!ret) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINISH_MAC, ERR_R_INTERNAL_ERROR); return 0; } } return 1; }
EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { if (!s->ext.status_expected) return EXT_RETURN_NOT_SENT; if (SSL_IS_TLS13(s) && chainidx != 0) return EXT_RETURN_NOT_SENT; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request) || !WPACKET_start_sub_packet_u16(pkt)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } /* * In TLSv1.3 we include the certificate status itself. In <= TLSv1.2 we * send back an empty extension, with the certificate status appearing as a * separate message */ if (SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) { /* SSLfatal() already called */ return EXT_RETURN_FAIL; } if (!WPACKET_close(pkt)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) { if (s->max_early_data == 0) return EXT_RETURN_NOT_SENT; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_put_bytes_u32(pkt, s->max_early_data) || !WPACKET_close(pkt)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; } if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED) return EXT_RETURN_NOT_SENT; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_close(pkt)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET supported_groups_list; /* Each group is 2 bytes and we must have at least 1. */ if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) || PACKET_remaining(&supported_groups_list) == 0 || (PACKET_remaining(&supported_groups_list) % 2) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION); return 0; } if (!s->hit || SSL_IS_TLS13(s)) { OPENSSL_free(s->session->ext.supportedgroups); s->session->ext.supportedgroups = NULL; s->session->ext.supportedgroups_len = 0; if (!tls1_save_u16(&supported_groups_list, &s->session->ext.supportedgroups, &s->session->ext.supportedgroups_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return 0; } } return 1; }
int ssl_get_new_session(SSL *s, int session) { /* This gets used by clients and servers. */ SSL_SESSION *ss = NULL; if ((ss = SSL_SESSION_new()) == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE); return 0; } /* If the context has a default timeout, use it */ if (s->session_ctx->session_timeout == 0) ss->timeout = SSL_get_default_timeout(s); else ss->timeout = s->session_ctx->session_timeout; SSL_SESSION_free(s->session); s->session = NULL; if (session) { if (!ssl_generate_session_id(s, ss)) { /* SSLfatal() already called */ SSL_SESSION_free(ss); return 0; } if (s->ext.hostname) { ss->ext.hostname = OPENSSL_strdup(s->ext.hostname); if (ss->ext.hostname == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR); SSL_SESSION_free(ss); return 0; } } } else { ss->session_id_length = 0; } if (s->sid_ctx_length > sizeof ss->sid_ctx) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR); SSL_SESSION_free(ss); return 0; } memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); ss->sid_ctx_length = s->sid_ctx_length; s->session = ss; ss->ssl_version = s->version; ss->verify_result = X509_V_OK; /* If client supports extended master secret set it in session */ if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) ss->flags |= SSL_SESS_FLAG_EXTMS; return 1; }
int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, size_t len, size_t *secret_size) { static const unsigned char *salt[3] = { #ifndef CHARSET_EBCDIC (const unsigned char *)"A", (const unsigned char *)"BB", (const unsigned char *)"CCC", #else (const unsigned char *)"\x41", (const unsigned char *)"\x42\x42", (const unsigned char *)"\x43\x43\x43", #endif }; unsigned char buf[EVP_MAX_MD_SIZE]; EVP_MD_CTX *ctx = EVP_MD_CTX_new(); int i, ret = 1; unsigned int n; size_t ret_secret_size = 0; if (ctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_MALLOC_FAILURE); return 0; } for (i = 0; i < 3; i++) { if (EVP_DigestInit_ex(ctx, s->ctx->sha1, NULL) <= 0 || EVP_DigestUpdate(ctx, salt[i], strlen((const char *)salt[i])) <= 0 || EVP_DigestUpdate(ctx, p, len) <= 0 || EVP_DigestUpdate(ctx, &(s->s3->client_random[0]), SSL3_RANDOM_SIZE) <= 0 || EVP_DigestUpdate(ctx, &(s->s3->server_random[0]), SSL3_RANDOM_SIZE) <= 0 /* TODO(size_t) : convert me */ || EVP_DigestFinal_ex(ctx, buf, &n) <= 0 || EVP_DigestInit_ex(ctx, s->ctx->md5, NULL) <= 0 || EVP_DigestUpdate(ctx, p, len) <= 0 || EVP_DigestUpdate(ctx, buf, n) <= 0 || EVP_DigestFinal_ex(ctx, out, &n) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR); ret = 0; break; } out += n; ret_secret_size += n; } EVP_MD_CTX_free(ctx); OPENSSL_cleanse(buf, sizeof(buf)); if (ret) *secret_size = ret_secret_size; return ret; }
size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t len, unsigned char *p) { int ret; EVP_MD_CTX *ctx = NULL; if (!ssl3_digest_cached_records(s, 0)) { /* SSLfatal() already called */ return 0; } if (EVP_MD_CTX_type(s->s3->handshake_dgst) != NID_md5_sha1) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, SSL_R_NO_REQUIRED_DIGEST); return 0; } ctx = EVP_MD_CTX_new(); if (ctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_MALLOC_FAILURE); return 0; } if (!EVP_MD_CTX_copy_ex(ctx, s->s3->handshake_dgst)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR); return 0; } ret = EVP_MD_CTX_size(ctx); if (ret < 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR); EVP_MD_CTX_reset(ctx); return 0; } if ((sender != NULL && EVP_DigestUpdate(ctx, sender, len) <= 0) || EVP_MD_CTX_ctrl(ctx, EVP_CTRL_SSL3_MASTER_SECRET, (int)s->session->master_key_length, s->session->master_key) <= 0 || EVP_DigestFinal_ex(ctx, p, NULL) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR); ret = 0; } EVP_MD_CTX_free(ctx); return ret; }
/* * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. */ int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { #ifndef OPENSSL_NO_TLS1_3 PACKET psk_kex_modes; unsigned int mode; if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes) || PACKET_remaining(&psk_kex_modes) == 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES, SSL_R_BAD_EXTENSION); return 0; } while (PACKET_get_1(&psk_kex_modes, &mode)) { if (mode == TLSEXT_KEX_MODE_KE_DHE) s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE; else if (mode == TLSEXT_KEX_MODE_KE && (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0) s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; } #endif return 1; }
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)) && (s->session->ext.ecpointformats != NULL); const unsigned char *plist; size_t plistlen; if (!using_ecc) return EXT_RETURN_NOT_SENT; tls1_get_formatlist(s, &plist, &plistlen); if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats) || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_sub_memcpy_u8(pkt, plist, plistlen) || !WPACKET_close(pkt)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { const unsigned char *npa; unsigned int npalen; int ret; int npn_seen = s->s3->npn_seen; s->s3->npn_seen = 0; if (!npn_seen || s->ctx->ext.npn_advertised_cb == NULL) return EXT_RETURN_NOT_SENT; ret = s->ctx->ext.npn_advertised_cb(s, &npa, &npalen, s->ctx->ext.npn_advertised_cb_arg); if (ret == SSL_TLSEXT_ERR_OK) { if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg) || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } s->s3->npn_seen = 1; } return EXT_RETURN_SENT; }
EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { if (!s->ext.use_etm) return EXT_RETURN_NOT_SENT; /* * Don't use encrypt_then_mac if AEAD or RC4 might want to disable * for other cases too. */ if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4 || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) { s->ext.use_etm = 0; return EXT_RETURN_NOT_SENT; } if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac) || !WPACKET_put_bytes_u16(pkt, 0)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_ETM, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { const unsigned char cryptopro_ext[36] = { 0xfd, 0xe8, /* 65000 */ 0x00, 0x20, /* 32 bytes length */ 0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17 }; if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80 && (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81) || (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0) return EXT_RETURN_NOT_SENT; if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { if (PACKET_remaining(pkt) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION); return 0; } if (s->hello_retry_request) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION); return 0; } return 1; }
int dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) { DTLS1_RECORD_DATA *rdata; pitem *item; /* Limit the size of the queue to prevent DOS attacks */ if (pqueue_size(queue->q) >= 100) return 0; rdata = OPENSSL_malloc(sizeof(*rdata)); item = pitem_new(priority, rdata); if (rdata == NULL || item == NULL) { OPENSSL_free(rdata); pitem_free(item); SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR); return -1; } rdata->packet = s->rlayer.packet; rdata->packet_length = s->rlayer.packet_length; memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER)); memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD)); item->data = rdata; #ifndef OPENSSL_NO_SCTP /* Store bio_dgram_sctp_rcvinfo struct */ if (BIO_dgram_is_sctp(SSL_get_rbio(s)) && (SSL_get_state(s) == TLS_ST_SR_FINISHED || SSL_get_state(s) == TLS_ST_CR_FINISHED)) { BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, sizeof(rdata->recordinfo), &rdata->recordinfo); } #endif s->rlayer.packet = NULL; s->rlayer.packet_length = 0; memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf)); memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec)); if (!ssl3_setup_buffers(s)) { /* SSLfatal() already called */ OPENSSL_free(rdata->rbuf.buf); OPENSSL_free(rdata); pitem_free(item); return -1; } if (pqueue_insert(queue->q, item) == NULL) { /* Must be a duplicate so ignore it */ OPENSSL_free(rdata->rbuf.buf); OPENSSL_free(rdata); pitem_free(item); } return 1; }
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET supported_sig_algs; if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) || PACKET_remaining(&supported_sig_algs) == 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION); return 0; } if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION); return 0; } return 1; }
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { unsigned int value; if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, SSL_R_BAD_EXTENSION); return 0; } /* Received |value| should be a valid max-fragment-length code. */ if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); return 0; } /* * RFC 6066: The negotiated length applies for the duration of the session * including session resumptions. * We should receive the same code as in resumed session ! */ if (s->hit && s->session->ext.max_fragment_len_mode != value) { SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH); return 0; } /* * Store it in session, so it'll become binding for us * and we'll include it in a next Server Hello. */ s->session->ext.max_fragment_len_mode = value; return 1; }
/* * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN * extension, not including type and length. Returns: 1 on success, 0 on error. */ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET protocol_list, save_protocol_list, protocol; if (!SSL_IS_FIRST_HANDSHAKE(s)) return 1; if (!PACKET_as_length_prefixed_2(pkt, &protocol_list) || PACKET_remaining(&protocol_list) < 2) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN, SSL_R_BAD_EXTENSION); return 0; } save_protocol_list = protocol_list; do { /* Protocol names can't be empty. */ if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol) || PACKET_remaining(&protocol) == 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN, SSL_R_BAD_EXTENSION); return 0; } } while (PACKET_remaining(&protocol_list) != 0); OPENSSL_free(s->s3->alpn_proposed); s->s3->alpn_proposed = NULL; s->s3->alpn_proposed_len = 0; if (!PACKET_memdup(&save_protocol_list, &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
/* * Call this to write data in records of type 'type' It will return <= 0 if * not all data has been sent or non-blocking IO. */ int dtls1_write_bytes(SSL *s, int type, const void *buf, size_t len, size_t *written) { int i; if (!ossl_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_WRITE_BYTES, ERR_R_INTERNAL_ERROR); return -1; } s->rwstate = SSL_NOTHING; i = do_dtls1_write(s, type, buf, len, 0, written); return i; }
int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { if (s->ext.session_ticket_cb && !s->ext.session_ticket_cb(s, PACKET_data(pkt), PACKET_remaining(pkt), s->ext.session_ticket_cb_arg)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
int ssl3_init_finished_mac(SSL *s) { BIO *buf = BIO_new(BIO_s_mem()); if (buf == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_INIT_FINISHED_MAC, ERR_R_MALLOC_FAILURE); return 0; } ssl3_free_digest_list(s); s->s3->handshake_buffer = buf; (void)BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE); return 1; }
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { /* The extension must always be empty */ if (PACKET_remaining(pkt) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EMS, SSL_R_BAD_EXTENSION); return 0; } s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS; return 1; }
/* * Generates the mac for the Finished message. Returns the length of the MAC or * 0 on error. */ size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen, unsigned char *out) { const EVP_MD *md = ssl_handshake_md(s); unsigned char hash[EVP_MAX_MD_SIZE]; size_t hashlen, ret = 0; EVP_PKEY *key = NULL; EVP_MD_CTX *ctx = EVP_MD_CTX_new(); if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) { /* SSLfatal() already called */ goto err; } if (str == s->method->ssl3_enc->server_finished_label) { key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, s->server_finished_secret, hashlen); } else if (SSL_IS_FIRST_HANDSHAKE(s)) { key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, s->client_finished_secret, hashlen); } else { unsigned char finsecret[EVP_MAX_MD_SIZE]; if (!tls13_derive_finishedkey(s, ssl_handshake_md(s), s->client_app_traffic_secret, finsecret, hashlen)) goto err; key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret, hashlen); OPENSSL_cleanse(finsecret, sizeof(finsecret)); } if (key == NULL || ctx == NULL || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0 || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0 || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR); goto err; } ret = hashlen; err: EVP_PKEY_free(key); EVP_MD_CTX_free(ctx); return ret; }
EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0) return EXT_RETURN_NOT_SENT; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret) || !WPACKET_put_bytes_u16(pkt, 0)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EMS, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET ec_point_format_list; if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list) || PACKET_remaining(&ec_point_format_list) == 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, SSL_R_BAD_EXTENSION); return 0; } if (!s->hit) { if (!PACKET_memdup(&ec_point_format_list, &s->session->ext.ecpointformats, &s->session->ext.ecpointformats_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); return 0; } } return 1; }
int ssl3_digest_cached_records(SSL *s, int keep) { const EVP_MD *md; long hdatalen; void *hdata; if (s->s3->handshake_dgst == NULL) { hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); if (hdatalen <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH); return 0; } s->s3->handshake_dgst = EVP_MD_CTX_new(); if (s->s3->handshake_dgst == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE); return 0; } md = ssl_handshake_md(s); if (md == NULL || !EVP_DigestInit_ex(s->s3->handshake_dgst, md, NULL) || !EVP_DigestUpdate(s->s3->handshake_dgst, hdata, hdatalen)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_INTERNAL_ERROR); return 0; } } if (keep == 0) { BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; } return 1; }
EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { if (!s->hit) return EXT_RETURN_NOT_SENT; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk) || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_put_bytes_u16(pkt, s->session->ext.tick_identity) || !WPACKET_close(pkt)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { if (s->hit || s->servername_done != 1 || s->session->ext.hostname == NULL) return EXT_RETURN_NOT_SENT; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name) || !WPACKET_put_bytes_u16(pkt, 0)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { if (!s->ext.ticket_expected || !tls_use_ticket(s)) { s->ext.ticket_expected = 0; return EXT_RETURN_NOT_SENT; } if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket) || !WPACKET_put_bytes_u16(pkt, 0)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }