Skip to content

Commit

Permalink
Add signature algo check for cert
Browse files Browse the repository at this point in the history
Fix the issue: #2658

Signed-off-by: Wenxing Hou <[email protected]>
  • Loading branch information
Wenxing-hou authored and jyao1 committed Jun 18, 2024
1 parent 9eece14 commit 3106d12
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 60 deletions.
19 changes: 19 additions & 0 deletions include/hal/library/cryptlib/cryptlib_cert.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
5 changes: 5 additions & 0 deletions include/library/spdm_lib_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
37 changes: 29 additions & 8 deletions library/spdm_crypt_lib/libspdm_crypt_cert.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down
21 changes: 12 additions & 9 deletions os_stub/cryptlib_mbedtls/pk/x509.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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,
Expand All @@ -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;
}

Expand All @@ -1150,13 +1150,16 @@ bool libspdm_x509_get_signature_algorithm(const uint8_t *cert,
}
*oid_size = crt.sig_oid.len;
status = true;
} else {
*oid_size = 0;
}

cleanup:
mbedtls_x509_crt_free(&crt);

return status;
}
#endif /* LIBSPDM_ADDITIONAL_CHECK_CERT */

/**
* Find first Extension data match with given OID
Expand Down
15 changes: 6 additions & 9 deletions os_stub/cryptlib_null/pk/x509.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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,
Expand All @@ -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.
Expand Down
30 changes: 12 additions & 18 deletions os_stub/cryptlib_openssl/pk/x509.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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
Expand Down
17 changes: 1 addition & 16 deletions os_stub/spdm_crypt_ext_lib/cryptlib_ext.h
Original file line number Diff line number Diff line change
@@ -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
**/

Expand Down Expand Up @@ -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.
*
Expand Down

0 comments on commit 3106d12

Please sign in to comment.