New function ssl_generate_param_group
[openssl.git] / ssl / s3_msg.c
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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
8  */
9
10 #include "ssl_locl.h"
11
12 int ssl3_do_change_cipher_spec(SSL *s)
13 {
14     int i;
15     size_t finish_md_len;
16     const char *sender;
17     size_t slen;
18
19     if (s->server)
20         i = SSL3_CHANGE_CIPHER_SERVER_READ;
21     else
22         i = SSL3_CHANGE_CIPHER_CLIENT_READ;
23
24     if (s->s3->tmp.key_block == NULL) {
25         if (s->session == NULL || s->session->master_key_length == 0) {
26             /* might happen if dtls1_read_bytes() calls this */
27             SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
28             return (0);
29         }
30
31         s->session->cipher = s->s3->tmp.new_cipher;
32         if (!s->method->ssl3_enc->setup_key_block(s))
33             return (0);
34     }
35
36     if (!s->method->ssl3_enc->change_cipher_state(s, i))
37         return (0);
38
39     /*
40      * we have to record the message digest at this point so we can get it
41      * before we read the finished message
42      */
43     if (!s->server) {
44         sender = s->method->ssl3_enc->server_finished_label;
45         slen = s->method->ssl3_enc->server_finished_label_len;
46     } else {
47         sender = s->method->ssl3_enc->client_finished_label;
48         slen = s->method->ssl3_enc->client_finished_label_len;
49     }
50
51     finish_md_len = s->method->ssl3_enc->final_finish_mac(s, sender, slen,
52                                             s->s3->tmp.peer_finish_md);
53     if (finish_md_len == 0) {
54         SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
55         return 0;
56     }
57     s->s3->tmp.peer_finish_md_len = finish_md_len;
58
59     return (1);
60 }
61
62 int ssl3_send_alert(SSL *s, int level, int desc)
63 {
64     /* Map tls/ssl alert value to correct one */
65     if (SSL_TREAT_AS_TLS13(s))
66         desc = tls13_alert_code(desc);
67     else
68         desc = s->method->ssl3_enc->alert_value(desc);
69     if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION)
70         desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have
71                                           * protocol_version alerts */
72     if (desc < 0)
73         return -1;
74     /* If a fatal one, remove from cache */
75     if ((level == SSL3_AL_FATAL) && (s->session != NULL))
76         SSL_CTX_remove_session(s->session_ctx, s->session);
77
78     s->s3->alert_dispatch = 1;
79     s->s3->send_alert[0] = level;
80     s->s3->send_alert[1] = desc;
81     if (!RECORD_LAYER_write_pending(&s->rlayer)) {
82         /* data still being written out? */
83         return s->method->ssl_dispatch_alert(s);
84     }
85     /*
86      * else data is still being written out, we will get written some time in
87      * the future
88      */
89     return -1;
90 }
91
92 int ssl3_dispatch_alert(SSL *s)
93 {
94     int i, j;
95     size_t alertlen;
96     void (*cb) (const SSL *ssl, int type, int val) = NULL;
97     size_t written;
98
99     s->s3->alert_dispatch = 0;
100     alertlen = 2;
101     i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], &alertlen, 1, 0,
102                       &written);
103     if (i <= 0) {
104         s->s3->alert_dispatch = 1;
105     } else {
106         /*
107          * Alert sent to BIO - now flush. If the message does not get sent due
108          * to non-blocking IO, we will not worry too much.
109          */
110         (void)BIO_flush(s->wbio);
111
112         if (s->msg_callback)
113             s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert,
114                             2, s, s->msg_callback_arg);
115
116         if (s->info_callback != NULL)
117             cb = s->info_callback;
118         else if (s->ctx->info_callback != NULL)
119             cb = s->ctx->info_callback;
120
121         if (cb != NULL) {
122             j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1];
123             cb(s, SSL_CB_WRITE_ALERT, j);
124         }
125     }
126     return i;
127 }