diff --git a/src/crl.c b/src/crl.c index 1a62f7f521e..1e930d02e50 100644 --- a/src/crl.c +++ b/src/crl.c @@ -217,6 +217,11 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, XMEMCPY(crle->crlNumber, dcrl->crlNumber, sizeof(crle->crlNumber)); } crle->verified = verified; +#if !defined(NO_SKID) && !defined(NO_ASN) + crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; + if (crle->extAuthKeyIdSet) + XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); +#endif if (!verified) { crle->tbsSz = dcrl->sigIndex - dcrl->certBegin; crle->signatureSz = dcrl->sigLength; @@ -251,11 +256,6 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, #endif XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz); XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz); - #ifndef NO_SKID - crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; - if (crle->extAuthKeyIdSet) - XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); - #endif } else { crle->toBeSigned = NULL; @@ -536,89 +536,176 @@ static int VerifyCRLE(const WOLFSSL_CRL* crl, CRL_Entry* crle, return ret; } +/* Check the cert (issuer name hash + serial) against every stored CRL from + * that issuer name. + * + * akid is the cert's Authority Key Identifier, or NULL if it has none. A CA + * that has rolled its key can have several CRLs under the same name, one per + * key, so the AKID splits them into: + * own-key CRLs: signed by the key that signed the cert (CRL AKID == akid), + * or either side has no AKID. + * other-key CRLs: signed by a different key of the same-name CA. + * + * A if a cert has an own key CRL we prefer that. Otherwise we check the other + * CRLs for the issuer to see if the cert is revoked there. + * + * CRLs that fail signature verification are skipped entirely. + * + * Returns CRL_CERT_REVOKED if revoked, CRL_CERT_DATE_ERR if the CRLs that + * count are all past their next update, or 0. */ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int serialSz, byte* serialHash, int *pFoundEntry, - WOLFSSL_CERT_MANAGER* cm) + WOLFSSL_CERT_MANAGER* cm, const byte* akid) { CRL_Entry* crle; - int foundEntry = 0; int ret = 0; + int ownSeen = 0; /* found CRL with AKID == Cert AKID + Issuer same */ + int ownFresh = 0; /* CRL was not expired */ + int otherSeen = 0; /* Found CRL with same Issuer as Cert */ + int otherFresh = 0; /* CRL was not expired */ +#if !defined(NO_SKID) && !defined(NO_ASN) + /* Trust anchor of the cert's issuer. Only needed for other-key CRLs, so + * it is looked up lazily the first time one is found. */ + Signer* certAnchor = NULL; + int certAnchorSet = 0; +#endif if (wc_LockRwLock_Rd(&crl->crlLock) != 0) { WOLFSSL_MSG("wc_LockRwLock_Rd failed"); return BAD_MUTEX_E; } +#if defined(NO_SKID) || defined(NO_ASN) + (void)akid; +#endif + for (crle = crl->crlList; crle != NULL; crle = crle->next) { - if (XMEMCMP(crle->issuerHash, issuerHash, CRL_DIGEST_SIZE) == 0) { - int nextDateValid = 1; - - WOLFSSL_MSG("Found CRL Entry on list"); - - if (cm != crl->cm) { - /* cm is not the owning cm of crl. The cached result is only - * valid for the owning cm. Verify again without caching. */ - ret = VerifyCRLE(crl, crle, cm, 0); - if (ret != 0) { - WOLFSSL_MSG("Cannot use CRL as it didn't verify"); - break; - } - } - else { - if (crle->verified == 0) { - if (wc_LockMutex(&crle->verifyMutex) != 0) { - WOLFSSL_MSG("wc_LockMutex failed"); - break; - } + int nextDateValid = 1; + int vret = 0; + int ownKey = 1; + /* Whether this CRL can count toward coverage. It can always revoke. */ + int vouches = 1; - /* A different thread may have verified the entry while we - * were waiting for the mutex. */ - if (crle->verified == 0) - ret = VerifyCRLE(crl, crle, cm, 1); + if (XMEMCMP(crle->issuerHash, issuerHash, CRL_DIGEST_SIZE) != 0) { + continue; + } - wc_UnLockMutex(&crle->verifyMutex); + #if !defined(NO_SKID) && !defined(NO_ASN) + /* Only an AKID mismatch makes it an other-key CRL. If either the + * cert or the CRL has no AKID, treat the CRL as own-key. */ + if (akid != NULL && crle->extAuthKeyIdSet && + XMEMCMP(crle->extAuthKeyId, akid, KEYID_SIZE) != 0) { + ownKey = 0; + } + #endif - if (ret != 0) - break; - } + WOLFSSL_MSG("Found CRL Entry on list"); - if (crle->verified < 0) { - WOLFSSL_MSG("Cannot use CRL as it didn't verify"); - ret = crle->verified; - break; - } + if (cm != crl->cm) { + /* cm is not the owning cm of crl. The cached result is only + * valid for the owning cm. Verify again without caching. */ + vret = VerifyCRLE(crl, crle, cm, 0); + } + else if (crle->verified == 0) { + if (wc_LockMutex(&crle->verifyMutex) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + break; } - WOLFSSL_MSG("Checking next date validity"); + /* A different thread may have verified the entry while we + * were waiting for the mutex. */ + if (crle->verified == 0) + vret = VerifyCRLE(crl, crle, cm, 1); - #ifdef WOLFSSL_NO_CRL_NEXT_DATE - if (crle->nextDateFormat != ASN_OTHER_TYPE) - #endif - { - #if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) - if (!XVALIDATE_DATE(crle->nextDate, crle->nextDateFormat, - ASN_AFTER, MAX_DATE_SIZE)) { - WOLFSSL_MSG("CRL next date is no longer valid"); - nextDateValid = 0; - } - #endif + wc_UnLockMutex(&crle->verifyMutex); + } + + /* A CRL that failed verification (now, or cached from an earlier + * check) is skipped rather than failing the whole check, since + * another CRL for this issuer may still apply. */ + if (vret == 0 && cm == crl->cm && crle->verified < 0) + vret = crle->verified; + if (vret != 0) { + WOLFSSL_MSG("Cannot use CRL as it didn't verify"); + continue; + } + + #ifdef WOLFSSL_NO_CRL_NEXT_DATE + if (crle->nextDateFormat != ASN_OTHER_TYPE) + #endif + { + #if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) + if (!XVALIDATE_DATE(crle->nextDate, crle->nextDateFormat, + ASN_AFTER, MAX_DATE_SIZE)) { + WOLFSSL_MSG("CRL next date is no longer valid"); + nextDateValid = 0; } - if (nextDateValid) { - foundEntry = 1; - ret = FindRevokedSerial(crle->certs, serial, serialSz, - serialHash, crle->totalCerts); - if (ret != 0) - break; + #endif + } + #if !defined(NO_SKID) && !defined(NO_ASN) + /* RFC 5280 6.3.3(f): We can only trust a CRL to tell us a cert is + * not revoked if it comes from the same trust anchor. We can + * still use it to revoke however so we track that here by setting + * vouches to 0 if the anchors do not match */ + if (!ownKey) { + Signer* crlAnchor; + + if (!certAnchorSet) { + certAnchor = GetCATrustAnchor(cm, GetCA(cm, (byte*)akid)); + certAnchorSet = 1; } - else if (foundEntry == 0) { - ret = CRL_CERT_DATE_ERR; + crlAnchor = GetCATrustAnchor(cm, + GetCA(cm, (byte*)crle->extAuthKeyId)); + if (certAnchor == NULL || crlAnchor != certAnchor) { + WOLFSSL_MSG("CRL issuer chains to another trust anchor"); + vouches = 0; } } + #endif + + if (ownKey) { + ownSeen = 1; + } else if (vouches) { + otherSeen = 1; + } + + if (!nextDateValid) { + continue; + } + + if (ownKey) { + ownFresh = 1; + } + + else if (vouches) { + otherFresh = 1; + } + + /* Issuer name + serial uniquely identify the cert, so any fresh, + * verified CRL for this name can revoke it, whichever key signed it + * and whichever anchor it chains to. */ + ret = FindRevokedSerial(crle->certs, serial, serialSz, + serialHash, crle->totalCerts); + /* Cert was found to be revoked so break out */ + if (ret != 0) + break; } wc_UnLockRwLock(&crl->crlLock); - *pFoundEntry = foundEntry; + if (ret == 0) { + /* If a crl for the cert was found we check if the crl was expired and + * return our finding. If the CRL was fresh we set pEntryFound to 1. */ + int seen = ownSeen ? ownSeen : otherSeen; + int fresh = ownSeen ? ownFresh : otherFresh; + + *pFoundEntry = fresh; + if (!fresh && seen) + ret = CRL_CERT_DATE_ERR; + } + else { + *pFoundEntry = 1; + } return ret; } @@ -629,7 +716,7 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int serialSz, byte* serialHash, const byte* extCrlInfo, int extCrlInfoSz, void* issuerName, WOLFSSL_CERT_MANAGER* cm, - int canRetry) + int canRetry, const byte* akid) { int foundEntry = 0; int ret = 0; @@ -651,7 +738,7 @@ static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, #endif ret = CheckCertCRLList(crl, issuerHash, serial, serialSz, serialHash, - &foundEntry, cm); + &foundEntry, cm, akid); #ifdef HAVE_CRL_IO if (foundEntry == 0) { @@ -665,7 +752,7 @@ static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, else if (cbRet >= 0) { /* try again */ ret = CheckCertCRLList(crl, issuerHash, serial, serialSz, - serialHash, &foundEntry, cm); + serialHash, &foundEntry, cm, akid); } } } @@ -684,7 +771,7 @@ static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, if (loadRet == WOLFSSL_SUCCESS) { /* try again */ ret = CheckCertCRLList(crl, issuerHash, serial, serialSz, - serialHash, &foundEntry, cm); + serialHash, &foundEntry, cm, akid); } } } @@ -731,10 +818,10 @@ static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int serialSz, byte* serialHash, const byte* extCrlInfo, - int extCrlInfoSz, void* issuerName) + int extCrlInfoSz, void* issuerName, const byte* akid) { return CheckCertCRLCm(crl, issuerHash, serial, serialSz, serialHash, - extCrlInfo, extCrlInfoSz, issuerName, crl->cm, 1); + extCrlInfo, extCrlInfoSz, issuerName, crl->cm, 1, akid); } /* Get the issuer X509_NAME of cert to pass to CheckCertCRLCm(). */ @@ -760,7 +847,13 @@ static int CheckDecodedCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert, return CheckCertCRLCm(crl, cert->issuerHash, cert->serial, cert->serialSz, NULL, cert->extCrlInfo, cert->extCrlInfoSz, issuerName, cm, - canRetry); + canRetry, + #if !defined(NO_SKID) && !defined(NO_ASN) + cert->extAuthKeyIdSet ? cert->extAuthKeyId : NULL + #else + NULL + #endif + ); } /* Is the cert ok with CRL, return 0 on success */ @@ -903,50 +996,74 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, CRL_Entry* crle, #endif for (curr = crl->crlList; curr != NULL; curr = curr->next) { - if (XMEMCMP(curr->issuerHash, crle->issuerHash, CRL_DIGEST_SIZE) == 0) { - if ((curr->verified > 0) && (crle->verified == 0)) { - WOLFSSL_MSG("Unverified CRL cannot replace a verified entry"); - wc_UnLockRwLock(&crl->crlLock); - return DUPE_ENTRY_E; - } - - ret = CompareCRLnumber(crle, curr); - /* Error out if the CRL we're attempting to add isn't more - * authoritative than the existing entry */ - if (ret == MP_LT || ret == MP_EQ) { - WOLFSSL_MSG("Same or newer CRL entry already exists"); - wc_UnLockRwLock(&crl->crlLock); - return DUPE_ENTRY_E; - } - else if (ret < 0) { - WOLFSSL_MSG("Error comparing CRL Numbers"); - wc_UnLockRwLock(&crl->crlLock); - return ret; - } + if (XMEMCMP(crle->issuerHash, curr->issuerHash, CRL_DIGEST_SIZE) != 0) { + prev = curr; + continue; + } - /* Insert the new entry after the current entry. */ - crle->next = curr->next; - if (prev != NULL) { - prev->next = crle; - } - else { - crl->crlList = crle; - } + /* An unverified CRL can't replace a verified one from the same + * issuer. */ + if ((curr->verified > 0) && (crle->verified == 0)) { + WOLFSSL_MSG("Cannot replace a verified CRL with an " + "unverified one"); + wc_UnLockRwLock(&crl->crlLock); + return DUPE_ENTRY_E; + } -#ifdef HAVE_CRL_UPDATE_CB - if (crl->cm && crl->cm->cbUpdateCRL != NULL) { - SetCrlInfo(curr, &old); - SetCrlInfo(crle, &cnew); - crl->cm->cbUpdateCRL(&old, &cnew); - } +#if !defined(NO_SKID) && !defined(NO_ASN) + /* Each signing key of a same-name CA keeps its own CRL series, so a + * CRL only replaces a stored one signed by the same key. Keep + * looking (and add it as a new series if nothing matches) when: + * - both have an AKID and they differ, or + * - the new CRL has no AKID but the stored one does. + * A new CRL with an AKID may replace a stored one without. */ + if (crle->extAuthKeyIdSet && curr->extAuthKeyIdSet) { + if(XMEMCMP(crle->extAuthKeyId, curr->extAuthKeyId, + KEYID_SIZE) != 0) { + prev = curr; + continue; + } + } + else if (!crle->extAuthKeyIdSet && curr->extAuthKeyIdSet) { + prev = curr; + continue; + } #endif + ret = CompareCRLnumber(crle, curr); + /* Error out if the CRL we're attempting to add isn't more + * authoritative than the existing entry */ + if (ret == MP_LT || ret == MP_EQ) { + WOLFSSL_MSG("Same or newer CRL entry already exists"); + wc_UnLockRwLock(&crl->crlLock); + return DUPE_ENTRY_E; + } + else if (ret < 0) { + WOLFSSL_MSG("Error comparing CRL Numbers"); + wc_UnLockRwLock(&crl->crlLock); + return ret; + } - /* Remove the current entry which was replaced */ - CRL_Entry_free(curr, crl->heap); + /* Insert the new entry after the current entry. */ + crle->next = curr->next; + if (prev != NULL) { + prev->next = crle; + } + else { + crl->crlList = crle; + } - break; +#ifdef HAVE_CRL_UPDATE_CB + if (crl->cm && crl->cm->cbUpdateCRL != NULL) { + SetCrlInfo(curr, &old); + SetCrlInfo(crle, &cnew); + crl->cm->cbUpdateCRL(&old, &cnew); } - prev = curr; +#endif + + /* Remove the current entry which was replaced */ + CRL_Entry_free(curr, crl->heap); + + break; } if (curr == NULL) { @@ -1547,9 +1664,6 @@ static CRL_Entry* DupCRL_Entry(const CRL_Entry* ent, void* heap) #ifdef WC_RSA_PSS dupl->sigParams = NULL; dupl->sigParamsSz = 0; -#endif -#if !defined(NO_SKID) && !defined(NO_ASN) - dupl->extAuthKeyIdSet = 0; #endif } diff --git a/src/internal.c b/src/internal.c index 34fc49a735b..cf65dbbda26 100644 --- a/src/internal.c +++ b/src/internal.c @@ -18477,18 +18477,36 @@ static int ProcessPeerCertsChainOCSPStatusCheck(WOLFSSL* ssl) #endif #ifdef HAVE_CRL + static int ProcessPeerCertsChainCRLCheck(WOLFSSL* ssl, ProcPeerCertArgs* args) { Signer* prev = NULL; + Signer* prevPrev = NULL; int ret = 0; WOLFSSL_CERT_MANAGER* cm = SSL_CM(ssl); Signer* ca = args->dCert->ca; - /* End loop if no more issuers found or if we have - * found a self signed cert (ca == prev) */ - for (; ret == 0 && ca != NULL && ca != prev; - prev = ca, ca = GetCAByName(cm, ca->issuerNameHash)) { + word32 walkIterationCnt = 0; + /* Walk up the chain checking each CA against its issuer's CRL. Stop when: + * - the issuer isn't loaded (ca == NULL), + * - we reach a self-signed root (GetCAIssuer returns ca, so ca == prev), + * - two cross-certified CAs point back at each other (ca == prevPrev). + * Longer loops are stopped by the WOLFSSL_MAX_CHAIN_DEPTH limit. */ + for (; ret == 0 && ca != NULL && ca != prev && ca != prevPrev; + prevPrev = prev, prev = ca, ca = GetCAIssuer(cm, ca)) { + /* ca's AKID identifies the key that signed ca, which picks out that + * key's CRL when the issuer has several keys under one name. */ + const byte* caAkid = NULL; + + if (++walkIterationCnt > WOLFSSL_MAX_CHAIN_DEPTH) { + ret = ASN_PATHLEN_SIZE_E; + break; + } + #ifndef NO_SKID + if (ca->authKeyIdSet) + caAkid = ca->authKeyIdHash; + #endif ret = CheckCertCRL_ex(cm->crl, ca->issuerNameHash, NULL, 0, - ca->serialHash, NULL, 0, NULL); + ca->serialHash, NULL, 0, NULL, caAkid); #ifdef WOLFSSL_NONBLOCK_OCSP if (ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) break; diff --git a/src/ssl_certman.c b/src/ssl_certman.c index 0946251320b..a9e29fb9cf0 100644 --- a/src/ssl_certman.c +++ b/src/ssl_certman.c @@ -3096,6 +3096,66 @@ Signer* GetCAByName(WOLFSSL_CERT_MANAGER* cm, byte* hash) } #endif +#ifdef HAVE_CRL +/* Find the loaded CA that issued ca. + * Returns ca itself if ca is self-signed (a root), or NULL if the issuer is + * not loaded in cm. */ +Signer* GetCAIssuer(WOLFSSL_CERT_MANAGER* cm, Signer* ca) +{ + Signer* candidateIssuer = NULL; + + if (ca->selfSigned) + return ca; + +#ifndef NO_SKID + if (ca->authKeyIdSet) { + /* Look the issuer up by key (ca's AKID) */ + candidateIssuer = GetCA(cm, ca->authKeyIdHash); + if (candidateIssuer != NULL && + XMEMCMP(candidateIssuer->subjectNameHash, ca->issuerNameHash, + SIGNER_DIGEST_SIZE) != 0) { + candidateIssuer = NULL; + } + return candidateIssuer; + } + /* No AKID: the issuer name is all there is to go on. */ + return GetCAByName(cm, ca->issuerNameHash); +#else + /* No AKID: the issuer name is all there is to go on. + * GetCA uses issuer when NO_SKID is set */ + (void)candidateIssuer; + return GetCA(cm, ca->issuerNameHash); +#endif +} + +/* Find the trust anchor that ca chains up to in cm. + * Walks issuers with GetCAIssuer() and returns the top of the chain: the first + * CA that is self-signed or whose issuer isn't loaded. + * Returns NULL if ca is NULL, or if no single anchor exists because the chain + * loops or is longer than WOLFSSL_MAX_CHAIN_DEPTH. */ +Signer* GetCATrustAnchor(WOLFSSL_CERT_MANAGER* cm, Signer* ca) +{ + Signer* prev = NULL; + Signer* issuer; + word32 depth = 0; + + while (ca != NULL) { + if (++depth > WOLFSSL_MAX_CHAIN_DEPTH) + return NULL; + issuer = GetCAIssuer(cm, ca); + if (issuer == NULL || issuer == ca) + return ca; + /* Two CAs that issued each other (cross-certified): no anchor. + * Longer loops are caught by the depth limit. */ + if (issuer == prev) + return NULL; + prev = ca; + ca = issuer; + } + return NULL; +} +#endif /* HAVE_CRL */ + #ifdef WOLFSSL_TRUST_PEER_CERT /* add a trusted peer cert to linked list */ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) diff --git a/tests/api.c b/tests/api.c index 403545cd342..7daaf4bef51 100644 --- a/tests/api.c +++ b/tests/api.c @@ -32037,17 +32037,21 @@ static int test_sk_X509_CRL_encode(void) defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ !defined(NO_STDIO_FILESYSTEM) && defined(WOLFSSL_CERT_GEN) && \ !defined(NO_ASN_TIME) + /* The generated CRLs really revoke server-cert.pem and server-ecc.pem, so + * write them to a private directory, not certs/crl/ where the example + * client loads every CRL and would then reject the test servers. */ + char tmpDir[16] = {0}; #ifndef NO_RSA - static const char* crlRsaPemFile = "./certs/crl/crlRsaOut.pem"; - static const char* crlRsaDerFile = "./certs/crl/crlRsaOut.der"; + char crlRsaPemFile[64] = {0}; + char crlRsaDerFile[64] = {0}; static const char* testRsaKeyFile = "./certs/ca-key.pem"; /* Use ca-cert.pem to match ca-key.pem for proper CRL verification */ static const char* testRsaCertFile = "./certs/ca-cert.pem"; static const char* revokeRsaCertFile = "./certs/server-cert.pem"; #endif #ifdef HAVE_ECC - static const char* crlEccPemFile = "./certs/crl/crlEccOut.pem"; - static const char* crlEccDerFile = "./certs/crl/crlEccOut.der"; + char crlEccPemFile[64] = {0}; + char crlEccDerFile[64] = {0}; static const char* testEccKeyFile = "./certs/ca-ecc-key.pem"; /* Use ca-ecc-cert.pem to match ca-ecc-key.pem for proper CRL * verification */ @@ -32055,17 +32059,39 @@ static int test_sk_X509_CRL_encode(void) static const char* revokeEccCertFile = "./certs/server-ecc.pem"; #endif + XMEMSET(tmpDir, 0, sizeof(tmpDir)); + ExpectNotNull(create_tmp_dir(tmpDir, (int)sizeof(tmpDir) - 1)); + #ifndef NO_RSA + ExpectIntGT(XSNPRINTF(crlRsaPemFile, sizeof(crlRsaPemFile), + "%s/crlRsaOut.pem", tmpDir), 0); + ExpectIntGT(XSNPRINTF(crlRsaDerFile, sizeof(crlRsaDerFile), + "%s/crlRsaOut.der", tmpDir), 0); /* Generate RSA-signed CRL (PEM and DER) */ ExpectIntEQ(generate_crl_test(testRsaKeyFile, testRsaCertFile, crlRsaDerFile, crlRsaPemFile, revokeRsaCertFile), TEST_SUCCESS); + if (crlRsaPemFile[0] != '\0') + (void)rem_file(crlRsaPemFile); + if (crlRsaDerFile[0] != '\0') + (void)rem_file(crlRsaDerFile); #endif #ifdef HAVE_ECC + ExpectIntGT(XSNPRINTF(crlEccPemFile, sizeof(crlEccPemFile), + "%s/crlEccOut.pem", tmpDir), 0); + ExpectIntGT(XSNPRINTF(crlEccDerFile, sizeof(crlEccDerFile), + "%s/crlEccOut.der", tmpDir), 0); /* Generate ECC-signed CRL (PEM and DER) */ ExpectIntEQ(generate_crl_test(testEccKeyFile, testEccCertFile, crlEccDerFile, crlEccPemFile, revokeEccCertFile), TEST_SUCCESS); + if (crlEccPemFile[0] != '\0') + (void)rem_file(crlEccPemFile); + if (crlEccDerFile[0] != '\0') + (void)rem_file(crlEccDerFile); #endif + + if (tmpDir[0] != '\0') + (void)rem_dir(tmpDir); #endif return EXPECT_RESULT(); } diff --git a/tests/api/include.am b/tests/api/include.am index c67ed918039..32181fab3e8 100644 --- a/tests/api/include.am +++ b/tests/api/include.am @@ -271,6 +271,7 @@ EXTRA_DIST += tests/api/test_evp_digest.h EXTRA_DIST += tests/api/test_evp_cipher.h EXTRA_DIST += tests/api/test_evp_pkey.h EXTRA_DIST += tests/api/test_certman.h +EXTRA_DIST += tests/api/test_certman_crl_fixtures.h EXTRA_DIST += tests/api/test_tls13.h EXTRA_DIST += tests/api/test_tls13_bounds.h EXTRA_DIST += tests/api/test_tls13_features.h diff --git a/tests/api/test_certman.c b/tests/api/test_certman.c index 2b8f2064c34..c2673ce7984 100644 --- a/tests/api/test_certman.c +++ b/tests/api/test_certman.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -3720,6 +3721,769 @@ int test_wolfSSL_CRL_unverified_no_evict(void) return EXPECT_RESULT(); } +#if defined(HAVE_CRL) && !defined(NO_CERTS) && defined(HAVE_ECC) && \ + !defined(NO_ECC256) && !defined(NO_SKID) && \ + !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) && \ + !defined(WOLFSSL_NO_CRL_NEXT_DATE) && \ + !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) +/* Fake clock for the fixture CRLs. NOW (2027) has every CRL current. LATER + * (2035) has the *Expiring CRLs (next update 2030) expired. Expired CRLs can't + * be loaded, so tests load at NOW and check at LATER. */ +#define TEST_CRL_FIXTURE_NOW 1798761600L +#define TEST_CRL_FIXTURE_LATER 2051222400L + +static time_t test_crl_fixture_time = (time_t)TEST_CRL_FIXTURE_NOW; + +static WC_MAYBE_UNUSED time_t test_crl_fixture_time_cb(time_t* t) +{ + if (t != NULL) + *t = test_crl_fixture_time; + return test_crl_fixture_time; +} +#endif + +#if defined(TEST_CRL_UNVERIFIED_NO_EVICT) && !defined(NO_FILESYSTEM) && \ + defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_SKID) && \ + !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) && \ + !defined(WOLFSSL_NO_CRL_NEXT_DATE) && \ + !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) + #define TEST_CRL_SKIP_UNVERIFIABLE +#endif + +/* A stored CRL that fails verification is skipped, not an error. If a good CRL + * is also loaded, it decides (including its date error); otherwise the result + * is CRL_MISSING. + * + * The bad CRL is loaded with X509_STORE_load_locations(), which doesn't + * verify, and before the good CRL, since a verified CRL would block it. The + * leaf has no AKID, so every CRL for the issuer's name applies. + * + * Fixtures: the old root, its leaf with no AKID (0x60), and old-key CRLs. */ +int test_wolfSSL_CRL_skip_unverifiable(void) +{ + EXPECT_DECLS; +#ifdef TEST_CRL_SKIP_UNVERIFIABLE + + static const struct { + const char* bad; /* Stored unverified; fails when checked. */ + int caAfterBad; /* Load the CA after the bad CRL. */ + const unsigned char* good; /* Loaded after the bad CRL, or NULL. */ + int goodSz; + int checks; /* Times the leaf is checked. */ + int later; /* Check at TEST_CRL_FIXTURE_LATER. */ + int expected; + } cases[] = { + /* No signer for the bad CRL: the good one decides. */ + { fxCrlStrayPem, 0, fxCrlOld5, (int)sizeof(fxCrlOld5), 1, 0, + WOLFSSL_SUCCESS }, + /* No signer and no good CRL: missing. */ + { fxCrlStrayPem, 0, NULL, 0, 1, 0, WC_NO_ERR_TRACE(CRL_MISSING) }, + /* Bad signature, checked twice: the cached failure is skipped too. */ + { fxCrlBadSigPem, 1, NULL, 0, 2, 0, WC_NO_ERR_TRACE(CRL_MISSING) }, + /* Good CRL expired: the bad one doesn't hide that. */ + { fxCrlStrayPem, 0, fxCrlOld4Expiring, (int)sizeof(fxCrlOld4Expiring), + 1, 1, WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR) } + }; + char tmpDir[16]; + char fileWithBadCrl[64]; + size_t i; + + XMEMSET(tmpDir, 0, sizeof(tmpDir)); + XMEMSET(fileWithBadCrl, 0, sizeof(fileWithBadCrl)); + + /* Per-run directory so concurrent unit.test runs don't collide. */ + ExpectNotNull(create_tmp_dir(tmpDir, (int)sizeof(tmpDir) - 1)); + ExpectIntGT(XSNPRINTF(fileWithBadCrl, sizeof(fileWithBadCrl), + "%s/crl.pem", tmpDir), 0); + + for (i = 0; i < XELEM_CNT(cases) && !EXPECT_FAIL(); i++) { + WOLFSSL_X509_STORE* store = NULL; + WOLFSSL_CERT_MANAGER* cm = NULL; + XFILE f = XBADFILE; + int badSz = (int)XSTRLEN(cases[i].bad); + int j; + + test_crl_fixture_time = (time_t)TEST_CRL_FIXTURE_NOW; + ExpectIntEQ(wc_SetTimeCb(test_crl_fixture_time_cb), 0); + ExpectNotNull(store = wolfSSL_X509_STORE_new()); + if (store != NULL) + cm = store->cm; + ExpectIntEQ(wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK), + WOLFSSL_SUCCESS); + if (!cases[i].caAfterBad) { + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootOld, + sizeof(fxRootOld), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + } + + ExpectTrue((f = XFOPEN(fileWithBadCrl, "wb")) != XBADFILE); + ExpectIntEQ((int)XFWRITE(cases[i].bad, 1, (size_t)badSz, f), badSz); + if (f != XBADFILE) + XFCLOSE(f); + ExpectIntEQ(wolfSSL_X509_STORE_load_locations(store, fileWithBadCrl, + NULL), WOLFSSL_SUCCESS); + + if (cases[i].caAfterBad) { + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootOld, + sizeof(fxRootOld), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + } + if (cases[i].good != NULL) { + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, cases[i].good, + cases[i].goodSz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + } + + if (cases[i].later) { + test_crl_fixture_time = (time_t)TEST_CRL_FIXTURE_LATER; + } + for (j = 0; j < cases[i].checks; j++) { + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxLeafNoAkid, + (int)sizeof(fxLeafNoAkid)), cases[i].expected); + } + (void)wc_SetTimeCb(NULL); + if (EXPECT_FAIL()) { + fprintf(stderr, "CRL skip case %d failed\n", (int)i); + } + + wolfSSL_X509_STORE_free(store); + } + + if (fileWithBadCrl[0] != '\0') + (void)rem_file(fileWithBadCrl); + if (tmpDir[0] != '\0') + (void)rem_dir(tmpDir); +#endif + return EXPECT_RESULT(); +} + +/* A CA that rolled its key has one CRL series per key. One key's CRL doesn't + * replace or block the other's, in any order or CRL number. Within a key, a + * higher CRL number replaces a lower one. + * + * Fixtures: the old and new roots and a leaf from each, revoked by its key's + * CRL. CRL numbers: old 5; new 1 or 6. */ +int test_wolfSSL_CRL_same_name_key_rollover(void) +{ + EXPECT_DECLS; +#if defined(HAVE_CRL) && !defined(NO_CERTS) && defined(HAVE_ECC) && \ + !defined(NO_ECC256) && !defined(NO_SHA256) && !defined(NO_SKID) && \ + !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) + struct { + const unsigned char* der; + int sz; + } crls[3]; + /* One CRL per key, both orders. The new key's number is both lower and + * higher than the old key's. */ + static const int rollover[4][2] = { + { 0, 1 }, { 1, 0 }, /* old 5, new 1 */ + { 0, 2 }, { 2, 0 } /* old 5, new 6 */ + }; + WOLFSSL_CERT_MANAGER* cm = NULL; + size_t i; + int ret; + + crls[0].der = fxCrlOld5; crls[0].sz = (int)sizeof(fxCrlOld5); + crls[1].der = fxCrlNew1; crls[1].sz = (int)sizeof(fxCrlNew1); + crls[2].der = fxCrlNew6; crls[2].sz = (int)sizeof(fxCrlNew6); + + /* Controls: each CRL on its own revokes its own key's leaf. */ + for (i = 0; i < XELEM_CNT(crls); i++) { + ExpectNotNull(cm = wolfSSL_CertManagerNew()); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootOld, + sizeof(fxRootOld), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootNew, + sizeof(fxRootNew), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, crls[i].der, + crls[i].sz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + if (i == 0) { + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxLeafOld, + (int)sizeof(fxLeafOld)), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); + } + else { + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxLeafNew, + (int)sizeof(fxLeafNew)), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); + } + wolfSSL_CertManagerFree(cm); + cm = NULL; + } + + /* Same key: 6 replaces 1, then 1 is rejected as older. */ + ExpectNotNull(cm = wolfSSL_CertManagerNew()); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootNew, + sizeof(fxRootNew), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, fxCrlNew1, + sizeof(fxCrlNew1), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, fxCrlNew6, + sizeof(fxCrlNew6), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, fxCrlNew1, + sizeof(fxCrlNew1), WOLFSSL_FILETYPE_ASN1), + WC_NO_ERR_TRACE(DUPE_ENTRY_E)); + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxLeafNew, + (int)sizeof(fxLeafNew)), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); + wolfSSL_CertManagerFree(cm); + cm = NULL; + + /* One CRL per key: both leaves revoked. */ + for (i = 0; i < 4; i++) { + const int first = rollover[i][0]; + const int second = rollover[i][1]; + + ExpectNotNull(cm = wolfSSL_CertManagerNew()); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootOld, + sizeof(fxRootOld), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootNew, + sizeof(fxRootNew), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, crls[first].der, + crls[first].sz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + /* Asserted after the revocation checks. */ + ret = WOLFSSL_FATAL_ERROR; + if (EXPECT_SUCCESS()) { + ret = wolfSSL_CertManagerLoadCRLBuffer(cm, crls[second].der, + crls[second].sz, WOLFSSL_FILETYPE_ASN1); + } + + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxLeafOld, + (int)sizeof(fxLeafOld)), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxLeafNew, + (int)sizeof(fxLeafNew)), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); + /* Not rejected as a duplicate of the other key's CRL. */ + ExpectIntEQ(ret, WOLFSSL_SUCCESS); + + wolfSSL_CertManagerFree(cm); + cm = NULL; + } +#endif + return EXPECT_RESULT(); +} + +/* A CA may sign CRLs with a key that signs no certs (RFC 5280 5.2.1). Its CRLs + * still revoke despite the AKID mismatch, as does a CRL from a same-name key + * that also signs certs. + * + * Fixtures: the old root and its leaf (0x10), a CRL-only key under the old + * root, and the new root as the dual-use key. Each key has a CRL revoking the + * leaf. */ +int test_wolfSSL_CRL_crl_only_signing_key(void) +{ + EXPECT_DECLS; +#if defined(HAVE_CRL) && !defined(NO_CERTS) && defined(HAVE_ECC) && \ + !defined(NO_ECC256) && !defined(NO_SHA256) && !defined(NO_SKID) && \ + !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) + WOLFSSL_CERT_MANAGER* cm = NULL; + + /* CRL-only key: chains to the leaf's trust anchor, so its CRL covers the + * leaf (RFC 5280 6.3.3(f)). */ + ExpectNotNull(cm = wolfSSL_CertManagerNew()); + /* Leaf issuer. */ + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootOld, + sizeof(fxRootOld), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + /* CRL signer. */ + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxCrlOnlyKey, + sizeof(fxCrlOnlyKey), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, fxCrlByCrlOnlyKey, + sizeof(fxCrlByCrlOnlyKey), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + /* Revoked. */ + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxLeafOld, + (int)sizeof(fxLeafOld)), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); + wolfSSL_CertManagerFree(cm); + cm = NULL; + + /* Dual-use key: another trust anchor, but its CRL still revokes. */ + ExpectNotNull(cm = wolfSSL_CertManagerNew()); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootOld, + sizeof(fxRootOld), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootNew, + sizeof(fxRootNew), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, fxCrlNew1, + sizeof(fxCrlNew1), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxLeafOld, + (int)sizeof(fxLeafOld)), WC_NO_ERR_TRACE(CRL_CERT_REVOKED)); + wolfSSL_CertManagerFree(cm); +#endif + return EXPECT_RESULT(); +} + +#if defined(HAVE_CRL) && !defined(NO_CERTS) && defined(HAVE_ECC) && \ + !defined(NO_ECC256) && !defined(NO_SHA256) && !defined(NO_SKID) && \ + !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) && \ + !defined(WOLFSSL_NO_CRL_NEXT_DATE) && \ + !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) + #define TEST_CRL_OTHER_KEY_FALLBACK +#endif + +/* Another key's CRL always revokes. The keys here are separate roots (RFC 5280 + * 6.3.3(f)), so it never covers the cert: with no own-key CRL the result is + * CRL_MISSING, and a fresh own-key CRL decides even if the other has expired. + * + * Fixtures: the old and new roots and the old key's leaf (0x10). The old key's + * CRL doesn't list the leaf. The new key has one CRL that revokes it and one + * that expires. */ +int test_wolfSSL_CRL_other_key_fallback(void) +{ + EXPECT_DECLS; +#ifdef TEST_CRL_OTHER_KEY_FALLBACK + /* A: the leaf's own key. B: the other key. */ + enum { XK_A, XK_B_REVOKED, XK_B_EXPIRING, XK_NONE }; + struct { + const unsigned char* der; + int sz; + } crls[XK_NONE]; + static const struct { + int first; + int second; + int later; /* Check at TEST_CRL_FIXTURE_LATER. */ + int expected; + } cases[] = { + /* Control: A's CRL covers the leaf. */ + { XK_A, XK_NONE, 0, WOLFSSL_SUCCESS }, + /* B revokes, even with A's fresh CRL. */ + { XK_A, XK_B_REVOKED, 0, WC_NO_ERR_TRACE(CRL_CERT_REVOKED) }, + { XK_B_REVOKED, XK_A, 0, WC_NO_ERR_TRACE(CRL_CERT_REVOKED) }, + /* B revokes with no A CRL. */ + { XK_B_REVOKED, XK_NONE, 0, WC_NO_ERR_TRACE(CRL_CERT_REVOKED) }, + /* B alone doesn't cover the leaf, fresh or expired. */ + { XK_B_EXPIRING, XK_NONE, 0, WC_NO_ERR_TRACE(CRL_MISSING) }, + { XK_B_EXPIRING, XK_NONE, 1, WC_NO_ERR_TRACE(CRL_MISSING) }, + /* A fresh, B expired: A decides. */ + { XK_A, XK_B_EXPIRING, 1, WOLFSSL_SUCCESS }, + { XK_B_EXPIRING, XK_A, 1, WOLFSSL_SUCCESS } + }; + WOLFSSL_CERT_MANAGER* cm = NULL; + size_t i; + + crls[XK_A].der = fxCrlOld6; + crls[XK_A].sz = (int)sizeof(fxCrlOld6); + crls[XK_B_REVOKED].der = fxCrlNew1; + crls[XK_B_REVOKED].sz = (int)sizeof(fxCrlNew1); + crls[XK_B_EXPIRING].der = fxCrlNew2Expiring; + crls[XK_B_EXPIRING].sz = (int)sizeof(fxCrlNew2Expiring); + + for (i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + test_crl_fixture_time = (time_t)TEST_CRL_FIXTURE_NOW; + ExpectIntEQ(wc_SetTimeCb(test_crl_fixture_time_cb), 0); + + ExpectNotNull(cm = wolfSSL_CertManagerNew()); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootOld, + sizeof(fxRootOld), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxRootNew, + sizeof(fxRootNew), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, + crls[cases[i].first].der, crls[cases[i].first].sz, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + if (cases[i].second != XK_NONE) { + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, + crls[cases[i].second].der, crls[cases[i].second].sz, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + } + if (cases[i].later) + test_crl_fixture_time = (time_t)TEST_CRL_FIXTURE_LATER; + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxLeafOld, + (int)sizeof(fxLeafOld)), cases[i].expected); + (void)wc_SetTimeCb(NULL); + if (EXPECT_FAIL()) { + fprintf(stderr, "CRL other key case %d failed\n", (int)i); + } + + wolfSSL_CertManagerFree(cm); + cm = NULL; + } +#endif + return EXPECT_RESULT(); +} + +/* RFC 5280 6.3.3(f): another key's CRL covers the cert only if that key + * chains to the cert's trust anchor. From another anchor it can still revoke, + * but otherwise the CRL counts as missing. + * + * Fixtures: two roots and three same-name intermediates (keys 1 and 2 under + * root 1, key 3 under root 2), and a leaf (0x70) under key 1. No key 1 CRL is + * loaded. */ +int test_wolfSSL_CRL_other_key_trust_anchor(void) +{ + EXPECT_DECLS; +#ifdef TEST_CRL_OTHER_KEY_FALLBACK + enum { AK_K2, AK_K3, AK_K3_REVOKED, AK_NONE }; + struct { + const unsigned char* der; + int sz; + } crls[AK_NONE]; + static const struct { + int first; + int second; + int expected; + } cases[] = { + /* Same anchor: key 2's CRL covers the leaf. */ + { AK_K2, AK_NONE, WOLFSSL_SUCCESS }, + /* Other anchor: key 3's doesn't. */ + { AK_K3, AK_NONE, WC_NO_ERR_TRACE(CRL_MISSING) }, + /* Key 2's covers it either way. */ + { AK_K2, AK_K3, WOLFSSL_SUCCESS }, + { AK_K3, AK_K2, WOLFSSL_SUCCESS }, + /* Other anchor's CRL still revokes. */ + { AK_K3_REVOKED, AK_NONE, WC_NO_ERR_TRACE(CRL_CERT_REVOKED) }, + { AK_K2, AK_K3_REVOKED, WC_NO_ERR_TRACE(CRL_CERT_REVOKED) } + }; + WOLFSSL_CERT_MANAGER* cm = NULL; + size_t i; + + crls[AK_K2].der = fxAnchorCrlK2; + crls[AK_K2].sz = (int)sizeof(fxAnchorCrlK2); + crls[AK_K3].der = fxAnchorCrlK3; + crls[AK_K3].sz = (int)sizeof(fxAnchorCrlK3); + crls[AK_K3_REVOKED].der = fxAnchorCrlK3Revoked; + crls[AK_K3_REVOKED].sz = (int)sizeof(fxAnchorCrlK3Revoked); + + for (i = 0; i < XELEM_CNT(cases) && !EXPECT_FAIL(); i++) { + test_crl_fixture_time = (time_t)TEST_CRL_FIXTURE_NOW; + ExpectIntEQ(wc_SetTimeCb(test_crl_fixture_time_cb), 0); + + ExpectNotNull(cm = wolfSSL_CertManagerNew()); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxAnchorRoot1, + sizeof(fxAnchorRoot1), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxAnchorRoot2, + sizeof(fxAnchorRoot2), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxAnchorIntK1, + sizeof(fxAnchorIntK1), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxAnchorIntK2, + sizeof(fxAnchorIntK2), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, fxAnchorIntK3, + sizeof(fxAnchorIntK3), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, + crls[cases[i].first].der, crls[cases[i].first].sz, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + if (cases[i].second != AK_NONE) { + ExpectIntEQ(wolfSSL_CertManagerLoadCRLBuffer(cm, + crls[cases[i].second].der, crls[cases[i].second].sz, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + } + ExpectIntEQ(wolfSSL_CertManagerCheckCRL(cm, fxAnchorLeaf, + (int)sizeof(fxAnchorLeaf)), cases[i].expected); + (void)wc_SetTimeCb(NULL); + if (EXPECT_FAIL()) { + fprintf(stderr, "CRL trust anchor case %d failed\n", (int)i); + } + + wolfSSL_CertManagerFree(cm); + cm = NULL; + } +#endif + return EXPECT_RESULT(); +} + +/* Key rollover during the WOLFSSL_CRL_CHECKALL chain walk. The intermediate's + * AKID picks the old key's CRL, and the new key's CRL can't stand in for an + * expired or missing one, since the keys are separate roots (RFC 5280 + * 6.3.3(f)). + * + * Fixtures: the old and new roots, the old key's intermediate (0x30) and its + * leaf. The server sends only the leaf, so the walk runs. */ +int test_wolfSSL_CRL_chain_same_name_key_rollover(void) +{ + EXPECT_DECLS; +#if defined(HAVE_CRL) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_SHA256) && \ + !defined(NO_SKID) && \ + !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) && \ + !defined(WOLFSSL_NO_CRL_NEXT_DATE) && \ + !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) + /* Root CRLs, as indexes into crls. fxCrlInt is always loaded. */ + enum { CRL_OLD, CRL_OLD_REVOKED, CRL_OLD_EXPIRING, CRL_NEW, CRL_NONE }; + struct { + const unsigned char* der; + int sz; + } crls[CRL_NONE]; + static const struct { + int first; + int second; + int later; /* Handshake at TEST_CRL_FIXTURE_LATER. */ + int expected; + } cases[] = { + /* Control: both current, nothing revoked. */ + { CRL_OLD, CRL_NEW, 0, 0 }, + { CRL_NEW, CRL_OLD, 0, 0 }, + { CRL_OLD_EXPIRING, CRL_NEW, 0, 0 }, + /* Old key revokes the intermediate. */ + { CRL_OLD_REVOKED, CRL_NEW, 0, WC_NO_ERR_TRACE(CRL_CERT_REVOKED) }, + { CRL_NEW, CRL_OLD_REVOKED, 0, WC_NO_ERR_TRACE(CRL_CERT_REVOKED) }, + /* No old-key CRL: the new key's doesn't cover. */ + { CRL_NEW, CRL_NONE, 0, WC_NO_ERR_TRACE(CRL_MISSING) }, + /* Old-key CRL expired: the new key's doesn't hide that. */ + { CRL_OLD_EXPIRING, CRL_NEW, 1, WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR) }, + { CRL_NEW, CRL_OLD_EXPIRING, 1, WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR) } + }; + size_t i; + + crls[CRL_OLD].der = fxCrlOld5; + crls[CRL_OLD].sz = (int)sizeof(fxCrlOld5); + crls[CRL_OLD_REVOKED].der = fxCrlOld6; + crls[CRL_OLD_REVOKED].sz = (int)sizeof(fxCrlOld6); + crls[CRL_OLD_EXPIRING].der = fxCrlOld4Expiring; + crls[CRL_OLD_EXPIRING].sz = (int)sizeof(fxCrlOld4Expiring); + crls[CRL_NEW].der = fxCrlNew1; + crls[CRL_NEW].sz = (int)sizeof(fxCrlNew1); + + for (i = 0; i < XELEM_CNT(cases) && !EXPECT_FAIL(); i++) { + struct test_memio_ctx test_ctx; + WOLFSSL_CTX* ctx_c = NULL; + WOLFSSL_CTX* ctx_s = NULL; + WOLFSSL* ssl_c = NULL; + WOLFSSL* ssl_s = NULL; + int load[2]; + int j; + + load[0] = cases[i].first; + load[1] = cases[i].second; + + test_crl_fixture_time = (time_t)TEST_CRL_FIXTURE_NOW; + ExpectIntEQ(wc_SetTimeCb(test_crl_fixture_time_cb), 0); + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup_ex(&test_ctx, &ctx_c, &ctx_s, &ssl_c, + &ssl_s, wolfSSLv23_client_method, wolfSSLv23_server_method, + (byte*)fxRootOld, (int)sizeof(fxRootOld), (byte*)fxLeafInt, + (int)sizeof(fxLeafInt), (byte*)fxLeafKey, (int)sizeof(fxLeafKey)), + 0); + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer(ctx_c, fxRootNew, + (long)sizeof(fxRootNew), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer(ctx_c, fxIntCa, + (long)sizeof(fxIntCa), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx_c, + WOLFSSL_CRL_CHECK | WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_LoadCRLBuffer(ctx_c, fxCrlInt, + (long)sizeof(fxCrlInt), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + for (j = 0; j < 2; j++) { + if (load[j] == CRL_NONE) + continue; + /* Different keys' CRLs coexist. */ + ExpectIntEQ(wolfSSL_CTX_LoadCRLBuffer(ctx_c, crls[load[j]].der, + (long)crls[load[j]].sz, WOLFSSL_FILETYPE_ASN1), + WOLFSSL_SUCCESS); + } + wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, NULL); + if (cases[i].later) { + test_crl_fixture_time = + (time_t)TEST_CRL_FIXTURE_LATER; + } + + if (cases[i].expected == 0) { + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + } + else { + ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectIntEQ(wolfSSL_get_error(ssl_c, 0), cases[i].expected); + } + (void)wc_SetTimeCb(NULL); + if (EXPECT_FAIL()) { + fprintf(stderr, "chain key rollover case %d failed\n", (int)i); + } + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); + } +#endif + return EXPECT_RESULT(); +} + +/* WOLFSSL_CRL_CHECKALL chain walk with two same-name roots. The walk steps to + * the root matching the intermediate's AKID, not the first root with that + * name. Roots are loaded in both orders, so in one a name lookup would land on + * the new root, whose CRL isn't loaded. + * + * Fixtures: the old and new roots, the old key's intermediate (0x30) and its + * leaf. Only the old key's CRL is loaded. The server sends only the leaf, so + * the walk runs. */ +int test_wolfSSL_CRL_chain_walk_follows_akid(void) +{ + EXPECT_DECLS; +#if defined(HAVE_CRL) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_SHA256) && \ + !defined(NO_SKID) && \ + !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) + static const struct { + const unsigned char* crl; /* Old root key's CRL, or NULL. */ + int crlSz; + int expected; + } cases[] = { + /* Old key's CRL is enough. */ + { fxCrlOld5, (int)sizeof(fxCrlOld5), 0 }, + /* Old key's CRL revokes the intermediate. */ + { fxCrlOld6, (int)sizeof(fxCrlOld6), + WC_NO_ERR_TRACE(CRL_CERT_REVOKED) }, + /* No root CRL: the intermediate isn't covered. */ + { NULL, 0, WC_NO_ERR_TRACE(CRL_MISSING) } + }; + size_t i; + int order; + + for (i = 0; i < XELEM_CNT(cases) && !EXPECT_FAIL(); i++) { + /* Load the roots in both orders. */ + for (order = 0; order < 2 && !EXPECT_FAIL(); order++) { + struct test_memio_ctx test_ctx; + WOLFSSL_CTX* ctx_c = NULL; + WOLFSSL_CTX* ctx_s = NULL; + WOLFSSL* ssl_c = NULL; + WOLFSSL* ssl_s = NULL; + const unsigned char* rootA = order ? fxRootNew : fxRootOld; + const unsigned char* rootB = order ? fxRootOld : fxRootNew; + int rootASz = order ? (int)sizeof(fxRootNew) : + (int)sizeof(fxRootOld); + int rootBSz = order ? (int)sizeof(fxRootOld) : + (int)sizeof(fxRootNew); + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup_ex(&test_ctx, &ctx_c, &ctx_s, &ssl_c, + &ssl_s, wolfSSLv23_client_method, wolfSSLv23_server_method, + (byte*)rootA, rootASz, (byte*)fxLeafInt, (int)sizeof(fxLeafInt), + (byte*)fxLeafKey, (int)sizeof(fxLeafKey)), 0); + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer(ctx_c, rootB, + (long)rootBSz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer(ctx_c, fxIntCa, + (long)sizeof(fxIntCa), WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx_c, + WOLFSSL_CRL_CHECK | WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_LoadCRLBuffer(ctx_c, fxCrlInt, + (long)sizeof(fxCrlInt), WOLFSSL_FILETYPE_ASN1), + WOLFSSL_SUCCESS); + if (cases[i].crl != NULL) { + ExpectIntEQ(wolfSSL_CTX_LoadCRLBuffer(ctx_c, cases[i].crl, + (long)cases[i].crlSz, WOLFSSL_FILETYPE_ASN1), + WOLFSSL_SUCCESS); + } + wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, NULL); + + if (cases[i].expected == 0) { + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), + 0); + } + else { + ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), + 0); + ExpectIntEQ(wolfSSL_get_error(ssl_c, 0), cases[i].expected); + } + if (EXPECT_FAIL()) { + fprintf(stderr, "chain walk case %d order %d failed\n", + (int)i, order); + } + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); + } + } +#endif + return EXPECT_RESULT(); +} + +/* WOLFSSL_CRL_CHECKALL chain walk over CAs that issue each other. A two-CA + * loop (A by B, B by A) is detected and each CA is checked once. A three-CA + * loop (A by C, C by B, B by A) isn't, so the walk stops at + * WOLFSSL_MAX_CHAIN_DEPTH with ASN_PATHLEN_SIZE_E. + * + * Fixtures: CAs CN=crl-cycle-a/b/c, their CRLs, and a leaf from A. The server + * sends only the leaf, so the walk runs. */ +int test_wolfSSL_CRL_chain_walk_cycle(void) +{ + EXPECT_DECLS; +#if defined(HAVE_CRL) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_SHA256) && \ + !defined(NO_SKID) && \ + !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) + struct { + const unsigned char* der; + int sz; + } cas[3][3], crls[3][3]; + int expected[3]; + size_t i; + size_t j; + + XMEMSET(cas, 0, sizeof(cas)); + XMEMSET(crls, 0, sizeof(crls)); + /* Two-CA loop, nothing revoked. */ + cas[0][0].der = fxCycleAbyB; cas[0][0].sz = (int)sizeof(fxCycleAbyB); + cas[0][1].der = fxCycleBbyA; cas[0][1].sz = (int)sizeof(fxCycleBbyA); + crls[0][0].der = fxCycleCrlA; crls[0][0].sz = (int)sizeof(fxCycleCrlA); + crls[0][1].der = fxCycleCrlB; crls[0][1].sz = (int)sizeof(fxCycleCrlB); + expected[0] = 0; + /* Same loop: the walk reaches B's CRL, which revokes A. */ + cas[1][0] = cas[0][0]; + cas[1][1] = cas[0][1]; + crls[1][0].der = fxCycleCrlA; + crls[1][0].sz = (int)sizeof(fxCycleCrlA); + crls[1][1].der = fxCycleCrlBRevoked; + crls[1][1].sz = (int)sizeof(fxCycleCrlBRevoked); + expected[1] = WC_NO_ERR_TRACE(CRL_CERT_REVOKED); + /* Three-CA loop: stopped by the depth limit. */ + cas[2][0].der = fxCycleAbyC; cas[2][0].sz = (int)sizeof(fxCycleAbyC); + cas[2][1].der = fxCycleBbyA; cas[2][1].sz = (int)sizeof(fxCycleBbyA); + cas[2][2].der = fxCycleCbyB; cas[2][2].sz = (int)sizeof(fxCycleCbyB); + crls[2][0].der = fxCycleCrlA; crls[2][0].sz = (int)sizeof(fxCycleCrlA); + crls[2][1].der = fxCycleCrlB; crls[2][1].sz = (int)sizeof(fxCycleCrlB); + crls[2][2].der = fxCycleCrlC; crls[2][2].sz = (int)sizeof(fxCycleCrlC); + expected[2] = WC_NO_ERR_TRACE(ASN_PATHLEN_SIZE_E); + + for (i = 0; i < XELEM_CNT(expected) && !EXPECT_FAIL(); i++) { + struct test_memio_ctx test_ctx; + WOLFSSL_CTX* ctx_c = NULL; + WOLFSSL_CTX* ctx_s = NULL; + WOLFSSL* ssl_c = NULL; + WOLFSSL* ssl_s = NULL; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup_ex(&test_ctx, &ctx_c, &ctx_s, &ssl_c, + &ssl_s, wolfSSLv23_client_method, wolfSSLv23_server_method, + (byte*)cas[i][0].der, cas[i][0].sz, (byte*)fxCycleLeaf, + (int)sizeof(fxCycleLeaf), (byte*)fxLeafKey, + (int)sizeof(fxLeafKey)), 0); + for (j = 1; j < 3; j++) { + if (cas[i][j].der == NULL) + continue; + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer(ctx_c, cas[i][j].der, + (long)cas[i][j].sz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + } + ExpectIntEQ(wolfSSL_CTX_EnableCRL(ctx_c, + WOLFSSL_CRL_CHECK | WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); + for (j = 0; j < 3; j++) { + if (crls[i][j].der == NULL) + continue; + ExpectIntEQ(wolfSSL_CTX_LoadCRLBuffer(ctx_c, crls[i][j].der, + (long)crls[i][j].sz, WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + } + wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, NULL); + + if (expected[i] == 0) { + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + } + else { + ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectIntEQ(wolfSSL_get_error(ssl_c, 0), expected[i]); + } + if (EXPECT_FAIL()) { + fprintf(stderr, "chain walk cycle case %d failed\n", (int)i); + } + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); + } +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_cert_critical_policy_constraints(void) { EXPECT_DECLS; diff --git a/tests/api/test_certman.h b/tests/api/test_certman.h index feb9cb687fa..251a03c11d0 100644 --- a/tests/api/test_certman.h +++ b/tests/api/test_certman.h @@ -59,6 +59,14 @@ int test_wolfSSL_CRL_unknown_ext_cb_positive_return_fails_load(void); int test_wolfSSL_CRL_unknown_ext_cb_noctx(void); int test_wolfSSL_CRL_cross_ca_akid(void); int test_wolfSSL_CRL_unverified_no_evict(void); +int test_wolfSSL_CRL_skip_unverifiable(void); +int test_wolfSSL_CRL_same_name_key_rollover(void); +int test_wolfSSL_CRL_chain_same_name_key_rollover(void); +int test_wolfSSL_CRL_crl_only_signing_key(void); +int test_wolfSSL_CRL_other_key_fallback(void); +int test_wolfSSL_CRL_other_key_trust_anchor(void); +int test_wolfSSL_CRL_chain_walk_follows_akid(void); +int test_wolfSSL_CRL_chain_walk_cycle(void); int test_wolfSSL_cert_critical_policy_constraints(void); int test_wolfSSL_CRL_unknown_ext_cb_32_preferred(void); int test_wolfSSL_CertManagerCheckOCSPResponse(void); @@ -108,6 +116,16 @@ int test_wolfSSL_trust_peer_cert_dates(void); test_wolfSSL_CRL_unknown_ext_cb_noctx), \ TEST_DECL_GROUP("certman", test_wolfSSL_CRL_cross_ca_akid), \ TEST_DECL_GROUP("certman", test_wolfSSL_CRL_unverified_no_evict), \ + TEST_DECL_GROUP("certman", test_wolfSSL_CRL_skip_unverifiable), \ + TEST_DECL_GROUP("certman", test_wolfSSL_CRL_same_name_key_rollover), \ + TEST_DECL_GROUP("certman", \ + test_wolfSSL_CRL_chain_same_name_key_rollover), \ + TEST_DECL_GROUP("certman", test_wolfSSL_CRL_crl_only_signing_key), \ + TEST_DECL_GROUP("certman", test_wolfSSL_CRL_other_key_fallback), \ + TEST_DECL_GROUP("certman", test_wolfSSL_CRL_other_key_trust_anchor), \ + TEST_DECL_GROUP("certman", \ + test_wolfSSL_CRL_chain_walk_follows_akid), \ + TEST_DECL_GROUP("certman", test_wolfSSL_CRL_chain_walk_cycle), \ TEST_DECL_GROUP("certman", test_wolfSSL_cert_critical_policy_constraints), \ TEST_DECL_GROUP("certman", \ test_wolfSSL_CRL_unknown_ext_cb_32_preferred), \ diff --git a/tests/api/test_certman_crl_fixtures.h b/tests/api/test_certman_crl_fixtures.h new file mode 100644 index 00000000000..9be068fc5b1 --- /dev/null +++ b/tests/api/test_certman_crl_fixtures.h @@ -0,0 +1,1144 @@ +/* test_certman_crl_fixtures.h + * + * Copyright (C) 2006-2026 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Fixtures for the CRL key rollover, CRL-only key and chain walk tests. All + * P-256, valid 2026-01-01 to 2046-01-01 unless noted. + * + * One CA name, CN=crl-rollover-root, with old and new self-signed keys, a + * CRL-only key, an intermediate under the old key, leaves, and one CRL series + * per key. Serials: 0x10 old-key leaf, 0x20 new-key leaf, 0x30 intermediate, + * 0x40 intermediate's leaf, 0x60 old-key leaf with no AKID. Each CRL revokes + * only the serials listed. + * + * The cycle tests use CN=crl-cycle-a/b/c, keys A, B and C issued by each + * other. + * + * Generated with Python cryptography, deterministic ECDSA. */ + +#ifndef WOLFSSL_TEST_CERTMAN_CRL_FIXTURES_H +#define WOLFSSL_TEST_CERTMAN_CRL_FIXTURES_H + +#include +#include + +#if defined(HAVE_CRL) && !defined(NO_CERTS) + +/* Old root key, CN=crl-rollover-root, serial 1. keyCertSign | + * cRLSign, AKID = SKID. */ +WC_MAYBE_UNUSED static const unsigned char fxRootOld[] = { + 0x30, 0x82, 0x01, 0x8a, 0x30, 0x82, 0x01, 0x30, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, 0x6f, 0x6c, + 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, + 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x96, 0x5b, 0x3f, 0x64, 0x22, 0x0a, 0x34, 0xb8, 0xea, + 0x1f, 0x48, 0x8b, 0x39, 0xd3, 0xf8, 0x62, 0x02, 0x26, 0xe3, 0x7d, 0x37, + 0xac, 0xb0, 0xa6, 0x84, 0xd3, 0x9b, 0x56, 0xdd, 0x9a, 0x8b, 0xb1, 0x13, + 0x32, 0xb4, 0x3b, 0x75, 0xcc, 0x19, 0x77, 0x79, 0x59, 0x3a, 0x53, 0x55, + 0x32, 0xe1, 0xbb, 0x23, 0x30, 0x3e, 0x0d, 0xb0, 0x9f, 0x62, 0x34, 0x72, + 0x3a, 0x5f, 0x64, 0x11, 0xb8, 0xb6, 0x51, 0xa3, 0x63, 0x30, 0x61, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xe5, 0xfc, 0xf7, 0xda, 0xee, + 0x0f, 0xb7, 0xbe, 0x48, 0x36, 0x3d, 0x4b, 0x73, 0xda, 0xdc, 0x05, 0x36, + 0x11, 0xfc, 0xc2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xe5, 0xfc, 0xf7, 0xda, 0xee, 0x0f, 0xb7, 0xbe, + 0x48, 0x36, 0x3d, 0x4b, 0x73, 0xda, 0xdc, 0x05, 0x36, 0x11, 0xfc, 0xc2, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x3e, 0x7c, 0x9c, 0x01, 0xc8, + 0x22, 0x69, 0xb2, 0xea, 0xa7, 0x9f, 0xe4, 0xa4, 0x10, 0x7b, 0xff, 0x37, + 0xd1, 0x51, 0x39, 0x23, 0xb0, 0xc4, 0x74, 0x95, 0x65, 0x68, 0x0f, 0xc2, + 0x0a, 0x1d, 0x51, 0x02, 0x21, 0x00, 0xdd, 0x3a, 0xca, 0x23, 0x72, 0x18, + 0xd7, 0xb5, 0xfa, 0xef, 0x62, 0x43, 0xd2, 0x26, 0x41, 0xc1, 0x0b, 0x39, + 0x12, 0xd7, 0xc0, 0x81, 0xcf, 0x8e, 0x4d, 0x2a, 0xab, 0xdd, 0x5e, 0x60, + 0xb5, 0x05 +}; + +/* New root key, same name, serial 2. keyCertSign | cRLSign, + * AKID = SKID. Sorts before the old root in the CA table. */ +WC_MAYBE_UNUSED static const unsigned char fxRootNew[] = { + 0x30, 0x82, 0x01, 0x8a, 0x30, 0x82, 0x01, 0x30, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, 0x6f, 0x6c, + 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, + 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xc3, 0x7d, 0xcf, 0x8d, 0x3d, 0xeb, 0x99, 0x19, 0xa2, + 0x6a, 0xad, 0x59, 0x1f, 0x0e, 0x12, 0x82, 0xeb, 0xa3, 0x3a, 0x3a, 0xf4, + 0x36, 0xc2, 0xed, 0x1c, 0x3c, 0xc0, 0x79, 0x77, 0x3c, 0x01, 0x24, 0x48, + 0x79, 0xa7, 0xe8, 0xe5, 0x4e, 0x65, 0x78, 0x7b, 0xa7, 0x5a, 0x44, 0x41, + 0xe1, 0xb0, 0xee, 0xdf, 0xae, 0x66, 0x7e, 0x33, 0x1d, 0xdd, 0xe5, 0xbb, + 0x50, 0xff, 0x82, 0x65, 0x52, 0x0d, 0x94, 0xa3, 0x63, 0x30, 0x61, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xff, 0x7f, 0x01, 0x2f, 0x99, + 0x70, 0x4c, 0x92, 0xf4, 0x23, 0xae, 0x88, 0x55, 0xa0, 0x02, 0xb6, 0xa6, + 0x93, 0x7f, 0x96, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xff, 0x7f, 0x01, 0x2f, 0x99, 0x70, 0x4c, 0x92, + 0xf4, 0x23, 0xae, 0x88, 0x55, 0xa0, 0x02, 0xb6, 0xa6, 0x93, 0x7f, 0x96, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x43, 0x69, 0x34, 0x76, 0xeb, + 0x4a, 0xdb, 0x79, 0xa4, 0xb5, 0x5f, 0xf5, 0x7d, 0x06, 0xba, 0xe0, 0xe4, + 0x32, 0xda, 0xdc, 0x0a, 0x4e, 0x1b, 0x7b, 0xf5, 0x73, 0xdd, 0x70, 0xac, + 0xee, 0xc5, 0x8e, 0x02, 0x21, 0x00, 0x88, 0x32, 0xaf, 0xc4, 0x70, 0x2c, + 0xed, 0x8d, 0xe9, 0x75, 0x7e, 0xe5, 0xbb, 0xee, 0x75, 0xf3, 0x9b, 0x63, + 0x0b, 0x77, 0x86, 0xbf, 0x5f, 0x55, 0x89, 0x54, 0xfd, 0xe7, 0xa3, 0xa8, + 0x24, 0xe9 +}; + +/* Same name, serial 3, issued by the old key. CA:FALSE, cRLSign + * only. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlOnlyKey[] = { + 0x30, 0x82, 0x01, 0x86, 0x30, 0x82, 0x01, 0x2d, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x03, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, 0x6f, 0x6c, + 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, + 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xb2, 0x77, 0xcb, 0x5b, 0x28, 0x89, 0xa0, 0xb2, 0x41, + 0x03, 0x33, 0x91, 0x81, 0xb0, 0x0d, 0x85, 0xbe, 0x8b, 0x1d, 0xe0, 0xa7, + 0x34, 0xa5, 0x90, 0x32, 0xf3, 0xc2, 0x32, 0x24, 0x5c, 0x52, 0xe9, 0x9e, + 0xb5, 0xb9, 0xb8, 0xfb, 0x06, 0x7d, 0x9a, 0xe8, 0xc1, 0x1f, 0x03, 0x76, + 0x70, 0xe5, 0x7b, 0xe3, 0x54, 0xbd, 0x9d, 0x2d, 0x8f, 0x46, 0x93, 0x70, + 0xe2, 0x80, 0xa1, 0x18, 0x28, 0x19, 0x44, 0xa3, 0x60, 0x30, 0x5e, 0x30, + 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, + 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, + 0x04, 0x03, 0x02, 0x01, 0x82, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, + 0x04, 0x16, 0x04, 0x14, 0x1c, 0x74, 0x87, 0xc1, 0xcc, 0x0f, 0x00, 0x5c, + 0xb0, 0xf4, 0x5a, 0x74, 0x33, 0x5e, 0xa9, 0x9b, 0x65, 0xd2, 0xfe, 0x47, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0xe5, 0xfc, 0xf7, 0xda, 0xee, 0x0f, 0xb7, 0xbe, 0x48, 0x36, 0x3d, + 0x4b, 0x73, 0xda, 0xdc, 0x05, 0x36, 0x11, 0xfc, 0xc2, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, + 0x30, 0x44, 0x02, 0x20, 0x1c, 0x05, 0x09, 0x04, 0xd1, 0x7c, 0x55, 0xde, + 0xe9, 0xb2, 0xa6, 0x32, 0x0b, 0x95, 0x0c, 0xcb, 0x57, 0x99, 0x4c, 0x9a, + 0x08, 0xa8, 0xb5, 0xc1, 0x97, 0x16, 0x3a, 0x2c, 0xe9, 0x0f, 0xaf, 0x83, + 0x02, 0x20, 0x15, 0xd6, 0x48, 0x85, 0x09, 0x8c, 0xc9, 0xe4, 0x45, 0x22, + 0x6e, 0x1b, 0x42, 0x45, 0x47, 0x70, 0x34, 0x33, 0xe8, 0x3c, 0xd9, 0x1e, + 0x03, 0xba, 0x8b, 0xab, 0x9d, 0xef, 0x45, 0x28, 0xda, 0x4d +}; + +/* Intermediate CN=crl-rollover-int, serial 0x30, issued by the old + * key. */ +WC_MAYBE_UNUSED static const unsigned char fxIntCa[] = { + 0x30, 0x82, 0x01, 0x89, 0x30, 0x82, 0x01, 0x2f, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x30, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, 0x6f, 0x6c, + 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1b, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x63, 0x72, 0x6c, 0x2d, 0x72, + 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x74, 0x30, + 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, + 0x00, 0x04, 0x88, 0x00, 0x80, 0xe7, 0x94, 0xc9, 0x37, 0x59, 0xaf, 0x05, + 0xe3, 0x8c, 0x66, 0x14, 0xd8, 0xe8, 0xde, 0xe9, 0x60, 0x96, 0xd7, 0x17, + 0x7e, 0xdb, 0x80, 0x3a, 0x76, 0x3f, 0x51, 0x2a, 0x32, 0x95, 0x10, 0xd2, + 0x65, 0xfe, 0x6e, 0xe3, 0xa5, 0x5a, 0xbc, 0x39, 0xd1, 0x73, 0x37, 0x48, + 0x89, 0x09, 0xce, 0x19, 0x31, 0xa6, 0xff, 0x55, 0x76, 0x66, 0x6e, 0x0e, + 0x9d, 0x10, 0x28, 0x8a, 0xc4, 0x73, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, + 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, + 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, + 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x77, 0x27, 0x58, 0x5f, 0xb2, 0xd4, + 0x26, 0x8d, 0x55, 0x17, 0xf4, 0x36, 0x35, 0xf1, 0x68, 0x09, 0x0c, 0x9c, + 0xdf, 0x15, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, + 0x16, 0x80, 0x14, 0xe5, 0xfc, 0xf7, 0xda, 0xee, 0x0f, 0xb7, 0xbe, 0x48, + 0x36, 0x3d, 0x4b, 0x73, 0xda, 0xdc, 0x05, 0x36, 0x11, 0xfc, 0xc2, 0x30, + 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, + 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x2c, 0x6b, 0x59, 0x0c, 0x4c, 0xbb, + 0x46, 0xa8, 0x86, 0x06, 0x1d, 0xde, 0xf9, 0x17, 0xac, 0xcb, 0x9a, 0xe4, + 0x31, 0x0f, 0x13, 0x21, 0xa7, 0xa5, 0x3b, 0xc2, 0x1f, 0x9b, 0xd4, 0xca, + 0xc7, 0x25, 0x02, 0x21, 0x00, 0xfe, 0x4b, 0xf7, 0x3c, 0x50, 0xfa, 0x05, + 0xc6, 0x62, 0xa0, 0x10, 0x21, 0x85, 0xfb, 0x73, 0x32, 0xec, 0x77, 0x5d, + 0x45, 0x04, 0x4d, 0xef, 0xd8, 0xe2, 0xb9, 0xbf, 0xea, 0x37, 0x22, 0xe3, + 0x48 +}; + +/* Leaf serial 0x10, issued by the old key. */ +WC_MAYBE_UNUSED static const unsigned char fxLeafOld[] = { + 0x30, 0x82, 0x01, 0x5d, 0x30, 0x82, 0x01, 0x02, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x10, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, 0x6f, 0x6c, + 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x20, 0x31, 0x1e, 0x30, 0x1c, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, 0x63, 0x72, 0x6c, 0x2d, 0x72, + 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x6c, 0x65, 0x61, 0x66, + 0x2d, 0x6f, 0x6c, 0x64, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x2f, 0x9b, 0xd6, 0x72, 0xc3, + 0xca, 0x8d, 0x08, 0xc8, 0x19, 0xbf, 0x1a, 0x2d, 0x09, 0xc3, 0x2e, 0x6d, + 0x05, 0x92, 0x36, 0x63, 0x97, 0x71, 0x9c, 0x0a, 0xb3, 0xf4, 0x84, 0xfb, + 0x52, 0xa5, 0xc9, 0xcc, 0x74, 0x55, 0xe0, 0x6e, 0xc5, 0x09, 0x97, 0xdc, + 0x36, 0xc2, 0x87, 0x80, 0x7e, 0x58, 0x1a, 0x0b, 0xb9, 0x75, 0x67, 0xb4, + 0x48, 0x6f, 0xf7, 0xc9, 0x33, 0x49, 0x4a, 0xea, 0x44, 0x78, 0xbe, 0xa3, + 0x31, 0x30, 0x2f, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, + 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xe5, 0xfc, 0xf7, 0xda, 0xee, 0x0f, + 0xb7, 0xbe, 0x48, 0x36, 0x3d, 0x4b, 0x73, 0xda, 0xdc, 0x05, 0x36, 0x11, + 0xfc, 0xc2, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, + 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xf8, 0xdc, + 0xa4, 0xbc, 0x1e, 0x8f, 0x63, 0x16, 0xca, 0x7c, 0x3c, 0xd2, 0x13, 0x41, + 0x65, 0x03, 0xd8, 0xdc, 0xb5, 0x51, 0x29, 0x8c, 0xea, 0x50, 0x7e, 0x93, + 0x49, 0xed, 0xc1, 0xa6, 0x12, 0x91, 0x02, 0x21, 0x00, 0x91, 0x26, 0x13, + 0x5e, 0xfe, 0xfb, 0x18, 0xe6, 0x5b, 0xd7, 0x61, 0x4d, 0xac, 0x20, 0x11, + 0x7e, 0x8c, 0xce, 0x62, 0x66, 0x5d, 0xe2, 0x3e, 0x5a, 0xe2, 0x5a, 0xcb, + 0x0c, 0x5a, 0xbd, 0x28, 0x0e +}; + +/* Leaf serial 0x20, issued by the new key. */ +WC_MAYBE_UNUSED static const unsigned char fxLeafNew[] = { + 0x30, 0x82, 0x01, 0x5d, 0x30, 0x82, 0x01, 0x02, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x20, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, 0x6f, 0x6c, + 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x20, 0x31, 0x1e, 0x30, 0x1c, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, 0x63, 0x72, 0x6c, 0x2d, 0x72, + 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x6c, 0x65, 0x61, 0x66, + 0x2d, 0x6e, 0x65, 0x77, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x2f, 0x9b, 0xd6, 0x72, 0xc3, + 0xca, 0x8d, 0x08, 0xc8, 0x19, 0xbf, 0x1a, 0x2d, 0x09, 0xc3, 0x2e, 0x6d, + 0x05, 0x92, 0x36, 0x63, 0x97, 0x71, 0x9c, 0x0a, 0xb3, 0xf4, 0x84, 0xfb, + 0x52, 0xa5, 0xc9, 0xcc, 0x74, 0x55, 0xe0, 0x6e, 0xc5, 0x09, 0x97, 0xdc, + 0x36, 0xc2, 0x87, 0x80, 0x7e, 0x58, 0x1a, 0x0b, 0xb9, 0x75, 0x67, 0xb4, + 0x48, 0x6f, 0xf7, 0xc9, 0x33, 0x49, 0x4a, 0xea, 0x44, 0x78, 0xbe, 0xa3, + 0x31, 0x30, 0x2f, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, + 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xff, 0x7f, 0x01, 0x2f, 0x99, 0x70, + 0x4c, 0x92, 0xf4, 0x23, 0xae, 0x88, 0x55, 0xa0, 0x02, 0xb6, 0xa6, 0x93, + 0x7f, 0x96, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, + 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xbb, 0xec, + 0x42, 0xf0, 0xc4, 0x01, 0x95, 0xe0, 0xad, 0xc6, 0x81, 0x89, 0x84, 0x54, + 0x63, 0xe4, 0xf9, 0x33, 0xb0, 0x2f, 0x8d, 0x14, 0x36, 0x01, 0x64, 0xc7, + 0x5c, 0xda, 0x70, 0xe7, 0x52, 0x85, 0x02, 0x21, 0x00, 0xb4, 0x8c, 0x4b, + 0x37, 0xfc, 0x15, 0x76, 0xa1, 0x83, 0xf0, 0x07, 0x1f, 0x33, 0x14, 0x2c, + 0x5b, 0x9c, 0x5a, 0xac, 0xf7, 0x75, 0xfd, 0x74, 0x38, 0xdb, 0x31, 0xd6, + 0xc2, 0xf9, 0x07, 0xaa, 0xae +}; + +/* Leaf serial 0x60, issued by the old key, no AKID. */ +WC_MAYBE_UNUSED static const unsigned char fxLeafNoAkid[] = { + 0x30, 0x82, 0x01, 0x3c, 0x30, 0x81, 0xe4, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x01, 0x60, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x72, 0x6f, 0x6c, 0x6c, + 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, + 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1f, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x18, 0x63, 0x72, 0x6c, 0x2d, 0x72, 0x6f, + 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x6c, 0x65, 0x61, 0x66, 0x2d, + 0x6e, 0x6f, 0x61, 0x6b, 0x69, 0x64, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x2f, 0x9b, 0xd6, + 0x72, 0xc3, 0xca, 0x8d, 0x08, 0xc8, 0x19, 0xbf, 0x1a, 0x2d, 0x09, 0xc3, + 0x2e, 0x6d, 0x05, 0x92, 0x36, 0x63, 0x97, 0x71, 0x9c, 0x0a, 0xb3, 0xf4, + 0x84, 0xfb, 0x52, 0xa5, 0xc9, 0xcc, 0x74, 0x55, 0xe0, 0x6e, 0xc5, 0x09, + 0x97, 0xdc, 0x36, 0xc2, 0x87, 0x80, 0x7e, 0x58, 0x1a, 0x0b, 0xb9, 0x75, + 0x67, 0xb4, 0x48, 0x6f, 0xf7, 0xc9, 0x33, 0x49, 0x4a, 0xea, 0x44, 0x78, + 0xbe, 0xa3, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0a, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, + 0x02, 0x20, 0x36, 0x23, 0x4c, 0xb0, 0x97, 0xd9, 0x46, 0xd0, 0x32, 0x58, + 0xf5, 0xb0, 0x1c, 0x1b, 0x36, 0xed, 0x65, 0xe6, 0xa1, 0xb7, 0x73, 0x2c, + 0xcd, 0x1a, 0x0f, 0x38, 0xdf, 0x58, 0x97, 0x40, 0xc0, 0x04, 0x02, 0x20, + 0x15, 0xef, 0xad, 0x2c, 0x78, 0x77, 0x28, 0xe4, 0xd7, 0x2f, 0xfd, 0xd4, + 0x53, 0x02, 0xed, 0x91, 0xd2, 0xb4, 0xf9, 0x98, 0x72, 0xe9, 0xdb, 0xdc, + 0x47, 0x63, 0x23, 0x69, 0xac, 0xb8, 0x41, 0xaa +}; + +/* Leaf serial 0x40, CN=localhost, issued by the intermediate. */ +WC_MAYBE_UNUSED static const unsigned char fxLeafInt[] = { + 0x30, 0x82, 0x01, 0x4e, 0x30, 0x81, 0xf5, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x01, 0x40, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x04, 0x03, 0x02, 0x30, 0x1b, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x10, 0x63, 0x72, 0x6c, 0x2d, 0x72, 0x6f, 0x6c, 0x6c, + 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x74, 0x30, 0x1e, 0x17, 0x0d, + 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, + 0x73, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, + 0x07, 0x03, 0x42, 0x00, 0x04, 0x2f, 0x9b, 0xd6, 0x72, 0xc3, 0xca, 0x8d, + 0x08, 0xc8, 0x19, 0xbf, 0x1a, 0x2d, 0x09, 0xc3, 0x2e, 0x6d, 0x05, 0x92, + 0x36, 0x63, 0x97, 0x71, 0x9c, 0x0a, 0xb3, 0xf4, 0x84, 0xfb, 0x52, 0xa5, + 0xc9, 0xcc, 0x74, 0x55, 0xe0, 0x6e, 0xc5, 0x09, 0x97, 0xdc, 0x36, 0xc2, + 0x87, 0x80, 0x7e, 0x58, 0x1a, 0x0b, 0xb9, 0x75, 0x67, 0xb4, 0x48, 0x6f, + 0xf7, 0xc9, 0x33, 0x49, 0x4a, 0xea, 0x44, 0x78, 0xbe, 0xa3, 0x31, 0x30, + 0x2f, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, + 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x77, 0x27, 0x58, 0x5f, 0xb2, 0xd4, 0x26, 0x8d, + 0x55, 0x17, 0xf4, 0x36, 0x35, 0xf1, 0x68, 0x09, 0x0c, 0x9c, 0xdf, 0x15, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xb8, 0x71, 0x2d, 0xd0, + 0xbe, 0x66, 0x73, 0xec, 0xa9, 0xa7, 0x2e, 0x1e, 0xae, 0x94, 0x42, 0x0e, + 0xd7, 0x47, 0x9d, 0xb3, 0xf9, 0xa3, 0xd5, 0xcc, 0xee, 0xac, 0x13, 0x3b, + 0xb4, 0x5d, 0xa9, 0x97, 0x02, 0x20, 0x4d, 0x8f, 0x94, 0xb3, 0xed, 0x76, + 0x45, 0x4d, 0xcb, 0x13, 0xd6, 0x63, 0xb6, 0x55, 0x82, 0x06, 0xb2, 0x2b, + 0xdd, 0x7d, 0x72, 0xa7, 0x59, 0x0d, 0x9b, 0xec, 0x5e, 0x78, 0x72, 0xae, + 0xb1, 0x17 +}; + +/* Private key of every leaf. */ +WC_MAYBE_UNUSED static const unsigned char fxLeafKey[] = { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xdf, 0xf8, 0xfe, 0x6a, 0x8c, + 0x90, 0xad, 0xe9, 0x87, 0xf3, 0x09, 0x68, 0x08, 0x92, 0x68, 0x4c, 0x5c, + 0x26, 0x8a, 0x7f, 0x32, 0x3d, 0xfb, 0xf5, 0x8d, 0x5c, 0x22, 0xd0, 0x2d, + 0xea, 0xad, 0x85, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x2f, 0x9b, 0xd6, + 0x72, 0xc3, 0xca, 0x8d, 0x08, 0xc8, 0x19, 0xbf, 0x1a, 0x2d, 0x09, 0xc3, + 0x2e, 0x6d, 0x05, 0x92, 0x36, 0x63, 0x97, 0x71, 0x9c, 0x0a, 0xb3, 0xf4, + 0x84, 0xfb, 0x52, 0xa5, 0xc9, 0xcc, 0x74, 0x55, 0xe0, 0x6e, 0xc5, 0x09, + 0x97, 0xdc, 0x36, 0xc2, 0x87, 0x80, 0x7e, 0x58, 0x1a, 0x0b, 0xb9, 0x75, + 0x67, 0xb4, 0x48, 0x6f, 0xf7, 0xc9, 0x33, 0x49, 0x4a, 0xea, 0x44, 0x78, + 0xbe +}; + +/* Intermediate CRL number 1, empty. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlInt[] = { + 0x30, 0x81, 0xd2, 0x30, 0x7b, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1b, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x63, 0x72, 0x6c, + 0x2d, 0x72, 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x69, 0x6e, + 0x74, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, + 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, 0x04, 0x03, 0x02, 0x01, 0x01, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x77, 0x27, 0x58, 0x5f, 0xb2, 0xd4, 0x26, 0x8d, 0x55, 0x17, 0xf4, 0x36, + 0x35, 0xf1, 0x68, 0x09, 0x0c, 0x9c, 0xdf, 0x15, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, + 0x44, 0x02, 0x20, 0x0c, 0xe1, 0xac, 0xb5, 0x81, 0xe7, 0xeb, 0x14, 0xdf, + 0x99, 0x43, 0x26, 0x1c, 0x22, 0xfc, 0xd2, 0x83, 0x69, 0x57, 0x84, 0x9c, + 0x5c, 0xb8, 0x4c, 0x81, 0x63, 0xd1, 0x2b, 0x12, 0x24, 0x85, 0x25, 0x02, + 0x20, 0x6c, 0xbd, 0x78, 0x02, 0xef, 0x1b, 0xaf, 0x19, 0x3e, 0x63, 0xf8, + 0xcd, 0xff, 0xbb, 0x7a, 0x13, 0x0a, 0xe2, 0x2a, 0x09, 0x45, 0xe7, 0xed, + 0x66, 0x61, 0x40, 0xcd, 0x3a, 0xdb, 0x2d, 0x6f, 0x52 +}; + +/* Old key CRL number 4, empty, next update 2030-01-01. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlOld4Expiring[] = { + 0x30, 0x81, 0xd4, 0x30, 0x7c, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, + 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, + 0x2d, 0x72, 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, + 0x6f, 0x74, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x30, 0x31, 0x30, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, + 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, 0x04, 0x03, 0x02, 0x01, 0x04, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0xe5, 0xfc, 0xf7, 0xda, 0xee, 0x0f, 0xb7, 0xbe, 0x48, 0x36, 0x3d, + 0x4b, 0x73, 0xda, 0xdc, 0x05, 0x36, 0x11, 0xfc, 0xc2, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, + 0x30, 0x45, 0x02, 0x20, 0x27, 0x31, 0xdd, 0x00, 0x49, 0x82, 0x19, 0x63, + 0xb7, 0x2a, 0xe8, 0x88, 0x47, 0xa0, 0xf7, 0x22, 0xd5, 0x04, 0x04, 0x40, + 0x3c, 0x7e, 0xae, 0xc4, 0x6f, 0x8e, 0xbd, 0xed, 0xbf, 0xb6, 0x72, 0x7a, + 0x02, 0x21, 0x00, 0xc4, 0xf8, 0xe9, 0x83, 0x1b, 0x81, 0x06, 0x95, 0xcb, + 0x98, 0x93, 0xc9, 0x3e, 0xbf, 0x24, 0xf1, 0x1a, 0x72, 0x7e, 0xa5, 0x72, + 0x63, 0x22, 0xb4, 0x0d, 0x2f, 0xb7, 0x08, 0x14, 0x7d, 0xb2, 0xe5 +}; + +/* Old key CRL number 5, revokes 0x10. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlOld5[] = { + 0x30, 0x81, 0xeb, 0x30, 0x81, 0x92, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, + 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, + 0x6c, 0x2d, 0x72, 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, + 0x6f, 0x6f, 0x74, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14, 0x30, + 0x12, 0x02, 0x01, 0x10, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, + 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, 0x04, 0x03, 0x02, 0x01, 0x05, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0xe5, 0xfc, 0xf7, 0xda, 0xee, 0x0f, 0xb7, 0xbe, 0x48, 0x36, 0x3d, 0x4b, + 0x73, 0xda, 0xdc, 0x05, 0x36, 0x11, 0xfc, 0xc2, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, + 0x45, 0x02, 0x20, 0x60, 0x01, 0x0e, 0x05, 0x6c, 0x83, 0xf5, 0x42, 0x15, + 0x17, 0x7a, 0xd3, 0x2e, 0xc5, 0x06, 0xa6, 0xe5, 0x10, 0xfe, 0xb3, 0xe2, + 0x33, 0x64, 0x85, 0xe7, 0xb0, 0x86, 0xa9, 0x64, 0xf6, 0xe1, 0x6d, 0x02, + 0x21, 0x00, 0x96, 0xe7, 0xce, 0x59, 0x3a, 0xa7, 0x4a, 0xd9, 0x37, 0xbb, + 0xb0, 0xf7, 0xbb, 0x67, 0x37, 0x6b, 0x03, 0x3d, 0xfb, 0xc0, 0x49, 0xcf, + 0x33, 0x29, 0xb5, 0x44, 0xcd, 0xf9, 0x38, 0xd7, 0xd4, 0xaf +}; + +/* Old key CRL number 6, revokes 0x30. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlOld6[] = { + 0x30, 0x81, 0xec, 0x30, 0x81, 0x92, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, + 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, + 0x6c, 0x2d, 0x72, 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, + 0x6f, 0x6f, 0x74, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14, 0x30, + 0x12, 0x02, 0x01, 0x30, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, + 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0xe5, 0xfc, 0xf7, 0xda, 0xee, 0x0f, 0xb7, 0xbe, 0x48, 0x36, 0x3d, 0x4b, + 0x73, 0xda, 0xdc, 0x05, 0x36, 0x11, 0xfc, 0xc2, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, + 0x46, 0x02, 0x21, 0x00, 0xed, 0x85, 0x86, 0x96, 0xf7, 0xa2, 0x13, 0xa9, + 0xfd, 0x0b, 0x11, 0x7f, 0xbb, 0x7b, 0xbf, 0xf3, 0x8b, 0xfd, 0x8e, 0xfb, + 0x26, 0xb0, 0x4a, 0x32, 0xb5, 0x8e, 0x14, 0xd1, 0x16, 0xc0, 0x0a, 0xd7, + 0x02, 0x21, 0x00, 0x8e, 0xec, 0xf0, 0xef, 0xd6, 0x2f, 0x4a, 0xfd, 0x46, + 0x14, 0x55, 0x10, 0xc8, 0x6e, 0x53, 0xc3, 0x45, 0x60, 0x89, 0xc4, 0x8e, + 0xde, 0x79, 0xf2, 0x5a, 0xf7, 0x30, 0x48, 0x96, 0x33, 0x88, 0xb7 +}; + +/* Old key CRL number 7, no AKID, empty. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlOld7NoAkid[] = { + 0x30, 0x81, 0xb3, 0x30, 0x5b, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, + 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, + 0x2d, 0x72, 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, + 0x6f, 0x74, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x0e, 0x30, 0x0c, + 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, 0x04, 0x03, 0x02, 0x01, 0x07, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x02, 0x9f, 0xb1, 0x18, 0xea, + 0x81, 0x89, 0xf1, 0xc9, 0xac, 0x58, 0x74, 0xc0, 0x0d, 0x73, 0x6e, 0x2a, + 0x80, 0x73, 0x9d, 0xca, 0x09, 0x54, 0xe0, 0xf8, 0xa6, 0x26, 0x0a, 0xa9, + 0xab, 0xcd, 0x32, 0x02, 0x21, 0x00, 0xfb, 0xe6, 0x30, 0x27, 0x3d, 0x5c, + 0x59, 0xc2, 0xd9, 0x6f, 0x37, 0xe5, 0x05, 0xc4, 0x24, 0xf8, 0xaf, 0x54, + 0xde, 0xbe, 0xaf, 0x66, 0x72, 0xd0, 0x95, 0xc4, 0xe3, 0x21, 0xe9, 0x43, + 0x9c, 0x9c +}; + +/* New key CRL number 1, revokes 0x10 and 0x20. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlNew1[] = { + 0x30, 0x81, 0xfe, 0x30, 0x81, 0xa6, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, + 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, + 0x6c, 0x2d, 0x72, 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, + 0x6f, 0x6f, 0x74, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x28, 0x30, + 0x12, 0x02, 0x01, 0x10, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x02, 0x01, 0x20, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, 0x0a, 0x06, 0x03, 0x55, + 0x1d, 0x14, 0x04, 0x03, 0x02, 0x01, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xff, 0x7f, 0x01, 0x2f, + 0x99, 0x70, 0x4c, 0x92, 0xf4, 0x23, 0xae, 0x88, 0x55, 0xa0, 0x02, 0xb6, + 0xa6, 0x93, 0x7f, 0x96, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x3b, + 0xe6, 0x3b, 0xc0, 0xd2, 0x15, 0x26, 0x0e, 0xf7, 0x06, 0xba, 0x9a, 0x30, + 0xe9, 0x51, 0xe8, 0x95, 0x79, 0x30, 0xf3, 0xaf, 0x3b, 0xa1, 0x17, 0x55, + 0x5e, 0x6c, 0x55, 0x59, 0x87, 0xbb, 0x8b, 0x02, 0x20, 0x5d, 0xa7, 0xf8, + 0x6c, 0xef, 0x80, 0xa8, 0x4f, 0x78, 0x54, 0x32, 0x9d, 0xe8, 0xeb, 0xf9, + 0x14, 0xed, 0xa5, 0xf7, 0x1a, 0x8e, 0x8e, 0x0b, 0x1a, 0x3a, 0x83, 0xaa, + 0x47, 0x54, 0x39, 0xfd, 0x69 +}; + +/* New key CRL number 2, empty, next update 2030-01-01. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlNew2Expiring[] = { + 0x30, 0x81, 0xd5, 0x30, 0x7c, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, + 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, + 0x2d, 0x72, 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, 0x6f, + 0x6f, 0x74, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x30, 0x31, 0x30, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, + 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, 0x04, 0x03, 0x02, 0x01, 0x02, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0xff, 0x7f, 0x01, 0x2f, 0x99, 0x70, 0x4c, 0x92, 0xf4, 0x23, 0xae, + 0x88, 0x55, 0xa0, 0x02, 0xb6, 0xa6, 0x93, 0x7f, 0x96, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, + 0x30, 0x46, 0x02, 0x21, 0x00, 0xf9, 0x06, 0x29, 0x8d, 0xd6, 0x8d, 0x36, + 0x6b, 0xc1, 0x2b, 0x20, 0x50, 0x3c, 0xca, 0x1e, 0xe3, 0x38, 0x8a, 0xdd, + 0xac, 0x13, 0x11, 0x7f, 0xd0, 0x1c, 0xd9, 0x03, 0xc5, 0x97, 0x1e, 0xf8, + 0x1f, 0x02, 0x21, 0x00, 0xc1, 0xd7, 0x46, 0x43, 0x4d, 0x90, 0x94, 0x38, + 0xd5, 0xa6, 0x20, 0x7e, 0xf5, 0x55, 0xa1, 0x91, 0xf2, 0x10, 0x8f, 0xbb, + 0xe7, 0xb1, 0x8f, 0x44, 0xca, 0xc1, 0xb3, 0xa3, 0x4d, 0xaa, 0x14, 0xf3 +}; + +/* New key CRL number 6, revokes 0x20. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlNew6[] = { + 0x30, 0x81, 0xeb, 0x30, 0x81, 0x92, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, + 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, + 0x6c, 0x2d, 0x72, 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, + 0x6f, 0x6f, 0x74, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14, 0x30, + 0x12, 0x02, 0x01, 0x20, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, + 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0xff, 0x7f, 0x01, 0x2f, 0x99, 0x70, 0x4c, 0x92, 0xf4, 0x23, 0xae, 0x88, + 0x55, 0xa0, 0x02, 0xb6, 0xa6, 0x93, 0x7f, 0x96, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, + 0x45, 0x02, 0x21, 0x00, 0x96, 0x91, 0xf5, 0xc0, 0x7c, 0x69, 0x3a, 0xe2, + 0x23, 0xcf, 0x46, 0xc7, 0x40, 0x68, 0x5d, 0xc7, 0x84, 0x32, 0xde, 0xe3, + 0xa3, 0x5d, 0x4f, 0x9d, 0x9e, 0xcd, 0x7f, 0xc3, 0xfa, 0x65, 0xbe, 0x74, + 0x02, 0x20, 0x21, 0x46, 0x05, 0xb1, 0xb7, 0x69, 0xe5, 0x6d, 0xea, 0x13, + 0x69, 0x57, 0xe1, 0x3a, 0xe6, 0xfc, 0xfd, 0x44, 0x96, 0x0c, 0x82, 0xef, + 0xc0, 0x0e, 0xac, 0x4c, 0x7a, 0x30, 0x58, 0x34, 0x34, 0x77 +}; + +/* CRL-only key CRL number 1, revokes 0x10. */ +WC_MAYBE_UNUSED static const unsigned char fxCrlByCrlOnlyKey[] = { + 0x30, 0x81, 0xec, 0x30, 0x81, 0x92, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, + 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, + 0x6c, 0x2d, 0x72, 0x6f, 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x72, + 0x6f, 0x6f, 0x74, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14, 0x30, + 0x12, 0x02, 0x01, 0x10, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, + 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, 0x04, 0x03, 0x02, 0x01, 0x01, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x1c, 0x74, 0x87, 0xc1, 0xcc, 0x0f, 0x00, 0x5c, 0xb0, 0xf4, 0x5a, 0x74, + 0x33, 0x5e, 0xa9, 0x9b, 0x65, 0xd2, 0xfe, 0x47, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, + 0x46, 0x02, 0x21, 0x00, 0xb3, 0x98, 0x64, 0xa4, 0x2b, 0xd8, 0xa6, 0xda, + 0x4f, 0x0b, 0xce, 0xb4, 0xd3, 0xa2, 0x21, 0xe7, 0xdd, 0x48, 0xfd, 0xb6, + 0x85, 0xc5, 0xe9, 0xd7, 0x69, 0x5f, 0x90, 0x4d, 0x6a, 0x6c, 0x25, 0x1c, + 0x02, 0x21, 0x00, 0x92, 0x8f, 0x2a, 0x88, 0xf4, 0x42, 0xbf, 0xa9, 0x20, + 0x21, 0x6c, 0xd1, 0x0b, 0xc4, 0x79, 0x30, 0x38, 0x2b, 0xfc, 0xeb, 0x74, + 0x37, 0xbd, 0xae, 0x66, 0x69, 0x51, 0x26, 0x9c, 0xcf, 0x3c, 0x0d +}; + +/* Same name, signed by a key no CA holds, revokes 0x60. */ +WC_MAYBE_UNUSED static const char fxCrlStrayPem[] = + "-----BEGIN X509 CRL-----\n" + "MIHsMIGSAgEBMAoGCCqGSM49BAMCMBwxGjAYBgNVBAMMEWNybC1yb2xsb3Zlci1y\n" + "b290Fw0yNjAxMDEwMDAwMDBaFw00NjAxMDEwMDAwMDBaMBQwEgIBYBcNMjYwMTAx\n" + "MDAwMDAwWqAvMC0wCgYDVR0UBAMCAQEwHwYDVR0jBBgwFoAUbi4H5KL+94Siulwf\n" + "mzhhIG87GYUwCgYIKoZIzj0EAwIDSQAwRgIhAM2dbAE5rKzGUV5El3/D+clLO0py\n" + "UstlhWN2FxIO9fpuAiEA3WWL7lDZhEVOguBne6iL5pfUgDDlYze+9DfVQ55chb8=\n" + "-----END X509 CRL-----\n"; + +/* Old key CRL number 1 revoking 0x60, last signature byte + * flipped. */ +WC_MAYBE_UNUSED static const char fxCrlBadSigPem[] = + "-----BEGIN X509 CRL-----\n" + "MIHrMIGSAgEBMAoGCCqGSM49BAMCMBwxGjAYBgNVBAMMEWNybC1yb2xsb3Zlci1y\n" + "b290Fw0yNjAxMDEwMDAwMDBaFw00NjAxMDEwMDAwMDBaMBQwEgIBYBcNMjYwMTAx\n" + "MDAwMDAwWqAvMC0wCgYDVR0UBAMCAQEwHwYDVR0jBBgwFoAU5fz32u4Pt75INj1L\n" + "c9rcBTYR/MIwCgYIKoZIzj0EAwIDSAAwRQIgKu/NmwoaP94GtAUKtLSg2xddXtYo\n" + "u9g0Avjj5Ptr1OsCIQCo88VG7SS5qS9luYDNoDjZexwO17urfPApQp3jmg99Sw==\n" + "-----END X509 CRL-----\n"; + +/* CN=crl-cycle-a, key A, serial 2, issued by key B. */ +WC_MAYBE_UNUSED static const unsigned char fxCycleAbyB[] = { + 0x30, 0x82, 0x01, 0x7d, 0x30, 0x82, 0x01, 0x24, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x63, 0x72, 0x6c, 0x2d, 0x63, 0x79, 0x63, + 0x6c, 0x65, 0x2d, 0x62, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, + 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x0b, 0x63, 0x72, 0x6c, 0x2d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2d, 0x61, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x81, 0x75, 0x6d, 0xc3, 0x87, 0x12, 0xc9, 0x74, 0xe9, + 0xdd, 0x52, 0xe1, 0xa0, 0x90, 0x71, 0x8c, 0xef, 0x8c, 0xcb, 0x73, 0x95, + 0x66, 0xbc, 0x29, 0x24, 0x98, 0x23, 0xf0, 0x4c, 0x72, 0xed, 0x81, 0xe5, + 0x50, 0xea, 0x9e, 0x11, 0xd6, 0x76, 0xc1, 0xce, 0x17, 0xe1, 0xa3, 0x74, + 0xdc, 0x82, 0x69, 0x8c, 0xe8, 0xe8, 0x8c, 0x4a, 0x09, 0xd5, 0x5e, 0x29, + 0x52, 0xae, 0x31, 0x2f, 0xfb, 0x08, 0xb6, 0xa3, 0x63, 0x30, 0x61, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x53, 0x37, 0x5e, 0x36, 0x99, + 0xad, 0x13, 0x5d, 0x82, 0xcf, 0x5f, 0x06, 0xff, 0x0d, 0xb6, 0x15, 0x8e, + 0xe1, 0x9c, 0xf9, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xfc, 0x36, 0xe0, 0xfb, 0xd9, 0x75, 0x04, 0x43, + 0x80, 0x7c, 0x91, 0xf6, 0xbe, 0x45, 0xd2, 0x96, 0xd2, 0x8d, 0xca, 0x64, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x2b, 0x49, 0x84, 0xc0, 0x4e, + 0x6f, 0x1b, 0xa9, 0x71, 0xae, 0xec, 0x22, 0x66, 0x4e, 0xee, 0x4d, 0xca, + 0xe2, 0x40, 0x7e, 0xae, 0x0f, 0x72, 0xa9, 0x50, 0x74, 0xaa, 0x2c, 0xc3, + 0x78, 0x9c, 0xe3, 0x02, 0x20, 0x36, 0x08, 0x08, 0xfc, 0x9c, 0x34, 0x2a, + 0x69, 0xc0, 0x2e, 0x6a, 0x6b, 0x0a, 0x63, 0xec, 0xdf, 0x0e, 0x86, 0xbb, + 0x04, 0x54, 0xc0, 0xf1, 0x13, 0xda, 0x51, 0x0a, 0xc9, 0xc6, 0xdc, 0xc6, + 0x32 +}; + +/* CN=crl-cycle-a, key A, serial 3, issued by key C. */ +WC_MAYBE_UNUSED static const unsigned char fxCycleAbyC[] = { + 0x30, 0x82, 0x01, 0x7e, 0x30, 0x82, 0x01, 0x24, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x03, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x63, 0x72, 0x6c, 0x2d, 0x63, 0x79, 0x63, + 0x6c, 0x65, 0x2d, 0x63, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, + 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x0b, 0x63, 0x72, 0x6c, 0x2d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2d, 0x61, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x81, 0x75, 0x6d, 0xc3, 0x87, 0x12, 0xc9, 0x74, 0xe9, + 0xdd, 0x52, 0xe1, 0xa0, 0x90, 0x71, 0x8c, 0xef, 0x8c, 0xcb, 0x73, 0x95, + 0x66, 0xbc, 0x29, 0x24, 0x98, 0x23, 0xf0, 0x4c, 0x72, 0xed, 0x81, 0xe5, + 0x50, 0xea, 0x9e, 0x11, 0xd6, 0x76, 0xc1, 0xce, 0x17, 0xe1, 0xa3, 0x74, + 0xdc, 0x82, 0x69, 0x8c, 0xe8, 0xe8, 0x8c, 0x4a, 0x09, 0xd5, 0x5e, 0x29, + 0x52, 0xae, 0x31, 0x2f, 0xfb, 0x08, 0xb6, 0xa3, 0x63, 0x30, 0x61, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x53, 0x37, 0x5e, 0x36, 0x99, + 0xad, 0x13, 0x5d, 0x82, 0xcf, 0x5f, 0x06, 0xff, 0x0d, 0xb6, 0x15, 0x8e, + 0xe1, 0x9c, 0xf9, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x59, 0x12, 0xea, 0x1e, 0x1a, 0x06, 0xb2, 0x5a, + 0x4d, 0x22, 0x67, 0x9a, 0x03, 0x2b, 0xf6, 0xec, 0xff, 0xb6, 0x3f, 0xaa, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xc6, 0x7c, 0x89, 0xea, + 0x37, 0xaa, 0x6c, 0x7f, 0xc7, 0x89, 0xbc, 0x87, 0xe1, 0x1a, 0x6a, 0x09, + 0xed, 0x17, 0x66, 0x43, 0x80, 0x89, 0x03, 0xb0, 0x5c, 0xbf, 0xfc, 0xf4, + 0x1d, 0xd2, 0x98, 0x3c, 0x02, 0x20, 0x3f, 0xc7, 0x69, 0x35, 0x4a, 0xf6, + 0x44, 0x2b, 0xd0, 0xad, 0x9a, 0x31, 0x6e, 0xb7, 0x11, 0xb1, 0x60, 0xbe, + 0xe0, 0x14, 0x22, 0x93, 0x05, 0xa1, 0xc8, 0x35, 0x26, 0x9f, 0xd2, 0x69, + 0xc7, 0xc7 +}; + +/* CN=crl-cycle-b, key B, serial 4, issued by key A. */ +WC_MAYBE_UNUSED static const unsigned char fxCycleBbyA[] = { + 0x30, 0x82, 0x01, 0x7e, 0x30, 0x82, 0x01, 0x24, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x04, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x63, 0x72, 0x6c, 0x2d, 0x63, 0x79, 0x63, + 0x6c, 0x65, 0x2d, 0x61, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, + 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x0b, 0x63, 0x72, 0x6c, 0x2d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2d, 0x62, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x2a, 0x55, 0x45, 0xe0, 0x66, 0x55, 0x3e, 0xc7, 0xd3, + 0x19, 0xe4, 0x6e, 0xe3, 0x6a, 0x7d, 0xe4, 0xb2, 0x10, 0xd5, 0x02, 0x4f, + 0x81, 0x88, 0xcd, 0x76, 0x41, 0x7a, 0x86, 0xfd, 0x32, 0xbf, 0x70, 0x5f, + 0x1f, 0xa9, 0xb9, 0x2c, 0x36, 0x4c, 0xce, 0x61, 0x96, 0x5b, 0x10, 0xbb, + 0xf6, 0xcd, 0x77, 0x43, 0x78, 0xa8, 0xc0, 0x28, 0xe4, 0xe6, 0x97, 0x5a, + 0x7e, 0x17, 0xa0, 0x0c, 0xb3, 0x22, 0xbd, 0xa3, 0x63, 0x30, 0x61, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xfc, 0x36, 0xe0, 0xfb, 0xd9, + 0x75, 0x04, 0x43, 0x80, 0x7c, 0x91, 0xf6, 0xbe, 0x45, 0xd2, 0x96, 0xd2, + 0x8d, 0xca, 0x64, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x53, 0x37, 0x5e, 0x36, 0x99, 0xad, 0x13, 0x5d, + 0x82, 0xcf, 0x5f, 0x06, 0xff, 0x0d, 0xb6, 0x15, 0x8e, 0xe1, 0x9c, 0xf9, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xb5, 0x31, 0x05, 0xb6, + 0xd9, 0xdd, 0xe0, 0xc1, 0xdf, 0x6b, 0x7b, 0x2a, 0x96, 0x8d, 0x4f, 0x45, + 0x82, 0x81, 0x78, 0xb9, 0x04, 0x79, 0xc3, 0xf5, 0x20, 0x7a, 0x09, 0x2c, + 0x3c, 0xa2, 0xd7, 0x2b, 0x02, 0x20, 0x6c, 0x16, 0xbb, 0xcf, 0x39, 0xe3, + 0xd2, 0xa5, 0x1e, 0x91, 0xfd, 0xf6, 0x0d, 0x54, 0x7d, 0x3b, 0xe6, 0x6d, + 0x1c, 0x5b, 0x14, 0x02, 0xc8, 0x95, 0x63, 0x81, 0xa8, 0x5c, 0x03, 0xd1, + 0x2a, 0x8f +}; + +/* CN=crl-cycle-c, key C, serial 5, issued by key B. */ +WC_MAYBE_UNUSED static const unsigned char fxCycleCbyB[] = { + 0x30, 0x82, 0x01, 0x7e, 0x30, 0x82, 0x01, 0x24, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x05, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x63, 0x72, 0x6c, 0x2d, 0x63, 0x79, 0x63, + 0x6c, 0x65, 0x2d, 0x62, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, + 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x0b, 0x63, 0x72, 0x6c, 0x2d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2d, 0x63, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x26, 0xae, 0xa9, 0xf2, 0x36, 0x76, 0x41, 0x88, 0x0c, + 0x87, 0x11, 0x32, 0x11, 0xe0, 0xd9, 0xdc, 0xe5, 0x06, 0xa0, 0xfe, 0x18, + 0x5d, 0xe6, 0x72, 0x89, 0x73, 0x4a, 0x5a, 0xfe, 0x5f, 0x2a, 0x18, 0x8f, + 0x49, 0x8d, 0xc3, 0x14, 0xb0, 0x67, 0x1f, 0xae, 0xea, 0x9a, 0x3c, 0x89, + 0x64, 0xba, 0x0c, 0x0c, 0xeb, 0x6e, 0xea, 0x2f, 0x9f, 0x11, 0x35, 0x6a, + 0x81, 0x62, 0x43, 0x96, 0x7a, 0x4f, 0xae, 0xa3, 0x63, 0x30, 0x61, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x59, 0x12, 0xea, 0x1e, 0x1a, + 0x06, 0xb2, 0x5a, 0x4d, 0x22, 0x67, 0x9a, 0x03, 0x2b, 0xf6, 0xec, 0xff, + 0xb6, 0x3f, 0xaa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xfc, 0x36, 0xe0, 0xfb, 0xd9, 0x75, 0x04, 0x43, + 0x80, 0x7c, 0x91, 0xf6, 0xbe, 0x45, 0xd2, 0x96, 0xd2, 0x8d, 0xca, 0x64, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xf0, 0x34, 0xb6, 0x38, + 0xb2, 0xa5, 0x9a, 0x6f, 0x8c, 0xc4, 0xae, 0xf4, 0x4c, 0xaf, 0x4f, 0x29, + 0x7a, 0x7e, 0xa1, 0xb6, 0xd1, 0xa6, 0xa4, 0xa8, 0x27, 0x74, 0xc7, 0x6c, + 0xac, 0xea, 0x3b, 0x0e, 0x02, 0x20, 0x37, 0x45, 0xf7, 0x70, 0x5b, 0x08, + 0xd4, 0xd1, 0x0c, 0x7f, 0xcd, 0x4d, 0x13, 0xcf, 0x1a, 0xca, 0x72, 0xd4, + 0xb6, 0xdc, 0x28, 0x97, 0xfc, 0x7c, 0x07, 0x64, 0xa9, 0x9e, 0x88, 0xc8, + 0x31, 0x2a +}; + +/* Leaf serial 0x10, CN=localhost, issued by key A. */ +WC_MAYBE_UNUSED static const unsigned char fxCycleLeaf[] = { + 0x30, 0x82, 0x01, 0x4a, 0x30, 0x81, 0xf0, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x01, 0x10, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x04, 0x03, 0x02, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x0b, 0x63, 0x72, 0x6c, 0x2d, 0x63, 0x79, 0x63, 0x6c, + 0x65, 0x2d, 0x61, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, + 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, + 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x59, 0x30, + 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, + 0x2f, 0x9b, 0xd6, 0x72, 0xc3, 0xca, 0x8d, 0x08, 0xc8, 0x19, 0xbf, 0x1a, + 0x2d, 0x09, 0xc3, 0x2e, 0x6d, 0x05, 0x92, 0x36, 0x63, 0x97, 0x71, 0x9c, + 0x0a, 0xb3, 0xf4, 0x84, 0xfb, 0x52, 0xa5, 0xc9, 0xcc, 0x74, 0x55, 0xe0, + 0x6e, 0xc5, 0x09, 0x97, 0xdc, 0x36, 0xc2, 0x87, 0x80, 0x7e, 0x58, 0x1a, + 0x0b, 0xb9, 0x75, 0x67, 0xb4, 0x48, 0x6f, 0xf7, 0xc9, 0x33, 0x49, 0x4a, + 0xea, 0x44, 0x78, 0xbe, 0xa3, 0x31, 0x30, 0x2f, 0x30, 0x0c, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x53, + 0x37, 0x5e, 0x36, 0x99, 0xad, 0x13, 0x5d, 0x82, 0xcf, 0x5f, 0x06, 0xff, + 0x0d, 0xb6, 0x15, 0x8e, 0xe1, 0x9c, 0xf9, 0x30, 0x0a, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, + 0x02, 0x21, 0x00, 0xb0, 0x49, 0x3c, 0xa7, 0xfb, 0x88, 0x5d, 0x9e, 0xb1, + 0xcf, 0xa9, 0x69, 0xbe, 0xad, 0x95, 0x85, 0xba, 0xbf, 0x0d, 0x9a, 0xc4, + 0x33, 0x0c, 0xc4, 0x56, 0x71, 0x04, 0xde, 0x06, 0xbd, 0xfe, 0x60, 0x02, + 0x21, 0x00, 0xd3, 0x8d, 0xc7, 0x35, 0x33, 0x0f, 0x52, 0x12, 0x5d, 0x6d, + 0x10, 0xb0, 0x5e, 0xe6, 0x26, 0x7d, 0x88, 0x4d, 0x51, 0xa1, 0x33, 0x5c, + 0x55, 0x0f, 0x13, 0xec, 0xfe, 0x5a, 0x80, 0xd4, 0x51, 0xb5 +}; + +/* Key A CRL number 1, empty. */ +WC_MAYBE_UNUSED static const unsigned char fxCycleCrlA[] = { + 0x30, 0x81, 0xcd, 0x30, 0x76, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x16, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x63, 0x72, 0x6c, + 0x2d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2d, 0x61, 0x17, 0x0d, 0x32, 0x36, + 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, + 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, + 0x14, 0x04, 0x03, 0x02, 0x01, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x53, 0x37, 0x5e, 0x36, 0x99, + 0xad, 0x13, 0x5d, 0x82, 0xcf, 0x5f, 0x06, 0xff, 0x0d, 0xb6, 0x15, 0x8e, + 0xe1, 0x9c, 0xf9, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x3f, 0x2a, + 0x0f, 0x3a, 0xbd, 0x18, 0x2a, 0x99, 0x21, 0x66, 0xe0, 0x14, 0x97, 0xdf, + 0x36, 0x07, 0xc6, 0x0c, 0xa4, 0xc1, 0x38, 0x92, 0x24, 0xa5, 0xc2, 0xb5, + 0x75, 0x55, 0x4c, 0xb5, 0x23, 0x1a, 0x02, 0x20, 0x66, 0x88, 0x00, 0x96, + 0xf3, 0xfc, 0xc8, 0xa5, 0x5d, 0x09, 0xb2, 0xac, 0x2e, 0xeb, 0x8d, 0xb2, + 0xcb, 0x2e, 0x7e, 0x54, 0x16, 0xcf, 0x8d, 0x68, 0x65, 0x85, 0x94, 0x81, + 0x75, 0x0b, 0x6c, 0x3e +}; + +/* Key B CRL number 1, empty. */ +WC_MAYBE_UNUSED static const unsigned char fxCycleCrlB[] = { + 0x30, 0x81, 0xcf, 0x30, 0x76, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x16, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x63, 0x72, 0x6c, + 0x2d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2d, 0x62, 0x17, 0x0d, 0x32, 0x36, + 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, + 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, + 0x14, 0x04, 0x03, 0x02, 0x01, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfc, 0x36, 0xe0, 0xfb, 0xd9, + 0x75, 0x04, 0x43, 0x80, 0x7c, 0x91, 0xf6, 0xbe, 0x45, 0xd2, 0x96, 0xd2, + 0x8d, 0xca, 0x64, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x95, + 0x56, 0x23, 0x0e, 0x83, 0x4b, 0x69, 0x01, 0x99, 0x86, 0xb1, 0x2d, 0x61, + 0xc1, 0x38, 0x33, 0xbe, 0xc2, 0x5a, 0xe9, 0x53, 0xd6, 0x2e, 0x35, 0x3a, + 0x8c, 0xda, 0x23, 0x83, 0x74, 0xc3, 0x80, 0x02, 0x21, 0x00, 0x93, 0xcd, + 0x18, 0x0e, 0xf6, 0xa7, 0xe6, 0x88, 0xce, 0xc1, 0x7d, 0xfa, 0xd1, 0x70, + 0x58, 0xb5, 0x01, 0xa8, 0xad, 0x06, 0x8d, 0x2c, 0x0f, 0xb7, 0xa6, 0xe2, + 0x75, 0xe0, 0x98, 0xa6, 0xc5, 0x7f +}; + +/* Key B CRL number 1, revokes serial 2 (fxCycleAbyB). */ +WC_MAYBE_UNUSED static const unsigned char fxCycleCrlBRevoked[] = { + 0x30, 0x81, 0xe4, 0x30, 0x81, 0x8c, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x16, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x63, 0x72, + 0x6c, 0x2d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2d, 0x62, 0x17, 0x0d, 0x32, + 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x30, 0x14, 0x30, 0x12, 0x02, 0x01, 0x02, 0x17, 0x0d, + 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, + 0x04, 0x03, 0x02, 0x01, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, + 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfc, 0x36, 0xe0, 0xfb, 0xd9, 0x75, + 0x04, 0x43, 0x80, 0x7c, 0x91, 0xf6, 0xbe, 0x45, 0xd2, 0x96, 0xd2, 0x8d, + 0xca, 0x64, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, + 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x16, 0xf9, 0xa2, + 0xfc, 0x01, 0x6a, 0x69, 0x11, 0x7a, 0xc2, 0xf8, 0x37, 0x29, 0x3c, 0x0c, + 0xe2, 0x0e, 0x1f, 0x8d, 0x8e, 0xfb, 0x23, 0x77, 0xd4, 0xf2, 0x6d, 0xd5, + 0x87, 0x10, 0x0a, 0x12, 0x64, 0x02, 0x20, 0x72, 0xd1, 0x84, 0x2c, 0x07, + 0x10, 0x78, 0xa3, 0x1d, 0x6c, 0x5f, 0xd9, 0xe5, 0x92, 0xfe, 0x47, 0x9d, + 0x1c, 0x84, 0x30, 0x0b, 0x5c, 0xf1, 0xb8, 0x17, 0x5c, 0xc0, 0xf1, 0x24, + 0x55, 0x83, 0x20 +}; + +/* Key C CRL number 1, empty. */ +WC_MAYBE_UNUSED static const unsigned char fxCycleCrlC[] = { + 0x30, 0x81, 0xce, 0x30, 0x76, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x16, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x63, 0x72, 0x6c, + 0x2d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2d, 0x63, 0x17, 0x0d, 0x32, 0x36, + 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, + 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, + 0x14, 0x04, 0x03, 0x02, 0x01, 0x01, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x59, 0x12, 0xea, 0x1e, 0x1a, + 0x06, 0xb2, 0x5a, 0x4d, 0x22, 0x67, 0x9a, 0x03, 0x2b, 0xf6, 0xec, 0xff, + 0xb6, 0x3f, 0xaa, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x6c, 0x0c, + 0xb8, 0x1e, 0xef, 0x10, 0x19, 0x56, 0x7b, 0x31, 0xbf, 0x48, 0x17, 0x03, + 0xc7, 0x71, 0x23, 0x33, 0x5d, 0x80, 0x71, 0x48, 0x53, 0x0d, 0xfc, 0xd0, + 0xef, 0x86, 0x2a, 0x7f, 0xb7, 0x6f, 0x02, 0x21, 0x00, 0xb1, 0xc9, 0xe4, + 0x4e, 0xb1, 0xe6, 0x4d, 0x47, 0xea, 0x9e, 0x0d, 0xcb, 0x66, 0xed, 0x8f, + 0xbe, 0x54, 0xc4, 0x2c, 0x48, 0x88, 0x77, 0xe5, 0xe5, 0x5a, 0x22, 0xfc, + 0xe1, 0x90, 0x7a, 0x21, 0x0e +}; + +/* Trust anchor fixtures. Roots crl-anchor-root-1 and -2 are separate + * anchors. Root 1 issues CN=crl-anchor-int with keys 1 and 2, root 2 + * with key 3. The leaf is under key 1, so CRLs from keys 2 and 3 are + * other-key CRLs: key 2's shares the leaf's anchor, key 3's does not. + * Valid 2026-01-01 to 2046-01-01. */ + +/* Root CN=crl-anchor-root-1, serial 1, self-signed. */ +WC_MAYBE_UNUSED static const unsigned char fxAnchorRoot1[] = { + 0x30, 0x82, 0x01, 0x8b, 0x30, 0x82, 0x01, 0x30, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x61, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x31, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x61, + 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x31, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xfb, 0xd0, 0xea, 0x5b, 0xd9, 0x6b, 0x85, 0x86, 0xf0, + 0x96, 0xb4, 0x3c, 0x07, 0x53, 0x74, 0x8e, 0x9a, 0xea, 0x49, 0x3c, 0xe7, + 0x5e, 0xa2, 0xe1, 0xa8, 0x6b, 0x57, 0x2a, 0x15, 0xd3, 0xaa, 0x3a, 0x3c, + 0x96, 0x37, 0x1a, 0x3a, 0x3f, 0x5b, 0x91, 0xdd, 0xcf, 0xb1, 0x8f, 0xfc, + 0xc8, 0xe9, 0x16, 0x52, 0xcb, 0xdf, 0xa0, 0xec, 0x44, 0xd9, 0x66, 0xe8, + 0x0b, 0xac, 0x6b, 0xca, 0x0c, 0xe8, 0xf2, 0xa3, 0x63, 0x30, 0x61, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0x6c, 0x4d, 0xa7, 0x11, 0x46, 0x59, 0x4d, 0xba, 0x1e, + 0x53, 0x3e, 0xcb, 0x95, 0x55, 0x74, 0x0a, 0xca, 0x99, 0x45, 0x33, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x6c, 0x4d, 0xa7, 0x11, 0x46, 0x59, 0x4d, 0xba, 0x1e, 0x53, 0x3e, 0xcb, + 0x95, 0x55, 0x74, 0x0a, 0xca, 0x99, 0x45, 0x33, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xf5, 0x3f, 0x6e, 0xea, + 0x95, 0xaf, 0x85, 0x92, 0x03, 0x1f, 0x05, 0x8e, 0x9d, 0x88, 0x98, 0x54, + 0xa0, 0xe6, 0x71, 0x63, 0x1b, 0xa9, 0x22, 0xd9, 0xc2, 0x37, 0x8d, 0x90, + 0x29, 0xef, 0x2c, 0x3c, 0x02, 0x21, 0x00, 0x88, 0xe6, 0x27, 0x58, 0x26, + 0x7b, 0x99, 0xb2, 0x66, 0x5d, 0x87, 0x3a, 0x29, 0xfe, 0x22, 0xce, 0x15, + 0x6d, 0x63, 0x90, 0x97, 0xf7, 0x61, 0xd8, 0x26, 0x81, 0x52, 0xdd, 0xb3, + 0xd6, 0xf6, 0x53, +}; + +/* Root CN=crl-anchor-root-2, serial 2, self-signed. */ +WC_MAYBE_UNUSED static const unsigned char fxAnchorRoot2[] = { + 0x30, 0x82, 0x01, 0x8b, 0x30, 0x82, 0x01, 0x30, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x61, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x32, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x61, + 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x32, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0xf0, 0x31, 0x50, 0x7b, 0x52, 0x31, 0x56, 0x1f, 0xb1, + 0x05, 0xd2, 0x3f, 0x1d, 0x81, 0x6e, 0xe1, 0x90, 0x71, 0xfd, 0x76, 0xdd, + 0x4f, 0x5d, 0xf4, 0x24, 0x53, 0xb5, 0xbb, 0x2e, 0x78, 0x08, 0x03, 0x40, + 0x7c, 0xde, 0x0b, 0x4a, 0x79, 0x2a, 0x9a, 0xf3, 0x26, 0xd1, 0x1a, 0xe4, + 0x5c, 0x7a, 0x53, 0x54, 0x8f, 0x6e, 0x60, 0x34, 0xa8, 0x5c, 0xd8, 0x55, + 0x5f, 0x72, 0xab, 0x9f, 0x90, 0x3b, 0xee, 0xa3, 0x63, 0x30, 0x61, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0x14, 0x15, 0xa7, 0x0f, 0x99, 0x30, 0xdd, 0xbb, 0x1c, + 0x9b, 0x6f, 0x8b, 0x95, 0xc1, 0x06, 0x0b, 0x21, 0xbb, 0x7c, 0x8a, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x14, 0x15, 0xa7, 0x0f, 0x99, 0x30, 0xdd, 0xbb, 0x1c, 0x9b, 0x6f, 0x8b, + 0x95, 0xc1, 0x06, 0x0b, 0x21, 0xbb, 0x7c, 0x8a, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x83, 0x3b, 0x1b, 0xae, + 0xb1, 0x17, 0x37, 0xda, 0xd4, 0xa8, 0x79, 0xce, 0xfe, 0x40, 0xc8, 0x7d, + 0x27, 0xf4, 0xfa, 0x16, 0xa0, 0xb1, 0x63, 0x47, 0x32, 0xff, 0x8c, 0x55, + 0x28, 0x5c, 0x39, 0x8d, 0x02, 0x21, 0x00, 0x88, 0xcc, 0x40, 0x42, 0x8f, + 0xd2, 0x3f, 0x59, 0x5f, 0xeb, 0x6a, 0xc2, 0xc9, 0x71, 0x5b, 0x76, 0xf8, + 0xce, 0xd0, 0xf8, 0xa4, 0x73, 0xf7, 0x90, 0x15, 0x14, 0x12, 0xf4, 0xe0, + 0x7a, 0x99, 0xff, +}; + +/* CN=crl-anchor-int, key 1, serial 0x31, issued by root 1. */ +WC_MAYBE_UNUSED static const unsigned char fxAnchorIntK1[] = { + 0x30, 0x82, 0x01, 0x87, 0x30, 0x82, 0x01, 0x2d, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x31, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x61, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x31, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x19, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x63, 0x72, 0x6c, 0x2d, 0x61, + 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, 0x69, 0x6e, 0x74, 0x30, 0x59, 0x30, + 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, + 0xa6, 0x19, 0xb7, 0xfc, 0xe3, 0xc6, 0xb2, 0x9b, 0x25, 0xbf, 0x4f, 0x3e, + 0x2c, 0x92, 0xc4, 0xe3, 0xea, 0xe5, 0x28, 0x2b, 0x66, 0x2c, 0x26, 0x5b, + 0xe2, 0xbf, 0x63, 0xc2, 0xb9, 0x4f, 0xbf, 0x04, 0x9f, 0x3f, 0x19, 0x95, + 0x63, 0xb7, 0x11, 0x1e, 0x3f, 0xb7, 0xee, 0x6e, 0xf8, 0xfe, 0x36, 0x63, + 0xeb, 0x03, 0xb2, 0xb7, 0xbb, 0x74, 0xbe, 0x2d, 0x69, 0xfb, 0xf9, 0x15, + 0x52, 0x1e, 0xdf, 0x0c, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0xd6, 0x9f, 0xd6, 0x18, 0xe5, 0x17, 0x00, 0x70, 0x01, 0x27, 0x33, 0x22, + 0x36, 0x72, 0x0c, 0xb4, 0x67, 0x68, 0x47, 0xba, 0x30, 0x1f, 0x06, 0x03, + 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x6c, 0x4d, 0xa7, + 0x11, 0x46, 0x59, 0x4d, 0xba, 0x1e, 0x53, 0x3e, 0xcb, 0x95, 0x55, 0x74, + 0x0a, 0xca, 0x99, 0x45, 0x33, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, + 0x30, 0x45, 0x02, 0x20, 0x6b, 0x68, 0x2c, 0xef, 0x66, 0x6e, 0xca, 0xbb, + 0xb0, 0xc7, 0xe2, 0xea, 0xed, 0x22, 0xe6, 0xee, 0x1f, 0x8c, 0x7f, 0xc5, + 0x62, 0x48, 0x25, 0xd9, 0x48, 0x52, 0x9f, 0x2d, 0x25, 0x22, 0xd7, 0x69, + 0x02, 0x21, 0x00, 0xf6, 0x6b, 0xa5, 0xaa, 0xc3, 0x8b, 0x7f, 0x07, 0xac, + 0x0b, 0xa3, 0xb5, 0x38, 0xfa, 0x0f, 0xc4, 0xdd, 0x68, 0x0f, 0x2d, 0x2d, + 0x43, 0x96, 0xe5, 0xbf, 0x55, 0x6e, 0xe0, 0x34, 0x8c, 0xe8, 0x3a, +}; + +/* CN=crl-anchor-int, key 2, serial 0x32, issued by root 1. */ +WC_MAYBE_UNUSED static const unsigned char fxAnchorIntK2[] = { + 0x30, 0x82, 0x01, 0x88, 0x30, 0x82, 0x01, 0x2d, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x32, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x61, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x31, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x19, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x63, 0x72, 0x6c, 0x2d, 0x61, + 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, 0x69, 0x6e, 0x74, 0x30, 0x59, 0x30, + 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, + 0x78, 0xea, 0x8d, 0xac, 0x1a, 0x5c, 0xce, 0xca, 0xe4, 0xbc, 0x5c, 0x5f, + 0xd5, 0x7e, 0x80, 0x3d, 0x1e, 0x2c, 0x5e, 0x00, 0x74, 0xe2, 0xd3, 0x80, + 0x71, 0xd7, 0x25, 0x48, 0x4c, 0x35, 0xad, 0xc8, 0xf7, 0xaa, 0xf4, 0x12, + 0x23, 0xb1, 0x28, 0xa7, 0x41, 0xf4, 0x78, 0x27, 0x2a, 0x2f, 0x29, 0xc9, + 0x1e, 0x49, 0x65, 0x4b, 0x8e, 0x48, 0xd6, 0x70, 0xd0, 0xa2, 0x97, 0x29, + 0xf7, 0x3c, 0x44, 0x56, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0x78, 0x19, 0x67, 0xd2, 0xdd, 0x62, 0x9a, 0xfb, 0x55, 0x1c, 0x53, 0x5b, + 0xe5, 0x29, 0xdb, 0xca, 0x44, 0x57, 0xbb, 0x1f, 0x30, 0x1f, 0x06, 0x03, + 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x6c, 0x4d, 0xa7, + 0x11, 0x46, 0x59, 0x4d, 0xba, 0x1e, 0x53, 0x3e, 0xcb, 0x95, 0x55, 0x74, + 0x0a, 0xca, 0x99, 0x45, 0x33, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, + 0x30, 0x46, 0x02, 0x21, 0x00, 0xa7, 0x5b, 0xe4, 0x1b, 0xb0, 0xaf, 0xbc, + 0xf0, 0x8e, 0x60, 0x35, 0x79, 0x74, 0x25, 0x80, 0x9e, 0xd1, 0x47, 0x55, + 0x99, 0x9c, 0x6b, 0x8f, 0x04, 0x84, 0x7b, 0xd7, 0xe9, 0x36, 0x3b, 0x00, + 0x59, 0x02, 0x21, 0x00, 0xd7, 0x02, 0xc7, 0x7e, 0x08, 0x9f, 0x6b, 0xa0, + 0xa0, 0xcd, 0x56, 0xdf, 0xe6, 0x8b, 0x6d, 0x94, 0x7d, 0x06, 0xb0, 0x02, + 0xb1, 0x58, 0xa5, 0xa2, 0xa7, 0xad, 0xd8, 0x81, 0x4b, 0x36, 0x77, 0xfe, +}; + +/* CN=crl-anchor-int, key 3, serial 0x33, issued by root 2. */ +WC_MAYBE_UNUSED static const unsigned char fxAnchorIntK3[] = { + 0x30, 0x82, 0x01, 0x87, 0x30, 0x82, 0x01, 0x2d, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x33, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x11, 0x63, 0x72, 0x6c, 0x2d, 0x61, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x32, 0x30, 0x1e, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x19, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x63, 0x72, 0x6c, 0x2d, 0x61, + 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, 0x69, 0x6e, 0x74, 0x30, 0x59, 0x30, + 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, + 0x02, 0xb2, 0x8c, 0x18, 0x76, 0x5e, 0x0d, 0xd6, 0x0f, 0x19, 0x62, 0xdb, + 0x12, 0xbf, 0x8e, 0xdc, 0x5d, 0x7d, 0xff, 0xca, 0xde, 0xbd, 0xbe, 0x25, + 0x56, 0x31, 0xdb, 0x4f, 0x54, 0xa3, 0xe4, 0x4b, 0x9c, 0x60, 0xf5, 0xac, + 0x82, 0x4b, 0x0d, 0x6a, 0xa4, 0xb5, 0x47, 0x5e, 0xaf, 0x02, 0xb5, 0x00, + 0x0b, 0xf8, 0x1d, 0x70, 0x6a, 0x13, 0xc7, 0xd6, 0x0e, 0xf2, 0xd7, 0x52, + 0xd3, 0xf1, 0xe9, 0x3b, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0x54, 0xbd, 0xe6, 0xcf, 0xbd, 0x2b, 0x98, 0x58, 0xd9, 0xe2, 0x0c, 0xf2, + 0xee, 0xa2, 0x43, 0x47, 0x1e, 0x69, 0x84, 0x2f, 0x30, 0x1f, 0x06, 0x03, + 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x14, 0x15, 0xa7, + 0x0f, 0x99, 0x30, 0xdd, 0xbb, 0x1c, 0x9b, 0x6f, 0x8b, 0x95, 0xc1, 0x06, + 0x0b, 0x21, 0xbb, 0x7c, 0x8a, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, + 0x30, 0x45, 0x02, 0x20, 0x37, 0x88, 0x21, 0x24, 0x2e, 0x1a, 0x2c, 0x57, + 0x34, 0x7f, 0x55, 0x4b, 0xb2, 0x3e, 0x13, 0x61, 0x37, 0xc5, 0x93, 0xa4, + 0x34, 0x1a, 0x47, 0xf7, 0x29, 0x88, 0x0c, 0x58, 0x8c, 0x80, 0x20, 0x7c, + 0x02, 0x21, 0x00, 0xe3, 0x52, 0x7a, 0xe3, 0x57, 0xe8, 0xcd, 0x8f, 0x91, + 0xb2, 0x97, 0xa0, 0x19, 0x8b, 0x7f, 0xff, 0x79, 0x8f, 0x1a, 0x1b, 0x88, + 0x87, 0xcd, 0x4d, 0x24, 0x5b, 0xe8, 0x94, 0xfb, 0xaf, 0x8b, 0x1e, +}; + +/* Leaf serial 0x70, issued by intermediate key 1. */ +WC_MAYBE_UNUSED static const unsigned char fxAnchorLeaf[] = { + 0x30, 0x82, 0x01, 0x73, 0x30, 0x82, 0x01, 0x18, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x70, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x19, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x63, 0x72, 0x6c, 0x2d, 0x61, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x2d, 0x69, 0x6e, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32, + 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x0f, 0x63, 0x72, 0x6c, 0x2d, 0x61, 0x6e, 0x63, 0x68, + 0x6f, 0x72, 0x2d, 0x6c, 0x65, 0x61, 0x66, 0x30, 0x59, 0x30, 0x13, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x83, 0x46, + 0xaf, 0x94, 0xd7, 0xbc, 0xed, 0x68, 0x68, 0xab, 0x55, 0x7c, 0x3c, 0xbc, + 0x70, 0x21, 0x0d, 0x43, 0xa8, 0xee, 0x83, 0xae, 0x73, 0x4d, 0x12, 0x24, + 0x86, 0xca, 0xe1, 0x5a, 0x0d, 0xb7, 0xac, 0x25, 0x60, 0x88, 0xf6, 0x86, + 0xaa, 0xfc, 0x16, 0xca, 0xb6, 0xb9, 0x58, 0xd8, 0x07, 0xf5, 0xdf, 0x2d, + 0x80, 0x35, 0xe9, 0x1f, 0xea, 0xf8, 0x94, 0x81, 0xa1, 0x0b, 0xcd, 0x4c, + 0xb0, 0x82, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xf2, 0x85, 0xae, 0x86, 0x2e, + 0xcc, 0xa2, 0xcd, 0x9a, 0xaa, 0x75, 0xee, 0xba, 0x5d, 0x0e, 0xa9, 0x61, + 0x3a, 0x7e, 0xa1, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xd6, 0x9f, 0xd6, 0x18, 0xe5, 0x17, 0x00, 0x70, + 0x01, 0x27, 0x33, 0x22, 0x36, 0x72, 0x0c, 0xb4, 0x67, 0x68, 0x47, 0xba, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xe2, 0x19, 0x53, 0xed, + 0x34, 0x5d, 0xc5, 0xc6, 0xf4, 0x3c, 0xb6, 0x6b, 0x44, 0x8c, 0x3f, 0xeb, + 0x45, 0x3c, 0x0b, 0x8c, 0xd2, 0x9e, 0x6f, 0x2e, 0x51, 0x63, 0xd9, 0x78, + 0x54, 0xa6, 0xc7, 0xc0, 0x02, 0x21, 0x00, 0x83, 0xf7, 0x6c, 0xa1, 0xc4, + 0xbd, 0xc3, 0xce, 0x4c, 0xa2, 0x07, 0x07, 0xc0, 0x7e, 0xb7, 0xf0, 0xba, + 0x20, 0x96, 0x6f, 0xa7, 0x42, 0xec, 0x66, 0xdd, 0x8a, 0xf8, 0xa4, 0x58, + 0xc1, 0xcf, 0x96, +}; + +/* Intermediate key 2 CRL number 1, empty. */ +WC_MAYBE_UNUSED static const unsigned char fxAnchorCrlK2[] = { + 0x30, 0x81, 0xd0, 0x30, 0x79, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x19, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x63, 0x72, 0x6c, + 0x2d, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, 0x69, 0x6e, 0x74, 0x17, + 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, 0x1f, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x78, 0x19, + 0x67, 0xd2, 0xdd, 0x62, 0x9a, 0xfb, 0x55, 0x1c, 0x53, 0x5b, 0xe5, 0x29, + 0xdb, 0xca, 0x44, 0x57, 0xbb, 0x1f, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, + 0x14, 0x04, 0x03, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, + 0x20, 0x01, 0x74, 0x97, 0x27, 0x08, 0x3e, 0xb0, 0x13, 0x2e, 0x39, 0x71, + 0xd2, 0x0f, 0xcf, 0xfe, 0xcb, 0x1e, 0x43, 0xf5, 0xb8, 0x04, 0x70, 0x68, + 0xa7, 0xb4, 0x71, 0x5a, 0x31, 0x3c, 0x2c, 0x43, 0xbd, 0x02, 0x20, 0x2a, + 0x65, 0x0f, 0xfc, 0x4a, 0xf8, 0x68, 0x9e, 0x20, 0x40, 0x00, 0xcc, 0xa6, + 0x2b, 0x78, 0xa5, 0x9c, 0xd8, 0x51, 0x65, 0xb9, 0x16, 0xab, 0xdd, 0xaf, + 0x91, 0x9d, 0xc2, 0xd3, 0x76, 0xe8, 0xfa, +}; + +/* Intermediate key 3 CRL number 1, empty. */ +WC_MAYBE_UNUSED static const unsigned char fxAnchorCrlK3[] = { + 0x30, 0x81, 0xd2, 0x30, 0x79, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x19, 0x31, 0x17, + 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x63, 0x72, 0x6c, + 0x2d, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, 0x69, 0x6e, 0x74, 0x17, + 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, 0x1f, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x54, 0xbd, + 0xe6, 0xcf, 0xbd, 0x2b, 0x98, 0x58, 0xd9, 0xe2, 0x0c, 0xf2, 0xee, 0xa2, + 0x43, 0x47, 0x1e, 0x69, 0x84, 0x2f, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, + 0x14, 0x04, 0x03, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, + 0x21, 0x00, 0x8f, 0x31, 0x9e, 0x82, 0xbe, 0x04, 0x46, 0x5c, 0x98, 0x83, + 0x89, 0xf3, 0xdf, 0x42, 0x69, 0x7f, 0x84, 0x65, 0xd7, 0x3f, 0x5c, 0x5e, + 0x78, 0x01, 0x6d, 0x8f, 0x0e, 0xbb, 0xfb, 0xf4, 0xd6, 0x95, 0x02, 0x21, + 0x00, 0xc5, 0x4d, 0xc1, 0xb3, 0x9c, 0x32, 0xd3, 0x4d, 0xb3, 0x5b, 0x1a, + 0x02, 0x35, 0xce, 0xaf, 0x42, 0x83, 0x01, 0x7c, 0x04, 0xc4, 0xea, 0xea, + 0xf5, 0x0f, 0x3e, 0x7a, 0xe3, 0xda, 0xea, 0x6a, 0x8d, +}; + +/* Intermediate key 3 CRL number 2, revokes 0x70. */ +WC_MAYBE_UNUSED static const unsigned char fxAnchorCrlK3Revoked[] = { + 0x30, 0x81, 0xe8, 0x30, 0x81, 0x8f, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x19, 0x31, + 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x63, 0x72, + 0x6c, 0x2d, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, 0x69, 0x6e, 0x74, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14, 0x30, 0x12, 0x02, 0x01, + 0x70, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5a, 0xa0, 0x2f, 0x30, 0x2d, 0x30, 0x1f, 0x06, 0x03, + 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x54, 0xbd, 0xe6, + 0xcf, 0xbd, 0x2b, 0x98, 0x58, 0xd9, 0xe2, 0x0c, 0xf2, 0xee, 0xa2, 0x43, + 0x47, 0x1e, 0x69, 0x84, 0x2f, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x1d, 0x14, + 0x04, 0x03, 0x02, 0x01, 0x02, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, + 0x5d, 0x2e, 0x74, 0xb1, 0x8f, 0x33, 0x5c, 0xf9, 0x9d, 0x0d, 0x70, 0xeb, + 0x4d, 0x82, 0xc3, 0x03, 0xb7, 0x56, 0xf5, 0x76, 0xd2, 0x47, 0xcf, 0xaa, + 0x44, 0xf2, 0xe2, 0x8b, 0x72, 0x35, 0xac, 0x6a, 0x02, 0x21, 0x00, 0xb8, + 0xe4, 0x87, 0x76, 0xaf, 0xd6, 0x3e, 0xca, 0x50, 0x43, 0x9a, 0x03, 0xb8, + 0x66, 0xd2, 0x11, 0xed, 0x1a, 0xc0, 0x1d, 0x78, 0xa7, 0xa5, 0xe7, 0x83, + 0x86, 0x6c, 0xd8, 0x31, 0xef, 0x5a, 0x8e, +}; + +#endif /* HAVE_CRL && !NO_CERTS */ + +#endif /* WOLFSSL_TEST_CERTMAN_CRL_FIXTURES_H */ diff --git a/tests/unit-mcdc/test_crl_whitebox.c b/tests/unit-mcdc/test_crl_whitebox.c index 3ee20d4f938..b4118e8b33c 100644 --- a/tests/unit-mcdc/test_crl_whitebox.c +++ b/tests/unit-mcdc/test_crl_whitebox.c @@ -55,6 +55,7 @@ #include #include +#include #include #include @@ -62,7 +63,17 @@ #if defined(HAVE_CRL) && !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) static int g_checks; +static int g_fail; #define WB_NOTE(what) do { g_checks++; (void)(what); } while (0) +/* For vectors with a known result: prints FAIL if cond is false. main still + * returns 0; run-whitebox-smoke.sh fails on "with failures". */ +#define WB_EXPECT(cond, what) do { \ + g_checks++; \ + if (!(cond)) { \ + g_fail = 1; \ + printf("crl white-box: FAIL %s\n", (what)); \ + } \ + } while (0) /* ------------------------------------------------ CheckCertCRLCm :607 */ /* `if ((serial == NULL || serialSz == 0) && serialHash == NULL)` @@ -90,13 +101,13 @@ static void wb_check_cert_crl_ex(WOLFSSL_CERT_MANAGER* cm) XMEMSET(issuerHash, 0x22, sizeof(issuerHash)); WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, NULL, (int)sizeof(serial), - hash, NULL, 0, NULL, cm, 1)); + hash, NULL, 0, NULL, cm, 1, NULL)); WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, NULL, (int)sizeof(serial), - NULL, NULL, 0, NULL, cm, 1)); + NULL, NULL, 0, NULL, cm, 1, NULL)); WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, 0, - NULL, NULL, 0, NULL, cm, 1)); + NULL, NULL, 0, NULL, cm, 1, NULL)); WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), - NULL, NULL, 0, NULL, cm, 1)); + NULL, NULL, 0, NULL, cm, 1, NULL)); } @@ -154,14 +165,14 @@ static void wb_missing_crl_callbacks(WOLFSSL_CERT_MANAGER* cm) /* 1. cm NULL: operand 0 false for both decisions. */ WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)url, (int)XSTRLEN(url), NULL, - NULL, 1)); + NULL, 1, NULL)); /* 2. real cm, no callbacks: operand 0 true, operand 1 false. */ cm->cbMissingCRL = NULL; cm->crlCb = NULL; WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)url, (int)XSTRLEN(url), NULL, - cm, 1)); + cm, 1, NULL)); /* 3. both callbacks installed, error cb returns 0: takes :668 TRUE (the * partner that gives operands 0 and 1 their pairs) and :686 to its third @@ -171,14 +182,14 @@ static void wb_missing_crl_callbacks(WOLFSSL_CERT_MANAGER* cm) g_crlCbResult = 0; WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)url, (int)XSTRLEN(url), NULL, - cm, 1)); + cm, 1, NULL)); /* 4. error cb returns non-zero: :686 operand 2 true, decision TRUE, which * is the override-the-CRL-error path. */ g_crlCbResult = 1; WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)url, (int)XSTRLEN(url), NULL, - cm, 1)); + cm, 1, NULL)); /* 5. a url longer than the 256-byte stack buffer takes the "CRL url too * long" arm of the copy guard inside the :668 body, which the short url @@ -189,7 +200,7 @@ static void wb_missing_crl_callbacks(WOLFSSL_CERT_MANAGER* cm) longUrl[sizeof(longUrl) - 1] = '\0'; WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)longUrl, - (int)sizeof(longUrl) - 1, NULL, cm, 1)); + (int)sizeof(longUrl) - 1, NULL, cm, 1, NULL)); } cm->cbMissingCRL = NULL; @@ -478,6 +489,243 @@ static void wb_store_crl(WOLFSSL_CERT_MANAGER* cm) (void)remove(out); } +/* ------------------------------------------- AKID: AddCRL, CheckCertCRLList */ +/* A CA with several keys has one CRL series per key, told apart by AKID. + * These vectors drive the AKID decisions: + * + * AddCRL: + * crle->extAuthKeyIdSet && curr->extAuthKeyIdSet && + * XMEMCMP(crle AKID, curr AKID) != 0 -> new series + * !crle->extAuthKeyIdSet && curr->extAuthKeyIdSet -> new series + * + * CheckCertCRLList: + * akid != NULL && crle->extAuthKeyIdSet && + * XMEMCMP(crle AKID, akid) != 0 -> other-key CRL + * ownSeen ? own : other -> coverage + * + * The MC/DC vectors above all pass akid == NULL. Here the CRLs are loaded + * unverified, then marked verified by hand. + * + * Fixtures (tests/api/test_certman_crl_fixtures.h): key A is the old root, + * key B the new one. A's CRLs are numbers 5 (revokes 0x10), 6 and 7 (no + * AKID). B's is number 1 (revokes 0x10 and 0x20). */ +#if !defined(NO_SKID) && !defined(NO_ASN) && defined(HAVE_ECC) && \ + !defined(NO_ECC256) && !defined(NO_SHA256) + +/* Loads der unverified. Returns the list head, or NULL on failure. */ +static CRL_Entry* wb_akid_load(WOLFSSL_CRL* crl, const byte* der, int sz) +{ + if (BufferLoadCRL(crl, der, sz, WOLFSSL_FILETYPE_ASN1, NO_VERIFY) + != WOLFSSL_SUCCESS) + return NULL; + return crl->crlList; +} + +static int wb_akid_count(const WOLFSSL_CRL* crl) +{ + const CRL_Entry* e; + int n = 0; + for (e = crl->crlList; e != NULL; e = e->next) + n++; + return n; +} + +/* Key A's key ID, read from its CRL by wb_akid(). */ +static byte wb_akid_a[KEYID_SIZE]; +static int wb_akid_a_set; + +/* Loads CA A into cm and returns its signer. Load it after the CRLs to keep + * them unverified. */ +static Signer* wb_akid_load_ca(WOLFSSL_CERT_MANAGER* cm) +{ + if (!wb_akid_a_set || + wolfSSL_CertManagerLoadCABuffer(cm, fxRootOld, sizeof(fxRootOld), + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) + return NULL; + return GetCA(cm, wb_akid_a); +} + +/* AddCRL's AKID checks: load two CRLs and count entries (1 = replaced or + * rejected, 2 = separate series). Each row has its own CertManager. */ +static void wb_akid_add_crl(void) +{ + static const struct { + int caFirst; /* Load CA A first: its CRLs are verified. */ + const byte* first; int firstSz; + const byte* second; int secondSz; + int count; /* Entries after both loads. */ + const char* what; + } rows[] = { + { 0, fxCrlOld7NoAkid, sizeof(fxCrlOld7NoAkid), + fxCrlOld5, sizeof(fxCrlOld5), 1, + "AddCRL: stored entry has no AKID, number 5 < 7 rejected" }, + { 0, fxCrlOld5, sizeof(fxCrlOld5), + fxCrlOld7NoAkid, sizeof(fxCrlOld7NoAkid), 2, + "AddCRL: new entry has no AKID, kept beside the AKID one" }, + { 0, fxCrlOld5, sizeof(fxCrlOld5), fxCrlOld6, sizeof(fxCrlOld6), 1, + "AddCRL: same AKID, replaces by number" }, + { 0, fxCrlOld5, sizeof(fxCrlOld5), fxCrlNew1, sizeof(fxCrlNew1), 2, + "AddCRL: other AKID, new series" }, + { 1, fxCrlOld5, sizeof(fxCrlOld5), fxCrlNew1, sizeof(fxCrlNew1), 1, + "AddCRL: verified entry blocks an unverified new series" }, + }; + size_t i; + + for (i = 0; i < sizeof(rows) / sizeof(rows[0]); i++) { + WOLFSSL_CERT_MANAGER* cm = wolfSSL_CertManagerNew(); + WOLFSSL_CRL crl; + + if (cm == NULL || InitCRL(&crl, cm) != 0) { + printf("crl white-box: no CRL context, skipping AddCRL AKID\n"); + wolfSSL_CertManagerFree(cm); + return; + } + if (rows[i].caFirst) + WB_EXPECT(wb_akid_load_ca(cm) != NULL, rows[i].what); + WB_EXPECT(wb_akid_load(&crl, rows[i].first, rows[i].firstSz) != NULL, + rows[i].what); + (void)wb_akid_load(&crl, rows[i].second, rows[i].secondSz); + WB_EXPECT(wb_akid_count(&crl) == rows[i].count, rows[i].what); + FreeCRL(&crl, 0); + wolfSSL_CertManagerFree(cm); + } +} + +#if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) && \ + !defined(WOLFSSL_NO_CRL_NEXT_DATE) + #define WB_AKID_DATES +#endif + +/* Moves e's next update to 2020-01-01, in place over the fixtures' same-length + * 2046-01-01 UTCTime. */ +static void wb_akid_expire(CRL_Entry* e) +{ + static const char past[] = "200101000000Z"; + if (e->nextDateFormat == ASN_UTC_TIME) + XMEMCPY(e->nextDate, past, sizeof(past) - 1); +} + +/* CheckCertCRLList with a cert AKID. "Own" CRLs match the cert's AKID, "other" + * ones don't. Only CA A is loaded, so key B has no trust anchor. */ +static void wb_akid_check_list(void) +{ + /* CRLs loaded: A's 5, B's 1, both, or A's 7 (no AKID). */ + enum { L_A, L_B, L_A_B, L_NOAKID }; + static const byte s1[] = { 0x10 }; /* Revoked by A (and B). */ + static const byte s2[] = { 0x20 }; /* Revoked by B only. */ + static const byte s3[] = { 0x99 }; /* Revoked by neither. */ + static const struct { + int list; + int staleA; + int staleB; + int akid; /* Cert's AKID: 0 none, 1 key A, 2 key B. */ + const byte* serial; + int ret; + int found; /* Expected *pFoundEntry. */ + const char* what; + } rows[] = { + { L_A_B, 0, 0, 0, s3, 0, 1, + "CheckCertCRLList: no cert AKID, every CRL is own" }, + { L_NOAKID, 0, 0, 1, s3, 0, 1, + "CheckCertCRLList: CRL without AKID is own" }, + { L_A_B, 0, 0, 1, s3, 0, 1, + "CheckCertCRLList: own and other fresh, not revoked" }, + { L_A, 0, 0, 1, s1, WC_NO_ERR_TRACE(CRL_CERT_REVOKED), 1, + "CheckCertCRLList: revoked by own key" }, + { L_A_B, 0, 0, 1, s2, WC_NO_ERR_TRACE(CRL_CERT_REVOKED), 1, + "CheckCertCRLList: revoked by other key" }, + /* Key B's root isn't loaded, so its CRL can't chain to the cert's + * trust anchor (RFC 5280 6.3.3(f)) and doesn't count as found. */ + { L_B, 0, 0, 1, s3, 0, 0, + "CheckCertCRLList: no own CRL, other anchor doesn't cover" }, + #ifdef WB_AKID_DATES + { L_B, 0, 1, 1, s3, 0, 0, + "CheckCertCRLList: no own CRL, other anchor stale ignored" }, + { L_A_B, 1, 0, 1, s3, WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR), 0, + "CheckCertCRLList: own stale, other fresh doesn't cover" }, + { L_A_B, 0, 1, 1, s3, 0, 1, + "CheckCertCRLList: own fresh, other stale ignored" }, + #endif + }; + size_t i; + + for (i = 0; i < sizeof(rows) / sizeof(rows[0]); i++) { + WOLFSSL_CERT_MANAGER* cm = wolfSSL_CertManagerNew(); + WOLFSSL_CRL crl; + CRL_Entry* eA = NULL; + CRL_Entry* eB = NULL; + CRL_Entry* e; + Signer* ca; + byte akidB[KEYID_SIZE]; + byte issuerHash[CRL_DIGEST_SIZE]; + int found = -1; + int ret; + + if (cm == NULL || InitCRL(&crl, cm) != 0) { + wolfSSL_CertManagerFree(cm); + return; + } + /* CRLs first so they are stored unverified, then the CA. */ + if (rows[i].list == L_A || rows[i].list == L_A_B) + eA = wb_akid_load(&crl, fxCrlOld5, sizeof(fxCrlOld5)); + if (rows[i].list == L_B || rows[i].list == L_A_B) + eB = wb_akid_load(&crl, fxCrlNew1, sizeof(fxCrlNew1)); + if (rows[i].list == L_NOAKID) + (void)wb_akid_load(&crl, fxCrlOld7NoAkid, sizeof(fxCrlOld7NoAkid)); + ca = wb_akid_load_ca(cm); + if (crl.crlList == NULL || ca == NULL || + (rows[i].akid == 2 && eB == NULL)) { + WB_EXPECT(0, rows[i].what); + FreeCRL(&crl, 0); + wolfSSL_CertManagerFree(cm); + continue; + } + if (eB != NULL) + XMEMCPY(akidB, eB->extAuthKeyId, KEYID_SIZE); + XMEMCPY(issuerHash, crl.crlList->issuerHash, CRL_DIGEST_SIZE); + /* Use them without a signature check. */ + for (e = crl.crlList; e != NULL; e = e->next) + e->verified = 1; + if (rows[i].staleA && eA != NULL) + wb_akid_expire(eA); + if (rows[i].staleB && eB != NULL) + wb_akid_expire(eB); + + ret = CheckCertCRLList(&crl, issuerHash, (byte*)rows[i].serial, + (int)sizeof(s1), NULL, &found, cm, + rows[i].akid == 1 ? wb_akid_a : + rows[i].akid == 2 ? akidB : NULL); + WB_EXPECT(ret == rows[i].ret && found == rows[i].found, + rows[i].what); + + FreeCRL(&crl, 0); + wolfSSL_CertManagerFree(cm); + } +} + +static void wb_akid(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_CRL crl; + + if (InitCRL(&crl, cm) == 0) { + CRL_Entry* eA = wb_akid_load(&crl, fxCrlOld5, sizeof(fxCrlOld5)); + if (eA != NULL && eA->extAuthKeyIdSet) { + XMEMCPY(wb_akid_a, eA->extAuthKeyId, KEYID_SIZE); + wb_akid_a_set = 1; + } + FreeCRL(&crl, 0); + } + if (!wb_akid_a_set) { + printf("crl white-box: AKID CRL did not load, AKID vectors " + "skipped\n"); + return; + } + + wb_akid_add_crl(); + wb_akid_check_list(); +} +#endif /* !NO_SKID && !NO_ASN && HAVE_ECC && !NO_ECC256 && !NO_SHA256 */ + /* ---------------------------------------------------------- main */ int main(void) @@ -512,8 +760,13 @@ int main(void) wb_buffer_store(cm); wb_load_crl(cm); wb_store_crl(cm); +#if !defined(NO_SKID) && !defined(NO_ASN) && defined(HAVE_ECC) && \ + !defined(NO_ECC256) && !defined(NO_SHA256) + wb_akid(cm); +#endif - printf("crl white-box: %d vectors driven\n", g_checks); + printf("crl white-box: %d vectors driven (%s)\n", g_checks, + g_fail ? "with failures" : "ok"); done: if (cm != NULL) diff --git a/tests/unit-mcdc/test_internal_revocation_whitebox.c b/tests/unit-mcdc/test_internal_revocation_whitebox.c index d2d41a7a2c6..6cafdc04fe7 100644 --- a/tests/unit-mcdc/test_internal_revocation_whitebox.c +++ b/tests/unit-mcdc/test_internal_revocation_whitebox.c @@ -103,10 +103,11 @@ static int mcdc_CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) * answer. */ static int mcdc_CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int serialSz, byte* serialHash, const byte* extCrlInfo, - int extCrlInfoSz, void* issuerName) + int extCrlInfoSz, void* issuerName, const byte* akid) { (void)crl; (void)issuerHash; (void)serial; (void)serialSz; (void)serialHash; (void)extCrlInfo; (void)extCrlInfoSz; (void)issuerName; + (void)akid; g_crlCalls++; return g_crlRet; } @@ -121,8 +122,8 @@ static int mcdc_CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, #endif #ifdef HAVE_CRL #define CheckCertCRL(a, b) mcdc_CheckCertCRL((a), (b)) - #define CheckCertCRL_ex(a, b, c, d, e, f, g, h) \ - mcdc_CheckCertCRL_ex((a), (b), (c), (d), (e), (f), (g), (h)) + #define CheckCertCRL_ex(a, b, c, d, e, f, g, h, i) \ + mcdc_CheckCertCRL_ex((a), (b), (c), (d), (e), (f), (g), (h), (i)) #endif #include diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 74eae07c332..c23d696a030 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -26995,7 +26995,7 @@ int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der) #ifndef NO_SKID XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, SIGNER_DIGEST_SIZE); - #ifndef IGNORE_NAME_CONSTRAINTS + #if !defined(IGNORE_NAME_CONSTRAINTS) || defined(HAVE_CRL) if (cert->extAuthKeyIdSet) { XMEMCPY(signer->authKeyIdHash, cert->extAuthKeyId, SIGNER_DIGEST_SIZE); diff --git a/wolfssl/crl.h b/wolfssl/crl.h index 0a1c72d7d5e..13b5d402d5f 100644 --- a/wolfssl/crl.h +++ b/wolfssl/crl.h @@ -47,7 +47,7 @@ WOLFSSL_LOCAL int BufferStoreCRL(WOLFSSL_CRL* crl, byte* buff, long* inOutSz, WOLFSSL_LOCAL int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert); WOLFSSL_LOCAL int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int serialSz, byte* serialHash, const byte* extCrlInfo, - int extCrlInfoSz, void* issuerName); + int extCrlInfoSz, void* issuerName, const byte* akid); WOLFSSL_LOCAL int CheckCertCRLFromCm(WOLFSSL_CERT_MANAGER* cm, WOLFSSL_CRL* crl, DecodedCert* cert); #ifdef HAVE_CRL_UPDATE_CB diff --git a/wolfssl/internal.h b/wolfssl/internal.h index c96be637e07..7dc154e6673 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -8077,6 +8077,12 @@ WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG, WOLFSSL_LOCAL Signer* GetCAByName(WOLFSSL_CERT_MANAGER* cm, byte* hash); #endif + #ifdef HAVE_CRL + WOLFSSL_LOCAL Signer* GetCAIssuer(WOLFSSL_CERT_MANAGER* cm, + Signer* ca); + WOLFSSL_LOCAL Signer* GetCATrustAnchor(WOLFSSL_CERT_MANAGER* cm, + Signer* ca); + #endif #endif /* !NO_CERTS */ WOLFSSL_LOCAL int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index d5f89a90f0e..d1871ae04ff 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2393,10 +2393,11 @@ struct Signer { */ WC_BITFIELD extNameConstraintCrit:1; WC_BITFIELD extNameConstraintHasUnsupported:1; -#ifndef NO_SKID +#endif +#if !defined(NO_SKID) && \ + (!defined(IGNORE_NAME_CONSTRAINTS) || defined(HAVE_CRL)) WC_BITFIELD authKeyIdSet:1; /* true when authKeyIdHash holds the * AKID extension's keyId */ -#endif #endif const byte* publicKey; int nameLen; @@ -2417,10 +2418,12 @@ struct Signer { #ifndef NO_SKID byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; /* sha hash of key in certificate */ -#ifndef IGNORE_NAME_CONSTRAINTS +#if !defined(IGNORE_NAME_CONSTRAINTS) || defined(HAVE_CRL) byte authKeyIdHash[SIGNER_DIGEST_SIZE]; - /* sha hash of AKID; locates signer - * during name-constraint walk */ + /* This CA's AKID, as in DecodedCert's + * extAuthKeyId. Finds its issuer by key + * during name-constraint and CRL chain + * walks */ #endif #endif #ifdef HAVE_OCSP