void ssl3_free(SSL *ssl) { if (ssl == NULL || ssl->s3 == NULL) { return; } ssl3_cleanup_key_block(ssl); ssl_read_buffer_clear(ssl); ssl_write_buffer_clear(ssl); SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx); OPENSSL_free(ssl->s3->tmp.peer_key); sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free); OPENSSL_free(ssl->s3->tmp.certificate_types); OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist); OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint); ssl3_free_handshake_buffer(ssl); ssl3_free_handshake_hash(ssl); OPENSSL_free(ssl->s3->next_proto_negotiated); OPENSSL_free(ssl->s3->alpn_selected); SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx); SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx); OPENSSL_cleanse(ssl->s3, sizeof *ssl->s3); OPENSSL_free(ssl->s3); ssl->s3 = NULL; }
void ssl3_free(SSL *ssl) { if (ssl == NULL || ssl->s3 == NULL) { return; } ssl3_cleanup_key_block(ssl); ssl_read_buffer_clear(ssl); ssl_write_buffer_clear(ssl); SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx); OPENSSL_free(ssl->s3->tmp.peer_key); OPENSSL_free(ssl->s3->tmp.server_params); sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free); OPENSSL_free(ssl->s3->tmp.certificate_types); OPENSSL_free(ssl->s3->tmp.peer_supported_group_list); OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint); SSL_SESSION_free(ssl->s3->new_session); SSL_SESSION_free(ssl->s3->established_session); ssl3_free_handshake_buffer(ssl); ssl3_free_handshake_hash(ssl); ssl_handshake_free(ssl->s3->hs); OPENSSL_free(ssl->s3->next_proto_negotiated); OPENSSL_free(ssl->s3->alpn_selected); SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx); SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx); OPENSSL_free(ssl->s3->pending_message); OPENSSL_cleanse(ssl->s3, sizeof *ssl->s3); OPENSSL_free(ssl->s3); ssl->s3 = NULL; }
static int ssl3_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) { if (ssl->s3->rrec.length != 0) { /* There may not be unprocessed record data at a cipher change. */ OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); SSL_AEAD_CTX_free(aead_ctx); return 0; } memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence)); SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx); ssl->s3->aead_read_ctx = aead_ctx; return 1; }
static int ssl3_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) { memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence)); SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx); ssl->s3->aead_write_ctx = aead_ctx; return 1; }
void ssl3_free(SSL *ssl) { if (ssl == NULL || ssl->s3 == NULL) { return; } ssl3_cleanup_key_block(ssl); ssl_read_buffer_clear(ssl); ssl_write_buffer_clear(ssl); SSL_SESSION_free(ssl->s3->new_session); SSL_SESSION_free(ssl->s3->established_session); ssl3_free_handshake_buffer(ssl); ssl3_free_handshake_hash(ssl); ssl_handshake_free(ssl->s3->hs); OPENSSL_free(ssl->s3->next_proto_negotiated); OPENSSL_free(ssl->s3->alpn_selected); SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx); SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx); OPENSSL_free(ssl->s3->pending_message); OPENSSL_cleanse(ssl->s3, sizeof *ssl->s3); OPENSSL_free(ssl->s3); ssl->s3 = NULL; }
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; }
SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction, uint16_t version, const SSL_CIPHER *cipher, const uint8_t *enc_key, size_t enc_key_len, const uint8_t *mac_key, size_t mac_key_len, const uint8_t *fixed_iv, size_t fixed_iv_len) { const EVP_AEAD *aead; size_t discard; if (!ssl_cipher_get_evp_aead(&aead, &discard, &discard, cipher, version)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH]; if (mac_key_len > 0) { /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher * suites). */ if (mac_key_len + enc_key_len + fixed_iv_len > sizeof(merged_key)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } memcpy(merged_key, mac_key, mac_key_len); memcpy(merged_key + mac_key_len, enc_key, enc_key_len); memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv, fixed_iv_len); enc_key = merged_key; enc_key_len += mac_key_len; enc_key_len += fixed_iv_len; } SSL_AEAD_CTX *aead_ctx = (SSL_AEAD_CTX *)OPENSSL_malloc(sizeof(SSL_AEAD_CTX)); if (aead_ctx == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return NULL; } memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX)); aead_ctx->cipher = cipher; if (!EVP_AEAD_CTX_init_with_direction( &aead_ctx->ctx, aead, enc_key, enc_key_len, EVP_AEAD_DEFAULT_TAG_LENGTH, direction)) { OPENSSL_free(aead_ctx); return NULL; } assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH); aead_ctx->variable_nonce_len = (uint8_t)EVP_AEAD_nonce_length(aead); if (mac_key_len == 0) { /* For a real AEAD, the IV is the fixed part of the nonce. */ if (fixed_iv_len > sizeof(aead_ctx->fixed_nonce) || fixed_iv_len > aead_ctx->variable_nonce_len) { SSL_AEAD_CTX_free(aead_ctx); OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } aead_ctx->variable_nonce_len -= fixed_iv_len; memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len); aead_ctx->fixed_nonce_len = fixed_iv_len; /* AES-GCM uses an explicit nonce. */ if (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) { aead_ctx->variable_nonce_included_in_record = 1; } } else { aead_ctx->variable_nonce_included_in_record = 1; aead_ctx->random_variable_nonce = 1; aead_ctx->omit_length_in_ad = 1; aead_ctx->omit_version_in_ad = (version == SSL3_VERSION); } return aead_ctx; }