Skip to content

Commit 2962233

Browse files
committed
Sync Set_certificate to 1.3 for erase cert feature
Fix the issue: #2292 Only add the erase new 1.3 feature for set_certificate. Signed-off-by: Wenxing Hou <[email protected]>
1 parent 052bc7b commit 2962233

File tree

7 files changed

+192
-56
lines changed

7 files changed

+192
-56
lines changed

include/hal/library/responder/setcertlib.h

+11
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ extern bool libspdm_write_certificate_to_nvm(uint8_t slot_id, const void * cert_
3838
size_t cert_chain_size,
3939
uint32_t base_hash_algo, uint32_t base_asym_algo);
4040

41+
/**
42+
* Erase a certificate chain in non-volatile memory.
43+
*
44+
*
45+
* @param[in] slot_id The number of slot for the certificate chain.
46+
*
47+
* @retval true The certificate chain was successfully erased to non-volatile memory.
48+
* @retval false Unable to erase certificate chain to non-volatile memory.
49+
**/
50+
extern bool libspdm_erase_nvm_certificate(uint8_t slot_id);
51+
4152
#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP */
4253

4354
#endif /* RESPONDER_SETCERTLIB_H */

include/industry_standard/spdm.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,9 @@ typedef struct {
439439
uint16_t length;
440440
} spdm_get_certificate_request_t;
441441

442-
#define SPDM_GET_CERTIFICATE_REQUEST_SLOT_ID_MASK 0xF
442+
#define SPDM_GET_CERTIFICATE_REQUEST_SLOT_ID_MASK 0xF
443+
#define SPDM_SET_CERTIFICATE_REQUEST_SETCERTMODEL_MASK 0x70
444+
#define SPDM_SET_CERTIFICATE_REQUEST_ERASE_MASK 0x80
443445

444446
/* SPDM GET_CERTIFICATE response */
445447
typedef struct {
@@ -669,6 +671,9 @@ typedef struct {
669671
#define SPDM_ERROR_CODE_LARGE_RESPONSE 0x0F
670672
#define SPDM_ERROR_CODE_MESSAGE_LOST 0x10
671673

674+
/* SPDM error code (1.3) */
675+
#define SPDM_ERROR_CODE_OPERATION_FAILED 0x44
676+
672677
/* SPDM ResponseNotReady extended data */
673678
typedef struct {
674679
uint8_t rd_exponent;
@@ -959,6 +964,9 @@ typedef struct {
959964
spdm_message_header_t header;
960965
/* param1 == BIT[0:3]=slot_id, BIT[4:7]=RSVD
961966
* param2 == RSVD
967+
* param1 and param2 are updated in 1.3
968+
* param1 == Request attributes, BIT[0:3]=slot_id, BIT[4:6]=SetCertModel, BIT[7]=Erase
969+
* param2 == KeyPairID
962970
* void * cert_chain*/
963971
} spdm_set_certificate_request_t;
964972

include/library/spdm_requester_lib.h

+16
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,22 @@ 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 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+
*
718+
* @retval RETURN_SUCCESS The erase certificate measurement is got successfully.
719+
* @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
720+
* @retval RETURN_SECURITY_VIOLATION Any verification fails.
721+
**/
722+
libspdm_return_t libspdm_set_certificate_erase(void *spdm_context,
723+
const uint32_t *session_id, uint8_t slot_id);
708724
#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP */
709725

710726
#if LIBSPDM_ENABLE_MSG_LOG

library/spdm_requester_lib/libspdm_req_set_certificate.c

+49-7
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@
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 erase_cert If ture, erase the slot_id cert chain.
2223
*
2324
* @retval RETURN_SUCCESS The measurement is got successfully.
2425
* @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
2526
* @retval RETURN_SECURITY_VIOLATION Any verification fails.
2627
**/
2728
static libspdm_return_t libspdm_try_set_certificate(libspdm_context_t *spdm_context,
2829
const uint32_t *session_id, uint8_t slot_id,
29-
void *cert_chain, size_t cert_chain_size)
30+
void *cert_chain, size_t cert_chain_size,
31+
bool erase_cert)
3032
{
3133
libspdm_return_t status;
3234
spdm_set_certificate_request_t *spdm_request;
@@ -48,8 +50,10 @@ static libspdm_return_t libspdm_try_set_certificate(libspdm_context_t *spdm_cont
4850

4951
LIBSPDM_ASSERT(slot_id < SPDM_MAX_SLOT_COUNT);
5052

51-
if ((cert_chain == NULL) || (cert_chain_size == 0)) {
52-
return LIBSPDM_STATUS_INVALID_PARAMETER;
53+
if (libspdm_get_connection_version (spdm_context) < SPDM_MESSAGE_VERSION_13) {
54+
if ((cert_chain == NULL) || (cert_chain_size == 0)) {
55+
return LIBSPDM_STATUS_INVALID_PARAMETER;
56+
}
5357
}
5458

5559
if (spdm_context->connection_info.connection_state <
@@ -87,11 +91,24 @@ static libspdm_return_t libspdm_try_set_certificate(libspdm_context_t *spdm_cont
8791
spdm_request->header.param1 = slot_id;
8892
spdm_request->header.param2 = 0;
8993

94+
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
95+
if (erase_cert) {
96+
/*the CertChain field shall be absent*/
97+
cert_chain_size = 0;
98+
/*the value of SetCertModel shall be zero*/
99+
spdm_request->header.param1 &= ~SPDM_SET_CERTIFICATE_REQUEST_SETCERTMODEL_MASK;
100+
/*set Erase bit */
101+
spdm_request->header.param1 |= SPDM_SET_CERTIFICATE_REQUEST_ERASE_MASK;
102+
}
103+
}
104+
90105
LIBSPDM_ASSERT(spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12);
91106

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);
107+
if (libspdm_get_connection_version (spdm_context) < SPDM_MESSAGE_VERSION_13) {
108+
libspdm_copy_mem(spdm_request + 1,
109+
spdm_request_size - sizeof(spdm_set_certificate_request_t),
110+
(uint8_t *)cert_chain, cert_chain_size);
111+
}
95112

96113
spdm_request_size = sizeof(spdm_set_certificate_request_t) + cert_chain_size;
97114

@@ -171,7 +188,32 @@ libspdm_return_t libspdm_set_certificate(void *spdm_context,
171188
retry_delay_time = context->retry_delay_time;
172189
do {
173190
status = libspdm_try_set_certificate(context, session_id, slot_id,
174-
cert_chain, cert_chain_size);
191+
cert_chain, cert_chain_size, false);
192+
if ((status != LIBSPDM_STATUS_BUSY_PEER) || (retry == 0)) {
193+
return status;
194+
}
195+
196+
libspdm_sleep(retry_delay_time);
197+
} while (retry-- != 0);
198+
199+
return status;
200+
}
201+
202+
libspdm_return_t libspdm_set_certificate_erase(void *spdm_context,
203+
const uint32_t *session_id, uint8_t slot_id)
204+
{
205+
libspdm_context_t *context;
206+
size_t retry;
207+
uint64_t retry_delay_time;
208+
libspdm_return_t status;
209+
210+
context = spdm_context;
211+
context->crypto_request = true;
212+
retry = context->retry_times;
213+
retry_delay_time = context->retry_delay_time;
214+
do {
215+
status = libspdm_try_set_certificate(context, session_id, slot_id,
216+
NULL, 0, true);
175217
if ((status != LIBSPDM_STATUS_BUSY_PEER) || (retry == 0)) {
176218
return status;
177219
}

library/spdm_responder_lib/libspdm_rsp_set_certificate.c

+68-48
Original file line numberDiff line numberDiff line change
@@ -147,63 +147,83 @@ 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_ERASE_MASK) != 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 & SPDM_SET_CERTIFICATE_REQUEST_SETCERTMODEL_MASK) != 0)) {
155+
return libspdm_generate_error_response(spdm_context,
156+
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
157+
response_size, response);
158+
}
156159

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

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-
}
175+
/*point to full SPDM certificate chain*/
176+
cert_chain = (const void*)(spdm_request + 1);
177+
cert_chain_header = cert_chain;
171178

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

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);
190+
/*get actual cert_chain size*/
191+
cert_chain_size = cert_chain_header->length - sizeof(spdm_cert_chain_t) -
192+
root_cert_hash_size;
178193

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-
}
194+
/*point to actual cert_chain*/
195+
cert_chain = (const void*)((const uint8_t *)cert_chain
196+
+ sizeof(spdm_cert_chain_t) + root_cert_hash_size);
197+
198+
is_device_cert_model = false;
199+
if((spdm_context->local_context.capability.flags &
200+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ALIAS_CERT_CAP) == 0) {
201+
is_device_cert_model = true;
202+
}
184203

185204
#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-
}
205+
/*check the cert_chain*/
206+
result = libspdm_set_cert_verify_certchain(cert_chain, cert_chain_size,
207+
spdm_context->connection_info.algorithm.base_asym_algo,
208+
spdm_context->connection_info.algorithm.base_hash_algo,
209+
is_device_cert_model);
210+
if (!result) {
211+
return libspdm_generate_error_response(spdm_context,
212+
SPDM_ERROR_CODE_UNSPECIFIED, 0,
213+
response_size, response);
214+
}
196215
#endif /*LIBSPDM_CERT_PARSE_SUPPORT*/
197216

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);
217+
/* set certificate to NV*/
218+
result = libspdm_write_certificate_to_nvm(slot_id, cert_chain,
219+
cert_chain_size,
220+
spdm_context->connection_info.algorithm.base_hash_algo,
221+
spdm_context->connection_info.algorithm.base_asym_algo);
222+
if (!result) {
223+
return libspdm_generate_error_response(spdm_context,
224+
SPDM_ERROR_CODE_UNSPECIFIED, 0,
225+
response_size, response);
226+
}
207227
}
208228

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

os_stub/spdm_device_secret_lib_null/lib.c

+6
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ bool libspdm_write_certificate_to_nvm(uint8_t slot_id, const void * cert_chain,
139139
{
140140
return false;
141141
}
142+
143+
bool libspdm_erase_nvm_certificate(uint8_t slot_id)
144+
{
145+
return false;
146+
}
147+
142148
#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP */
143149

144150
#if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP

os_stub/spdm_device_secret_lib_sample/lib.c

+33
Original file line numberDiff line numberDiff line change
@@ -1725,4 +1725,37 @@ bool libspdm_write_certificate_to_nvm(uint8_t slot_id, const void * cert_chain,
17251725

17261726
return true;
17271727
}
1728+
1729+
bool libspdm_erase_nvm_certificate(uint8_t slot_id)
1730+
{
1731+
#if defined(_WIN32) || (defined(__clang__) && (defined (LIBSPDM_CPU_AARCH64) || \
1732+
defined(LIBSPDM_CPU_ARM)))
1733+
FILE *fp_out;
1734+
#else
1735+
int64_t fp_out;
1736+
#endif
1737+
1738+
char file_name[] = "slot_id_0_cert_chain.der";
1739+
/*change the file name, for example: slot_id_1_cert_chain.der*/
1740+
file_name[8] = (char)(slot_id+'0');
1741+
1742+
#if defined(_WIN32) || (defined(__clang__) && (defined (LIBSPDM_CPU_AARCH64) || \
1743+
defined(LIBSPDM_CPU_ARM)))
1744+
if ((fp_out = fopen(file_name, "w+b")) == NULL) {
1745+
printf("Unable to open file %s\n", file_name);
1746+
return false;
1747+
}
1748+
1749+
fclose(fp_out);
1750+
#else
1751+
if ((fp_out = open(file_name, O_WRONLY | O_TRUNC)) == -1) {
1752+
printf("Unable to open file %s\n", file_name);
1753+
return false;
1754+
}
1755+
1756+
close(fp_out);
1757+
#endif
1758+
1759+
return true;
1760+
}
17281761
#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP */

0 commit comments

Comments
 (0)