1 /*
2 * Copyright (C) 2014 Red Hat, Inc.
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GnuTLS.
7 *
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 *
21 */
22
23 /* This file contains the code for the Max Record Size TLS extension.
24 */
25
26 #include "gnutls_int.h"
27 #include "errors.h"
28 #include "num.h"
29 #include <hello_ext.h>
30 #include <ext/etm.h>
31
32 static int _gnutls_ext_etm_recv_params(gnutls_session_t session,
33 const uint8_t * data,
34 size_t data_size);
35 static int _gnutls_ext_etm_send_params(gnutls_session_t session,
36 gnutls_buffer_st * extdata);
37
38 const hello_ext_entry_st ext_mod_etm = {
39 .name = "Encrypt-then-MAC",
40 .tls_id = 22,
41 .gid = GNUTLS_EXTENSION_ETM,
42 .client_parse_point = GNUTLS_EXT_MANDATORY,
43 .server_parse_point = GNUTLS_EXT_MANDATORY,
44 .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
45 GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
46 .recv_func = _gnutls_ext_etm_recv_params,
47 .send_func = _gnutls_ext_etm_send_params,
48 .pack_func = NULL,
49 .unpack_func = NULL,
50 .deinit_func = NULL,
51 .cannot_be_overriden = 1
52 };
53
54 /*
55 * In case of a server: if an EXT_MASTER_SECRET extension type is received then it
56 * sets a flag into the session security parameters.
57 *
58 */
59 static int
_gnutls_ext_etm_recv_params(gnutls_session_t session,const uint8_t * data,size_t _data_size)60 _gnutls_ext_etm_recv_params(gnutls_session_t session,
61 const uint8_t * data, size_t _data_size)
62 {
63 ssize_t data_size = _data_size;
64
65 if (data_size != 0) {
66 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
67 }
68
69 if (session->security_parameters.entity == GNUTLS_SERVER) {
70 gnutls_ext_priv_data_t epriv;
71
72 if (session->internals.no_etm != 0)
73 return 0;
74
75 epriv = (void*)(intptr_t)1;
76 _gnutls_hello_ext_set_priv(session,
77 GNUTLS_EXTENSION_ETM,
78 epriv);
79
80 /* don't decide now, decide on send */
81 return 0;
82 } else { /* client */
83 const gnutls_cipher_suite_entry_st *e =
84 session->security_parameters.cs;
85 if (e != NULL) {
86 const cipher_entry_st *c;
87 c = cipher_to_entry(e->block_algorithm);
88 if (c == NULL || (c->type == CIPHER_AEAD || c->type == CIPHER_STREAM))
89 return 0;
90
91 session->security_parameters.etm = 1;
92 }
93 }
94
95 return 0;
96 }
97
98 /* returns data_size or a negative number on failure
99 */
100 static int
_gnutls_ext_etm_send_params(gnutls_session_t session,gnutls_buffer_st * extdata)101 _gnutls_ext_etm_send_params(gnutls_session_t session,
102 gnutls_buffer_st * extdata)
103 {
104 if (session->internals.no_etm != 0)
105 return 0;
106
107 /* this function sends the client extension data */
108 if (session->security_parameters.entity == GNUTLS_CLIENT) {
109 if (session->internals.priorities->have_cbc != 0)
110 return GNUTLS_E_INT_RET_0;
111 else
112 return 0;
113 } else { /* server side */
114 const gnutls_cipher_suite_entry_st *e;
115 const cipher_entry_st *c;
116 int ret;
117 gnutls_ext_priv_data_t epriv;
118
119 e = session->security_parameters.cs;
120 if (e != NULL) {
121 c = cipher_to_entry(e->block_algorithm);
122 if (c == NULL || (c->type == CIPHER_AEAD || c->type == CIPHER_STREAM))
123 return 0;
124
125 ret = _gnutls_hello_ext_get_priv(session,
126 GNUTLS_EXTENSION_ETM,
127 &epriv);
128 if (ret < 0 || ((intptr_t)epriv) == 0)
129 return 0;
130
131 session->security_parameters.etm = 1;
132 return GNUTLS_E_INT_RET_0;
133 }
134 }
135
136 return 0;
137 }
138
139 /**
140 * gnutls_session_etm_status:
141 * @session: is a #gnutls_session_t type.
142 *
143 * Get the status of the encrypt-then-mac extension negotiation.
144 * This is in accordance to rfc7366
145 *
146 * Returns: Non-zero if the negotiation was successful or zero otherwise.
147 **/
gnutls_session_etm_status(gnutls_session_t session)148 unsigned gnutls_session_etm_status(gnutls_session_t session)
149 {
150 return session->security_parameters.etm;
151 }
152