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