diff --git a/src/x509.c b/src/x509.c index ae044624bc..b6ebc1e3e2 100644 --- a/src/x509.c +++ b/src/x509.c @@ -16333,6 +16333,9 @@ int wolfSSL_X509_set_subject_key_id_ex(WOLFSSL_X509* x509) #endif /* !NO_SHA */ /* Set Authority Key Identifier from raw bytes. + * The bytes passed in are the keyIdentifier OCTET STRING contents only, + * they must not be a pre-encoded AuthorityKeyIdentifier SEQUENCE. + * The cert encoder wraps them in SEQUENCE { [0] keyIdentifier } at sign time. * * x509 - Certificate to modify * akid - Raw AKID bytes @@ -16343,27 +16346,38 @@ int wolfSSL_X509_set_subject_key_id_ex(WOLFSSL_X509* x509) int wolfSSL_X509_set_authority_key_id(WOLFSSL_X509* x509, const unsigned char* akid, int akidSz) { + byte* newAkid = NULL; + WOLFSSL_ENTER("wolfSSL_X509_set_authority_key_id"); if (x509 == NULL || akid == NULL || akidSz <= 0) { return WOLFSSL_FAILURE; } - /* Allocate/reallocate memory for authKeyIdSrc */ - if (x509->authKeyIdSrc == NULL || (int)x509->authKeyIdSrcSz < akidSz) { - if (x509->authKeyIdSrc != NULL) { - XFREE(x509->authKeyIdSrc, x509->heap, DYNAMIC_TYPE_X509_EXT); - } - x509->authKeyIdSrc = (byte*)XMALLOC((word32)akidSz, x509->heap, - DYNAMIC_TYPE_X509_EXT); - if (x509->authKeyIdSrc == NULL) { - return WOLFSSL_FAILURE; - } + /* Allocate new buffer up front so failure leaves prior state intact */ + newAkid = (byte*)XMALLOC((word32)akidSz, x509->heap, DYNAMIC_TYPE_X509_EXT); + if (newAkid == NULL) { + return WOLFSSL_FAILURE; + } + XMEMCPY(newAkid, akid, (word32)akidSz); + + /* Free any prior storage. authKeyIdSrc may be populated from a prior + * parse cert operation. authKeyId aliases inside that buffer, so + * authKeyIdSrc must be freed first to avoid a dangling authKeyId. */ + if (x509->authKeyIdSrc != NULL) { + XFREE(x509->authKeyIdSrc, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->authKeyIdSrc = NULL; + x509->authKeyIdSrcSz = 0; + } + else if (x509->authKeyId != NULL) { + XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); } - XMEMCPY(x509->authKeyIdSrc, akid, (word32)akidSz); - x509->authKeyIdSrcSz = (word32)akidSz; - x509->authKeyId = x509->authKeyIdSrc; + /* Store newAkid as authKeyId only, do not populate authKeyIdSrc. + * When authKeyIdSrc is non-NULL, the encoder writes those bytes without + * SEQUENCE/[0] wrapper. authKeyIdSrc must be NULL here so encoder does + * wrap them. */ + x509->authKeyId = newAkid; x509->authKeyIdSz = (word32)akidSz; x509->authKeyIdSet = 1; diff --git a/tests/api.c b/tests/api.c index b3193c5ad0..c4791b4ca0 100644 --- a/tests/api.c +++ b/tests/api.c @@ -19832,6 +19832,419 @@ static int test_wolfSSL_X509_set_extensions(void) return EXPECT_RESULT(); } +/* Round trip test for wolfSSL_X509_set_authority_key_id() with a raw key ID. + * + * Builds a cert, calls the setter with a 20-byte raw keyId, signs the cert, + * serializes to DER via wolfSSL_i2d_X509(), re-parses the DER, locates the + * AKID extension, and asserts the OCTET STRING contents match the + * AuthorityKeyIdentifier ASN.1 structure required by RFC 5280 4.2.1.1: + * + * SEQUENCE (0x30) length 22 (0x16) + * [0] (0x80) length 20 (0x14) + * <20 keyId bytes> + * + * The keyId bytes inside the [0] tag must equal the input passed the setter. */ +static int test_wolfSSL_X509_set_authority_key_id_roundtrip(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && \ + !defined(NO_RSA) && !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) + WOLFSSL_X509* src = NULL; + WOLFSSL_X509* built = NULL; + WOLFSSL_X509* parsed = NULL; + WOLFSSL_EVP_PKEY* priv = NULL; + WOLFSSL_EVP_PKEY* pub = NULL; + WOLFSSL_ASN1_TIME* notBefore = NULL; + WOLFSSL_ASN1_TIME* notAfter = NULL; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLFSSL_ASN1_STRING* extData = NULL; + unsigned char* der = NULL; + const unsigned char* derPtr = NULL; + unsigned char* key = NULL; + unsigned char* keyPt = NULL; + char* name = NULL; + char* header = NULL; + long keySz = 0; + int derSz = 0; + int extIdx = -1; + XFILE fp = XBADFILE; + time_t t; + + /* Raw 20-byte key identifier */ + byte akid[20] = { + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23 + }; + + /* Load reference cert + key (RSA) */ + src = wolfSSL_X509_load_certificate_file(cliCertFile, WOLFSSL_FILETYPE_PEM); + ExpectNotNull(src); + + ExpectTrue((fp = XFOPEN(cliKeyFile, "rb")) != XBADFILE); + ExpectIntEQ(wolfSSL_PEM_read(fp, &name, &header, &key, &keySz), + WOLFSSL_SUCCESS); + if (fp != XBADFILE) { + XFCLOSE(fp); + } + keyPt = key; + ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, + (const unsigned char**)&keyPt, keySz)); + + /* Build a v3 cert and copy fields from src */ + ExpectNotNull(built = wolfSSL_X509_new()); + ExpectIntEQ(wolfSSL_X509_set_version(built, 2), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_set_subject_name(built, + wolfSSL_X509_get_subject_name(src)), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_set_issuer_name(built, + wolfSSL_X509_get_issuer_name(src)), WOLFSSL_SUCCESS); + ExpectNotNull(pub = wolfSSL_X509_get_pubkey(src)); + ExpectIntEQ(wolfSSL_X509_set_pubkey(built, pub), WOLFSSL_SUCCESS); + + t = time(NULL); + ExpectNotNull(notBefore = wolfSSL_ASN1_TIME_adj(NULL, t, 0, 0)); + ExpectNotNull(notAfter = wolfSSL_ASN1_TIME_adj(NULL, t, 365, 0)); + ExpectTrue(wolfSSL_X509_set_notBefore(built, notBefore)); + ExpectTrue(wolfSSL_X509_set_notAfter(built, notAfter)); + + /* Set AKID with a raw key identifier */ + ExpectIntEQ(wolfSSL_X509_set_authority_key_id(built, akid, sizeof(akid)), + WOLFSSL_SUCCESS); + + /* Sign and serialize. */ + ExpectIntGT(wolfSSL_X509_sign(built, priv, EVP_sha256()), 0); + ExpectIntGT((derSz = wolfSSL_i2d_X509(built, &der)), 0); + + /* Re-parse the DER we just produced */ + derPtr = der; + ExpectNotNull(parsed = wolfSSL_d2i_X509(NULL, &derPtr, derSz)); + + /* Locate the AKID extension and pull out the OCTET STRING contents + * (per RFC 5280 must be a SEQUENCE { [0] keyIdentifier ... }) */ + ExpectIntGE((extIdx = wolfSSL_X509_get_ext_by_NID(parsed, + NID_authority_key_identifier, -1)), 0); + ExpectNotNull(ext = wolfSSL_X509_get_ext(parsed, extIdx)); + ExpectNotNull(extData = wolfSSL_X509_EXTENSION_get_data(ext)); + + /* Encoded inner extension structure for a 20-byte keyId is 24 bytes: + * SEQUENCE (0x30) length 22 (0x16) + * [0] (0x80) length 20 (0x14) + * <20 keyId bytes> + */ + ExpectIntEQ(extData->length, 24); + if (extData != NULL && extData->data != NULL && extData->length == 24) { + ExpectIntEQ((unsigned char)extData->data[0], 0x30); + ExpectIntEQ((unsigned char)extData->data[1], 0x16); + ExpectIntEQ((unsigned char)extData->data[2], 0x80); + ExpectIntEQ((unsigned char)extData->data[3], 0x14); + ExpectIntEQ(XMEMCMP((const byte*)extData->data + 4, akid, + sizeof(akid)), 0); + } + + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); + XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(name, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(header, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + wolfSSL_X509_free(src); + wolfSSL_X509_free(built); + wolfSSL_X509_free(parsed); + + wolfSSL_EVP_PKEY_free(priv); + wolfSSL_EVP_PKEY_free(pub); + + wolfSSL_ASN1_TIME_free(notBefore); + wolfSSL_ASN1_TIME_free(notAfter); +#endif + return EXPECT_RESULT(); +} + +/* Round trip test for wolfSSL_X509_set_authority_key_id_ex(). + * + * Inserts a known SubjectKeyIdentifier on the issuer cert, calls the _ex + * variant of the setter (which derives the AKID keyId from the issuer SKID, + * or from SHA-1 of the issuer public key when no SKID is set), signs, + * serializes to DER, re-parses, and asserts the AKID extension OCTET STRING + * contents match the RFC 5280 4.2.1.1 structure + * + * SEQUENCE (0x30) length 22 (0x16) + * [0] (0x80) length 20 (0x14) + * <20 keyId bytes> + * + * with the embedded keyId equal to the issuer's SKID. */ +static int test_wolfSSL_X509_set_authority_key_id_ex_roundtrip(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && \ + !defined(NO_RSA) && !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) && \ + !defined(NO_SHA) + WOLFSSL_X509* issuer = NULL; + WOLFSSL_X509* built = NULL; + WOLFSSL_X509* parsed = NULL; + WOLFSSL_EVP_PKEY* priv = NULL; + WOLFSSL_EVP_PKEY* pub = NULL; + WOLFSSL_ASN1_TIME* notBefore = NULL; + WOLFSSL_ASN1_TIME* notAfter = NULL; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLFSSL_ASN1_STRING* extData = NULL; + unsigned char* der = NULL; + const unsigned char* derPtr = NULL; + unsigned char* key = NULL; + unsigned char* keyPt = NULL; + char* name = NULL; + char* header = NULL; + long keySz = 0; + int derSz = 0; + int extIdx = -1; + XFILE fp = XBADFILE; + time_t t; + + /* SKID on the issuer. The AKID on the built cert should match this. */ + byte issuerSkid[20] = { + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39, + 0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43 + }; + + /* Load the cert to use as both issuer and the source of subject/key. */ + ExpectNotNull(issuer = wolfSSL_X509_load_certificate_file(cliCertFile, + WOLFSSL_FILETYPE_PEM)); + + /* Stamp known SKID on the issuer so set_authority_key_id_ex has a + * deterministic value to copy into the AKID. */ + ExpectIntEQ(wolfSSL_X509_set_subject_key_id(issuer, issuerSkid, + sizeof(issuerSkid)), WOLFSSL_SUCCESS); + + ExpectTrue((fp = XFOPEN(cliKeyFile, "rb")) != XBADFILE); + ExpectIntEQ(wolfSSL_PEM_read(fp, &name, &header, &key, &keySz), + WOLFSSL_SUCCESS); + + if (fp != XBADFILE) { + XFCLOSE(fp); + } + + keyPt = key; + ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, + (const unsigned char**)&keyPt, keySz)); + + ExpectNotNull(built = wolfSSL_X509_new()); + ExpectIntEQ(wolfSSL_X509_set_version(built, 2), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_set_subject_name(built, + wolfSSL_X509_get_subject_name(issuer)), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_set_issuer_name(built, + wolfSSL_X509_get_subject_name(issuer)), WOLFSSL_SUCCESS); + ExpectNotNull(pub = wolfSSL_X509_get_pubkey(issuer)); + ExpectIntEQ(wolfSSL_X509_set_pubkey(built, pub), WOLFSSL_SUCCESS); + + t = time(NULL); + ExpectNotNull(notBefore = wolfSSL_ASN1_TIME_adj(NULL, t, 0, 0)); + ExpectNotNull(notAfter = wolfSSL_ASN1_TIME_adj(NULL, t, 365, 0)); + ExpectTrue(wolfSSL_X509_set_notBefore(built, notBefore)); + ExpectTrue(wolfSSL_X509_set_notAfter(built, notAfter)); + + /* Derive AKID from the issuer's SKID */ + ExpectIntEQ(wolfSSL_X509_set_authority_key_id_ex(built, issuer), + WOLFSSL_SUCCESS); + + ExpectIntGT(wolfSSL_X509_sign(built, priv, EVP_sha256()), 0); + ExpectIntGT((derSz = wolfSSL_i2d_X509(built, &der)), 0); + + derPtr = der; + ExpectNotNull(parsed = wolfSSL_d2i_X509(NULL, &derPtr, derSz)); + + ExpectIntGE((extIdx = wolfSSL_X509_get_ext_by_NID(parsed, + NID_authority_key_identifier, -1)), 0); + ExpectNotNull(ext = wolfSSL_X509_get_ext(parsed, extIdx)); + ExpectNotNull(extData = wolfSSL_X509_EXTENSION_get_data(ext)); + + /* AuthorityKeyIdentifier inner structure for a 20-byte keyId is 24 bytes: + * SEQUENCE { [0] keyId }. keyId on built cert must equal issuer SKID. */ + ExpectIntEQ(extData->length, 24); + if (extData != NULL && extData->data != NULL && extData->length == 24) { + ExpectIntEQ((unsigned char)extData->data[0], 0x30); + ExpectIntEQ((unsigned char)extData->data[1], 0x16); + ExpectIntEQ((unsigned char)extData->data[2], 0x80); + ExpectIntEQ((unsigned char)extData->data[3], 0x14); + ExpectIntEQ(XMEMCMP((const byte*)extData->data + 4, issuerSkid, + sizeof(issuerSkid)), 0); + } + + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); + XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(name, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(header, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + wolfSSL_X509_free(issuer); + wolfSSL_X509_free(built); + wolfSSL_X509_free(parsed); + + wolfSSL_EVP_PKEY_free(priv); + wolfSSL_EVP_PKEY_free(pub); + + wolfSSL_ASN1_TIME_free(notBefore); + wolfSSL_ASN1_TIME_free(notAfter); +#endif + return EXPECT_RESULT(); +} + +/* Verifies that wolfSSL_X509_set_authority_key_id() correctly handles being + * called on a WOLFSSL_X509 that already has AKID storage. + * + * Case 1: two consecutive setter calls on a fresh built cert. Calls setter + * twice with different keyIds (second call should replace first AKID). + * Case 2: setter called on an X509 loaded from a PEM file that already has + * an AKID extension. + */ +static int test_wolfSSL_X509_set_authority_key_id_overwrite(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) && \ + !defined(NO_RSA) && !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) + WOLFSSL_X509* src = NULL; + WOLFSSL_X509* built = NULL; + WOLFSSL_X509* parsed = NULL; + WOLFSSL_X509* loaded = NULL; + WOLFSSL_EVP_PKEY* priv = NULL; + WOLFSSL_EVP_PKEY* pub = NULL; + WOLFSSL_ASN1_TIME* notBefore = NULL; + WOLFSSL_ASN1_TIME* notAfter = NULL; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLFSSL_ASN1_STRING* extData = NULL; + unsigned char* der = NULL; + const unsigned char* derPtr = NULL; + unsigned char* key = NULL; + unsigned char* keyPt = NULL; + char* name = NULL; + char* header = NULL; + long keySz = 0; + int derSz = 0; + int extIdx = -1; + XFILE fp = XBADFILE; + time_t t; + + byte akid1[20] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a, + 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14 + }; + byte akid2[20] = { + 0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00,0x11,0x22,0x33, + 0x44,0x55,0x66,0x77,0x88,0x99,0xa0,0xb0,0xc0,0xd0 + }; + + /* Case 1: set twice on a fresh built cert */ + ExpectNotNull(src = wolfSSL_X509_load_certificate_file(cliCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectTrue((fp = XFOPEN(cliKeyFile, "rb")) != XBADFILE); + ExpectIntEQ(wolfSSL_PEM_read(fp, &name, &header, &key, &keySz), + WOLFSSL_SUCCESS); + if (fp != XBADFILE) { + XFCLOSE(fp); + } + + keyPt = key; + ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, + (const unsigned char**)&keyPt, keySz)); + + ExpectNotNull(built = wolfSSL_X509_new()); + ExpectIntEQ(wolfSSL_X509_set_version(built, 2), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_set_subject_name(built, + wolfSSL_X509_get_subject_name(src)), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_set_issuer_name(built, + wolfSSL_X509_get_issuer_name(src)), WOLFSSL_SUCCESS); + ExpectNotNull(pub = wolfSSL_X509_get_pubkey(src)); + ExpectIntEQ(wolfSSL_X509_set_pubkey(built, pub), WOLFSSL_SUCCESS); + + t = time(NULL); + ExpectNotNull(notBefore = wolfSSL_ASN1_TIME_adj(NULL, t, 0, 0)); + ExpectNotNull(notAfter = wolfSSL_ASN1_TIME_adj(NULL, t, 365, 0)); + ExpectTrue(wolfSSL_X509_set_notBefore(built, notBefore)); + ExpectTrue(wolfSSL_X509_set_notAfter(built, notAfter)); + + /* Two setter calls with distinct keyIds, no prior AKID on cert */ + ExpectIntEQ(wolfSSL_X509_set_authority_key_id(built, akid1, + sizeof(akid1)), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_set_authority_key_id(built, akid2, + sizeof(akid2)), WOLFSSL_SUCCESS); + + ExpectIntGT(wolfSSL_X509_sign(built, priv, EVP_sha256()), 0); + ExpectIntGT((derSz = wolfSSL_i2d_X509(built, &der)), 0); + + derPtr = der; + ExpectNotNull(parsed = wolfSSL_d2i_X509(NULL, &derPtr, derSz)); + + ExpectIntGE((extIdx = wolfSSL_X509_get_ext_by_NID(parsed, + NID_authority_key_identifier, -1)), 0); + ExpectNotNull(ext = wolfSSL_X509_get_ext(parsed, extIdx)); + ExpectNotNull(extData = wolfSSL_X509_EXTENSION_get_data(ext)); + /* AKID extension must hold akid2, wrapped in: + * SEQUENCE { [0] keyId } (24 bytes for a 20-byte keyId) */ + ExpectIntEQ(extData->length, 24); + if (extData != NULL && extData->data != NULL && extData->length == 24) { + ExpectIntEQ((unsigned char)extData->data[0], 0x30); + ExpectIntEQ((unsigned char)extData->data[2], 0x80); + ExpectIntEQ((unsigned char)extData->data[3], 0x14); + ExpectIntEQ(XMEMCMP((const byte*)extData->data + 4, akid2, + sizeof(akid2)), 0); + } + + /* Free DER/parsed cert so Case 2 can reuse the variables. */ + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); + der = NULL; + derSz = 0; + wolfSSL_X509_free(parsed); + parsed = NULL; + + /* Case 2: set on cert loaded from PEM file that already has an AKID. */ + ExpectNotNull(loaded = wolfSSL_X509_load_certificate_file(cliCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectIntEQ(wolfSSL_X509_set_authority_key_id(loaded, akid1, + sizeof(akid1)), WOLFSSL_SUCCESS); + + /* Re-sign with priv and re-encode so we can inspect the freshly + * encoded AKID. Signature/issuer binding correctness is not part of + * this test; only the DER round-trip of the AKID extension is. */ + ExpectIntGT(wolfSSL_X509_sign(loaded, priv, EVP_sha256()), 0); + ExpectIntGT((derSz = wolfSSL_i2d_X509(loaded, &der)), 0); + + derPtr = der; + ExpectNotNull(parsed = wolfSSL_d2i_X509(NULL, &derPtr, derSz)); + + extIdx = -1; + ExpectIntGE((extIdx = wolfSSL_X509_get_ext_by_NID(parsed, + NID_authority_key_identifier, -1)), 0); + ExpectNotNull(ext = wolfSSL_X509_get_ext(parsed, extIdx)); + ExpectNotNull(extData = wolfSSL_X509_EXTENSION_get_data(ext)); + /* AKID extension must hold akid1 wrapped in SEQUENCE { [0] keyId } + * (24 bytes for 20-byte keyId), not the original parsed-cert AKID. */ + ExpectIntEQ(extData->length, 24); + if (extData != NULL && extData->data != NULL && extData->length == 24) { + ExpectIntEQ((unsigned char)extData->data[0], 0x30); + ExpectIntEQ((unsigned char)extData->data[2], 0x80); + ExpectIntEQ((unsigned char)extData->data[3], 0x14); + ExpectIntEQ(XMEMCMP((const byte*)extData->data + 4, akid1, + sizeof(akid1)), 0); + } + + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL); + XFREE(key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(name, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(header, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + wolfSSL_X509_free(src); + wolfSSL_X509_free(built); + wolfSSL_X509_free(parsed); + wolfSSL_X509_free(loaded); + + wolfSSL_EVP_PKEY_free(priv); + wolfSSL_EVP_PKEY_free(pub); + + wolfSSL_ASN1_TIME_free(notBefore); + wolfSSL_ASN1_TIME_free(notAfter); +#endif + return EXPECT_RESULT(); +} + static int test_wolfSSL_OpenSSL_add_all_algorithms(void) { EXPECT_DECLS; @@ -37213,6 +37626,9 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_X509_ALGOR_get0), TEST_DECL(test_wolfSSL_X509_SEP), TEST_DECL(test_wolfSSL_X509_set_extensions), + TEST_DECL(test_wolfSSL_X509_set_authority_key_id_roundtrip), + TEST_DECL(test_wolfSSL_X509_set_authority_key_id_ex_roundtrip), + TEST_DECL(test_wolfSSL_X509_set_authority_key_id_overwrite), TEST_DECL(test_wolfSSL_X509_CRL), #ifndef NO_BIO TEST_DECL(test_wolfSSL_X509_print),