Skip to content

Commit 2c4ccff

Browse files
committed
Add 1.3 erase certificate feature for SET_CERTIFICATE
Fix the issue: #2292 Signed-off-by: Wenxing Hou <[email protected]>
1 parent 93cd9b2 commit 2c4ccff

File tree

8 files changed

+223
-73
lines changed

8 files changed

+223
-73
lines changed

include/hal/library/responder/setcertlib.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
extern bool libspdm_is_in_trusted_environment();
2323

2424
/**
25-
* Stores a certificate chain in non-volatile memory.
26-
*
25+
* Stores or erase a certificate chain in non-volatile memory.
26+
* If the cert_chain is NULL and cert_chain_size is 0,
27+
* the feature is to erase the certificate chain.
2728
*
2829
* @param[in] slot_id The number of slot for the certificate chain.
2930
* @param[in] cert_chain The pointer for the certificate chain to set.

include/industry_standard/spdm.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,9 @@ typedef struct {
747747
#define SPDM_ERROR_CODE_LARGE_RESPONSE 0x0F
748748
#define SPDM_ERROR_CODE_MESSAGE_LOST 0x10
749749

750+
/* SPDM error code (1.3) */
751+
#define SPDM_ERROR_CODE_OPERATION_FAILED 0x44
752+
750753
/* SPDM ResponseNotReady extended data */
751754
typedef struct {
752755
uint8_t rd_exponent;
@@ -1035,9 +1038,12 @@ typedef struct {
10351038
/* SPDM SET_CERTIFICATE request */
10361039
typedef struct {
10371040
spdm_message_header_t header;
1038-
/* param1 == BIT[0:3]=slot_id, Request Attribute in 1.3
1039-
* param2 == key_pair_id in 1.3
1040-
* uint8_t cert_chain[]; */
1041+
/* param1 == BIT[0:3]=slot_id, BIT[4:7]=RSVD
1042+
* param2 == RSVD
1043+
* param1 and param2 are updated in 1.3
1044+
* param1 == Request attributes, BIT[0:3]=slot_id, BIT[4:6]=SetCertModel, BIT[7]=Erase
1045+
* param2 == KeyPairID
1046+
* void * cert_chain*/
10411047
} spdm_set_certificate_request_t;
10421048

10431049
#define SPDM_SET_CERTIFICATE_REQUEST_SLOT_ID_MASK 0xF

include/internal/libspdm_responder_lib.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,20 @@ libspdm_return_t libspdm_get_response_csr(libspdm_context_t *spdm_context,
675675
/**
676676
* Process the SPDM SET_CERTIFICATE request and return the response.
677677
*
678+
* | Cert State in Slot | Req(KeyPairID,CertMode) | Req(Erase) | Res(KeyPairID,CertMode) | Action |
679+
* |-----------------------|-------------------------|------------|-----------------------------|--------------------------|
680+
* | Not exist | - | - | - | Invalid |
681+
* | exist and empty | Valid | No | Not exist | Provision |
682+
* | exist and empty | Valid | Yes | Not exist | Invalid |
683+
* | exist with key | Valid | No | KeyPairID/CertMode match | Provision |
684+
* | exist with key | Valid | Yes | KeyPairID/CertMode match | Invalid |
685+
* | exist with key | Valid | No | KeyPairID/CertMode not match| Invalid(or OverWrite) |
686+
* | exist with key | Valid | Yes | KeyPairID/CertMode not match| Invalid |
687+
* |exist with key and cert| Valid | No | KeyPairID/CertMode match | Invalid(or OverWrite) |
688+
* |exist with key and cert| Valid | Yes | KeyPairID/CertMode match | Erase Cert |
689+
* |exist with key and cert| Valid | No | KeyPairID/CertMode not match| Invalid |
690+
* |exist with key and cert| Valid | Yes | KeyPairID/CertMode not match| Invalid |
691+
*
678692
* @param spdm_context A pointer to the SPDM context.
679693
* @param request_size size in bytes of the request data.
680694
* @param request A pointer to the request data.

include/library/spdm_requester_lib.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,37 @@ libspdm_return_t libspdm_set_certificate(void *spdm_context,
705705
const uint32_t *session_id, uint8_t slot_id,
706706
void *cert_chain, size_t cert_chain_size);
707707

708+
/**
709+
* This function try to send SET_CERTIFICATE
710+
* to set certificate or erase certificate from the device.
711+
*
712+
* @param context A pointer to the SPDM context.
713+
* @param session_id Indicates if it is a secured message protected via SPDM session.
714+
* If session_id is NULL, it is a normal message.
715+
* If session_id is NOT NULL, it is a secured message.
716+
* @param slot_id The number of slot for the certificate chain.
717+
* @param cert_chain The pointer for the certificate chain to set.
718+
* The cert chain is a full SPDM certificate chain, including Length and Root Cert Hash.
719+
* For SPDM 1.2, the cert_chain must be non-NULL.
720+
* For SPDM 1.3 and above:
721+
* If the request_attribute Erase bit is set, the cert_chain must be NULL;
722+
* If the request_attribute Erase bit is not set, the cert_chain must be non-NULL.
723+
* @param cert_chain_size The size of the certificate chain to set.
724+
* For SPDM 1.2, the cert_chain_size must be non-zero.
725+
* For SPDM 1.3 and above:
726+
* If the request_attribute Erase bit is set, the cert_chain_size must be 0;
727+
* If the request_attribute Erase bit is not set, the cert_chain_size must be non-zero.
728+
* If the cert_chain is NULL, the cert_chain_size must be 0.
729+
* @param request_attribute Set certificate request attributes. This field is only used for SPDM 1.3 and above.
730+
* And the bit[0~3] of request_attribute must be 0.
731+
* @param key_pair_id The value of this field shall be the unique key pair number identifying the desired
732+
* asymmetric key pair to associate with SlotID .
733+
**/
734+
libspdm_return_t libspdm_set_certificate_ex(void *spdm_context,
735+
const uint32_t *session_id, uint8_t slot_id,
736+
void *cert_chain, size_t cert_chain_size,
737+
uint8_t request_attribute,
738+
uint8_t key_pair_id);
708739
#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP */
709740

710741
#if LIBSPDM_ENABLE_MSG_LOG

library/spdm_requester_lib/libspdm_req_set_certificate.c

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,20 @@
1919
* @param cert_chain The pointer for the certificate chain to set.
2020
* The cert chain is a full SPDM certificate chain, including Length and Root Cert Hash.
2121
* @param cert_chain_size The size of the certificate chain to set.
22+
* @param request_attribute Set certificate request attributes. This field is only used for SPDM 1.3 and above.
23+
* And the bit[0~3] of request_attribute must be 0.
24+
* @param key_pair_id The value of this field shall be the unique key pair number identifying the desired
25+
* asymmetric key pair to associate with SlotID .
2226
*
2327
* @retval RETURN_SUCCESS The measurement is got successfully.
2428
* @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
2529
* @retval RETURN_SECURITY_VIOLATION Any verification fails.
2630
**/
2731
static libspdm_return_t libspdm_try_set_certificate(libspdm_context_t *spdm_context,
2832
const uint32_t *session_id, uint8_t slot_id,
29-
void *cert_chain, size_t cert_chain_size)
33+
void *cert_chain, size_t cert_chain_size,
34+
uint8_t request_attribute,
35+
uint8_t key_pair_id)
3036
{
3137
libspdm_return_t status;
3238
spdm_set_certificate_request_t *spdm_request;
@@ -48,8 +54,10 @@ static libspdm_return_t libspdm_try_set_certificate(libspdm_context_t *spdm_cont
4854

4955
LIBSPDM_ASSERT(slot_id < SPDM_MAX_SLOT_COUNT);
5056

51-
if ((cert_chain == NULL) || (cert_chain_size == 0)) {
52-
return LIBSPDM_STATUS_INVALID_PARAMETER;
57+
if (libspdm_get_connection_version (spdm_context) < SPDM_MESSAGE_VERSION_13) {
58+
if ((cert_chain == NULL) || (cert_chain_size == 0)) {
59+
return LIBSPDM_STATUS_INVALID_PARAMETER;
60+
}
5361
}
5462

5563
if (spdm_context->connection_info.connection_state <
@@ -84,14 +92,37 @@ static libspdm_return_t libspdm_try_set_certificate(libspdm_context_t *spdm_cont
8492

8593
spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
8694
spdm_request->header.request_response_code = SPDM_SET_CERTIFICATE;
87-
spdm_request->header.param1 = slot_id;
95+
spdm_request->header.param1 = slot_id & SPDM_SET_CERTIFICATE_REQUEST_SLOT_ID_MASK;
8896
spdm_request->header.param2 = 0;
8997

98+
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
99+
/*And the bit[0~3] of request_attribute must be 0.*/
100+
if ((request_attribute & SPDM_SET_CERTIFICATE_REQUEST_SLOT_ID_MASK) != 0) {
101+
return LIBSPDM_STATUS_INVALID_PARAMETER;
102+
}
103+
104+
if ((request_attribute & SPDM_SET_CERTIFICATE_REQUEST_ATTRIBUTES_ERASE) != 0) {
105+
/*the CertChain field shall be absent*/
106+
cert_chain_size = 0;
107+
/*the value of SetCertModel shall be zero*/
108+
spdm_request->header.param1 &= ~SPDM_SET_CERTIFICATE_REQUEST_ATTRIBUTES_CERT_MODEL_MASK;
109+
/*set Erase bit */
110+
spdm_request->header.param1 |= SPDM_SET_CERTIFICATE_REQUEST_ATTRIBUTES_ERASE;
111+
}
112+
}
113+
90114
LIBSPDM_ASSERT(spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12);
91115

92-
libspdm_copy_mem(spdm_request + 1,
93-
spdm_request_size - sizeof(spdm_set_certificate_request_t),
94-
(uint8_t *)cert_chain, cert_chain_size);
116+
if ((libspdm_get_connection_version (spdm_context) < SPDM_MESSAGE_VERSION_13) ||
117+
(cert_chain_size != 0)) {
118+
if (cert_chain == NULL) {
119+
return LIBSPDM_STATUS_INVALID_PARAMETER;
120+
}
121+
122+
libspdm_copy_mem(spdm_request + 1,
123+
spdm_request_size - sizeof(spdm_set_certificate_request_t),
124+
(uint8_t *)cert_chain, cert_chain_size);
125+
}
95126

96127
spdm_request_size = sizeof(spdm_set_certificate_request_t) + cert_chain_size;
97128

@@ -171,7 +202,36 @@ libspdm_return_t libspdm_set_certificate(void *spdm_context,
171202
retry_delay_time = context->retry_delay_time;
172203
do {
173204
status = libspdm_try_set_certificate(context, session_id, slot_id,
174-
cert_chain, cert_chain_size);
205+
cert_chain, cert_chain_size, 0, 0);
206+
if ((status != LIBSPDM_STATUS_BUSY_PEER) || (retry == 0)) {
207+
return status;
208+
}
209+
210+
libspdm_sleep(retry_delay_time);
211+
} while (retry-- != 0);
212+
213+
return status;
214+
}
215+
216+
libspdm_return_t libspdm_set_certificate_ex(void *spdm_context,
217+
const uint32_t *session_id, uint8_t slot_id,
218+
void *cert_chain, size_t cert_chain_size,
219+
uint8_t request_attribute,
220+
uint8_t key_pair_id)
221+
{
222+
libspdm_context_t *context;
223+
size_t retry;
224+
uint64_t retry_delay_time;
225+
libspdm_return_t status;
226+
227+
context = spdm_context;
228+
context->crypto_request = true;
229+
retry = context->retry_times;
230+
retry_delay_time = context->retry_delay_time;
231+
do {
232+
status = libspdm_try_set_certificate(context, session_id, slot_id,
233+
cert_chain, cert_chain_size,
234+
request_attribute, key_pair_id);
175235
if ((status != LIBSPDM_STATUS_BUSY_PEER) || (retry == 0)) {
176236
return status;
177237
}

library/spdm_responder_lib/libspdm_rsp_set_certificate.c

Lines changed: 70 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ libspdm_return_t libspdm_get_response_set_certificate(libspdm_context_t *spdm_co
129129
SPDM_SET_CERTIFICATE, response_size, response);
130130
}
131131

132-
slot_id = spdm_request->header.param1 & SPDM_GET_CERTIFICATE_REQUEST_SLOT_ID_MASK;
132+
slot_id = spdm_request->header.param1 & SPDM_SET_CERTIFICATE_REQUEST_SLOT_ID_MASK;
133133
if (slot_id >= SPDM_MAX_SLOT_COUNT) {
134134
return libspdm_generate_error_response(spdm_context,
135135
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
@@ -147,63 +147,84 @@ libspdm_return_t libspdm_get_response_set_certificate(libspdm_context_t *spdm_co
147147
root_cert_hash_size = libspdm_get_hash_size(
148148
spdm_context->connection_info.algorithm.base_hash_algo);
149149

150-
if (request_size < sizeof(spdm_set_certificate_request_t) +
151-
sizeof(spdm_cert_chain_t) + root_cert_hash_size) {
152-
return libspdm_generate_error_response(spdm_context,
153-
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
154-
response_size, response);
155-
}
150+
if ((libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) &&
151+
((spdm_request->header.param1 & SPDM_SET_CERTIFICATE_REQUEST_ATTRIBUTES_ERASE) != 0)) {
152+
/*the CertChain field shall be absent;the value of SetCertModel shall be zero*/
153+
if ((request_size < sizeof(spdm_set_certificate_request_t)) ||
154+
((spdm_request->header.param1 &
155+
SPDM_SET_CERTIFICATE_REQUEST_ATTRIBUTES_CERT_MODEL_MASK) != 0)) {
156+
return libspdm_generate_error_response(spdm_context,
157+
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
158+
response_size, response);
159+
}
156160

157-
/*point to full SPDM certificate chain*/
158-
cert_chain = (const void*)(spdm_request + 1);
159-
cert_chain_header = cert_chain;
161+
/* erase slot_id cert_chain*/
162+
result = libspdm_write_certificate_to_nvm(slot_id, NULL, 0, 0, 0);
163+
if (!result) {
164+
return libspdm_generate_error_response(spdm_context,
165+
SPDM_ERROR_CODE_OPERATION_FAILED, 0,
166+
response_size, response);
167+
}
168+
} else {
169+
if (request_size < sizeof(spdm_set_certificate_request_t) +
170+
sizeof(spdm_cert_chain_t) + root_cert_hash_size) {
171+
return libspdm_generate_error_response(spdm_context,
172+
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
173+
response_size, response);
174+
}
160175

161-
if (cert_chain_header->length < sizeof(spdm_cert_chain_t) + root_cert_hash_size) {
162-
return libspdm_generate_error_response(spdm_context,
163-
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
164-
response_size, response);
165-
}
166-
if (cert_chain_header->length > request_size - sizeof(spdm_set_certificate_request_t)) {
167-
return libspdm_generate_error_response(spdm_context,
168-
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
169-
response_size, response);
170-
}
176+
/*point to full SPDM certificate chain*/
177+
cert_chain = (const void*)(spdm_request + 1);
178+
cert_chain_header = cert_chain;
171179

172-
/*get actual cert_chain size*/
173-
cert_chain_size = cert_chain_header->length - sizeof(spdm_cert_chain_t) - root_cert_hash_size;
180+
if (cert_chain_header->length < sizeof(spdm_cert_chain_t) + root_cert_hash_size) {
181+
return libspdm_generate_error_response(spdm_context,
182+
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
183+
response_size, response);
184+
}
185+
if (cert_chain_header->length > request_size - sizeof(spdm_set_certificate_request_t)) {
186+
return libspdm_generate_error_response(spdm_context,
187+
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
188+
response_size, response);
189+
}
174190

175-
/*point to actual cert_chain*/
176-
cert_chain = (const void*)((const uint8_t *)cert_chain
177-
+ sizeof(spdm_cert_chain_t) + root_cert_hash_size);
191+
/*get actual cert_chain size*/
192+
cert_chain_size = cert_chain_header->length - sizeof(spdm_cert_chain_t) -
193+
root_cert_hash_size;
178194

179-
is_device_cert_model = false;
180-
if((spdm_context->local_context.capability.flags &
181-
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ALIAS_CERT_CAP) == 0) {
182-
is_device_cert_model = true;
183-
}
195+
/*point to actual cert_chain*/
196+
cert_chain = (const void*)((const uint8_t *)cert_chain
197+
+ sizeof(spdm_cert_chain_t) + root_cert_hash_size);
198+
199+
is_device_cert_model = false;
200+
if((spdm_context->local_context.capability.flags &
201+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ALIAS_CERT_CAP) == 0) {
202+
is_device_cert_model = true;
203+
}
184204

185205
#if LIBSPDM_CERT_PARSE_SUPPORT
186-
/*check the cert_chain*/
187-
result = libspdm_set_cert_verify_certchain(cert_chain, cert_chain_size,
188-
spdm_context->connection_info.algorithm.base_asym_algo,
189-
spdm_context->connection_info.algorithm.base_hash_algo,
190-
is_device_cert_model);
191-
if (!result) {
192-
return libspdm_generate_error_response(spdm_context,
193-
SPDM_ERROR_CODE_UNSPECIFIED, 0,
194-
response_size, response);
195-
}
206+
/*check the cert_chain*/
207+
result = libspdm_set_cert_verify_certchain(cert_chain, cert_chain_size,
208+
spdm_context->connection_info.algorithm.base_asym_algo,
209+
spdm_context->connection_info.algorithm.base_hash_algo,
210+
is_device_cert_model);
211+
if (!result) {
212+
return libspdm_generate_error_response(spdm_context,
213+
SPDM_ERROR_CODE_UNSPECIFIED, 0,
214+
response_size, response);
215+
}
196216
#endif /*LIBSPDM_CERT_PARSE_SUPPORT*/
197217

198-
/* set certificate to NV*/
199-
result = libspdm_write_certificate_to_nvm(slot_id, cert_chain,
200-
cert_chain_size,
201-
spdm_context->connection_info.algorithm.base_hash_algo,
202-
spdm_context->connection_info.algorithm.base_asym_algo);
203-
if (!result) {
204-
return libspdm_generate_error_response(spdm_context,
205-
SPDM_ERROR_CODE_UNSPECIFIED, 0,
206-
response_size, response);
218+
/* set certificate to NV*/
219+
result = libspdm_write_certificate_to_nvm(slot_id, cert_chain,
220+
cert_chain_size,
221+
spdm_context->connection_info.algorithm.base_hash_algo,
222+
spdm_context->connection_info.algorithm.base_asym_algo);
223+
if (!result) {
224+
return libspdm_generate_error_response(spdm_context,
225+
SPDM_ERROR_CODE_UNSPECIFIED, 0,
226+
response_size, response);
227+
}
207228
}
208229

209230
LIBSPDM_ASSERT(*response_size >= sizeof(spdm_set_certificate_response_t));

os_stub/spdm_device_secret_lib_null/lib.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ bool libspdm_write_certificate_to_nvm(uint8_t slot_id, const void * cert_chain,
139139
{
140140
return false;
141141
}
142+
142143
#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP */
143144

144145
#if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP

0 commit comments

Comments
 (0)