diff --git a/include/hal/library/cryptlib/cryptlib_cert.h b/include/hal/library/cryptlib/cryptlib_cert.h index dbcd5ecce22..57fa372dd2e 100644 --- a/include/hal/library/cryptlib/cryptlib_cert.h +++ b/include/hal/library/cryptlib/cryptlib_cert.h @@ -80,6 +80,25 @@ extern bool libspdm_x509_get_serial_number(const uint8_t *cert, size_t cert_size uint8_t *serial_number, size_t *serial_number_size); +#if LIBSPDM_ADDITIONAL_CHECK_CERT +/** + * Retrieve the signature algorithm from one X.509 certificate. + * + * @param[in] cert Pointer to the DER-encoded X509 certificate. + * @param[in] cert_size Size of the X509 certificate in bytes. + * @param[out] oid Signature algorithm Object identifier buffer. + * @param[in,out] oid_size Signature algorithm Object identifier buffer size. + * + * @retval true if the oid_size is equal 0, the cert parse successfully, but cert doesn't have signature algo. + * @retval true if the oid_size is not equal 0, the cert parse and get signature algo successfully. + * @retval false if the oid_size is equal 0, the cert parse failed. + * @retval false if the oid_size is not equal 0, the cert parse and get signature algo successfully, but the input buffer size is small. + **/ +extern bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, + size_t cert_size, uint8_t *oid, + size_t *oid_size); +#endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */ + /** * Retrieve the issuer bytes from one X.509 certificate. * diff --git a/include/library/spdm_lib_config.h b/include/library/spdm_lib_config.h index d02f9208af2..d2f0e831e1e 100644 --- a/include/library/spdm_lib_config.h +++ b/include/library/spdm_lib_config.h @@ -410,4 +410,9 @@ #define LIBSPDM_HAL_PASS_SPDM_CONTEXT 0 #endif +/* Enable additional checks for cert. */ +#ifndef LIBSPDM_ADDITIONAL_CHECK_CERT +#define LIBSPDM_ADDITIONAL_CHECK_CERT 0 +#endif + #endif /* SPDM_LIB_CONFIG_H */ diff --git a/library/spdm_crypt_lib/libspdm_crypt_cert.c b/library/spdm_crypt_lib/libspdm_crypt_cert.c index c082d00b64d..2b0a5c6e8a8 100644 --- a/library/spdm_crypt_lib/libspdm_crypt_cert.c +++ b/library/spdm_crypt_lib/libspdm_crypt_cert.c @@ -1057,6 +1057,9 @@ bool libspdm_x509_common_certificate_check(const uint8_t *cert, size_t cert_size size_t cert_version; size_t value; void *context; +#if LIBSPDM_ADDITIONAL_CHECK_CERT + size_t signature_algo_oid_size; +#endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */ if (cert == NULL || cert_size == 0) { return false; @@ -1086,13 +1089,31 @@ bool libspdm_x509_common_certificate_check(const uint8_t *cert, size_t cert_size goto cleanup; } - /* 3. Verify public key algorithm. */ +#if LIBSPDM_ADDITIONAL_CHECK_CERT + /* 3. Verify signature algorithm. */ + signature_algo_oid_size = 0; + status = libspdm_x509_get_signature_algorithm(cert, cert_size, NULL, &signature_algo_oid_size); + if (status) { + if ((signature_algo_oid_size == 0) && + (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) { + status = false; + goto cleanup; + } + } else { + if (signature_algo_oid_size == 0) { + status = false; + goto cleanup; + } + } +#endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */ + + /* 4. Verify public key algorithm. */ status = libspdm_verify_cert_subject_public_key_info(cert, cert_size, base_asym_algo); if (!status) { goto cleanup; } - /* 4. issuer_name*/ + /* 5. issuer_name*/ asn1_buffer_len = 0; status = libspdm_x509_get_issuer_name(cert, cert_size, NULL, &asn1_buffer_len); if (status) { @@ -1108,7 +1129,7 @@ bool libspdm_x509_common_certificate_check(const uint8_t *cert, size_t cert_size } } - /* 5. subject_name*/ + /* 6. subject_name*/ asn1_buffer_len = 0; status = libspdm_x509_get_subject_name(cert, cert_size, NULL, &asn1_buffer_len); if (status) { @@ -1124,7 +1145,7 @@ bool libspdm_x509_common_certificate_check(const uint8_t *cert, size_t cert_size } } - /* 6. validity*/ + /* 7. validity*/ status = libspdm_x509_get_validity(cert, cert_size, end_cert_from, &end_cert_from_len, end_cert_to, &end_cert_to_len); @@ -1149,13 +1170,13 @@ bool libspdm_x509_common_certificate_check(const uint8_t *cert, size_t cert_size } } - /* 7. subject_public_key*/ + /* 8. subject_public_key*/ status = libspdm_asym_get_public_key_from_x509(base_asym_algo, cert, cert_size, &context); if (!status) { goto cleanup; } - /* 8. key_usage*/ + /* 9. key_usage*/ value = 0; status = libspdm_x509_get_key_usage(cert, cert_size, &value); if (!status) { @@ -1174,13 +1195,13 @@ bool libspdm_x509_common_certificate_check(const uint8_t *cert, size_t cert_size } } - /* 9. verify spdm defined extended key usage*/ + /* 10. verify spdm defined extended key usage*/ status = libspdm_verify_leaf_cert_spdm_eku(cert, cert_size, is_requester_cert); if (!status) { goto cleanup; } - /* 10. verify spdm defined extension*/ + /* 11. verify spdm defined extension*/ status = libspdm_verify_leaf_cert_spdm_extension(cert, cert_size, is_requester_cert, cert_model); if (!status) { diff --git a/os_stub/cryptlib_mbedtls/pk/x509.c b/os_stub/cryptlib_mbedtls/pk/x509.c index 2c6e01b7c05..5bbe44f82d5 100644 --- a/os_stub/cryptlib_mbedtls/pk/x509.c +++ b/os_stub/cryptlib_mbedtls/pk/x509.c @@ -1103,6 +1103,7 @@ libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t cert_size, sizeof(m_libspdm_oid_organization_name), name_buffer, name_buffer_size); } +#if LIBSPDM_ADDITIONAL_CHECK_CERT /** * Retrieve the signature algorithm from one X.509 certificate. * @@ -1111,15 +1112,10 @@ libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t cert_size, * @param[out] oid signature algorithm Object identifier buffer. * @param[in,out] oid_size signature algorithm Object identifier buffer size * - * @retval RETURN_SUCCESS The certificate Extension data retrieved successfully. - * @retval RETURN_INVALID_PARAMETER If cert is NULL. - * If oid_size is NULL. - * If oid is not NULL and *oid_size is 0. - * If Certificate is invalid. - * @retval RETURN_NOT_FOUND If no SignatureType. - * @retval RETURN_BUFFER_TOO_SMALL If the oid is NULL. The required buffer size - * is returned in the oid_size. - * @retval RETURN_UNSUPPORTED The operation is not supported. + * @retval true if the oid_size is equal 0, the cert parse successfully, but cert doesn't have signature algo. + * @retval true if the oid_size is not equal 0, the cert parse and get signature algo successfully. + * @retval false if the oid_size is equal 0, the cert parse failed. + * @retval false if the oid_size is not equal 0, the cert parse and get signature algo successfully, but the input buffer size is small. **/ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, size_t cert_size, uint8_t *oid, @@ -1129,7 +1125,11 @@ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, int ret; bool status; + /* Check input parameters.*/ if (cert == NULL || cert_size == 0 || oid_size == NULL) { + if (oid_size != NULL) { + *oid_size = 0; + } return false; } @@ -1150,6 +1150,8 @@ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, } *oid_size = crt.sig_oid.len; status = true; + } else { + *oid_size = 0; } cleanup: @@ -1157,6 +1159,7 @@ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, return status; } +#endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */ /** * Find first Extension data match with given OID diff --git a/os_stub/cryptlib_null/pk/x509.c b/os_stub/cryptlib_null/pk/x509.c index 73d637e8a5e..a16a7c9a191 100644 --- a/os_stub/cryptlib_null/pk/x509.c +++ b/os_stub/cryptlib_null/pk/x509.c @@ -534,6 +534,7 @@ libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t cert_size, return false; } +#if LIBSPDM_ADDITIONAL_CHECK_CERT /** * Retrieve the signature algorithm from one X.509 certificate. * @@ -542,15 +543,10 @@ libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t cert_size, * @param[out] oid signature algorithm Object identifier buffer. * @param[in,out] oid_size signature algorithm Object identifier buffer size * - * @retval RETURN_SUCCESS The certificate Extension data retrieved successfully. - * @retval RETURN_INVALID_PARAMETER If cert is NULL. - * If oid_size is NULL. - * If oid is not NULL and *oid_size is 0. - * If Certificate is invalid. - * @retval RETURN_NOT_FOUND If no SignatureType. - * @retval RETURN_BUFFER_TOO_SMALL If the oid is NULL. The required buffer size - * is returned in the oid_size. - * @retval RETURN_UNSUPPORTED The operation is not supported. + * @retval true if the oid_size is equal 0, the cert parse successfully, but cert doesn't have signature algo. + * @retval true if the oid_size is not equal 0, the cert parse and get signature algo successfully. + * @retval false if the oid_size is equal 0, the cert parse failed. + * @retval false if the oid_size is not equal 0, the cert parse and get signature algo successfully, but the input buffer size is small. **/ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, size_t cert_size, uint8_t *oid, @@ -559,6 +555,7 @@ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, LIBSPDM_ASSERT(false); return false; } +#endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */ /** * Retrieve Extension data from one X.509 certificate. diff --git a/os_stub/cryptlib_openssl/pk/x509.c b/os_stub/cryptlib_openssl/pk/x509.c index c77ab4cfe4b..3ca6411e6b8 100644 --- a/os_stub/cryptlib_openssl/pk/x509.c +++ b/os_stub/cryptlib_openssl/pk/x509.c @@ -981,6 +981,7 @@ libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t cert_size, name_buffer, name_buffer_size); } +#if LIBSPDM_ADDITIONAL_CHECK_CERT /** * Retrieve the signature algorithm from one X.509 certificate. * @@ -989,15 +990,10 @@ libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t cert_size, * @param[out] oid signature algorithm Object identifier buffer. * @param[in,out] oid_size signature algorithm Object identifier buffer size * - * @retval RETURN_SUCCESS The certificate Extension data retrieved successfully. - * @retval RETURN_INVALID_PARAMETER If cert is NULL. - * If oid_size is NULL. - * If oid is not NULL and *oid_size is 0. - * If Certificate is invalid. - * @retval RETURN_NOT_FOUND If no SignatureType. - * @retval RETURN_BUFFER_TOO_SMALL If the oid is NULL. The required buffer size - * is returned in the oid_size. - * @retval RETURN_UNSUPPORTED The operation is not supported. + * @retval true if the oid_size is equal 0, the cert parse successfully, but cert doesn't have signature algo. + * @retval true if the oid_size is not equal 0, the cert parse and get signature algo successfully. + * @retval false if the oid_size is equal 0, the cert parse failed. + * @retval false if the oid_size is not equal 0, the cert parse and get signature algo successfully, but the input buffer size is small. **/ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, size_t cert_size, uint8_t *oid, @@ -1009,32 +1005,30 @@ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, ASN1_OBJECT *asn1_obj; size_t obj_length; - /* Check input parameters.*/ - - if (cert == NULL || oid_size == NULL || cert_size == 0) { + if (cert == NULL || cert_size == 0 || oid_size == NULL) { + if (oid_size != NULL) { + *oid_size = 0; + } return false; } x509_cert = NULL; status = false; - /* Read DER-encoded X509 Certificate and Construct X509 object.*/ - status = libspdm_x509_construct_certificate(cert, cert_size, (uint8_t **)&x509_cert); if ((x509_cert == NULL) || (!status)) { status = false; + *oid_size = 0; goto done; } - /* Retrieve subject name from certificate object.*/ - nid = X509_get_signature_nid(x509_cert); if (nid == NID_undef) { *oid_size = 0; - status = false; + status = true; goto done; } asn1_obj = OBJ_nid2obj(nid); @@ -1059,13 +1053,13 @@ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, done: /* Release Resources.*/ - if (x509_cert != NULL) { X509_free(x509_cert); } return status; } +#endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */ /** * Retrieve the Validity from one X.509 certificate diff --git a/os_stub/spdm_crypt_ext_lib/cryptlib_ext.h b/os_stub/spdm_crypt_ext_lib/cryptlib_ext.h index 57fa97651db..d709625e1f9 100644 --- a/os_stub/spdm_crypt_ext_lib/cryptlib_ext.h +++ b/os_stub/spdm_crypt_ext_lib/cryptlib_ext.h @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2022 DMTF. All rights reserved. + * Copyright 2021-2024 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -108,21 +108,6 @@ extern bool libspdm_x509_get_issuer_orgnization_name(const uint8_t *cert, size_t char *name_buffer, size_t *name_buffer_size); -/** - * Retrieve the signature algorithm from one X.509 certificate. - * - * @param[in] cert Pointer to the DER-encoded X509 certificate. - * @param[in] cert_size Size of the X509 certificate in bytes. - * @param[out] oid Signature algorithm Object identifier buffer. - * @param[in,out] oid_size Signature algorithm Object identifier buffer size. - * - * @retval true - * @retval false - **/ -extern bool libspdm_x509_get_signature_algorithm(const uint8_t *cert, - size_t cert_size, uint8_t *oid, - size_t *oid_size); - /** * Construct a X509 object from DER-encoded certificate data. *