* In TLSv1.3, once encrypting, we always use application data for the
* record type
*/
- if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL)
+ if (SSL_TREAT_AS_TLS13(s)
+ && s->enc_write_ctx != NULL
+ && (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
+ || type != SSL3_RT_ALERT))
rectype = SSL3_RT_APPLICATION_DATA;
else
rectype = type;
SSL3_RECORD_reset_input(&wr[j]);
}
- if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) {
+ if (SSL_TREAT_AS_TLS13(s)
+ && s->enc_write_ctx != NULL
+ && (s->statem.enc_write_state != ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
+ || type != SSL3_RT_ALERT)) {
size_t rlen, max_send_fragment;
if (!WPACKET_put_bytes_u8(thispkt, type)) {
SSL3_RECORD_set_length(thiswr, len);
}
- if (s->early_data_state == SSL_EARLY_DATA_WRITING
- || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
+ if (s->statem.enc_write_state == ENC_WRITE_STATE_WRITE_PLAIN_ALERTS) {
/*
* We haven't actually negotiated the version yet, but we're trying to
* send early data - so we need to use the tls13enc function.
seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
}
- if (ctx == NULL) {
+ if (ctx == NULL
+ || (rec->type == SSL3_RT_ALERT
+ && s->statem.enc_write_state
+ == ENC_WRITE_STATE_WRITE_PLAIN_ALERTS)) {
memmove(rec->data, rec->input, rec->length);
rec->input = rec->data;
return 1;
RECORD_LAYER_reset_read_sequence(&s->rlayer);
mac_secret = &(s->s3->read_mac_secret[0]);
} else {
- s->statem.invalid_enc_write_ctx = 1;
+ s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
if (s->enc_write_ctx != NULL) {
reuse_dd = 1;
} else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL) {
goto err;
}
- s->statem.invalid_enc_write_ctx = 0;
+ s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
OPENSSL_cleanse(exp_key, sizeof(exp_key));
OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
return 1;
s->statem.in_init = 1;
s->statem.state = MSG_FLOW_ERROR;
ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
- if (al != SSL_AD_NO_ALERT && !s->statem.invalid_enc_write_ctx)
+ if (al != SSL_AD_NO_ALERT
+ && s->statem.enc_write_state != ENC_WRITE_STATE_INVALID)
ssl3_send_alert(s, SSL3_AL_FATAL, al);
}
WRITE_STATE_POST_WORK
} WRITE_STATE;
+typedef enum {
+ /* The enc_write_ctx can be used normally */
+ ENC_WRITE_STATE_VALID,
+ /* The enc_write_ctx cannot be used */
+ ENC_WRITE_STATE_INVALID,
+ /* Write alerts in plaintext, but otherwise use the enc_write_ctx */
+ ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
+} ENC_WRITE_STATES;
+
/*****************************************************************************
* *
* This structure should be considered "opaque" to anything outside of the *
/* Should we skip the CertificateVerify message? */
unsigned int no_cert_verify;
int use_timer;
- int invalid_enc_write_ctx;
+ ENC_WRITE_STATES enc_write_state;
};
typedef struct ossl_statem_st OSSL_STATEM;
mac_secret = &(s->s3->read_mac_secret[0]);
mac_secret_size = &(s->s3->read_mac_secret_size);
} else {
- s->statem.invalid_enc_write_ctx = 1;
+ s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
if (s->ext.use_etm)
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE;
else
ERR_R_INTERNAL_ERROR);
goto err;
}
- s->statem.invalid_enc_write_ctx = 0;
+ s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
#ifdef SSL_DEBUG
printf("which = %04X\nkey=", which);
RECORD_LAYER_reset_read_sequence(&s->rlayer);
} else {
- s->statem.invalid_enc_write_ctx = 1;
+ s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
if (s->enc_write_ctx != NULL) {
EVP_CIPHER_CTX_reset(s->enc_write_ctx);
} else {
goto err;
}
- s->statem.invalid_enc_write_ctx = 0;
+ if (!s->server && label == client_early_traffic)
+ s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS;
+ else
+ s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
ret = 1;
err:
OPENSSL_cleanse(secret, sizeof(secret));
insecret = s->client_app_traffic_secret;
if (sending) {
- s->statem.invalid_enc_write_ctx = 1;
+ s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
iv = s->write_iv;
ciph_ctx = s->enc_write_ctx;
RECORD_LAYER_reset_write_sequence(&s->rlayer);
memcpy(insecret, secret, hashlen);
- s->statem.invalid_enc_write_ctx = 0;
+ s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
ret = 1;
err:
OPENSSL_cleanse(secret, sizeof(secret));