diff --git a/include/hal/library/responder/csrlib.h b/include/hal/library/responder/csrlib.h index 67b33dcc7bc..c9b7afc660d 100644 --- a/include/hal/library/responder/csrlib.h +++ b/include/hal/library/responder/csrlib.h @@ -14,37 +14,36 @@ #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP /** - * Gen CSR - * - * @param[in] spdm_context A pointer to the SPDM context. - * - * @param[in] base_hash_algo Indicates the hash algorithm. - * @param[in] base_asym_algo Indicates the signing algorithm. - * @param[in, out] need_reset For input, it gives the value of CERT_INSTALL_RESET_CAP: - * If true, then device needs to be reset to complete the CSR. - * If false, the device doesn`t need to be reset to complete the CSR. - * For output, it specifies whether the device needs to be reset to complete the CSR or not. - * - * @param[in] request A pointer to the SPDM request data. - * @param[in] request_size The size of SPDM request data. - * - * @param[in] requester_info Requester info to generate the CSR. - * @param[in] requester_info_length The length of requester info. - * - * @param[in] opaque_data opaque data to generate the CSR. - * @param[in] opaque_data_length The length of opaque data. - * - * @param[in, out] csr_len For input, csr_len is the size of store CSR buffer. - * For output, csr_len is CSR len for DER format - * @param[in, out] csr_pointer On input, csr_pointer is buffer address to store CSR. - * On output, csr_pointer is address for stored CSR. - * The csr_pointer address will be changed. - * - * @param[in] is_device_cert_model If true, the cert chain is DeviceCert model. - * If false, the cert chain is AliasCert model. - * - * @retval true Success. - * @retval false Failed to gen CSR. + * Generate a PKCS #10 certificate signing request. + * + * @param[in] spdm_context A pointer to the SPDM context. + * @param[in] base_hash_algo Indicates the hash algorithm. + * @param[in] base_asym_algo Indicates the signing algorithm. + * @param[in,out] need_reset On input, indicates the value of CERT_INSTALL_RESET_CAP. + * On output, indicates whether the device needs to be reset (true) + * for the GET_CSR operation to complete. + * @param[in] request A pointer to the SPDM request data. + * @param[in] request_size The size of SPDM request data. + * @param[in] requester_info Requester info used to generate the CSR. + * @param[in] requester_info_length The length, in bytes, of requester_info. + * @param[in] opaque_data Requester opaque data used to generate the CSR. + * @param[in] opaque_data_length The length, in bytes, of opaque_data. + * @param[in,out] csr_len On input, the size, in bytes, of the buffer to store the + * CSR. + * On output, the size, in bytes, of the CSR. + * @param[in,out] csr_pointer A pointer to the buffer to store the CSR. + * @param[in] is_device_cert_model If true, the certificate chain is the DeviceCert model. + * If false, the certificate chain is the AliasCert model. + * @param[out] is_busy If true, indicates that the CSR cannot be generated at + * this time, but it may be successful in a later call. The + * function's return value must be false if this parameter is + * true. + * @param[out] unexpected_request If true, then request is different than the request that + * triggered a ResetRequired error response. The function's + * return value must be false if this parameter is true. + * + * @retval true CSR generated successfully. + * @retval false Failed to generate CSR. **/ extern bool libspdm_gen_csr( #if LIBSPDM_HAL_PASS_SPDM_CONTEXT @@ -55,57 +54,60 @@ extern bool libspdm_gen_csr( uint8_t *requester_info, size_t requester_info_length, uint8_t *opaque_data, uint16_t opaque_data_length, size_t *csr_len, uint8_t *csr_pointer, - bool is_device_cert_model); + bool is_device_cert_model +#if LIBSPDM_SET_CERT_CSR_PARAMS + , bool *is_busy, bool *unexpected_request +#endif + ); /** - * Gen CSR, which is used for SPDM 1.3 - * - * If the device need reset to gen csr, the all case is in the table. - * | Overwrite | Req CSRTrackingTag | Pending CSR | Reset | Res Action | - * |-----------|---------------------|-------------|-------|------------------------------| - * | No | 0 | No | - | ResetRequired | - * | No | 0 | Yes | - | ResetRequired or Busy | - * | No | Non-0 | No Match | - | Unexpected | - * | No | Non-0 | Match | Before| Busy | - * | No | Non-0 | Match | After | CSR | - * | Yes | 0 | No | - | ResetRequired | - * | Yes | 0 | Yes | - | ResetRequired | - * | Yes | Non-0 | - | - | Invalid | - * - * @param[in] spdm_context A pointer to the SPDM context. - * - * @param[in] base_hash_algo Indicates the hash algorithm. - * @param[in] base_asym_algo Indicates the signing algorithm. - * @param[in, out] need_reset For input, it gives the value of CERT_INSTALL_RESET_CAP: - * If true, then device needs to be reset to complete the CSR. - * If false, the device doesn`t need to be reset to complete the CSR. - * For output, it specifies whether the device needs to be reset to complete the CSR or not. - * - * @param[in] request A pointer to the SPDM request data. - * @param[in] request_size The size of SPDM request data. - * - * @param[in] requester_info Requester info to generate the CSR. - * @param[in] requester_info_length The length of requester info. - * - * @param[in] opaque_data opaque data to generate the CSR. - * @param[in] opaque_data_length The length of opaque data. - * - * @param[in, out] csr_len For input, csr_len is the size of store CSR buffer. - * For output, csr_len is CSR len for DER format - * @param[in, out] csr_pointer On input, csr_pointer is buffer address to store CSR. - * On output, csr_pointer is address for stored CSR. - * The csr_pointer address will be changed. - * - * @param[in] req_cert_model indicates the desired certificate model of the CSR - * - * @param[in, out] req_csr_tracking_tag For input, this field shall contain the CSRTrackingTag of the associated GET_CSR request. - * For output, this field indicate responder available csr_tracking_tag. - * @param[in] req_key_pair_id Indicates the desired key pair associated with the CSR. - * @param[in] overwrite If set, the Responder shall stop processing any existing GET_CSR request and - * overwrite it with this request - * - * @retval true Success. - * @retval false Failed to gen CSR. + * Generate a PKCS #10 certificate signing request for SPDM versions 1.3 and higher. + * + * Table for parameters and results when device requires a reset to process CSRs. + * Only valid if Responder sets CERT_INSTALL_RESET_CAP. + * + * | Overwrite | CSRTrackingTag | Pending CSR | Reset | Resulting Action | + * |-----------| ---------------|-------------|-------|------------------------------| + * | No | 0 | No | - | Return true | + * | No | 0 | Yes | - | Assert need_reset or is_busy | + * | No | Non-0 | No Match | - | Assert unexpected_request | + * | No | Non-0 | Match | Before| Assert is_busy | + * | No | Non-0 | Match | After | Return true | + * | Yes | 0 | - | - | Assert need_reset | + * + * @param[in] spdm_context A pointer to the SPDM context. + * @param[in] base_hash_algo Indicates the hash algorithm. + * @param[in] base_asym_algo Indicates the signing algorithm. + * @param[in,out] need_reset On input, indicates the value of CERT_INSTALL_RESET_CAP. + * On output, indicates whether the device needs to be reset (true) + * for the GET_CSR operation to complete. If true then + * req_csr_tracking_tag, on output, must be non-zero. + * @param[in] request A pointer to the SPDM request data. + * @param[in] request_size The size of SPDM request data. + * @param[in] requester_info Requester info used to generate the CSR. + * @param[in] requester_info_length The length, in bytes, of requester_info. + * @param[in] opaque_data Requester opaque data used to generate the CSR. + * @param[in] opaque_data_length The length, in bytes, of opaque_data. + * @param[in,out] csr_len On input, the size, in bytes, of the buffer to store the + * CSR. + * On output, the size, in bytes, of the CSR. + * @param[in,out] csr_pointer A pointer to the buffer to store the CSR. + * @param[in] req_cert_model Indicates the desired certificate model of the CSR. + * @param[in,out] req_csr_tracking_tag On input, the CSRTrackingTag of the GET_CSR request. + * On output, the CSRTrackingTag for the ResetRequired error. + * @param[in] req_key_pair_id Indicates the desired key pair associated with the CSR. + * @param[in] overwrite If set, the Responder shall stop processing any existing + * GET_CSR request and overwrite it with this request. + * @param[out] is_busy If true, indicates that the CSR cannot be generated at + * this time, but it may be successful in a later call. The + * function's return value must be false if this parameter is + * true. + * @param[out] unexpected_request If true, then request is different than the request that + * triggered a ResetRequired error response. The function's + * return value must be false if this parameter is true. + * + * @retval true CSR generated successfully. + * @retval false Failed to generate CSR. **/ #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX @@ -121,7 +123,11 @@ extern bool libspdm_gen_csr_ex( uint8_t req_cert_model, uint8_t *req_csr_tracking_tag, uint8_t req_key_pair_id, - bool overwrite); + bool overwrite +#if LIBSPDM_SET_CERT_CSR_PARAMS + , bool *is_busy, bool *unexpected_request +#endif + ); #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX*/ #endif /* LIBSPDM_ENABLE_CAPABILITY_CSR_CAP */ diff --git a/library/spdm_responder_lib/libspdm_rsp_csr.c b/library/spdm_responder_lib/libspdm_rsp_csr.c index 42c6f9202ec..b26a891f7a9 100644 --- a/library/spdm_responder_lib/libspdm_rsp_csr.c +++ b/library/spdm_responder_lib/libspdm_rsp_csr.c @@ -27,6 +27,8 @@ libspdm_return_t libspdm_get_response_csr(libspdm_context_t *spdm_context, uint8_t *requester_info; bool need_reset; bool is_device_cert_model; + bool is_busy; + bool unexpected_request; uint8_t csr_tracking_tag; spdm_request = request; @@ -138,10 +140,6 @@ libspdm_return_t libspdm_get_response_csr(libspdm_context_t *spdm_context, } } - need_reset = libspdm_is_capabilities_flag_supported( - spdm_context, false, 0, - SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP); - result = libspdm_verify_req_info(requester_info, requester_info_length); if (!result) { return libspdm_generate_error_response( @@ -165,7 +163,14 @@ libspdm_return_t libspdm_get_response_csr(libspdm_context_t *spdm_context, csr_len = *response_size - sizeof(spdm_csr_response_t); csr_p = (uint8_t*)(spdm_response + 1); + need_reset = libspdm_is_capabilities_flag_supported( + spdm_context, false, 0, + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP); + + is_busy = false; + unexpected_request = false; csr_tracking_tag = 0; + if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) { #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX const bool overwrite = @@ -215,7 +220,11 @@ libspdm_return_t libspdm_get_response_csr(libspdm_context_t *spdm_context, requester_info, requester_info_length, opaque_data, opaque_data_length, &csr_len, csr_p, req_cert_model, - &csr_tracking_tag, key_pair_id, overwrite); + &csr_tracking_tag, key_pair_id, overwrite +#if LIBSPDM_SET_CERT_CSR_PARAMS + , &is_busy, &unexpected_request +#endif + ); #else return libspdm_generate_error_response( spdm_context, @@ -232,16 +241,27 @@ libspdm_return_t libspdm_get_response_csr(libspdm_context_t *spdm_context, &need_reset, request, request_size, requester_info, requester_info_length, opaque_data, opaque_data_length, - &csr_len, csr_p, is_device_cert_model); + &csr_len, csr_p, is_device_cert_model +#if LIBSPDM_SET_CERT_CSR_PARAMS + , &is_busy, &unexpected_request +#endif + ); } + LIBSPDM_ASSERT(!(is_busy && unexpected_request)); + LIBSPDM_ASSERT(!(is_busy || unexpected_request) || !result); + if (!result) { - if ((csr_tracking_tag == 0xFF) && - (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13)) { + if (is_busy) { return libspdm_generate_error_response( spdm_context, SPDM_ERROR_CODE_BUSY, 0, response_size, response); + } else if (unexpected_request) { + return libspdm_generate_error_response( + spdm_context, + SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0, + response_size, response); } else { return libspdm_generate_error_response( spdm_context, @@ -255,8 +275,7 @@ libspdm_return_t libspdm_get_response_csr(libspdm_context_t *spdm_context, if (libspdm_is_capabilities_flag_supported( spdm_context, false, 0, - SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP) && - need_reset) { + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP) && need_reset) { return libspdm_generate_error_response(spdm_context, SPDM_ERROR_CODE_RESET_REQUIRED, csr_tracking_tag, response_size, response); diff --git a/os_stub/spdm_device_secret_lib_null/lib.c b/os_stub/spdm_device_secret_lib_null/lib.c index 482d61a278c..44b23db5d0b 100644 --- a/os_stub/spdm_device_secret_lib_null/lib.c +++ b/os_stub/spdm_device_secret_lib_null/lib.c @@ -204,7 +204,11 @@ bool libspdm_gen_csr( uint8_t *requester_info, size_t requester_info_length, uint8_t *opaque_data, uint16_t opaque_data_length, size_t *csr_len, uint8_t *csr_pointer, - bool is_device_cert_model) + bool is_device_cert_model +#if LIBSPDM_SET_CERT_CSR_PARAMS + , bool *is_busy, bool *unexpected_request +#endif + ) { return false; } @@ -222,7 +226,11 @@ bool libspdm_gen_csr_ex( uint8_t req_cert_model, uint8_t *csr_tracking_tag, uint8_t req_key_pair_id, - bool overwrite) + bool overwrite +#if LIBSPDM_SET_CERT_CSR_PARAMS + , bool *is_busy, bool *unexpected_request +#endif + ) { return false; } diff --git a/os_stub/spdm_device_secret_lib_sample/csr.c b/os_stub/spdm_device_secret_lib_sample/csr.c index 392d72b028e..3514da1bbb7 100644 --- a/os_stub/spdm_device_secret_lib_sample/csr.c +++ b/os_stub/spdm_device_secret_lib_sample/csr.c @@ -213,7 +213,11 @@ bool libspdm_gen_csr( uint8_t *requester_info, size_t requester_info_length, uint8_t *opaque_data, uint16_t opaque_data_length, size_t *csr_len, uint8_t *csr_pointer, - bool is_device_cert_model) + bool is_device_cert_model +#if LIBSPDM_SET_CERT_CSR_PARAMS + , bool *is_busy, bool *unexpected_request +#endif + ) { bool result; uint8_t *cached_last_csr_request; @@ -293,7 +297,11 @@ bool libspdm_gen_csr_ex( uint8_t req_cert_model, uint8_t *req_csr_tracking_tag, uint8_t req_key_pair_id, - bool overwrite) + bool overwrite +#if LIBSPDM_SET_CERT_CSR_PARAMS + , bool *is_busy, bool *unexpected_request +#endif + ) { bool result; uint8_t *cached_last_csr_request; @@ -327,7 +335,9 @@ bool libspdm_gen_csr_ex( if (*req_csr_tracking_tag == 0) { if (available_csr_tracking_tag == 0) { /*no available tracking tag*/ - *req_csr_tracking_tag = 0xFF; + #if LIBSPDM_SET_CERT_CSR_PARAMS + *is_busy = true; + #endif return false; } else { flag = false; @@ -406,7 +416,9 @@ bool libspdm_gen_csr_ex( return true; } else { /*the device is busy*/ - *req_csr_tracking_tag = 0xFF; + #if LIBSPDM_SET_CERT_CSR_PARAMS + *is_busy = true; + #endif return false; } } diff --git a/unit_test/test_spdm_responder/csr.c b/unit_test/test_spdm_responder/csr.c index 4a6c73e6da4..91fa1de3a10 100644 --- a/unit_test/test_spdm_responder/csr.c +++ b/unit_test/test_spdm_responder/csr.c @@ -1628,10 +1628,10 @@ void libspdm_test_responder_csr_case14(void **state) assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); assert_int_equal(response_size, sizeof(spdm_error_response_t)); spdm_response = (void *)response; - assert_int_equal(spdm_response->header.request_response_code, - SPDM_ERROR); - assert_int_equal(spdm_response->header.param1, - SPDM_ERROR_CODE_BUSY); + assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR); + (LIBSPDM_SET_CERT_CSR_PARAMS) ? + assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_BUSY) : + assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_INVALID_REQUEST); assert_int_equal(spdm_response->header.param2, 0); #else assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); @@ -1793,10 +1793,10 @@ void libspdm_test_responder_csr_case15(void **state) assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); assert_int_equal(response_size, sizeof(spdm_error_response_t)); spdm_response = (void *)response; - assert_int_equal(spdm_response->header.request_response_code, - SPDM_ERROR); - assert_int_equal(spdm_response->header.param1, - SPDM_ERROR_CODE_BUSY); + assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR); + (LIBSPDM_SET_CERT_CSR_PARAMS) ? + assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_BUSY) : + assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_INVALID_REQUEST); assert_int_equal(spdm_response->header.param2, 0);