1 /**
2  *  Copyright Notice:
3  *  Copyright 2021-2022 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 
7 #ifndef SPDM_SECURED_MESSAGE_LIB_INTERNAL_H
8 #define SPDM_SECURED_MESSAGE_LIB_INTERNAL_H
9 
10 #include "library/spdm_secured_message_lib.h"
11 #include "library/spdm_crypt_lib.h"
12 #include "internal/libspdm_common_lib.h"
13 #include "hal/library/memlib.h"
14 #include "hal/library/cryptlib.h"
15 
16 typedef struct {
17     uint8_t dhe_secret[LIBSPDM_MAX_DHE_KEY_SIZE];
18     uint8_t handshake_secret[LIBSPDM_MAX_HASH_SIZE];
19     uint8_t master_secret[LIBSPDM_MAX_HASH_SIZE];
20 } libspdm_session_info_struct_master_secret_t;
21 
22 typedef struct {
23     uint8_t request_handshake_secret[LIBSPDM_MAX_HASH_SIZE];
24     uint8_t response_handshake_secret[LIBSPDM_MAX_HASH_SIZE];
25     uint8_t request_finished_key[LIBSPDM_MAX_HASH_SIZE];
26     uint8_t response_finished_key[LIBSPDM_MAX_HASH_SIZE];
27     uint8_t request_handshake_encryption_key[LIBSPDM_MAX_AEAD_KEY_SIZE];
28     uint8_t request_handshake_salt[LIBSPDM_MAX_AEAD_IV_SIZE];
29     uint64_t request_handshake_sequence_number;
30     uint8_t response_handshake_encryption_key[LIBSPDM_MAX_AEAD_KEY_SIZE];
31     uint8_t response_handshake_salt[LIBSPDM_MAX_AEAD_IV_SIZE];
32     uint64_t response_handshake_sequence_number;
33 } libspdm_session_info_struct_handshake_secret_t;
34 
35 typedef struct {
36     uint8_t request_data_secret[LIBSPDM_MAX_HASH_SIZE];
37     uint8_t response_data_secret[LIBSPDM_MAX_HASH_SIZE];
38     uint8_t request_data_encryption_key[LIBSPDM_MAX_AEAD_KEY_SIZE];
39     uint8_t request_data_salt[LIBSPDM_MAX_AEAD_IV_SIZE];
40     uint64_t request_data_sequence_number;
41     uint8_t response_data_encryption_key[LIBSPDM_MAX_AEAD_KEY_SIZE];
42     uint8_t response_data_salt[LIBSPDM_MAX_AEAD_IV_SIZE];
43     uint64_t response_data_sequence_number;
44 } libspdm_session_info_struct_application_secret_t;
45 
46 typedef struct {
47     libspdm_session_type_t session_type;
48     spdm_version_number_t version;
49     spdm_version_number_t secured_message_version;
50     uint32_t base_hash_algo;
51     uint16_t dhe_named_group;
52     uint16_t aead_cipher_suite;
53     uint16_t key_schedule;
54     size_t hash_size;
55     size_t dhe_key_size;
56     size_t aead_key_size;
57     size_t aead_iv_size;
58     size_t aead_tag_size;
59     uint64_t max_spdm_session_sequence_number;
60     bool use_psk;
61     libspdm_session_state_t session_state;
62     libspdm_session_info_struct_master_secret_t master_secret;
63     libspdm_session_info_struct_handshake_secret_t handshake_secret;
64     libspdm_session_info_struct_application_secret_t application_secret;
65     libspdm_session_info_struct_application_secret_t application_secret_backup;
66     bool requester_backup_valid;
67     bool responder_backup_valid;
68     size_t psk_hint_size;
69     uint8_t psk_hint[LIBSPDM_PSK_MAX_HINT_LENGTH];
70     uint8_t export_master_secret[LIBSPDM_MAX_HASH_SIZE];
71     uint8_t sequence_number_endian;
72 
73     /* Cache the error in libspdm_decode_secured_message.
74      * It is handled in libspdm_build_response. */
75     libspdm_error_struct_t last_spdm_error;
76 } libspdm_secured_message_context_t;
77 
78 #define LIBSPDM_SECURED_MESSAGE_CONTEXT_SIZE (sizeof(libspdm_secured_message_context_t))
79 
80 /**
81  * Initialize an SPDM secured message context.
82  *
83  * The size in bytes of the spdm_secured_message_context can be returned by libspdm_secured_message_get_context_size.
84  *
85  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
86  */
87 void libspdm_secured_message_init_context(void *spdm_secured_message_context);
88 
89 /**
90  * Set use_psk to an SPDM secured message context.
91  *
92  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
93  * @param  use_psk                       Indicate if the SPDM session use PSK.
94  */
95 void libspdm_secured_message_set_use_psk(void *spdm_secured_message_context, bool use_psk);
96 
97 /**
98  * Set session_state to an SPDM secured message context.
99  *
100  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
101  * @param  session_state                 Indicate the SPDM session state.
102  */
103 void libspdm_secured_message_set_session_state(
104     void *spdm_secured_message_context,
105     libspdm_session_state_t session_state);
106 
107 /**
108  * Set session_type to an SPDM secured message context.
109  *
110  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
111  * @param  session_type                  Indicate the SPDM session type.
112  */
113 void libspdm_secured_message_set_session_type(void *spdm_secured_message_context,
114                                               libspdm_session_type_t session_type);
115 
116 /**
117  * Set algorithm to an SPDM secured message context.
118  *
119  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
120  * @param  base_hash_algo                 Indicate the negotiated base_hash_algo for the SPDM session.
121  * @param  dhe_named_group                Indicate the negotiated dhe_named_group for the SPDM session.
122  * @param  aead_cipher_suite              Indicate the negotiated aead_cipher_suite for the SPDM session.
123  * @param  key_schedule                  Indicate the negotiated key_schedule for the SPDM session.
124  */
125 void libspdm_secured_message_set_algorithms(void *spdm_secured_message_context,
126                                             const spdm_version_number_t version,
127                                             const spdm_version_number_t secured_message_version,
128                                             uint32_t base_hash_algo,
129                                             uint16_t dhe_named_group,
130                                             uint16_t aead_cipher_suite,
131                                             uint16_t key_schedule);
132 
133 /**
134  * Set the psk_hint to an SPDM secured message context.
135  *
136  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
137  * @param  psk_hint                      Indicate the PSK hint.
138  * @param  psk_hint_size                  The size in bytes of the PSK hint.
139  */
140 void libspdm_secured_message_set_psk_hint(void *spdm_secured_message_context,
141                                           const void *psk_hint,
142                                           size_t psk_hint_size);
143 
144 /**
145  * Set the maximum sequence_number to an SPDM secured message context.
146  *
147  * @param  spdm_secured_message_context      A pointer to the SPDM secured message context.
148  * @param  max_spdm_session_sequence_number  Indicate the maximum sequence_number in SPDM session.
149  */
150 void libspdm_secured_message_set_max_spdm_session_sequence_number(
151     void *spdm_secured_message_context,
152     uint64_t max_spdm_session_sequence_number);
153 
154 /**
155  * Set the endianness of the sequence number used to construct the AEAD IV.
156  *
157  * @param spdm_secured_message_context A pointer to the SPDM secured message context.
158  * @param endian_value                 The endianness value.
159  *
160  */
161 void libspdm_secured_message_set_sequence_number_endian(
162     void *spdm_secured_message_context,
163     uint8_t endian_value);
164 
165 /**
166  * Allocates and Initializes one Diffie-Hellman Ephemeral (DHE) context for subsequent use,
167  * based upon negotiated DHE algorithm.
168  *
169  * @param  dhe_named_group                SPDM dhe_named_group
170  * @param  is_initiator                   if the caller is initiator.
171  *                                       true: initiator
172  *                                       false: not an initiator
173  *
174  * @return  Pointer to the Diffie-Hellman context that has been initialized.
175  **/
176 void *libspdm_secured_message_dhe_new(spdm_version_number_t spdm_version,
177                                       uint16_t dhe_named_group, bool is_initiator);
178 
179 /**
180  * Release the specified DHE context,
181  * based upon negotiated DHE algorithm.
182  *
183  * @param  dhe_named_group                SPDM dhe_named_group
184  * @param  dhe_context                   Pointer to the DHE context to be released.
185  **/
186 void libspdm_secured_message_dhe_free(uint16_t dhe_named_group, void *dhe_context);
187 
188 /**
189  * Generates DHE public key,
190  * based upon negotiated DHE algorithm.
191  *
192  * This function generates random secret exponent, and computes the public key, which is
193  * returned via parameter public_key and public_key_size. DH context is updated accordingly.
194  * If the public_key buffer is too small to hold the public key, false is returned and
195  * public_key_size is set to the required buffer size to obtain the public key.
196  *
197  * @param  dhe_named_group                SPDM dhe_named_group
198  * @param  dhe_context                   Pointer to the DHE context.
199  * @param  public_key                    Pointer to the buffer to receive generated public key.
200  * @param  public_key_size                On input, the size of public_key buffer in bytes.
201  *                                     On output, the size of data returned in public_key buffer in bytes.
202  *
203  * @retval true   DHE public key generation succeeded.
204  * @retval false  DHE public key generation failed.
205  * @retval false  public_key_size is not large enough.
206  **/
207 bool libspdm_secured_message_dhe_generate_key(uint16_t dhe_named_group,
208                                               void *dhe_context,
209                                               uint8_t *public_key,
210                                               size_t *public_key_size);
211 
212 /**
213  * Computes exchanged common key,
214  * based upon negotiated DHE algorithm.
215  *
216  * Given peer's public key, this function computes the exchanged common key, based on its own
217  * context including value of prime modulus and random secret exponent.
218  *
219  * @param  dhe_named_group                SPDM dhe_named_group
220  * @param  dhe_context                   Pointer to the DHE context.
221  * @param  peer_public_key                Pointer to the peer's public key.
222  * @param  peer_public_key_size            size of peer's public key in bytes.
223  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
224  *
225  * @retval true   DHE exchanged key generation succeeded.
226  * @retval false  DHE exchanged key generation failed.
227  * @retval false  key_size is not large enough.
228  **/
229 bool libspdm_secured_message_dhe_compute_key(
230     uint16_t dhe_named_group, void *dhe_context,
231     const uint8_t *peer_public, size_t peer_public_size,
232     void *spdm_secured_message_context);
233 
234 /**
235  * Allocates and initializes one HMAC context for subsequent use, with request_finished_key.
236  *
237  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
238  *
239  * @return Pointer to the HMAC context that has been initialized.
240  **/
241 void *libspdm_hmac_new_with_request_finished_key(void *spdm_secured_message_context);
242 
243 /**
244  * Release the specified HMAC context, with request_finished_key.
245  *
246  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
247  * @param  hmac_ctx                   Pointer to the HMAC context to be released.
248  **/
249 void libspdm_hmac_free_with_request_finished_key(
250     void *spdm_secured_message_context, void *hmac_ctx);
251 
252 /**
253  * Set request_finished_key for subsequent use. It must be done before any
254  * calling to hmac_update().
255  *
256  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
257  * @param  hmac_ctx  Pointer to HMAC context.
258  *
259  * @retval true   The key is set successfully.
260  * @retval false  The key is set unsuccessfully.
261  **/
262 bool libspdm_hmac_init_with_request_finished_key(
263     void *spdm_secured_message_context, void *hmac_ctx);
264 
265 /**
266  * Makes a copy of an existing HMAC context, with request_finished_key.
267  *
268  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
269  * @param  hmac_ctx     Pointer to HMAC context being copied.
270  * @param  new_hmac_ctx  Pointer to new HMAC context.
271  *
272  * @retval true   HMAC context copy succeeded.
273  * @retval false  HMAC context copy failed.
274  **/
275 bool libspdm_hmac_duplicate_with_request_finished_key(
276     void *spdm_secured_message_context,
277     const void *hmac_ctx, void *new_hmac_ctx);
278 
279 /**
280  * Digests the input data and updates HMAC context, with request_finished_key.
281  *
282  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
283  * @param  hmac_ctx     Pointer to HMAC context being copied.
284  * @param  data              Pointer to the buffer containing the data to be digested.
285  * @param  data_size          size of data buffer in bytes.
286  *
287  * @retval true   HMAC data digest succeeded.
288  * @retval false  HMAC data digest failed.
289  **/
290 bool libspdm_hmac_update_with_request_finished_key(
291     void *spdm_secured_message_context,
292     void *hmac_ctx, const void *data,
293     size_t data_size);
294 
295 /**
296  * Completes computation of the HMAC digest value, with request_finished_key.
297  *
298  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
299  * @param  hmac_ctx     Pointer to HMAC context being copied.
300  * @param  hmac_value          Pointer to a buffer that receives the HMAC digest value
301  *
302  * @retval true   HMAC data digest succeeded.
303  * @retval false  HMAC data digest failed.
304  **/
305 bool libspdm_hmac_final_with_request_finished_key(
306     void *spdm_secured_message_context,
307     void *hmac_ctx,  uint8_t *hmac_value);
308 
309 /**
310  * Computes the HMAC of a input data buffer, with request_finished_key.
311  *
312  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
313  * @param  data                         Pointer to the buffer containing the data to be HMACed.
314  * @param  data_size                     size of data buffer in bytes.
315  * @param  hash_value                    Pointer to a buffer that receives the HMAC value.
316  *
317  * @retval true   HMAC computation succeeded.
318  * @retval false  HMAC computation failed.
319  **/
320 bool libspdm_hmac_all_with_request_finished_key(void *spdm_secured_message_context,
321                                                 const void *data, size_t data_size,
322                                                 uint8_t *hmac_value);
323 
324 /**
325  * Allocates and initializes one HMAC context for subsequent use, with response_finished_key.
326  *
327  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
328  *
329  * @return Pointer to the HMAC context that has been initialized.
330  **/
331 void *libspdm_hmac_new_with_response_finished_key(void *spdm_secured_message_context);
332 
333 /**
334  * Release the specified HMAC context, with response_finished_key.
335  *
336  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
337  * @param  hmac_ctx                   Pointer to the HMAC context to be released.
338  **/
339 void libspdm_hmac_free_with_response_finished_key(
340     void *spdm_secured_message_context, void *hmac_ctx);
341 
342 /**
343  * Set response_finished_key for subsequent use. It must be done before any
344  * calling to hmac_update().
345  *
346  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
347  * @param  hmac_ctx  Pointer to HMAC context.
348  *
349  * @retval true   The key is set successfully.
350  * @retval false  The key is set unsuccessfully.
351  **/
352 bool libspdm_hmac_init_with_response_finished_key(
353     void *spdm_secured_message_context, void *hmac_ctx);
354 
355 /**
356  * Makes a copy of an existing HMAC context, with response_finished_key.
357  *
358  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
359  * @param  hmac_ctx     Pointer to HMAC context being copied.
360  * @param  new_hmac_ctx  Pointer to new HMAC context.
361  *
362  * @retval true   HMAC context copy succeeded.
363  * @retval false  HMAC context copy failed.
364  **/
365 bool libspdm_hmac_duplicate_with_response_finished_key(
366     void *spdm_secured_message_context,
367     const void *hmac_ctx, void *new_hmac_ctx);
368 
369 /**
370  * Digests the input data and updates HMAC context, with response_finished_key.
371  *
372  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
373  * @param  hmac_ctx     Pointer to HMAC context being copied.
374  * @param  data              Pointer to the buffer containing the data to be digested.
375  * @param  data_size          size of data buffer in bytes.
376  *
377  * @retval true   HMAC data digest succeeded.
378  * @retval false  HMAC data digest failed.
379  **/
380 bool libspdm_hmac_update_with_response_finished_key(
381     void *spdm_secured_message_context,
382     void *hmac_ctx, const void *data,
383     size_t data_size);
384 
385 /**
386  * Completes computation of the HMAC digest value, with response_finished_key.
387  *
388  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
389  * @param  hmac_ctx     Pointer to HMAC context being copied.
390  * @param  hmac_value          Pointer to a buffer that receives the HMAC digest value
391  *
392  * @retval true   HMAC data digest succeeded.
393  * @retval false  HMAC data digest failed.
394  **/
395 bool libspdm_hmac_final_with_response_finished_key(
396     void *spdm_secured_message_context,
397     void *hmac_ctx,  uint8_t *hmac_value);
398 
399 /**
400  * Computes the HMAC of a input data buffer, with response_finished_key.
401  *
402  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
403  * @param  data                         Pointer to the buffer containing the data to be HMACed.
404  * @param  data_size                     size of data buffer in bytes.
405  * @param  hash_value                    Pointer to a buffer that receives the HMAC value.
406  *
407  * @retval true   HMAC computation succeeded.
408  * @retval false  HMAC computation failed.
409  **/
410 bool libspdm_hmac_all_with_response_finished_key(
411     void *spdm_secured_message_context, const void *data,
412     size_t data_size, uint8_t *hmac_value);
413 
414 /**
415  * Set the last SPDM error struct of an SPDM secured message context.
416  *
417  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
418  * @param  last_spdm_error                Last SPDM error struct of an SPDM secured message context.
419  */
420 void libspdm_secured_message_set_last_spdm_error_struct(
421     void *spdm_secured_message_context,
422     const libspdm_error_struct_t *last_spdm_error);
423 
424 /**
425  * This function generates SPDM HandshakeKey for a session.
426  *
427  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
428  * @param  th1_hash_data                  th1 hash
429  *
430  * @retval RETURN_SUCCESS  SPDM HandshakeKey for a session is generated.
431  **/
432 bool libspdm_generate_session_handshake_key(void *spdm_secured_message_context,
433                                             const uint8_t *th1_hash_data);
434 
435 /**
436  * This function generates SPDM DataKey for a session.
437  *
438  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
439  * @param  th2_hash_data                  th2 hash
440  *
441  * @retval RETURN_SUCCESS  SPDM DataKey for a session is generated.
442  **/
443 bool libspdm_generate_session_data_key(void *spdm_secured_message_context,
444                                        const uint8_t *th2_hash_data);
445 
446 /**
447  * This function creates the updates of SPDM DataKey for a session.
448  *
449  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
450  * @param  action                       Indicate of the key update action.
451  *
452  * @retval RETURN_SUCCESS  SPDM DataKey update is created.
453  **/
454 bool libspdm_create_update_session_data_key(void *spdm_secured_message_context,
455                                             libspdm_key_update_action_t action);
456 
457 /**
458  * This function activates the update of SPDM DataKey for a session.
459  *
460  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
461  * @param  action                       Indicate of the key update action.
462  * @param  use_new_key                    Indicate if the new key should be used.
463  *
464  * @retval RETURN_SUCCESS  SPDM DataKey update is activated.
465  **/
466 bool libspdm_activate_update_session_data_key(void *spdm_secured_message_context,
467                                               libspdm_key_update_action_t action,
468                                               bool use_new_key);
469 
470 #endif /* SPDM_SECURED_MESSAGE_LIB_INTERNAL_H */
471