Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2026 DMTF. All rights reserved.
4 : : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : : **/
6 : : #include "internal/libspdm_crypt_lib.h"
7 : : #include "internal/libspdm_common_lib.h"
8 : :
9 : 1628 : void libspdm_bin_concat(spdm_version_number_t spdm_version,
10 : : const char *label, size_t label_size,
11 : : const uint8_t *context, uint16_t length,
12 : : size_t hash_size, uint8_t *out_bin,
13 : : size_t *out_bin_size)
14 : : {
15 : : size_t final_size;
16 : :
17 : : /* The correct version characters (1.1 or 1.2) will replace the x.x. */
18 : : #define LIBSPDM_BIN_CONCAT_LABEL "spdmx.x "
19 : :
20 : 1628 : final_size = sizeof(uint16_t) + sizeof(LIBSPDM_BIN_CONCAT_LABEL) - 1 + label_size;
21 [ + + ]: 1628 : if (context != NULL) {
22 : 389 : final_size += hash_size;
23 : : }
24 : :
25 [ - + ]: 1628 : LIBSPDM_ASSERT(*out_bin_size >= final_size);
26 : :
27 : 1628 : *out_bin_size = final_size;
28 : :
29 : 1628 : libspdm_copy_mem(out_bin, *out_bin_size, &length, sizeof(uint16_t));
30 : 1628 : libspdm_copy_mem(out_bin + sizeof(uint16_t), *out_bin_size - sizeof(uint16_t),
31 : : LIBSPDM_BIN_CONCAT_LABEL, sizeof(LIBSPDM_BIN_CONCAT_LABEL) - 1);
32 : :
33 : : /* Patch the version. */
34 : 1628 : out_bin[6] = (char)('0' + ((spdm_version >> 12) & 0xF));
35 : 1628 : out_bin[8] = (char)('0' + ((spdm_version >> 8) & 0xF));
36 : 1628 : libspdm_copy_mem(out_bin + sizeof(uint16_t) + sizeof(LIBSPDM_BIN_CONCAT_LABEL) - 1,
37 : 1628 : *out_bin_size - (sizeof(uint16_t) + sizeof(LIBSPDM_BIN_CONCAT_LABEL) - 1),
38 : : label, label_size);
39 : :
40 [ + + ]: 1628 : if (context != NULL) {
41 : 389 : libspdm_copy_mem(out_bin + sizeof(uint16_t) + sizeof(LIBSPDM_BIN_CONCAT_LABEL) -
42 : 389 : 1 + label_size,
43 : 389 : *out_bin_size - (sizeof(uint16_t) + sizeof(LIBSPDM_BIN_CONCAT_LABEL) -
44 : : 1 + label_size), context, hash_size);
45 : : }
46 : :
47 : : #undef LIBSPDM_BIN_CONCAT_LABEL
48 : 1628 : }
49 : :
50 : 82 : bool libspdm_generate_handshake_key (
51 : : spdm_version_number_t spdm_version,
52 : : const uint8_t *shared_secret, size_t shared_secret_size,
53 : : bool shared_secret_use_psk,
54 : : const uint8_t *psk_hint, size_t psk_hint_size,
55 : : bool use_psk_hint,
56 : : uint32_t base_hash_algo,
57 : : const uint8_t *th1_hash_data,
58 : : uint8_t *handshake_secret, size_t *handshake_secret_size,
59 : : uint8_t *request_handshake_secret, size_t *request_handshake_secret_size,
60 : : uint8_t *response_handshake_secret, size_t *response_handshake_secret_size)
61 : : {
62 : 82 : bool status = false;
63 : : size_t hash_size;
64 : : uint8_t bin_str1[128];
65 : : size_t bin_str1_size;
66 : : uint8_t bin_str2[128];
67 : : size_t bin_str2_size;
68 : : uint8_t salt0[LIBSPDM_MAX_HASH_SIZE];
69 : :
70 [ + + ]: 82 : if (!use_psk_hint) {
71 [ + - - + ]: 47 : if (shared_secret == NULL || shared_secret_size == 0) {
72 : 0 : return false;
73 : : }
74 : : }
75 : :
76 : 82 : hash_size = libspdm_get_hash_size(base_hash_algo);
77 : :
78 [ + - ]: 82 : if (*handshake_secret_size < hash_size ||
79 [ + - ]: 82 : *request_handshake_secret_size < hash_size ||
80 [ - + ]: 82 : *response_handshake_secret_size < hash_size) {
81 : 0 : return false;
82 : : }
83 : 82 : *handshake_secret_size = hash_size;
84 : 82 : *request_handshake_secret_size = hash_size;
85 : 82 : *response_handshake_secret_size = hash_size;
86 : :
87 : 82 : bin_str1_size = sizeof(bin_str1);
88 : 82 : libspdm_bin_concat(spdm_version,
89 : : SPDM_BIN_STR_1_LABEL, sizeof(SPDM_BIN_STR_1_LABEL) - 1,
90 : 82 : th1_hash_data, (uint16_t)hash_size, hash_size,
91 : : bin_str1, &bin_str1_size);
92 : :
93 : 82 : bin_str2_size = sizeof(bin_str2);
94 : 82 : libspdm_bin_concat(spdm_version,
95 : : SPDM_BIN_STR_2_LABEL, sizeof(SPDM_BIN_STR_2_LABEL) - 1,
96 : 82 : th1_hash_data, (uint16_t)hash_size, hash_size,
97 : : bin_str2, &bin_str2_size);
98 : :
99 : : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
100 [ + + ]: 82 : if (use_psk_hint) {
101 : 35 : status = libspdm_psk_handshake_secret_hkdf_expand(
102 : : spdm_version,
103 : : base_hash_algo,
104 : : psk_hint, psk_hint_size,
105 : : bin_str1, bin_str1_size,
106 : : request_handshake_secret, hash_size);
107 : :
108 [ - + ]: 35 : if (!status) {
109 : 0 : return false;
110 : : }
111 : :
112 : 35 : status = libspdm_psk_handshake_secret_hkdf_expand(
113 : : spdm_version,
114 : : base_hash_algo,
115 : : psk_hint, psk_hint_size,
116 : : bin_str2, bin_str2_size,
117 : : response_handshake_secret, hash_size);
118 : :
119 [ - + ]: 35 : if (!status) {
120 : 0 : return false;
121 : : }
122 : :
123 : : }
124 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */
125 : :
126 [ + + ]: 82 : if (!use_psk_hint) {
127 : 47 : libspdm_zero_mem(salt0, sizeof(salt0));
128 : : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
129 [ - + ]: 47 : if ((shared_secret_use_psk) &&
130 [ # # ]: 0 : ((spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) >= SPDM_MESSAGE_VERSION_13)) {
131 : 0 : libspdm_set_mem(salt0, hash_size, 0xff);
132 : : }
133 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */
134 : :
135 : 47 : status = libspdm_hkdf_extract(
136 : : base_hash_algo,
137 : : shared_secret, shared_secret_size,
138 : : salt0, hash_size,
139 : : handshake_secret, hash_size);
140 [ - + ]: 47 : if (!status) {
141 : 0 : return false;
142 : : }
143 : :
144 : 47 : status = libspdm_hkdf_expand(
145 : : base_hash_algo,
146 : : handshake_secret,
147 : : hash_size, bin_str1, bin_str1_size,
148 : : request_handshake_secret, hash_size);
149 : :
150 [ - + ]: 47 : if (!status) {
151 : 0 : return false;
152 : : }
153 : :
154 : 47 : status = libspdm_hkdf_expand(
155 : : base_hash_algo,
156 : : handshake_secret,
157 : : hash_size, bin_str2, bin_str2_size,
158 : : response_handshake_secret, hash_size);
159 : :
160 [ - + ]: 47 : if (!status) {
161 : 0 : return false;
162 : : }
163 : : }
164 : :
165 : 82 : return status;
166 : : }
167 : :
168 : 52 : bool libspdm_generate_data_key (
169 : : spdm_version_number_t spdm_version,
170 : : const uint8_t *handshake_secret, size_t handshake_secret_size,
171 : : const uint8_t *psk_hint, size_t psk_hint_size,
172 : : bool use_psk_hint,
173 : : uint32_t base_hash_algo,
174 : : const uint8_t *th2_hash_data,
175 : : uint8_t *master_secret, size_t *master_secret_size,
176 : : uint8_t *request_data_secret, size_t *request_data_secret_size,
177 : : uint8_t *response_data_secret, size_t *response_data_secret_size,
178 : : uint8_t *export_master_secret, size_t *export_master_secret_size)
179 : : {
180 : 52 : bool status = false;
181 : : size_t hash_size;
182 : : uint8_t salt1[LIBSPDM_MAX_HASH_SIZE];
183 : : uint8_t bin_str0[128];
184 : : size_t bin_str0_size;
185 : : uint8_t bin_str3[128];
186 : : size_t bin_str3_size;
187 : : uint8_t bin_str4[128];
188 : : size_t bin_str4_size;
189 : : uint8_t bin_str8[128];
190 : : size_t bin_str8_size;
191 : : uint8_t zero_filled_buffer[LIBSPDM_MAX_HASH_SIZE];
192 : :
193 [ + + ]: 52 : if (!use_psk_hint) {
194 [ + - - + ]: 28 : if (handshake_secret == NULL || handshake_secret_size == 0) {
195 : 0 : return false;
196 : : }
197 : : }
198 : :
199 : 52 : hash_size = libspdm_get_hash_size(base_hash_algo);
200 : :
201 [ + - ]: 52 : if (*master_secret_size < hash_size ||
202 [ + - ]: 52 : *request_data_secret_size < hash_size ||
203 [ + - ]: 52 : *response_data_secret_size < hash_size ||
204 [ - + ]: 52 : *export_master_secret_size < hash_size) {
205 : 0 : return false;
206 : : }
207 : 52 : *master_secret_size = hash_size;
208 : 52 : *request_data_secret_size = hash_size;
209 : 52 : *response_data_secret_size = hash_size;
210 : 52 : *export_master_secret_size = hash_size;
211 : :
212 : 52 : bin_str3_size = sizeof(bin_str3);
213 : 52 : libspdm_bin_concat(spdm_version,
214 : : SPDM_BIN_STR_3_LABEL, sizeof(SPDM_BIN_STR_3_LABEL) - 1,
215 : 52 : th2_hash_data, (uint16_t)hash_size, hash_size,
216 : : bin_str3, &bin_str3_size);
217 : :
218 : 52 : bin_str4_size = sizeof(bin_str4);
219 : 52 : libspdm_bin_concat(spdm_version,
220 : : SPDM_BIN_STR_4_LABEL, sizeof(SPDM_BIN_STR_4_LABEL) - 1,
221 : 52 : th2_hash_data, (uint16_t)hash_size, hash_size,
222 : : bin_str4, &bin_str4_size);
223 : :
224 : 52 : bin_str8_size = sizeof(bin_str8);
225 : 52 : libspdm_bin_concat(spdm_version,
226 : : SPDM_BIN_STR_8_LABEL, sizeof(SPDM_BIN_STR_8_LABEL) - 1,
227 : 52 : th2_hash_data, (uint16_t)hash_size, hash_size,
228 : : bin_str8, &bin_str8_size);
229 : :
230 : : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
231 [ + + ]: 52 : if (use_psk_hint) {
232 : 24 : status = libspdm_psk_master_secret_hkdf_expand(
233 : : spdm_version,
234 : : base_hash_algo,
235 : : psk_hint, psk_hint_size,
236 : : bin_str3, bin_str3_size,
237 : : request_data_secret, hash_size);
238 : :
239 [ - + ]: 24 : if (!status) {
240 : 0 : goto cleanup;
241 : : }
242 : :
243 : 24 : status = libspdm_psk_master_secret_hkdf_expand(
244 : : spdm_version,
245 : : base_hash_algo,
246 : : psk_hint, psk_hint_size,
247 : : bin_str4, bin_str4_size,
248 : : response_data_secret, hash_size);
249 : :
250 [ - + ]: 24 : if (!status) {
251 : 0 : goto cleanup;
252 : : }
253 : :
254 : 24 : status = libspdm_psk_master_secret_hkdf_expand(
255 : : spdm_version,
256 : : base_hash_algo,
257 : : psk_hint, psk_hint_size,
258 : : bin_str8, bin_str8_size,
259 : : export_master_secret, hash_size);
260 : :
261 [ - + ]: 24 : if (!status) {
262 : 0 : goto cleanup;
263 : : }
264 : : }
265 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */
266 : :
267 [ + + ]: 52 : if (!use_psk_hint) {
268 : 28 : bin_str0_size = sizeof(bin_str0);
269 : 28 : libspdm_bin_concat(spdm_version,
270 : : SPDM_BIN_STR_0_LABEL,
271 : : sizeof(SPDM_BIN_STR_0_LABEL) - 1, NULL,
272 : 28 : (uint16_t)hash_size, hash_size, bin_str0,
273 : : &bin_str0_size);
274 : :
275 : 28 : status = libspdm_hkdf_expand(
276 : : base_hash_algo, handshake_secret,
277 : : hash_size, bin_str0, bin_str0_size, salt1, hash_size);
278 [ - + ]: 28 : if (!status) {
279 : 0 : goto cleanup;
280 : : }
281 : :
282 : 28 : libspdm_zero_mem(zero_filled_buffer, sizeof(zero_filled_buffer));
283 : 28 : status = libspdm_hkdf_extract(
284 : : base_hash_algo,
285 : : zero_filled_buffer, hash_size, salt1, hash_size,
286 : : master_secret, hash_size);
287 [ - + ]: 28 : if (!status) {
288 : 0 : goto cleanup;
289 : : }
290 : :
291 : 28 : status = libspdm_hkdf_expand(
292 : : base_hash_algo,
293 : : master_secret, hash_size,
294 : : bin_str3, bin_str3_size,
295 : : request_data_secret, hash_size);
296 : :
297 [ - + ]: 28 : if (!status) {
298 : 0 : goto cleanup;
299 : : }
300 : :
301 : 28 : status = libspdm_hkdf_expand(
302 : : base_hash_algo,
303 : : master_secret, hash_size,
304 : : bin_str4, bin_str4_size,
305 : : response_data_secret, hash_size);
306 : :
307 [ - + ]: 28 : if (!status) {
308 : 0 : goto cleanup;
309 : : }
310 : :
311 : 28 : status = libspdm_hkdf_expand(
312 : : base_hash_algo,
313 : : master_secret, hash_size,
314 : : bin_str8, bin_str8_size,
315 : : export_master_secret, hash_size);
316 : :
317 [ + - ]: 28 : if (!status) {
318 : 0 : goto cleanup;
319 : : }
320 : : }
321 : :
322 : 52 : cleanup:
323 : : /*zero salt1 for security*/
324 : 52 : libspdm_zero_mem(salt1, hash_size);
325 : 52 : return status;
326 : : }
|