Line data Source code
1 : /*
2 : * Copyright (C) 2017 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 : #include "gnutls_int.h"
24 : #include "errors.h"
25 : #include "handshake.h"
26 : #include "tls13/finished.h"
27 : #include "mem.h"
28 : #include "mbuffers.h"
29 : #include "secrets.h"
30 :
31 17836 : int _gnutls13_compute_finished(const mac_entry_st *prf,
32 : const uint8_t *base_key,
33 : gnutls_buffer_st *handshake_hash_buffer,
34 : void *out)
35 : {
36 17836 : int ret;
37 17836 : uint8_t fkey[MAX_HASH_SIZE];
38 17836 : uint8_t ts_hash[MAX_HASH_SIZE];
39 :
40 17836 : ret = _tls13_expand_secret2(prf,
41 : "finished", 8,
42 : NULL, 0,
43 : base_key,
44 : prf->output_size, fkey);
45 17836 : if (ret < 0)
46 0 : return gnutls_assert_val(ret);
47 :
48 17836 : ret = gnutls_hash_fast(MAC_TO_DIG(prf->id),
49 17836 : handshake_hash_buffer->data,
50 : handshake_hash_buffer->length,
51 : ts_hash);
52 17836 : if (ret < 0)
53 0 : return gnutls_assert_val(ret);
54 :
55 35672 : ret = gnutls_hmac_fast(prf->id,
56 : fkey, prf->output_size,
57 17836 : ts_hash, prf->output_size,
58 : out);
59 17836 : if (ret < 0)
60 0 : return gnutls_assert_val(ret);
61 :
62 : return 0;
63 : }
64 :
65 5955 : int _gnutls13_recv_finished(gnutls_session_t session)
66 : {
67 5955 : int ret;
68 5955 : gnutls_buffer_st buf;
69 5955 : uint8_t verifier[MAX_HASH_SIZE];
70 5955 : const uint8_t *base_key;
71 5955 : unsigned hash_size;
72 :
73 5955 : if (unlikely(session->security_parameters.prf == NULL))
74 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
75 :
76 5955 : hash_size = session->security_parameters.prf->output_size;
77 :
78 5955 : if (!session->internals.initial_negotiation_completed) {
79 5928 : if (session->security_parameters.entity == GNUTLS_CLIENT)
80 618 : base_key = session->key.proto.tls13.hs_skey;
81 : else
82 5310 : base_key = session->key.proto.tls13.hs_ckey;
83 : } else {
84 27 : if (session->security_parameters.entity == GNUTLS_CLIENT)
85 0 : base_key = session->key.proto.tls13.ap_skey;
86 : else
87 27 : base_key = session->key.proto.tls13.ap_ckey;
88 : }
89 :
90 5955 : ret = _gnutls13_compute_finished(session->security_parameters.prf,
91 : base_key,
92 : &session->internals.handshake_hash_buffer,
93 : verifier);
94 5955 : if (ret < 0) {
95 0 : gnutls_assert();
96 0 : goto cleanup;
97 : }
98 :
99 5955 : ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_FINISHED, 0, &buf);
100 5955 : if (ret < 0)
101 272 : return gnutls_assert_val(ret);
102 :
103 5705 : _gnutls_handshake_log("HSK[%p]: parsing finished\n", session);
104 :
105 5705 : if (buf.length != hash_size) {
106 0 : gnutls_assert();
107 0 : ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
108 0 : goto cleanup;
109 : }
110 :
111 :
112 : #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
113 : # warning This is unsafe for production builds
114 : #else
115 5705 : if (gnutls_memcmp(verifier, buf.data, buf.length) != 0) {
116 5 : gnutls_assert();
117 5 : ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET;
118 5 : goto cleanup;
119 : }
120 : #endif
121 :
122 : ret = 0;
123 5705 : cleanup:
124 :
125 5705 : _gnutls_buffer_clear(&buf);
126 5705 : return ret;
127 : }
128 :
129 5809 : int _gnutls13_send_finished(gnutls_session_t session, unsigned again)
130 : {
131 5809 : int ret;
132 5809 : uint8_t verifier[MAX_HASH_SIZE];
133 5809 : mbuffer_st *bufel = NULL;
134 5809 : const uint8_t *base_key;
135 5809 : unsigned hash_size;
136 :
137 5809 : if (again == 0) {
138 5775 : if (unlikely(session->security_parameters.prf == NULL))
139 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
140 :
141 5775 : hash_size = session->security_parameters.prf->output_size;
142 :
143 5775 : if (!session->internals.initial_negotiation_completed) {
144 5773 : if (session->security_parameters.entity == GNUTLS_CLIENT)
145 593 : base_key = session->key.proto.tls13.hs_ckey;
146 : else
147 5180 : base_key = session->key.proto.tls13.hs_skey;
148 : } else {
149 2 : if (session->security_parameters.entity == GNUTLS_CLIENT)
150 2 : base_key = session->key.proto.tls13.ap_ckey;
151 : else
152 0 : base_key = session->key.proto.tls13.ap_skey;
153 : }
154 :
155 5775 : ret = _gnutls13_compute_finished(session->security_parameters.prf,
156 : base_key,
157 : &session->internals.handshake_hash_buffer,
158 : verifier);
159 5775 : if (ret < 0) {
160 0 : gnutls_assert();
161 0 : goto cleanup;
162 : }
163 :
164 5775 : _gnutls_handshake_log("HSK[%p]: sending finished\n", session);
165 :
166 5775 : bufel = _gnutls_handshake_alloc(session, hash_size);
167 5775 : if (bufel == NULL)
168 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
169 :
170 5775 : _mbuffer_set_udata_size(bufel, 0);
171 5775 : ret = _mbuffer_append_data(bufel, verifier, hash_size);
172 5775 : if (ret < 0) {
173 0 : gnutls_assert();
174 0 : goto cleanup;
175 : }
176 : }
177 :
178 5809 : return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_FINISHED);
179 :
180 0 : cleanup:
181 0 : _mbuffer_xfree(&bufel);
182 : return ret;
183 : }
|