err:
/* No valid transition found */
+ if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ BIO *rbio;
+
+ /*
+ * CCS messages don't have a message sequence number so this is probably
+ * because of an out-of-order CCS. We'll just drop it.
+ */
+ s->init_num = 0;
+ s->rwstate = SSL_READING;
+ rbio = SSL_get_rbio(s);
+ BIO_clear_retry_flags(rbio);
+ BIO_set_retry_read(rbio);
+ return 0;
+ }
SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
SSL_R_UNEXPECTED_MESSAGE);
* and give the application the opportunity to delay sending the
* session ticket?
*/
- if (s->post_handshake_auth == SSL_PHA_REQUESTED)
- s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
st->hand_state = TLS_ST_SW_SESSION_TICKET;
+ if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
+ s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
+ } else if (s->hit && !s->ext.ticket_expected) {
+ /*
+ * If we resumed and we're not going to renew the ticket then we
+ * just finish the handshake at this point.
+ */
+ st->hand_state = TLS_ST_OK;
+ }
return WRITE_TRAN_CONTINUE;
case TLS_ST_SR_KEY_UPDATE:
s->ext.early_data_ok = 0;
if (!s->hit) {
- /* If a new session update it with the new ALPN value */
+ /*
+ * This is a new session and so alpn_selected should have
+ * been initialised to NULL. We should update it with the
+ * selected ALPN.
+ */
+ if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_HANDLE_ALPN,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
s->session->ext.alpn_selected = OPENSSL_memdup(selected,
selected_len);
if (s->session->ext.alpn_selected == NULL) {
}
dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey);
+ if (dh == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
EVP_PKEY_free(pkdh);
pkdh = NULL;
* fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
*/
- if (RAND_bytes(rand_premaster_secret,
+ if (RAND_priv_bytes(rand_premaster_secret,
sizeof(rand_premaster_secret)) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
ERR_R_INTERNAL_ERROR);
const unsigned char *start;
size_t outlen = 32, inlen;
unsigned long alg_a;
- int Ttag, Tclass;
- long Tlen;
- size_t sess_key_len;
- const unsigned char *data;
+ unsigned int asn1id, asn1len;
int ret = 0;
+ PACKET encdata;
/* Get our certificate private key */
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
ERR_clear_error();
}
/* Decrypt session key */
- sess_key_len = PACKET_remaining(pkt);
- if (!PACKET_get_bytes(pkt, &data, sess_key_len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
- ERR_R_INTERNAL_ERROR);
+ if (!PACKET_get_1(pkt, &asn1id)
+ || asn1id != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)
+ || !PACKET_peek_1(pkt, &asn1len)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+ SSL_R_DECRYPTION_FAILED);
goto err;
}
- /* TODO(size_t): Convert this function */
- if (ASN1_get_object((const unsigned char **)&data, &Tlen, &Ttag,
- &Tclass, (long)sess_key_len) != V_ASN1_CONSTRUCTED
- || Ttag != V_ASN1_SEQUENCE || Tclass != V_ASN1_UNIVERSAL) {
+ if (asn1len == 0x81) {
+ /*
+ * Long form length. Should only be one byte of length. Anything else
+ * isn't supported.
+ * We did a successful peek before so this shouldn't fail
+ */
+ if (!PACKET_forward(pkt, 1)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+ SSL_R_DECRYPTION_FAILED);
+ goto err;
+ }
+ } else if (asn1len >= 0x80) {
+ /*
+ * Indefinite length, or more than one long form length bytes. We don't
+ * support it
+ */
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
+ SSL_R_DECRYPTION_FAILED);
+ goto err;
+ } /* else short form length */
+
+ if (!PACKET_as_length_prefixed_1(pkt, &encdata)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
SSL_R_DECRYPTION_FAILED);
goto err;
}
- start = data;
- inlen = Tlen;
+ inlen = PACKET_remaining(&encdata);
+ start = PACKET_data(&encdata);
+
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start,
inlen) <= 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
EVP_PKEY *pkey;
i = ssl_verify_cert_chain(s, sk);
if (i <= 0) {
- SSLfatal(s, ssl_verify_alarm_type(s->verify_result),
+ SSLfatal(s, ssl_x509err2alert(s->verify_result),
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_CERTIFICATE_VERIFY_FAILED);
goto err;
} age_add_u;
if (SSL_IS_TLS13(s)) {
+ if (s->post_handshake_auth != SSL_PHA_EXT_RECEIVED) {
+ void (*cb) (const SSL *ssl, int type, int val) = NULL;
+
+ /*
+ * This is the first session ticket we've sent. In the state
+ * machine we "cheated" and tacked this onto the end of the first
+ * handshake. From an info callback perspective this should appear
+ * like the start of a new handshake.
+ */
+ 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_START, 1);
+ }
+
if (!ssl_generate_session_id(s, s->session)) {
/* SSLfatal() already called */
goto err;