/** * Copyright Notice: * Copyright 2021-2022 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ #include "test_crypt.h" #include "industry_standard/spdm.h" #include "spdm_device_secret_lib_sample/spdm_device_secret_lib_internal.h" static uint8_t m_libspdm_oid_subject_alt_name[] = { 0x55, 0x1D, 0x11 }; /** * save the CSR * * @param[out] csr_len CSR len for DER format * @param[in] csr_pointer csr_pointer is address to store CSR. * @param[in] base_asym_algo To distinguish file * * @retval true successfully. * @retval false unsuccessfully. **/ bool libspdm_write_csr_to_file(const void * csr_pointer, size_t csr_len, uint32_t base_asym_algo) { FILE *fp_out; char* file_name; switch (base_asym_algo) { case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048: case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048: file_name = "rsa2048.csr"; break; case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072: case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072: file_name = "rsa3072.csr"; break; case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096: case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096: file_name = "rsa4096.csr"; break; case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256: file_name = "ecp256.csr"; break; case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384: file_name = "ecp384.csr"; break; case SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521: file_name = "ecp521.csr"; break; default: return false; } if ((fp_out = fopen(file_name, "w+b")) == NULL) { printf("Unable to open file %s\n", file_name); return false; } if ((fwrite(csr_pointer, 1, csr_len, fp_out)) != csr_len) { printf("Write output file error %s\n", file_name); fclose(fp_out); return false; } fclose(fp_out); return true; } /** * Validate Crypto X509 certificate Verify * * @retval true Validation succeeded. * @retval false Validation failed. * **/ bool libspdm_validate_crypt_x509(char *Path, size_t len) { bool status; const uint8_t *leaf_cert; size_t leaf_cert_len; uint8_t *test_cert; size_t test_cert_len; uint8_t *test_ca_cert; size_t test_ca_cert_len; uint8_t *test_bundle_cert; size_t test_bundle_cert_len; uint8_t *test_end_cert; size_t test_end_cert_len; size_t subject_size; uint8_t *subject; size_t common_name_size; char common_name[64]; size_t cert_version; uint8_t asn1_buffer[1024]; size_t asn1_buffer_len; uint8_t end_cert_from[64]; size_t end_cert_from_len; uint8_t end_cert_to[64]; size_t end_cert_to_len; uint8_t date_time1[64]; uint8_t date_time2[64]; char file_name_buffer[1024]; test_cert = NULL; test_ca_cert = NULL; test_bundle_cert = NULL; test_end_cert = NULL; libspdm_zero_mem(file_name_buffer, 1024); libspdm_copy_mem(file_name_buffer, sizeof(file_name_buffer), Path, len); libspdm_copy_mem(file_name_buffer + len - 1, sizeof(file_name_buffer) - (len - 1), "/inter.cert.der", sizeof("/inter.cert.der")); status = libspdm_read_input_file(file_name_buffer, (void **)&test_cert, &test_cert_len); if (!status) { goto cleanup; } libspdm_zero_mem(file_name_buffer, 1024); libspdm_copy_mem(file_name_buffer, sizeof(file_name_buffer), Path, len); libspdm_copy_mem(file_name_buffer + len - 1, sizeof(file_name_buffer) - (len - 1), "/ca.cert.der", sizeof("/ca.cert.der")); status = libspdm_read_input_file(file_name_buffer, (void **)&test_ca_cert, &test_ca_cert_len); if (!status) { goto cleanup; } libspdm_zero_mem(file_name_buffer, 1024); libspdm_copy_mem(file_name_buffer, sizeof(file_name_buffer), Path, len); libspdm_copy_mem(file_name_buffer + len - 1, sizeof(file_name_buffer) - (len - 1), "/bundle_requester.certchain.der", sizeof("/bundle_requester.certchain.der")); status = libspdm_read_input_file(file_name_buffer, (void **)&test_bundle_cert, &test_bundle_cert_len); if (!status) { goto cleanup; } libspdm_zero_mem(file_name_buffer, 1024); libspdm_copy_mem(file_name_buffer, sizeof(file_name_buffer), Path, len); libspdm_copy_mem(file_name_buffer + len - 1, sizeof(file_name_buffer) - (len - 1), "/end_requester.cert.der", sizeof("/end_requester.cert.der")); status = libspdm_read_input_file(file_name_buffer, (void **)&test_end_cert, &test_end_cert_len); if (!status) { goto cleanup; } /* X509 Certificate Verification.*/ libspdm_my_print("\n- X509 Certificate Verification with Trusted CA ..."); status = libspdm_x509_verify_cert(test_cert, test_cert_len, test_ca_cert, test_ca_cert_len); if (!status) { libspdm_my_print("[Fail]\n"); goto cleanup; } else { libspdm_my_print("[Pass]\n"); } /* X509 Certificate Chain Verification.*/ LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "- X509 Certificate Chain Verification ... ")); status = libspdm_x509_verify_cert_chain((const uint8_t *)test_ca_cert, test_ca_cert_len, (const uint8_t *)test_bundle_cert, test_bundle_cert_len); if (!status) { libspdm_my_print("[Fail]\n"); goto cleanup; } else { libspdm_my_print("[Pass]\n"); } LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "- X509 Certificate CA cert verify itself Verification ... ")); status = libspdm_x509_verify_cert_chain((const uint8_t *)test_ca_cert, test_ca_cert_len, (const uint8_t *)test_ca_cert, test_ca_cert_len); if (!status) { libspdm_my_print("[Fail]\n"); goto cleanup; } else { libspdm_my_print("[Pass]\n"); } LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "- X509 Certificate CA cert verify itself Verification with large cert len")); status = libspdm_x509_verify_cert_chain((const uint8_t *)test_ca_cert, test_ca_cert_len, (const uint8_t *)test_ca_cert, test_ca_cert_len + 1); if (!status) { libspdm_my_print("[Fail]\n"); goto cleanup; } else { libspdm_my_print("[Pass]\n"); } LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "- X509 Certificate end cert verify itself Verification ... ")); status = libspdm_x509_verify_cert_chain((const uint8_t *)test_end_cert, test_end_cert_len, (const uint8_t *)test_end_cert, test_end_cert_len); if (status) { libspdm_my_print("[Fail]\n"); goto cleanup; } else { libspdm_my_print("[Pass]\n"); } LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "- X509 Certificate end cert verify itself Verification with large cert len")); status = libspdm_x509_verify_cert_chain((const uint8_t *)test_end_cert, test_end_cert_len, (const uint8_t *)test_end_cert, test_end_cert_len + 1); if (status) { libspdm_my_print("[Fail]\n"); goto cleanup; } else { libspdm_my_print("[Pass]\n"); } /* X509 Get leaf certificate from cert_chain Verificate*/ LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "- X509 Certificate Chain get leaf certificate Verification ... ")); status = libspdm_x509_get_cert_from_cert_chain(test_bundle_cert, test_bundle_cert_len, -1, &leaf_cert, &leaf_cert_len); if (!status) { libspdm_my_print("[Fail]\n"); goto cleanup; } if (leaf_cert_len != test_end_cert_len) { libspdm_my_print("[Fail]\n"); goto cleanup; } if (memcmp(leaf_cert, test_end_cert, leaf_cert_len) != 0) { libspdm_my_print("[Fail]\n"); goto cleanup; } else { libspdm_my_print("[Pass]\n"); } /* X509 Get leaf certificate from cert_chain Verificate*/ LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "- X509 Certificate Chain get leaf certificate Verification ... ")); status = libspdm_x509_get_cert_from_cert_chain(test_bundle_cert, test_bundle_cert_len, 2, &leaf_cert, &leaf_cert_len); if (!status) { libspdm_my_print("[Fail]\n"); goto cleanup; } if (leaf_cert_len != test_end_cert_len) { libspdm_my_print("[Fail]\n"); goto cleanup; } if (memcmp(leaf_cert, test_end_cert, leaf_cert_len) != 0) { libspdm_my_print("[Fail]\n"); goto cleanup; } else { libspdm_my_print("[Pass]\n"); } /* X509 Get root certificate from cert_chain Verificate*/ LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "- X509 Certificate Chain get root certificate Verification ... ")); status = libspdm_x509_get_cert_from_cert_chain(test_bundle_cert, test_bundle_cert_len, 0, &leaf_cert, &leaf_cert_len); if (!status) { libspdm_my_print("[Fail]\n"); goto cleanup; } if (leaf_cert_len != test_ca_cert_len) { libspdm_my_print("[Fail]\n"); goto cleanup; } if (memcmp(leaf_cert, test_ca_cert, leaf_cert_len) != 0) { libspdm_my_print("[Fail]\n"); goto cleanup; } else { libspdm_my_print("[Pass]\n"); } /* X509 Certificate subject Retrieving.*/ libspdm_my_print("- X509 Certificate subject Bytes Retrieving ... "); subject_size = 0; status = libspdm_x509_get_subject_name(test_cert, test_cert_len, NULL, &subject_size); subject = (uint8_t *)allocate_pool(subject_size); status = libspdm_x509_get_subject_name(test_cert, test_cert_len, subject, &subject_size); free_pool(subject); if (!status) { libspdm_my_print("[Fail]"); goto cleanup; } else { libspdm_my_print("[Pass]"); } libspdm_my_print("\n- X509 Certificate context Retrieving ... "); /* Get common_name from X509 Certificate subject*/ common_name_size = 64; libspdm_zero_mem(common_name, common_name_size); status = libspdm_x509_get_common_name(test_cert, test_cert_len, common_name, &common_name_size); if (!status) { libspdm_my_print("\n - Retrieving Common name - [Fail]"); goto cleanup; } else { LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n - Retrieving Common name = \"%s\" (size = %zu)", common_name, common_name_size)); libspdm_my_print(" - [PASS]"); } /* Get Issuer OrganizationName from X509 Certificate subject*/ common_name_size = 64; libspdm_zero_mem(common_name, common_name_size); status = libspdm_x509_get_organization_name(test_cert, test_cert_len, common_name, &common_name_size); if (status || common_name_size != 0) { libspdm_my_print("\n - Retrieving Oraganization name - [Fail]"); goto cleanup; } else { libspdm_my_print("\n - Retrieving Oraganization name - [PASS]"); } /* Get version from X509 Certificate*/ cert_version = 0; status = libspdm_x509_get_version(test_cert, test_cert_len, &cert_version); if (!status) { libspdm_my_print("\n - Retrieving version - [Fail]"); goto cleanup; } else { LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n - Retrieving version = %zu - ", cert_version)); libspdm_my_print("[Pass]"); } /* Get Serial from X509 Certificate*/ asn1_buffer_len = 1024; libspdm_zero_mem(asn1_buffer, asn1_buffer_len); status = libspdm_x509_get_serial_number(test_cert, test_cert_len, asn1_buffer, &asn1_buffer_len); if (!status) { libspdm_my_print("\n - Retrieving serial_number - [Fail]"); goto cleanup; } else { LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n - Retrieving serial_number = %llu - ", *((uint64_t *)asn1_buffer))); libspdm_my_print("[Pass]"); } /* X509 Certificate subject Retrieving.*/ libspdm_my_print("\n - Retrieving issuer Bytes ... "); subject_size = 0; status = libspdm_x509_get_issuer_name(test_cert, test_cert_len, NULL, &subject_size); subject = (uint8_t *)allocate_pool(subject_size); status = libspdm_x509_get_issuer_name(test_cert, test_cert_len, subject, &subject_size); free_pool(subject); if (!status) { libspdm_my_print("[Fail]"); goto cleanup; } else { libspdm_my_print(" - [Pass]"); } /* Get Issuer common_name from X509 Certificate subject*/ common_name_size = 64; libspdm_zero_mem(common_name, common_name_size); status = libspdm_x509_get_issuer_common_name(test_cert, test_cert_len, common_name, &common_name_size); if (!status) { libspdm_my_print("\n - Retrieving Issuer Common name - [Fail]"); goto cleanup; } else { LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n - Retrieving Issuer Common name = \"%s\" (size = %zu) - ", common_name, common_name_size)); libspdm_my_print("[Pass]"); } /* Get Issuer OrganizationName from X509 Certificate subject*/ common_name_size = 64; libspdm_zero_mem(common_name, common_name_size); status = libspdm_x509_get_issuer_orgnization_name(test_cert, test_cert_len, common_name, &common_name_size); if (status || common_name_size != 0) { libspdm_my_print("\n - Retrieving Issuer Oraganization name - [Fail]"); goto cleanup; } else { libspdm_my_print("\n - Retrieving Issuer Oraganization name - [Pass]"); } /* Get X509GetSubjectAltName*/ asn1_buffer_len = 1024; libspdm_zero_mem(asn1_buffer, asn1_buffer_len); status = libspdm_x509_get_extension_data(test_end_cert, test_end_cert_len, m_libspdm_oid_subject_alt_name, sizeof(m_libspdm_oid_subject_alt_name), asn1_buffer, &asn1_buffer_len); if (!status) { libspdm_my_print("\n - Retrieving SubjectAltName otherName - [Fail]"); goto cleanup; } else { LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n - Retrieving SubjectAltName (size = %zu) ", asn1_buffer_len)); libspdm_my_print("- [Pass]"); } /* Get X509 Validity*/ end_cert_from_len = 64; end_cert_to_len = 64; status = libspdm_x509_get_validity(test_end_cert, test_end_cert_len, end_cert_from, &end_cert_from_len, end_cert_to, &end_cert_to_len); if (!status) { libspdm_my_print("\n - Retrieving Validity - [Fail]"); goto cleanup; } else { libspdm_my_print("\n - Retrieving Validity - [Pass]"); } asn1_buffer_len = 64; status = libspdm_x509_set_date_time("19700101000000Z", date_time1, &asn1_buffer_len); if (status && (asn1_buffer_len != 0)) { libspdm_my_print("\n - Set date_time - [Pass]"); } else { libspdm_my_print("\n - Set date_time - [Fail]"); goto cleanup; } asn1_buffer_len = 64; status = libspdm_x509_set_date_time("19700201000000Z", date_time2, &asn1_buffer_len); if (status && (asn1_buffer_len != 0)) { libspdm_my_print("\n - Set date_time - [Pass]"); } else { libspdm_my_print("\n - Set date_time - [Fail]"); goto cleanup; } if (libspdm_x509_compare_date_time(date_time1, date_time2) < 0) { libspdm_my_print("\n - Compare date_time - [Pass]"); } else { libspdm_my_print("\n - Compare date_time- [Fail]"); goto cleanup; } libspdm_my_print("\n"); status = true; cleanup: if (test_cert != NULL) { free(test_cert); } if (test_ca_cert != NULL) { free(test_ca_cert); } if (test_bundle_cert != NULL) { free(test_bundle_cert); } if (test_end_cert != NULL) { free(test_end_cert); } return status; } void libspdm_dump_hex_str(const uint8_t *buffer, size_t buffer_size) { size_t index; for (index = 0; index < buffer_size; index++) { printf("%02x", buffer[index]); } }