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 : /* TLS 1.3 secret key derivation handling.
24 : */
25 :
26 : #include <config.h>
27 : #include "gnutls_int.h"
28 : #include "secrets.h"
29 :
30 : /* HKDF-Extract(0,0) or HKDF-Extract(0, PSK) */
31 4272 : int _tls13_init_secret(gnutls_session_t session, const uint8_t *psk, size_t psk_size)
32 : {
33 4272 : session->key.proto.tls13.temp_secret_size = session->security_parameters.prf->output_size;
34 :
35 8544 : return _tls13_init_secret2(session->security_parameters.prf,
36 : psk, psk_size,
37 4272 : session->key.proto.tls13.temp_secret);
38 : }
39 :
40 9149 : int _tls13_init_secret2(const mac_entry_st *prf,
41 : const uint8_t *psk, size_t psk_size,
42 : void *out)
43 : {
44 9149 : char buf[128];
45 :
46 9149 : if (unlikely(prf == NULL))
47 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
48 :
49 : /* when no PSK, use the zero-value */
50 9149 : if (psk == NULL) {
51 4272 : psk_size = prf->output_size;
52 4272 : if (unlikely(psk_size >= sizeof(buf)))
53 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
54 :
55 4272 : memset(buf, 0, psk_size);
56 4272 : psk = (uint8_t*) buf;
57 : }
58 :
59 9149 : return gnutls_hmac_fast(prf->id,
60 : "", 0,
61 : psk, psk_size,
62 : out);
63 : }
64 :
65 : /* HKDF-Extract(Prev-Secret, key) */
66 11664 : int _tls13_update_secret(gnutls_session_t session, const uint8_t *key, size_t key_size)
67 : {
68 11664 : gnutls_datum_t _key;
69 11664 : gnutls_datum_t salt;
70 :
71 11664 : _key.data = (void *)key;
72 11664 : _key.size = key_size;
73 11664 : salt.data = (void *)session->key.proto.tls13.temp_secret;
74 11664 : salt.size = session->key.proto.tls13.temp_secret_size;
75 :
76 11664 : return gnutls_hkdf_extract(session->security_parameters.prf->id,
77 : &_key, &salt,
78 : session->key.proto.tls13.temp_secret);
79 : }
80 :
81 : /* Derive-Secret(Secret, Label, Messages) */
82 53324 : int _tls13_derive_secret2(const mac_entry_st *prf,
83 : const char *label, unsigned label_size,
84 : const uint8_t *tbh, size_t tbh_size,
85 : const uint8_t secret[MAX_HASH_SIZE],
86 : void *out)
87 : {
88 53324 : uint8_t digest[MAX_HASH_SIZE];
89 53324 : int ret;
90 53324 : unsigned digest_size;
91 :
92 53324 : if (unlikely(prf == NULL))
93 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
94 53324 : if (unlikely(label_size >= sizeof(digest)))
95 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
96 :
97 53324 : digest_size = prf->output_size;
98 53324 : ret = gnutls_hash_fast((gnutls_digest_algorithm_t) prf->id,
99 : tbh, tbh_size, digest);
100 53324 : if (ret < 0)
101 0 : return gnutls_assert_val(ret);
102 :
103 53324 : return _tls13_expand_secret2(prf, label, label_size, digest, digest_size, secret, digest_size, out);
104 : }
105 :
106 : /* Derive-Secret(Secret, Label, Messages) */
107 46158 : int _tls13_derive_secret(gnutls_session_t session,
108 : const char *label, unsigned label_size,
109 : const uint8_t *tbh, size_t tbh_size,
110 : const uint8_t secret[MAX_HASH_SIZE],
111 : void *out)
112 : {
113 46158 : if (unlikely(session->security_parameters.prf == NULL))
114 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
115 :
116 46158 : return _tls13_derive_secret2(session->security_parameters.prf, label, label_size, tbh, tbh_size,
117 : secret,
118 : out);
119 : }
120 :
121 : /* HKDF-Expand-Label(Secret, Label, HashValue, Length) */
122 117974 : int _tls13_expand_secret2(const mac_entry_st *prf,
123 : const char *label, unsigned label_size,
124 : const uint8_t *msg, size_t msg_size,
125 : const uint8_t secret[MAX_HASH_SIZE],
126 : unsigned out_size,
127 : void *out)
128 : {
129 117974 : uint8_t tmp[256] = "tls13 ";
130 117974 : gnutls_buffer_st str;
131 117974 : gnutls_datum_t key;
132 117974 : gnutls_datum_t info;
133 117974 : int ret;
134 :
135 117974 : if (unlikely(label_size >= sizeof(tmp)-6))
136 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
137 :
138 117974 : _gnutls_buffer_init(&str);
139 :
140 117974 : ret = _gnutls_buffer_append_prefix(&str, 16, out_size);
141 117974 : if (ret < 0) {
142 0 : gnutls_assert();
143 0 : goto cleanup;
144 : }
145 :
146 117974 : memcpy(&tmp[6], label, label_size);
147 117974 : ret = _gnutls_buffer_append_data_prefix(&str, 8, tmp, label_size+6);
148 117974 : if (ret < 0) {
149 0 : gnutls_assert();
150 0 : goto cleanup;
151 : }
152 :
153 117974 : ret = _gnutls_buffer_append_data_prefix(&str, 8, msg, msg_size);
154 117974 : if (ret < 0) {
155 0 : gnutls_assert();
156 0 : goto cleanup;
157 : }
158 :
159 117974 : key.data = (void *)secret;
160 117974 : key.size =_gnutls_mac_get_algo_len(mac_to_entry(prf->id));
161 117974 : info.data = str.data;
162 117974 : info.size = str.length;
163 :
164 117974 : ret = gnutls_hkdf_expand(prf->id, &key, &info, out, out_size);
165 117974 : if (ret < 0) {
166 0 : gnutls_assert();
167 0 : goto cleanup;
168 : }
169 :
170 : #if 0
171 : _gnutls_hard_log("INT: hkdf label: %d,%s\n",
172 : out_size,
173 : _gnutls_bin2hex(str.data, str.length,
174 : (char*)tmp, sizeof(tmp), NULL));
175 : _gnutls_hard_log("INT: secret expanded for '%.*s': %d,%s\n",
176 : (int)label_size, label, out_size,
177 : _gnutls_bin2hex(out, out_size,
178 : (char*)tmp, sizeof(tmp), NULL));
179 : #endif
180 :
181 : ret = 0;
182 117974 : cleanup:
183 117974 : _gnutls_buffer_clear(&str);
184 117974 : return ret;
185 : }
186 :
187 46581 : int _tls13_expand_secret(gnutls_session_t session,
188 : const char *label, unsigned label_size,
189 : const uint8_t *msg, size_t msg_size,
190 : const uint8_t secret[MAX_CIPHER_KEY_SIZE],
191 : unsigned out_size,
192 : void *out)
193 : {
194 46581 : if (unlikely(session->security_parameters.prf == NULL))
195 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
196 :
197 46581 : return _tls13_expand_secret2(session->security_parameters.prf,
198 : label, label_size,
199 : msg, msg_size, secret,
200 : out_size, out);
201 : }
202 :
|