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 1283 : 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 1283 : final_size = sizeof(uint16_t) + sizeof(LIBSPDM_BIN_CONCAT_LABEL) - 1 + label_size;
21 1283 : if (context != NULL) {
22 286 : final_size += hash_size;
23 : }
24 :
25 1283 : LIBSPDM_ASSERT(*out_bin_size >= final_size);
26 :
27 1283 : *out_bin_size = final_size;
28 :
29 1283 : libspdm_copy_mem(out_bin, *out_bin_size, &length, sizeof(uint16_t));
30 1283 : 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 1283 : out_bin[6] = (char)('0' + ((spdm_version >> 12) & 0xF));
35 1283 : out_bin[8] = (char)('0' + ((spdm_version >> 8) & 0xF));
36 1283 : libspdm_copy_mem(out_bin + sizeof(uint16_t) + sizeof(LIBSPDM_BIN_CONCAT_LABEL) - 1,
37 1283 : *out_bin_size - (sizeof(uint16_t) + sizeof(LIBSPDM_BIN_CONCAT_LABEL) - 1),
38 : label, label_size);
39 :
40 1283 : if (context != NULL) {
41 286 : libspdm_copy_mem(out_bin + sizeof(uint16_t) + sizeof(LIBSPDM_BIN_CONCAT_LABEL) -
42 286 : 1 + label_size,
43 286 : *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 1283 : }
49 :
50 58 : 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 58 : 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 58 : if (!use_psk_hint) {
71 31 : if (shared_secret == NULL || shared_secret_size == 0) {
72 0 : return false;
73 : }
74 : }
75 :
76 58 : hash_size = libspdm_get_hash_size(base_hash_algo);
77 :
78 58 : if (*handshake_secret_size < hash_size ||
79 58 : *request_handshake_secret_size < hash_size ||
80 58 : *response_handshake_secret_size < hash_size) {
81 0 : return false;
82 : }
83 58 : *handshake_secret_size = hash_size;
84 58 : *request_handshake_secret_size = hash_size;
85 58 : *response_handshake_secret_size = hash_size;
86 :
87 58 : bin_str1_size = sizeof(bin_str1);
88 58 : libspdm_bin_concat(spdm_version,
89 : SPDM_BIN_STR_1_LABEL, sizeof(SPDM_BIN_STR_1_LABEL) - 1,
90 58 : th1_hash_data, (uint16_t)hash_size, hash_size,
91 : bin_str1, &bin_str1_size);
92 :
93 58 : bin_str2_size = sizeof(bin_str2);
94 58 : libspdm_bin_concat(spdm_version,
95 : SPDM_BIN_STR_2_LABEL, sizeof(SPDM_BIN_STR_2_LABEL) - 1,
96 58 : th1_hash_data, (uint16_t)hash_size, hash_size,
97 : bin_str2, &bin_str2_size);
98 :
99 : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
100 58 : if (use_psk_hint) {
101 27 : 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 27 : if (!status) {
109 0 : return false;
110 : }
111 :
112 27 : 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 27 : if (!status) {
120 0 : return false;
121 : }
122 :
123 : }
124 : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */
125 :
126 58 : if (!use_psk_hint) {
127 31 : libspdm_zero_mem(salt0, sizeof(salt0));
128 : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
129 31 : 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 31 : status = libspdm_hkdf_extract(
136 : base_hash_algo,
137 : shared_secret, shared_secret_size,
138 : salt0, hash_size,
139 : handshake_secret, hash_size);
140 31 : if (!status) {
141 0 : return false;
142 : }
143 :
144 31 : 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 31 : if (!status) {
151 0 : return false;
152 : }
153 :
154 31 : 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 31 : if (!status) {
161 0 : return false;
162 : }
163 : }
164 :
165 58 : return status;
166 : }
167 :
168 36 : 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 36 : 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 36 : if (!use_psk_hint) {
194 23 : if (handshake_secret == NULL || handshake_secret_size == 0) {
195 0 : return false;
196 : }
197 : }
198 :
199 36 : hash_size = libspdm_get_hash_size(base_hash_algo);
200 :
201 36 : if (*master_secret_size < hash_size ||
202 36 : *request_data_secret_size < hash_size ||
203 36 : *response_data_secret_size < hash_size ||
204 36 : *export_master_secret_size < hash_size) {
205 0 : return false;
206 : }
207 36 : *master_secret_size = hash_size;
208 36 : *request_data_secret_size = hash_size;
209 36 : *response_data_secret_size = hash_size;
210 36 : *export_master_secret_size = hash_size;
211 :
212 36 : bin_str3_size = sizeof(bin_str3);
213 36 : libspdm_bin_concat(spdm_version,
214 : SPDM_BIN_STR_3_LABEL, sizeof(SPDM_BIN_STR_3_LABEL) - 1,
215 36 : th2_hash_data, (uint16_t)hash_size, hash_size,
216 : bin_str3, &bin_str3_size);
217 :
218 36 : bin_str4_size = sizeof(bin_str4);
219 36 : libspdm_bin_concat(spdm_version,
220 : SPDM_BIN_STR_4_LABEL, sizeof(SPDM_BIN_STR_4_LABEL) - 1,
221 36 : th2_hash_data, (uint16_t)hash_size, hash_size,
222 : bin_str4, &bin_str4_size);
223 :
224 36 : bin_str8_size = sizeof(bin_str8);
225 36 : libspdm_bin_concat(spdm_version,
226 : SPDM_BIN_STR_8_LABEL, sizeof(SPDM_BIN_STR_8_LABEL) - 1,
227 36 : th2_hash_data, (uint16_t)hash_size, hash_size,
228 : bin_str8, &bin_str8_size);
229 :
230 : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
231 36 : if (use_psk_hint) {
232 13 : 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 13 : if (!status) {
240 0 : goto cleanup;
241 : }
242 :
243 13 : 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 13 : if (!status) {
251 0 : goto cleanup;
252 : }
253 :
254 13 : 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 13 : if (!status) {
262 0 : goto cleanup;
263 : }
264 : }
265 : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */
266 :
267 36 : if (!use_psk_hint) {
268 23 : bin_str0_size = sizeof(bin_str0);
269 23 : libspdm_bin_concat(spdm_version,
270 : SPDM_BIN_STR_0_LABEL,
271 : sizeof(SPDM_BIN_STR_0_LABEL) - 1, NULL,
272 23 : (uint16_t)hash_size, hash_size, bin_str0,
273 : &bin_str0_size);
274 :
275 23 : status = libspdm_hkdf_expand(
276 : base_hash_algo, handshake_secret,
277 : hash_size, bin_str0, bin_str0_size, salt1, hash_size);
278 23 : if (!status) {
279 0 : goto cleanup;
280 : }
281 :
282 23 : libspdm_zero_mem(zero_filled_buffer, sizeof(zero_filled_buffer));
283 23 : status = libspdm_hkdf_extract(
284 : base_hash_algo,
285 : zero_filled_buffer, hash_size, salt1, hash_size,
286 : master_secret, hash_size);
287 23 : if (!status) {
288 0 : goto cleanup;
289 : }
290 :
291 23 : 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 23 : if (!status) {
298 0 : goto cleanup;
299 : }
300 :
301 23 : 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 23 : if (!status) {
308 0 : goto cleanup;
309 : }
310 :
311 23 : 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 23 : if (!status) {
318 0 : goto cleanup;
319 : }
320 : }
321 :
322 36 : cleanup:
323 : /*zero salt1 for security*/
324 36 : libspdm_zero_mem(salt1, hash_size);
325 36 : return status;
326 : }
|