forked from DMTF/libspdm
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlibspdm_common_lib.h
More file actions
2058 lines (1834 loc) · 81.3 KB
/
libspdm_common_lib.h
File metadata and controls
2058 lines (1834 loc) · 81.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* Copyright Notice:
* Copyright 2021-2025 DMTF. All rights reserved.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/
#ifndef SPDM_COMMON_LIB_INTERNAL_H
#define SPDM_COMMON_LIB_INTERNAL_H
#include "library/spdm_common_lib.h"
#include "library/spdm_secured_message_lib.h"
#include "library/spdm_return_status.h"
#include "library/spdm_crypt_lib.h"
#include "hal/library/debuglib.h"
#include "hal/library/memlib.h"
#include "hal/library/requester/reqasymsignlib.h"
#include "hal/library/requester/psklib.h"
#include "hal/library/responder/asymsignlib.h"
#include "hal/library/responder/csrlib.h"
#include "hal/library/responder/measlib.h"
#include "hal/library/responder/key_pair_info.h"
#include "hal/library/responder/psklib.h"
#include "hal/library/responder/setcertlib.h"
#include "hal/library/endpointinfolib.h"
#include "hal/library/eventlib.h"
#include "hal/library/cryptlib.h"
#define INVALID_SESSION_ID LIBSPDM_INVALID_SESSION_ID
/* The SPDM specification does not limit the values of CTExponent and RDTExponent.
* libspdm artificially limits their values to 31, which corresponds to approximately 35 minutes
* for CT and RDT. If an endpoint takes longer than 35 minutes to generate an SPDM message then
* libspdm assumes the Integrator would not want to interact with such an endpoint. A maximum value
* of 31 also means that, when calculating CT and RDT, a left-shift will not result in C undefined
* behavior.
*/
#define LIBSPDM_MAX_CT_EXPONENT 31
#define LIBSPDM_MAX_RDT_EXPONENT 31
#define LIBSPDM_MAX_SPDM_SESSION_SEQUENCE_NUMBER 0xFFFFFFFFFFFFFFFFull
typedef struct {
uint8_t spdm_version_count;
spdm_version_number_t spdm_version[SPDM_MAX_VERSION_COUNT];
} libspdm_device_version_t;
typedef struct {
uint8_t secured_message_version_count;
spdm_version_number_t secured_message_version[SECURED_SPDM_MAX_VERSION_COUNT];
} libspdm_secured_message_version_t;
typedef struct {
uint8_t ct_exponent;
uint64_t rtt;
uint32_t st1;
uint32_t flags;
uint16_t ext_flags;
uint32_t data_transfer_size;
uint32_t sender_data_transfer_size;
uint32_t max_spdm_msg_size;
uint32_t transport_header_size;
uint32_t transport_tail_size;
} libspdm_device_capability_t;
typedef struct {
uint8_t measurement_spec;
uint8_t other_params_support;
uint8_t mel_spec;
uint32_t measurement_hash_algo;
uint32_t base_asym_algo;
uint32_t base_hash_algo;
uint16_t dhe_named_group;
uint16_t aead_cipher_suite;
uint16_t req_base_asym_alg;
uint16_t key_schedule;
uint32_t pqc_asym_algo;
uint32_t req_pqc_asym_alg;
uint32_t kem_alg;
bool pqc_first;
} libspdm_device_algorithm_t;
typedef struct {
#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
uint8_t buffer[LIBSPDM_MAX_CERT_CHAIN_SIZE];
size_t buffer_size;
#else
uint8_t buffer_hash[LIBSPDM_MAX_HASH_SIZE];
uint32_t buffer_hash_size;
/* leaf cert public key of the peer */
void *leaf_cert_public_key;
#endif
} libspdm_peer_used_cert_chain_t;
typedef struct {
/* Local device info */
libspdm_device_version_t version;
libspdm_device_capability_t capability;
libspdm_device_algorithm_t algorithm;
libspdm_secured_message_version_t secured_message_version;
/* My Certificate */
const void *local_cert_chain_provision[SPDM_MAX_SLOT_COUNT];
size_t local_cert_chain_provision_size[SPDM_MAX_SLOT_COUNT];
uint8_t local_supported_slot_mask;
uint8_t cert_slot_reset_mask;
spdm_key_pair_id_t local_key_pair_id[SPDM_MAX_SLOT_COUNT];
spdm_certificate_info_t local_cert_info[SPDM_MAX_SLOT_COUNT];
spdm_key_usage_bit_mask_t local_key_usage_bit_mask[SPDM_MAX_SLOT_COUNT];
/* My raw public key (slot_id - 0xFF) */
const void *local_public_key_provision;
size_t local_public_key_provision_size;
/* Peer Root Certificate */
const void *peer_root_cert_provision[LIBSPDM_MAX_ROOT_CERT_SUPPORT];
size_t peer_root_cert_provision_size[LIBSPDM_MAX_ROOT_CERT_SUPPORT];
/* Peer raw public key (slot_id - 0xFF) */
const void *peer_public_key_provision;
size_t peer_public_key_provision_size;
/* Peer Cert verify*/
libspdm_verify_spdm_cert_chain_func verify_peer_spdm_cert_chain;
/* Responder policy*/
bool basic_mut_auth_requested;
uint8_t mut_auth_requested;
bool mandatory_mut_auth;
uint8_t heartbeat_period;
/*The device role*/
bool is_requester;
} libspdm_local_context_t;
typedef struct {
/* Connection State */
libspdm_connection_state_t connection_state;
/* Peer device info (negotiated) */
spdm_version_number_t version;
libspdm_device_capability_t capability;
libspdm_device_algorithm_t algorithm;
/* Peer digests buffer */
uint8_t peer_provisioned_slot_mask;
uint8_t peer_supported_slot_mask;
uint8_t peer_total_digest_buffer[LIBSPDM_MAX_HASH_SIZE * SPDM_MAX_SLOT_COUNT];
spdm_key_pair_id_t peer_key_pair_id[SPDM_MAX_SLOT_COUNT];
spdm_certificate_info_t peer_cert_info[SPDM_MAX_SLOT_COUNT];
spdm_key_usage_bit_mask_t peer_key_usage_bit_mask[SPDM_MAX_SLOT_COUNT];
/* Peer CertificateChain */
libspdm_peer_used_cert_chain_t peer_used_cert_chain[SPDM_MAX_SLOT_COUNT];
uint8_t peer_used_cert_chain_slot_id;
/* Local Used CertificateChain (for responder, or requester in mut auth) */
const uint8_t *local_used_cert_chain_buffer;
size_t local_used_cert_chain_buffer_size;
uint8_t local_used_cert_chain_slot_id;
/* Specifies whether the cached negotiated state should be invalidated. (responder only)
* This is a "sticky" bit wherein if it is set to 1 then it cannot be set to 0. */
uint8_t end_session_attributes;
/* multi-key negotiated result */
bool multi_key_conn_req;
bool multi_key_conn_rsp;
} libspdm_connection_info_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
/*uint8_t buffer[max_buffer_size];*/
} libspdm_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE];
} libspdm_vca_managed_buffer_t;
/*
* +--------------------------+------------------------------------------+---------+
* | DIGESTS 1.4 | 4 + (H [+ 4]) * SlotNum = [36, 548] | [1, 18] |
* +--------------------------+------------------------------------------+---------+
* It is for multi-key.
*/
#define LIBSPDM_MAX_MESSAGE_D_BUFFER_SIZE (4 + \
(LIBSPDM_MAX_HASH_SIZE + 4) * SPDM_MAX_SLOT_COUNT)
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_D_BUFFER_SIZE];
} libspdm_message_d_managed_buffer_t;
#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
/*
* +--------------------------+------------------------------------------+---------+
* | GET_DIGESTS 1.4 | 4 | 1 |
* | DIGESTS 1.4 | 4 + (H [+ 4]) * SlotNum = [36, 548] | [1, 18] |
* +--------------------------+------------------------------------------+---------+
* | GET_CERTIFICATE 1.4 | 16 | 1 |
* | CERTIFICATE 1.4 | 16 + PortionLen | [1, ] |
* +--------------------------+------------------------------------------+---------+
*/
#define LIBSPDM_MAX_MESSAGE_B_BUFFER_SIZE (40 + \
(LIBSPDM_MAX_HASH_SIZE + 4) * SPDM_MAX_SLOT_COUNT + \
LIBSPDM_MAX_CERT_CHAIN_SIZE)
/*
* +--------------------------+------------------------------------------+---------+
* | CHALLENGE 1.4 | 44 | 1 |
* | CHALLENGE_AUTH 1.4 | 46 + H * 2 + S [+ O] = [166, 678] | [6, 23] |
* +--------------------------+------------------------------------------+---------+
*/
#define LIBSPDM_MAX_MESSAGE_C_BUFFER_SIZE (90 + \
LIBSPDM_MAX_HASH_SIZE * 2 + \
LIBSPDM_RSP_SIGNATURE_DATA_MAX_SIZE + \
SPDM_MAX_OPAQUE_DATA_SIZE)
/*
* +--------------------------+------------------------------------------+---------+
* | GET_MEASUREMENTS 1.4 | 13 + Nonce (0 or 32) | 1 |
* | MEASUREMENTS 1.4 | 50 + MeasRecLen (+ S) [+ O] = [106, 554] | [4, 19] |
* +--------------------------+------------------------------------------+---------+
*/
#define LIBSPDM_MAX_MESSAGE_M_BUFFER_SIZE (63 + SPDM_NONCE_SIZE + \
LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE + \
LIBSPDM_RSP_SIGNATURE_DATA_MAX_SIZE + \
SPDM_MAX_OPAQUE_DATA_SIZE)
/*
* +--------------------------+------------------------------------------+---------+
* | KEY_EXCHANGE 1.4 | 42 + D [+ O] = [106, 554] | [4, 19] |
* | KEY_EXCHANGE_RSP 1.4 | 42 + D + H + S (+ H) [+ O] = [234, 1194] | [8, 40] |
* +--------------------------+------------------------------------------+---------+
* | PSK_EXCHANGE 1.4 | 12 [+ PSKHint] + R [+ O] = 44 | 2 |
* | PSK_EXCHANGE_RSP 1.4 | 12 + R + H (+ H) [+ O] = [108, 172] | [4, 6] |
* +--------------------------+------------------------------------------+---------+
*/
#define LIBSPDM_MAX_MESSAGE_K_BUFFER_SIZE (84 + LIBSPDM_REQ_EXCHANGE_DATA_MAX_SIZE + \
LIBSPDM_RSP_EXCHANGE_DATA_MAX_SIZE + \
LIBSPDM_MAX_HASH_SIZE * 2 + \
LIBSPDM_RSP_SIGNATURE_DATA_MAX_SIZE + \
SPDM_MAX_OPAQUE_DATA_SIZE * 2)
/*
* +--------------------------+------------------------------------------+---------+
* | FINISH 1.4 | 6 (+ S) + H [+ O] = [100, 580] | [4, 20] |
* | FINISH_RSP 1.4 | 6 (+ H) [+ O] = [36, 69] | [1, 3] |
* +--------------------------+------------------------------------------+---------+
* | PSK_FINISH 1.4 | 6 + H [+ O] = [36, 68] | [1, 3] |
* | PSK_FINISH_RSP 1.4 | 6 [+ O] | 1 |
* +--------------------------+------------------------------------------+---------+
*/
#define LIBSPDM_MAX_MESSAGE_F_BUFFER_SIZE (12 + LIBSPDM_MAX_HASH_SIZE * 2 + \
LIBSPDM_REQ_SIGNATURE_DATA_MAX_SIZE + \
SPDM_MAX_OPAQUE_DATA_SIZE * 2)
/*
* +--------------------------+------------------------------------------+---------+
* | GET_EP_INFO 1.4 | 8 + Nonce (0 or 32) = [8, 40] | 1 |
* | EP_INFO 1.4 | 12 + Nonce + EPInfoLen (+ S) = [12, 1024]| [1, 25] |
* +--------------------------+------------------------------------------+---------+
*/
#define LIBSPDM_MAX_MESSAGE_E_BUFFER_SIZE (20 + SPDM_NONCE_SIZE * 2 + \
LIBSPDM_MAX_ENDPOINT_INFO_LENGTH + \
LIBSPDM_RSP_SIGNATURE_DATA_MAX_SIZE)
#define LIBSPDM_MAX_MESSAGE_L1L2_BUFFER_SIZE \
(LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + LIBSPDM_MAX_MESSAGE_M_BUFFER_SIZE)
#define LIBSPDM_MAX_MESSAGE_M1M2_BUFFER_SIZE \
(LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + \
LIBSPDM_MAX_MESSAGE_B_BUFFER_SIZE + LIBSPDM_MAX_MESSAGE_C_BUFFER_SIZE)
#define LIBSPDM_MAX_MESSAGE_TH_BUFFER_SIZE \
(LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + \
LIBSPDM_MAX_MESSAGE_D_BUFFER_SIZE + \
LIBSPDM_MAX_HASH_SIZE + LIBSPDM_MAX_MESSAGE_K_BUFFER_SIZE + \
LIBSPDM_MAX_MESSAGE_D_BUFFER_SIZE + \
LIBSPDM_MAX_HASH_SIZE + LIBSPDM_MAX_MESSAGE_F_BUFFER_SIZE)
#define LIBSPDM_MAX_MESSAGE_IL1IL2_BUFFER_SIZE \
(LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + LIBSPDM_MAX_MESSAGE_E_BUFFER_SIZE)
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_B_BUFFER_SIZE];
} libspdm_message_b_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_C_BUFFER_SIZE];
} libspdm_message_c_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_M_BUFFER_SIZE];
} libspdm_message_m_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_K_BUFFER_SIZE];
} libspdm_message_k_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_F_BUFFER_SIZE];
} libspdm_message_f_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_E_BUFFER_SIZE];
} libspdm_message_e_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_L1L2_BUFFER_SIZE];
} libspdm_l1l2_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_M1M2_BUFFER_SIZE];
} libspdm_m1m2_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_IL1IL2_BUFFER_SIZE];
} libspdm_il1il2_managed_buffer_t;
typedef struct {
size_t max_buffer_size;
size_t buffer_size;
uint8_t buffer[LIBSPDM_MAX_MESSAGE_TH_BUFFER_SIZE];
} libspdm_th_managed_buffer_t;
#endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
/* signature = Sign(SK, hash(M1))
* Verify(PK, hash(M2), signature)*/
/* M1/M2 = Concatenate (A, B, C)
* A = Concatenate (GET_VERSION, VERSION, GET_CAPABILITIES, CAPABILITIES, NEGOTIATE_ALGORITHMS, ALGORITHMS)
* B = Concatenate (GET_DIGEST, DIGEST, GET_CERTIFICATE, CERTIFICATE)
* C = Concatenate (CHALLENGE, CHALLENGE_AUTH\signature)*/
/* Mut M1/M2 = Concatenate (MutB, MutC)
* MutB = Concatenate (GET_DIGEST, DIGEST, GET_CERTIFICATE, CERTIFICATE)
* MutC = Concatenate (CHALLENGE, CHALLENGE_AUTH\signature)*/
/* signature = Sign(SK, hash(L1))
* Verify(PK, hash(L2), signature)*/
/* L1/L2 = Concatenate (M)
* M = Concatenate (GET_MEASUREMENT, MEASUREMENT\signature)*/
/* IL1/IL2 = Concatenate (A, E)
* E = Concatenate (GET_ENDPOINT_INFO, ENDPOINT_INFO\signature)*/
/* Encap IL1/IL2 = Concatenate (A, Encap E)
* Encap E = Concatenate (GET_ENDPOINT_INFO, ENDPOINT_INFO\signature)*/
typedef struct {
/* the message_a must be plan text because we do not know the algorithm yet.*/
libspdm_vca_managed_buffer_t message_a;
libspdm_message_d_managed_buffer_t message_d;
#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
libspdm_message_b_managed_buffer_t message_b;
libspdm_message_c_managed_buffer_t message_c;
libspdm_message_b_managed_buffer_t message_mut_b;
libspdm_message_c_managed_buffer_t message_mut_c;
libspdm_message_m_managed_buffer_t message_m;
libspdm_message_e_managed_buffer_t message_e;
libspdm_message_e_managed_buffer_t message_encap_e;
#else
void *digest_context_m1m2;
void *digest_context_mut_m1m2;
void *digest_context_l1l2;
void *digest_context_il1il2;
void *digest_context_encap_il1il2;
#endif
} libspdm_transcript_t;
/* TH for KEY_EXCHANGE response signature: Concatenate (A, D, Ct, K)
* D = DIGEST, if MULTI_KEY_CONN_RSP
* Ct = certificate chain
* K = Concatenate (KEY_EXCHANGE request, KEY_EXCHANGE response\signature+verify_data)*/
/* TH for KEY_EXCHANGE response HMAC: Concatenate (A, D, Ct, K)
* D = DIGEST, if MULTI_KEY_CONN_RSP
* Ct = certificate chain
* K = Concatenate (KEY_EXCHANGE request, KEY_EXCHANGE response\verify_data)*/
/* TH for FINISH request signature: Concatenate (A, D, Ct, K, EncapD, CM, F)
* D = DIGEST, if MULTI_KEY_CONN_RSP
* Ct = certificate chain
* K = Concatenate (KEY_EXCHANGE request, KEY_EXCHANGE response)
* EncapD = Encap DIGEST, if MULTI_KEY_CONN_REQ
* CM = mutual certificate chain
* F = Concatenate (FINISH request\signature+verify_data)*/
/* TH for FINISH response HMAC: Concatenate (A, D, Ct, K, EncapD, CM, F)
* D = DIGEST, if MULTI_KEY_CONN_RSP
* Ct = certificate chain
* K = Concatenate (KEY_EXCHANGE request, KEY_EXCHANGE response)
* EncapD = Encap DIGEST, if MULTI_KEY_CONN_REQ
* CM = mutual certificate chain, if MutAuth
* F = Concatenate (FINISH request\verify_data)*/
/* th1: Concatenate (A, D, Ct, K)
* D = DIGEST, if MULTI_KEY_CONN_RSP
* Ct = certificate chain
* K = Concatenate (KEY_EXCHANGE request, KEY_EXCHANGE response)*/
/* th2: Concatenate (A, D, Ct, K, EncapD, CM, F)
* D = DIGEST, if MULTI_KEY_CONN_RSP
* Ct = certificate chain
* K = Concatenate (KEY_EXCHANGE request, KEY_EXCHANGE response)
* EncapD = Encap DIGEST, if MULTI_KEY_CONN_REQ
* CM = mutual certificate chain, if MutAuth
* F = Concatenate (FINISH request, FINISH response)*/
/* TH for PSK_EXCHANGE response HMAC: Concatenate (A, K)
* K = Concatenate (PSK_EXCHANGE request, PSK_EXCHANGE response\verify_data)*/
/* TH for PSK_FINISH response HMAC: Concatenate (A, K, F)
* K = Concatenate (PSK_EXCHANGE request, PSK_EXCHANGE response)
* F = Concatenate (PSK_FINISH request\verify_data)*/
/* TH1_PSK1: Concatenate (A, K)
* K = Concatenate (PSK_EXCHANGE request, PSK_EXCHANGE response\verify_data)*/
/* TH1_PSK2: Concatenate (A, K, F)
* K = Concatenate (PSK_EXCHANGE request, PSK_EXCHANGE response)
* F = Concatenate (PSK_FINISH request\verify_data)*/
/* TH2_PSK: Concatenate (A, K, F)
* K = Concatenate (PSK_EXCHANGE request, PSK_EXCHANGE response)
* F = Concatenate (PSK_FINISH request, PSK_FINISH response)*/
typedef struct {
libspdm_message_d_managed_buffer_t message_encap_d;
#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
libspdm_message_k_managed_buffer_t message_k;
libspdm_message_f_managed_buffer_t message_f;
libspdm_message_m_managed_buffer_t message_m;
libspdm_message_e_managed_buffer_t message_e;
libspdm_message_e_managed_buffer_t message_encap_e;
#else
bool message_f_initialized;
void *digest_context_th;
void *digest_context_l1l2;
void *digest_context_il1il2;
void *digest_context_encap_il1il2;
/* this is back up for message F reset.*/
void *digest_context_th_backup;
#endif
} libspdm_session_transcript_t;
typedef struct {
uint32_t session_id;
bool use_psk;
uint8_t mut_auth_requested;
uint8_t end_session_attributes;
uint8_t session_policy;
uint8_t heartbeat_period;
libspdm_session_transcript_t session_transcript;
/* Register for the last KEY_UPDATE token and operation (responder only)*/
spdm_key_update_request_t last_key_update_request;
void *secured_message_context;
} libspdm_session_info_t;
#define LIBSPDM_MAX_ENCAP_REQUEST_OP_CODE_SEQUENCE_COUNT 3
typedef struct {
/* Valid OpCode: GET_DIGEST/GET_CERTIFICATE/CHALLENGE/KEY_UPDATE/GET_ENDPOINT_INFO/SEND_EVENT
* The last one is 0x00, as a terminator. */
uint8_t request_op_code_sequence[LIBSPDM_MAX_ENCAP_REQUEST_OP_CODE_SEQUENCE_COUNT + 1];
uint8_t request_op_code_count;
uint8_t current_request_op_code;
uint8_t request_id;
uint8_t req_slot_id;
spdm_message_header_t last_encap_request_header;
size_t last_encap_request_size;
uint32_t cert_chain_total_len;
uint8_t req_context[SPDM_REQ_CONTEXT_SIZE];
uint32_t session_id;
bool use_large_cert_chain;
} libspdm_encap_context_t;
#if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
typedef struct {
bool chunk_in_use;
uint8_t chunk_handle;
uint32_t chunk_seq_no;
size_t chunk_bytes_transferred;
void* large_message;
size_t large_message_size;
size_t large_message_capacity;
} libspdm_chunk_info_t;
typedef struct {
libspdm_chunk_info_t send;
libspdm_chunk_info_t get;
} libspdm_chunk_context_t;
#endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
#if LIBSPDM_ENABLE_MSG_LOG
typedef struct {
void *buffer;
size_t max_buffer_size;
uint32_t mode;
size_t buffer_size;
uint32_t status;
} libspdm_msg_log_t;
#endif /* LIBSPDM_ENABLE_MSG_LOG */
#if LIBSPDM_FIPS_MODE
typedef struct {
/**
* Tested algo flag: 0 represents that the algo is not tested.
* See LIBSPDM_FIPS_SELF_TEST_xxx;
**/
uint32_t tested_algo;
/**
* Flag for the result of run algo self_test, 0 represents the result is failed.
* See LIBSPDM_FIPS_SELF_TEST_xxx;
**/
uint32_t self_test_result;
/**
* Buffer provided by integrator to hold large intermediate results.
**/
void *selftest_buffer;
size_t selftest_buffer_size;
} libspdm_fips_selftest_context_t;
#endif /* LIBSPDM_FIPS_MODE */
#define LIBSPDM_CONTEXT_STRUCT_VERSION 0x3
typedef struct {
uint32_t version;
/* IO information */
libspdm_device_send_message_func send_message;
libspdm_device_receive_message_func receive_message;
/*
* reserved for request and response in the main dispatch function in SPDM responder.
* this buffer is the transport message received from spdm_context->receive_message()
* or sent to spdm_context->send_message().
* This message may be SPDM transport message or secured SPDM transport message.
**/
libspdm_device_acquire_sender_buffer_func acquire_sender_buffer;
libspdm_device_release_sender_buffer_func release_sender_buffer;
libspdm_device_acquire_receiver_buffer_func acquire_receiver_buffer;
libspdm_device_release_receiver_buffer_func release_receiver_buffer;
/* Transport Layer information */
libspdm_transport_encode_message_func transport_encode_message;
libspdm_transport_decode_message_func transport_decode_message;
/* Cached plain text command
* If the command is cipher text, decrypt then cache it. */
void *last_spdm_request;
size_t last_spdm_request_size;
/* Buffers used for data processing and transport. */
void *scratch_buffer;
size_t scratch_buffer_size;
void *sender_buffer;
size_t sender_buffer_size;
void *receiver_buffer;
size_t receiver_buffer_size;
/* Cache session_id in this spdm_message, only valid for secured message. */
uint32_t last_spdm_request_session_id;
bool last_spdm_request_session_id_valid;
/* Cache the error in libspdm_process_request. It is handled in libspdm_build_response. */
libspdm_error_struct_t last_spdm_error;
/* Register GetResponse function (responder only) */
void *get_response_func;
/* Register GetEncapResponse function (requester only) */
void *get_encap_response_func;
libspdm_encap_context_t encap_context;
/* Register spdm_session_state_callback function (responder only)
* Register can know the state after StartSession / EndSession. */
void *spdm_session_state_callback;
/* Register spdm_connection_state_callback function (responder only)
* Register can know the connection state such as negotiated. */
void *spdm_connection_state_callback;
/* Register libspdm_key_update_callback function (responder only)
* Register can know when session keys are updated during KEY_UPDATE operations. */
void *spdm_key_update_callback;
libspdm_local_context_t local_context;
libspdm_connection_info_t connection_info;
libspdm_transcript_t transcript;
libspdm_session_info_t session_info[LIBSPDM_MAX_SESSION_COUNT];
/* Buffer that the Responder uses to store the Requester's certificate chain for
* mutual authentication. */
void *mut_auth_cert_chain_buffer;
size_t mut_auth_cert_chain_buffer_size;
size_t mut_auth_cert_chain_buffer_max_size;
/* Cache latest session ID for HANDSHAKE_IN_THE_CLEAR */
uint32_t latest_session_id;
/* Register for Responder state, be initial to Normal (responder only) */
libspdm_response_state_t response_state;
/* Cached data for SPDM_ERROR_CODE_RESPONSE_NOT_READY/SPDM_RESPOND_IF_READY */
spdm_error_data_response_not_ready_t error_data;
#if LIBSPDM_RESPOND_IF_READY_SUPPORT
void *cache_spdm_request;
size_t cache_spdm_request_size;
#endif
uint8_t current_token;
/* Register for the retry times when receive "BUSY" Error response (requester only) */
uint8_t retry_times;
/* Register for the delay time in microseconds between retry requests
* when receive "BUSY" Error response (requester only) */
uint64_t retry_delay_time;
bool crypto_request;
/* App context data for use by application */
void *app_context_data_ptr;
/* See LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_*. */
uint8_t handle_error_return_policy;
/* Max session count for DHE session and PSK session
* Set via LIBSPDM_DATA_MAX_DHE_SESSION_COUNT and LIBSPDM_DATA_MAX_PSK_SESSION_COUNT */
uint32_t max_dhe_session_count;
uint32_t max_psk_session_count;
/* Current session count for DHE session and PSK session */
uint32_t current_dhe_session_count;
uint32_t current_psk_session_count;
/* see LIBSPDM_DATA_MAX_SPDM_SESSION_SEQUENCE_NUMBER */
uint64_t max_spdm_session_sequence_number;
uint8_t sequence_number_endian;
#if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
/* Chunk specific context */
libspdm_chunk_context_t chunk_context;
#endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
#if LIBSPDM_ENABLE_MSG_LOG
libspdm_msg_log_t msg_log;
#endif /* LIBSPDM_ENABLE_MSG_LOG */
#if LIBSPDM_FIPS_MODE
libspdm_fips_selftest_context_t fips_selftest_context;
#endif /* LIBSPDM_FIPS_MODE */
/* Endianness (BE/LE/Both) to use for signature verification on SPDM 1.0 and 1.1
* This field is ignored for other SPDM versions */
uint8_t spdm_10_11_verify_signature_endian;
#if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
libspdm_vendor_response_callback_func vendor_response_callback;
#endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
#if LIBSPDM_EVENT_RECIPIENT_SUPPORT
libspdm_process_event_func process_event;
#endif /* LIBSPDM_EVENT_RECIPIENT_SUPPORT */
#if (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT)
libspdm_get_endpoint_info_callback_func get_endpoint_info_callback;
#endif /* (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT) */
} libspdm_context_t;
#define LIBSPDM_CONTEXT_SIZE_WITHOUT_SECURED_CONTEXT (sizeof(libspdm_context_t))
#define LIBSPDM_CONTEXT_SIZE_ALL (LIBSPDM_CONTEXT_SIZE_WITHOUT_SECURED_CONTEXT + \
LIBSPDM_SECURED_MESSAGE_CONTEXT_SIZE * LIBSPDM_MAX_SESSION_COUNT)
#if LIBSPDM_DEBUG_PRINT_ENABLE
/**
* Return the request code name based on given request code.
*
* @param request_code The SPDM request code.
*
* @return request code name according to the request code.
**/
const char *libspdm_get_code_str(uint8_t request_code);
#ifdef LIBSPDM_INTERNAL_DUMP_HEX_STR_OVERRIDE
extern void LIBSPDM_INTERNAL_DUMP_HEX_STR_OVERRIDE(const uint8_t *data, size_t size);
#define LIBSPDM_INTERNAL_DUMP_HEX_STR(data, size) LIBSPDM_INTERNAL_DUMP_HEX_STR_OVERRIDE(data, size)
#else
/**
* This function dump raw data.
*
* @param data raw data
* @param size raw data size
**/
void libspdm_internal_dump_hex_str(const uint8_t *data, size_t size);
#define LIBSPDM_INTERNAL_DUMP_HEX_STR(data, size) libspdm_internal_dump_hex_str(data, size)
#endif /* LIBSPDM_INTERNAL_DUMP_HEX_STR_OVERRIDE */
#ifdef LIBSPDM_INTERNAL_DUMP_DATA_OVERRIDE
extern void LIBSPDM_INTERNAL_DUMP_DATA_OVERRIDE(const uint8_t *data, size_t size);
#define LIBSPDM_INTERNAL_DUMP_DATA(data, size) LIBSPDM_INTERNAL_DUMP_DATA_OVERRIDE(data, size)
#else
/**
* This function dump raw data.
*
* @param data raw data
* @param size raw data size
**/
void libspdm_internal_dump_data(const uint8_t *data, size_t size);
#define LIBSPDM_INTERNAL_DUMP_DATA(data, size) libspdm_internal_dump_data(data, size)
#endif /* LIBSPDM_INTERNAL_DUMP_DATA_OVERRIDE */
#ifdef LIBSPDM_INTERNAL_DUMP_HEX_OVERRIDE
extern void LIBSPDM_INTERNAL_DUMP_HEX_OVERRIDE(const uint8_t *data, size_t size);
#define LIBSPDM_INTERNAL_DUMP_HEX(data, size) LIBSPDM_INTERNAL_DUMP_HEX_OVERRIDE(data, size)
#else
/**
* This function dump raw data with column format.
*
* @param data raw data
* @param size raw data size
**/
void libspdm_internal_dump_hex(const uint8_t *data, size_t size);
#define LIBSPDM_INTERNAL_DUMP_HEX(data, size) libspdm_internal_dump_hex(data, size)
#endif /* LIBSPDM_INTERNAL_DUMP_HEX_OVERRIDE */
#else /* LIBSPDM_DEBUG_PRINT_ENABLE */
#define LIBSPDM_INTERNAL_DUMP_HEX(data, size)
#define LIBSPDM_INTERNAL_DUMP_HEX_STR(data, size)
#define LIBSPDM_INTERNAL_DUMP_DATA(data, size)
#endif /* LIBSPDM_DEBUG_PRINT_ENABLE */
/* Required scratch buffer size for libspdm internal usage.
* It may be used to hold the encrypted/decrypted message and/or last sent/received message.
* It may be used to hold the large request/response and intermediate send/receive buffer
* in case of chunking.
*
* If chunking is not supported, it should be at least below.
* +--------------------------+-----------------+-----------------+
* | SENDER_RECEIVER |MAX_SPDM_MSG_SIZE|MAX_SPDM_MSG_SIZE|
* +--------------------------+-----------------+-----------------+
* |<-Snd/Rcv buf for chunk ->|<-last request ->|<-cache request->|
*
*
* If chunking is supported, it should be at least below.
* +---------------+--------------+--------------------------+------------------------------+-----------------+-----------------+
* |SECURE_MESSAGE |LARGE_MESSAGE | SENDER_RECEIVER | LARGE SENDER_RECEIVER |MAX_SPDM_MSG_SIZE|MAX_SPDM_MSG_SIZE|
* +---------------+--------------+--------------------------+------------------------------+-----------------+-----------------+
* |<-Secure msg ->|<-Large msg ->|<-Snd/Rcv buf for chunk ->|<-Snd/Rcv buf for large msg ->|<-last request ->|<-cache request->|
*
*
* The value is configurable based on max_spdm_msg_size.
* The value MAY be changed in different libspdm version.
* It is exposed here, just in case the libspdm consumer wants to configure the setting at build time.
*/
#if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
/* first section */
uint32_t libspdm_get_scratch_buffer_secure_message_offset(libspdm_context_t *spdm_context);
uint32_t libspdm_get_scratch_buffer_secure_message_capacity(libspdm_context_t *spdm_context);
/* second section */
uint32_t libspdm_get_scratch_buffer_large_message_offset(libspdm_context_t *spdm_context);
uint32_t libspdm_get_scratch_buffer_large_message_capacity(libspdm_context_t *spdm_context);
#endif
/* third section */
uint32_t libspdm_get_scratch_buffer_sender_receiver_offset(libspdm_context_t *spdm_context);
uint32_t libspdm_get_scratch_buffer_sender_receiver_capacity(libspdm_context_t *spdm_context);
#if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
/* fourth section */
uint32_t libspdm_get_scratch_buffer_large_sender_receiver_offset(libspdm_context_t *spdm_context);
uint32_t libspdm_get_scratch_buffer_large_sender_receiver_capacity(libspdm_context_t *spdm_context);
#endif
/* fifth section */
uint32_t libspdm_get_scratch_buffer_last_spdm_request_offset(libspdm_context_t *spdm_context);
uint32_t libspdm_get_scratch_buffer_last_spdm_request_capacity(libspdm_context_t *spdm_context);
#if LIBSPDM_RESPOND_IF_READY_SUPPORT
/* sixth section */
uint32_t libspdm_get_scratch_buffer_cache_spdm_request_offset(libspdm_context_t *spdm_context);
uint32_t libspdm_get_scratch_buffer_cache_spdm_request_capacity(libspdm_context_t *spdm_context);
#endif
/* combination */
uint32_t libspdm_get_scratch_buffer_capacity(libspdm_context_t *spdm_context);
/**
* Append a new data buffer to the managed buffer.
*
* @param managed_buffer The managed buffer to be appended.
* @param buffer The address of the data buffer to be appended to the managed buffer.
* @param buffer_size The size in bytes of the data buffer to be appended to the managed buffer.
*
* @retval RETURN_SUCCESS The new data buffer is appended to the managed buffer.
* @retval RETURN_BUFFER_TOO_SMALL The managed buffer is too small to be appended.
**/
libspdm_return_t libspdm_append_managed_buffer(void *managed_buffer,
const void *buffer, size_t buffer_size);
/**
* Reset the managed buffer.
* The buffer_size is reset to 0.
* The max_buffer_size is unchanged.
* The buffer is not freed.
*
* @param managed_buffer The managed buffer.
**/
void libspdm_reset_managed_buffer(void *managed_buffer);
/**
* Return the size of managed buffer.
*
* @param managed_buffer The managed buffer.
*
* @return the size of managed buffer.
**/
size_t libspdm_get_managed_buffer_size(void *managed_buffer);
/**
* Return the address of managed buffer.
*
* @param managed_buffer The managed buffer.
*
* @return the address of managed buffer.
**/
void *libspdm_get_managed_buffer(void *managed_buffer);
/**
* Init the managed buffer.
*
* @param managed_buffer The managed buffer.
* @param max_buffer_size The maximum size in bytes of the managed buffer.
**/
void libspdm_init_managed_buffer(void *managed_buffer, size_t max_buffer_size);
/**
* Reset message buffer in SPDM context according to request code.
*
* @param spdm_context A pointer to the SPDM context.
* @param spdm_session_info A pointer to the SPDM session context.
* @param spdm_request The SPDM request code.
*/
void libspdm_reset_message_buffer_via_request_code(void *context, void *session_info,
uint8_t request_code);
/**
* This function initializes the session info.
*
* @param spdm_context A pointer to the SPDM context.
* @param session_id The SPDM session ID.
**/
void libspdm_session_info_init(libspdm_context_t *spdm_context,
libspdm_session_info_t *session_info,
uint32_t session_id, spdm_version_number_t secured_message_version,
bool use_psk);
#if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
/**
* Set the psk_hint to a session info.
*
* @param session_info A pointer to a session info.
* @param psk_hint Indicate the PSK hint.
* @param psk_hint_size The size in bytes of the PSK hint.
*/
void libspdm_session_info_set_psk_hint(libspdm_session_info_t *session_info,
const void *psk_hint,
size_t psk_hint_size);
#endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */
/**
* This function returns if a given version is supported based upon the GET_VERSION/VERSION.
*
* @param spdm_context A pointer to the SPDM context.
* @param version The SPDM version.
*
* @retval true the version is supported.
* @retval false the version is not supported.
**/
bool libspdm_is_version_supported(const libspdm_context_t *spdm_context, uint8_t version);
/**
* This function returns connection version negotiated by GET_VERSION/VERSION.
*
* @param spdm_context A pointer to the SPDM context.
*
* @return the connection version.
**/
uint8_t libspdm_get_connection_version(const libspdm_context_t *spdm_context);
/**
* This function returns if a capabilities flag is supported in current SPDM connection.
*
* @param spdm_context A pointer to the SPDM context.
* @param is_requester Is the function called from a requester.
* @param requester_capabilities_flag The requester capabilities flag to be checked
* @param responder_capabilities_flag The responder capabilities flag to be checked
*
* @retval true the capabilities flag is supported.
* @retval false the capabilities flag is not supported.
**/
bool libspdm_is_capabilities_flag_supported(const libspdm_context_t *spdm_context,
bool is_requester,
uint32_t requester_capabilities_flag,
uint32_t responder_capabilities_flag);
/**
* This function returns if a capabilities extended flag is supported in current SPDM connection.
*
* @param spdm_context A pointer to the SPDM context.
* @param is_requester Is the function called from a requester.
* @param requester_capabilities_ext_flag The requester capabilities extended flag to be checked
* @param responder_capabilities_ext_flag The responder capabilities extended flag to be checked
*
* @retval true the capabilities extended flag is supported.
* @retval false the capabilities extended flag is not supported.
**/
bool libspdm_is_capabilities_ext_flag_supported(const libspdm_context_t *spdm_context,
bool is_requester,
uint16_t requester_capabilities_ext_flag,
uint16_t responder_capabilities_ext_flag);
/**
* Checks the negotiated SPDM version and endpoint capabilities to determine if encapsulated
* messages are supported or not.
*
* @param spdm_context A pointer to the SPDM context.
*
* @retval true Both endpoints support encapsulated messages.
* @retval false At least one endpoint does not support encapsulated messages.
**/
bool libspdm_is_encap_supported(const libspdm_context_t *spdm_context);
/**
* This function generates the certificate chain hash.
*
* @param spdm_context A pointer to the SPDM context.
* @param slot_id The slot index of the certificate chain.
* @param signature The buffer to store the certificate chain hash.
*
* @retval true certificate chain hash is generated.
* @retval false certificate chain hash is not generated.
**/
bool libspdm_generate_cert_chain_hash(libspdm_context_t *spdm_context,
size_t slot_id, uint8_t *hash);
/**
* This function generates the public key hash.
*
* @param spdm_context A pointer to the SPDM context.
* @param hash The buffer to store the public key hash.
*
* @retval true public key hash is generated.
* @retval false public key hash is not generated.
**/
bool libspdm_generate_public_key_hash(libspdm_context_t *spdm_context,
uint8_t *hash);
/**
* This function verifies the integrity of peer certificate chain buffer including
* spdm_cert_chain_t header.
*
* @param spdm_context A pointer to the SPDM context.
* @param cert_chain_buffer Certificate chain buffer including spdm_cert_chain_t header.
* @param cert_chain_buffer_size size in bytes of the certificate chain buffer.
*
* @retval true Peer certificate chain buffer integrity verification passed.
* @retval false Peer certificate chain buffer integrity verification failed.
**/
bool libspdm_verify_peer_cert_chain_buffer_integrity(libspdm_context_t *spdm_context,
const void *cert_chain_buffer,
size_t cert_chain_buffer_size);
/**
* This function verifies peer certificate chain authority.