diff --git a/src/crl.c b/src/crl.c index c27e7ca0c..e185a36f4 100755 --- a/src/crl.c +++ b/src/crl.c @@ -74,7 +74,8 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm) /* Initialize CRL Entry */ -static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) +static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, + int verified, void* heap) { WOLFSSL_ENTER("InitCRL_Entry"); @@ -89,6 +90,34 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) crle->certs = dcrl->certs; /* take ownsership */ dcrl->certs = NULL; crle->totalCerts = dcrl->totalCerts; + crle->verified = verified; + if (!verified) { + crle->tbsSz = dcrl->sigIndex - dcrl->certBegin; + crle->signatureSz = dcrl->sigLength; + crle->signatureOID = dcrl->signatureOID; + crle->toBeSigned = XMALLOC(crle->tbsSz, heap, DYNAMIC_TYPE_CRL_ENTRY); + if (crle->toBeSigned == NULL) + return -1; + crle->signature = XMALLOC(crle->signatureSz, heap, + DYNAMIC_TYPE_CRL_ENTRY); + if (crle->signature == NULL) { + XFREE(crle->signature, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + return -1; + } + XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz); + XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz); + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; + if (crle->extAuthKeyIdSet) + XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); + #endif + } + else { + crle->toBeSigned = NULL; + crle->signature = NULL; + } + + (void)verified; return 0; } @@ -106,6 +135,10 @@ static void FreeCRL_Entry(CRL_Entry* crle, void* heap) XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED); tmp = next; } + if (crle->signature != NULL) + XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED); + if (crle->toBeSigned != NULL) + XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED); (void)heap; } @@ -167,6 +200,46 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntr int doNextDate = 1; WOLFSSL_MSG("Found CRL Entry on list"); + + if (crle->verified == 0) { + Signer* ca; + + wc_UnLockMutex(&crl->crlLock); + + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + if (crle->extAuthKeyIdSet) + ca = GetCA(crl->cm, crle->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(crl->cm, crle->issuerHash); + #else /* NO_SKID */ + ca = GetCA(crl->cm, crle->issuerHash); + #endif /* NO_SKID */ + if (ca == NULL) { + WOLFSSL_MSG("Did NOT find CRL issuer CA"); + return ASN_CRL_NO_SIGNER_E; + } + + ret = VerifyCRL_Signature(crle->toBeSigned, crle->tbsSz, + crle->signature, crle->signatureSz, crle->signatureOID, ca); + + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + + if (ret == 0) + crle->verified = 1; + else { + crle->verified = ret; + break; + } + } + else if (crle->verified < 0) { + WOLFSSL_MSG("Cannot use CRL as it didn't verify"); + ret = crle->verified; + break; + } + WOLFSSL_MSG("Checking next date validity"); #ifdef WOLFSSL_NO_CRL_NEXT_DATE @@ -260,7 +333,8 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) /* Add Decoded CRL, 0 on success */ -static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) +static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, + int verified) { CRL_Entry* crle; @@ -272,7 +346,7 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) return -1; } - if (InitCRL_Entry(crle, dcrl) < 0) { + if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) { WOLFSSL_MSG("Init CRL Entry failed"); XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); return -1; @@ -341,7 +415,7 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type, WOLFSSL_MSG("ParseCRL error"); } else { - ret = AddCRL(crl, dcrl); + ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E); if (ret != 0) { WOLFSSL_MSG("AddCRL error"); } diff --git a/tests/api.c b/tests/api.c index 89f31c2c3..b83ac7cd9 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2763,8 +2763,20 @@ static void test_wolfSSL_X509_LOOKUP_load_file(void) AssertNotNull(store = wolfSSL_X509_STORE_new()); AssertNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/client-ca.pem", + X509_FILETYPE_PEM), 1); AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/crl/crl2.pem", X509_FILETYPE_PEM), 1); + + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, cliCert, SSL_FILETYPE_PEM), + 1); + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCert, SSL_FILETYPE_PEM), + ASN_NO_SIGNER_E); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", + X509_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCert, SSL_FILETYPE_PEM), + 1); + wolfSSL_X509_STORE_free(store); printf(resultFmt, passed); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 8d9901c12..6bc30e2c3 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -10700,6 +10700,27 @@ static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl, return 0; } +int VerifyCRL_Signature(const byte* toBeSigned, word32 tbsSz, + const byte* signature, word32 sigSz, + word32 signatureOID, Signer *ca) +{ + /* try to confirm/verify signature */ +#ifndef IGNORE_KEY_EXTENSIONS + if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { + WOLFSSL_MSG("CA cannot sign CRLs"); + return ASN_CRL_NO_SIGNER_E; + } +#endif /* IGNORE_KEY_EXTENSIONS */ + + InitSignatureCtx(&sigCtx, dcrl->heap, INVALID_DEVID); + if (ConfirmSignature(toBeSigned, tbsSz, ca->publicKey, ca->pubKeySize, + ca->keyOID, signature, sigSz, signatureOID, NULL) != 0) { + WOLFSSL_MSG("CRL Confirm signature failed"); + return ASN_CRL_CONFIRM_E; + } + + return 0; +} /* prase crl buffer into decoded state, 0 on success */ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) @@ -10797,33 +10818,15 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) #endif /* !NO_SKID && CRL_SKID_READY */ WOLFSSL_MSG("About to verify CRL signature"); - if (ca) { - SignatureCtx sigCtx; - - WOLFSSL_MSG("Found CRL issuer CA"); - /* try to confirm/verify signature */ - #ifndef IGNORE_KEY_EXTENSIONS - if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { - WOLFSSL_MSG("CA cannot sign CRLs"); - return ASN_CRL_NO_SIGNER_E; - } - #endif /* IGNORE_KEY_EXTENSIONS */ - - InitSignatureCtx(&sigCtx, dcrl->heap, INVALID_DEVID); - if (ConfirmSignature(&sigCtx, buff + dcrl->certBegin, - dcrl->sigIndex - dcrl->certBegin, - ca->publicKey, ca->pubKeySize, ca->keyOID, - dcrl->signature, dcrl->sigLength, dcrl->signatureOID) != 0) { - WOLFSSL_MSG("CRL Confirm signature failed"); - return ASN_CRL_CONFIRM_E; - } - } - else { + if (ca == NULL) { WOLFSSL_MSG("Did NOT find CRL issuer CA"); return ASN_CRL_NO_SIGNER_E; } - return ret; + WOLFSSL_MSG("Found CRL issuer CA"); + return VerifyCRL_Signature(buff + dcrl->certBegin, + dcrl->sigIndex - dcrl->certBegin, dcrl->signature, dcrl->sigLength, + dcrl->signatureOID, ca); } #endif /* HAVE_CRL */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index aa6499328..ea56d93b6 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1571,6 +1571,16 @@ struct CRL_Entry { byte nextDateFormat; /* next date format */ RevokedCert* certs; /* revoked cert list */ int totalCerts; /* number on list */ + int verified; + byte* toBeSigned; + word32 tbsSz; + byte* signature; + word32 signatureSz; + word32 signatureOID; +#if !defined(NO_SKID) && defined(CRL_SKID_READY) + byte extAuthKeyIdSet; + byte extAuthKeyId[KEYID_SIZE]; +#endif }; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index d456818cf..13e09ed7f 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -976,6 +976,9 @@ struct DecodedCRL { }; WOLFSSL_LOCAL void InitDecodedCRL(DecodedCRL*, void* heap); +WOLFSSL_LOCAL int VerifyCRL_Signature(const byte* toBeSigned, word32 tbsSz, + const byte* signature, word32 sigSz, + word32 signatureOID, Signer *ca); WOLFSSL_LOCAL int ParseCRL(DecodedCRL*, const byte* buff, word32 sz, void* cm); WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL*);