2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #include "ssl_local.h"
12 int ssl3_do_change_cipher_spec(SSL_CONNECTION
*s
)
15 SSL
*ssl
= SSL_CONNECTION_GET_SSL(s
);
18 i
= SSL3_CHANGE_CIPHER_SERVER_READ
;
20 i
= SSL3_CHANGE_CIPHER_CLIENT_READ
;
22 if (s
->s3
.tmp
.key_block
== NULL
) {
23 if (s
->session
== NULL
|| s
->session
->master_key_length
== 0) {
24 /* might happen if dtls1_read_bytes() calls this */
25 ERR_raise(ERR_LIB_SSL
, SSL_R_CCS_RECEIVED_EARLY
);
29 s
->session
->cipher
= s
->s3
.tmp
.new_cipher
;
30 if (!ssl
->method
->ssl3_enc
->setup_key_block(s
)) {
31 /* SSLfatal() already called */
36 if (!ssl
->method
->ssl3_enc
->change_cipher_state(s
, i
)) {
37 /* SSLfatal() already called */
44 int ssl3_send_alert(SSL_CONNECTION
*s
, int level
, int desc
)
46 SSL
*ssl
= SSL_CONNECTION_GET_SSL(s
);
48 /* Map tls/ssl alert value to correct one */
49 if (SSL_CONNECTION_TREAT_AS_TLS13(s
))
50 desc
= tls13_alert_code(desc
);
52 desc
= ssl
->method
->ssl3_enc
->alert_value(desc
);
53 if (s
->version
== SSL3_VERSION
&& desc
== SSL_AD_PROTOCOL_VERSION
)
54 desc
= SSL_AD_HANDSHAKE_FAILURE
; /* SSL 3.0 does not have
55 * protocol_version alerts */
58 if (s
->shutdown
& SSL_SENT_SHUTDOWN
&& desc
!= SSL_AD_CLOSE_NOTIFY
)
60 /* If a fatal one, remove from cache */
61 if ((level
== SSL3_AL_FATAL
) && (s
->session
!= NULL
))
62 SSL_CTX_remove_session(s
->session_ctx
, s
->session
);
64 s
->s3
.alert_dispatch
= SSL_ALERT_DISPATCH_PENDING
;
65 s
->s3
.send_alert
[0] = level
;
66 s
->s3
.send_alert
[1] = desc
;
67 if (!RECORD_LAYER_write_pending(&s
->rlayer
)) {
68 /* data still being written out? */
69 return ssl
->method
->ssl_dispatch_alert(ssl
);
72 * else data is still being written out, we will get written some time in
78 int ssl3_dispatch_alert(SSL
*s
)
81 void (*cb
) (const SSL
*ssl
, int type
, int val
) = NULL
;
82 SSL_CONNECTION
*sc
= SSL_CONNECTION_FROM_SSL(s
);
83 OSSL_RECORD_TEMPLATE templ
;
88 if (sc
->rlayer
.wrlmethod
== NULL
) {
89 /* No write record layer so we can't sent and alert. We just ignore it */
90 sc
->s3
.alert_dispatch
= SSL_ALERT_DISPATCH_NONE
;
94 templ
.type
= SSL3_RT_ALERT
;
95 templ
.version
= (sc
->version
== TLS1_3_VERSION
) ? TLS1_2_VERSION
97 if (SSL_get_state(s
) == TLS_ST_CW_CLNT_HELLO
99 && TLS1_get_version(s
) > TLS1_VERSION
100 && sc
->hello_retry_request
== SSL_HRR_NONE
) {
101 templ
.version
= TLS1_VERSION
;
103 templ
.buf
= &sc
->s3
.send_alert
[0];
106 if (RECORD_LAYER_write_pending(&sc
->rlayer
)) {
107 if (sc
->s3
.alert_dispatch
!= SSL_ALERT_DISPATCH_RETRY
) {
109 * We have a write pending but it wasn't from a previous call to
110 * this function! Can we ever get here? Maybe via API misuse??
113 sc
->s3
.alert_dispatch
= SSL_ALERT_DISPATCH_NONE
;
116 /* Retry what we've already got pending */
117 i
= HANDLE_RLAYER_WRITE_RETURN(sc
,
118 sc
->rlayer
.wrlmethod
->retry_write_records(sc
->rlayer
.wrl
));
120 /* Could be NBIO. Keep alert_dispatch as SSL_ALERT_DISPATCH_RETRY */
123 sc
->rlayer
.wpend_tot
= 0;
124 sc
->s3
.alert_dispatch
= SSL_ALERT_DISPATCH_NONE
;
128 i
= HANDLE_RLAYER_WRITE_RETURN(sc
,
129 sc
->rlayer
.wrlmethod
->write_records(sc
->rlayer
.wrl
, &templ
, 1));
132 sc
->s3
.alert_dispatch
= SSL_ALERT_DISPATCH_RETRY
;
133 sc
->rlayer
.wpend_tot
= templ
.buflen
;
134 sc
->rlayer
.wpend_type
= templ
.type
;
135 sc
->rlayer
.wpend_buf
= templ
.buf
;
138 * Alert sent to BIO - now flush. If the message does not get sent due
139 * to non-blocking IO, we will not worry too much.
141 (void)BIO_flush(sc
->wbio
);
142 sc
->s3
.alert_dispatch
= SSL_ALERT_DISPATCH_NONE
;
144 if (sc
->msg_callback
)
145 sc
->msg_callback(1, sc
->version
, SSL3_RT_ALERT
, sc
->s3
.send_alert
,
146 2, s
, sc
->msg_callback_arg
);
148 if (sc
->info_callback
!= NULL
)
149 cb
= sc
->info_callback
;
150 else if (s
->ctx
->info_callback
!= NULL
)
151 cb
= s
->ctx
->info_callback
;
154 j
= (sc
->s3
.send_alert
[0] << 8) | sc
->s3
.send_alert
[1];
155 cb(s
, SSL_CB_WRITE_ALERT
, j
);