Skip to content

Commit

Permalink
Merge pull request wolfSSL#8006 from ColtonWilley/crl_update_cb
Browse files Browse the repository at this point in the history
CRL improvements and update callback
  • Loading branch information
dgarske authored Nov 19, 2024
2 parents c111bb8 + d65c17b commit 261ddc1
Show file tree
Hide file tree
Showing 8 changed files with 415 additions and 42 deletions.
79 changes: 79 additions & 0 deletions doc/dox_comments/header_files/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -10012,6 +10012,85 @@ int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm,
CbMissingCRL cb);

/*!
\ingroup CertManager
\brief This function sets the CRL Update callback. If
HAVE_CRL and HAVE_CRL_UPDATE_CB is defined , and an entry with the same
issuer and a lower CRL number exists when a CRL is added, then the
CbUpdateCRL is called with the details of the existing entry and the
new one replacing it.
\return SSL_SUCCESS returned upon successful execution of the function and
subroutines.
\return BAD_FUNC_ARG returned if the WOLFSSL_CERT_MANAGER structure is NULL.
\param cm the WOLFSSL_CERT_MANAGER structure holding the information for
the certificate.
\param cb a function pointer to (*CbUpdateCRL) that is set to the
cbUpdateCRL member of the WOLFSSL_CERT_MANAGER.
Signature requirement:
void (*CbUpdateCRL)(CrlInfo *old, CrlInfo *new);
_Example_
\code
#include <wolfssl/ssl.h>
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(protocol method);
WOLFSSL* ssl = wolfSSL_new(ctx);
void cb(CrlInfo *old, CrlInfo *new){
Function body.
}
CbUpdateCRL cb = CbUpdateCRL;
if(ctx){
return wolfSSL_CertManagerSetCRLUpdate_Cb(SSL_CM(ssl), cb);
}
\endcode
\sa CbUpdateCRL
*/
int wolfSSL_CertManagerSetCRLUpdate_Cb(WOLFSSL_CERT_MANAGER* cm,
CbUpdateCRL cb);

/*!
\ingroup CertManager
\brief This function yields a structure with parsed CRL information from
an encoded CRL buffer.
\return SSL_SUCCESS returned upon successful execution of the function and
subroutines.
\return BAD_FUNC_ARG returned if the WOLFSSL_CERT_MANAGER structure is NULL.
\param cm the WOLFSSL_CERT_MANAGER structure..
\param info pointer to caller managed CrlInfo structure that will receive
the CRL information.
\param buff input buffer containing encoded CRL.
\param sz the length in bytes of the input CRL data in buff.
\param type WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_DER
_Example_
\code
#include <wolfssl/ssl.h>
CrlInfo info;
WOLFSSL_CERT_MANAGER* cm = NULL;
cm = wolfSSL_CertManagerNew();
// Read crl data from file into buffer
wolfSSL_CertManagerGetCRLInfo(cm, &info, crlData, crlDataLen,
WOLFSSL_FILETYPE_PEM);
\endcode
\sa CbUpdateCRL
\sa wolfSSL_SetCRL_Cb
*/
int wolfSSL_CertManagerGetCRLInfo(WOLFSSL_CERT_MANAGER* cm, CrlInfo* info,
const byte* buff, long sz, int type)

/*!
\ingroup CertManager
\brief This function frees the CRL stored in the Cert Manager. An
Expand Down
154 changes: 151 additions & 3 deletions src/crl.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ static int FindRevokedSerial(RevokedCert* rc, byte* serial, int serialSz,
#else
(void)totalCerts;
/* search in the linked list*/

while (rc) {
if (serialHash == NULL) {
if (rc->serialSz == serialSz &&
Expand Down Expand Up @@ -560,12 +559,45 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
NULL, cert->extCrlInfo, cert->extCrlInfoSz, issuerName);
}

#ifdef HAVE_CRL_UPDATE_CB
static void SetCrlInfo(CRL_Entry* entry, CrlInfo *info)
{
info->issuerHash = (byte *)entry->issuerHash;
info->issuerHashLen = CRL_DIGEST_SIZE;
info->lastDate = (byte *)entry->lastDate;
info->lastDateMaxLen = MAX_DATE_SIZE;
info->lastDateFormat = entry->lastDateFormat;
info->nextDate = (byte *)entry->nextDate;
info->nextDateMaxLen = MAX_DATE_SIZE;
info->nextDateFormat = entry->nextDateFormat;
info->crlNumber = (sword32)entry->crlNumber;
}

static void SetCrlInfoFromDecoded(DecodedCRL* entry, CrlInfo *info)
{
info->issuerHash = (byte *)entry->issuerHash;
info->issuerHashLen = SIGNER_DIGEST_SIZE;
info->lastDate = (byte *)entry->lastDate;
info->lastDateMaxLen = MAX_DATE_SIZE;
info->lastDateFormat = entry->lastDateFormat;
info->nextDate = (byte *)entry->nextDate;
info->nextDateMaxLen = MAX_DATE_SIZE;
info->nextDateFormat = entry->nextDateFormat;
info->crlNumber = (sword32)entry->crlNumber;
}
#endif

/* Add Decoded CRL, 0 on success */
static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
int verified)
{
CRL_Entry* crle = NULL;
CRL_Entry* curr = NULL;
CRL_Entry* prev = NULL;
#ifdef HAVE_CRL_UPDATE_CB
CrlInfo old;
CrlInfo cnew;
#endif

WOLFSSL_ENTER("AddCRL");

Expand Down Expand Up @@ -594,8 +626,43 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
return BAD_MUTEX_E;
}

crle->next = crl->crlList;
crl->crlList = crle;
for (curr = crl->crlList; curr != NULL; curr = curr->next) {
if (XMEMCMP(curr->issuerHash, crle->issuerHash, CRL_DIGEST_SIZE) == 0) {
if (crle->crlNumber <= curr->crlNumber) {
WOLFSSL_MSG("Same or newer CRL entry already exists");
CRL_Entry_free(crle, crl->heap);
wc_UnLockRwLock(&crl->crlLock);
return BAD_FUNC_ARG;
}

crle->next = curr->next;
if (prev != NULL) {
prev->next = crle;
}
else {
crl->crlList = crle;
}

#ifdef HAVE_CRL_UPDATE_CB
if (crl->cm && crl->cm->cbUpdateCRL != NULL) {
SetCrlInfo(curr, &old);
SetCrlInfo(crle, &cnew);
crl->cm->cbUpdateCRL(&old, &cnew);
}
#endif

break;
}
prev = curr;
}

if (curr != NULL) {
CRL_Entry_free(curr, crl->heap);
}
else {
crle->next = crl->crlList;
crl->crlList = crle;
}
wc_UnLockRwLock(&crl->crlLock);
/* Avoid heap-use-after-free after crl->crlList is released */
crl->currentEntry = NULL;
Expand Down Expand Up @@ -686,6 +753,87 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
}

#ifdef HAVE_CRL_UPDATE_CB
/* Fill out CRL info structure, WOLFSSL_SUCCESS on ok */
int GetCRLInfo(WOLFSSL_CRL* crl, CrlInfo* info, const byte* buff,
long sz, int type)
{
int ret = WOLFSSL_SUCCESS;
const byte* myBuffer = buff; /* if DER ok, otherwise switch */
DerBuffer* der = NULL;
CRL_Entry* crle = NULL;
#ifdef WOLFSSL_SMALL_STACK
DecodedCRL* dcrl;
#else
DecodedCRL dcrl[1];
#endif

WOLFSSL_ENTER("GetCRLInfo");

if (crl == NULL || info == NULL || buff == NULL || sz == 0)
return BAD_FUNC_ARG;

if (type == WOLFSSL_FILETYPE_PEM) {
#ifdef WOLFSSL_PEM_TO_DER
ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL);
if (ret == 0) {
myBuffer = der->buffer;
sz = der->length;
}
else {
WOLFSSL_MSG("Pem to Der failed");
FreeDer(&der);
return -1;
}
#else
ret = NOT_COMPILED_IN;
#endif
}

#ifdef WOLFSSL_SMALL_STACK
dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (dcrl == NULL) {
FreeDer(&der);
return MEMORY_E;
}
#endif

crle = CRL_Entry_new(crl->heap);
if (crle == NULL) {
WOLFSSL_MSG("alloc CRL Entry failed");
#ifdef WOLFSSL_SMALL_STACK
XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
FreeDer(&der);
return MEMORY_E;
}

InitDecodedCRL(dcrl, crl->heap);
ret = ParseCRL(crle->certs, dcrl, myBuffer, (word32)sz,
0, crl->cm);
if (ret != 0 && !(ret == WC_NO_ERR_TRACE(ASN_CRL_NO_SIGNER_E))) {
WOLFSSL_MSG("ParseCRL error");
CRL_Entry_free(crle, crl->heap);
crle = NULL;
}
else {
SetCrlInfoFromDecoded((DecodedCRL*)dcrl, info);
}

FreeDecodedCRL(dcrl);

#ifdef WOLFSSL_SMALL_STACK
XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif

FreeDer(&der);
CRL_Entry_free(crle, crl->heap);

return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
}
#endif

#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
/* helper function to create a new dynamic WOLFSSL_X509_CRL structure */
static WOLFSSL_X509_CRL* wolfSSL_X509_crl_new(WOLFSSL_CERT_MANAGER* cm)
Expand Down
35 changes: 35 additions & 0 deletions src/ssl_certman.c
Original file line number Diff line number Diff line change
Expand Up @@ -1895,6 +1895,41 @@ int wolfSSL_CertManagerSetCRL_ErrorCb(WOLFSSL_CERT_MANAGER* cm, crlErrorCb cb,
return ret;
}

#ifdef HAVE_CRL_UPDATE_CB
int wolfSSL_CertManagerGetCRLInfo(WOLFSSL_CERT_MANAGER* cm, CrlInfo* info,
const byte* buff, long sz, int type)
{
return GetCRLInfo(cm->crl, info, buff, sz, type);
}

/* Set the callback to be called when a CRL entry has
* been updated (new entry had the same issuer hash and
* a newer CRL number).
*
* @param [in] cm Certificate manager.
* @param [in] cb CRL update callback.
* @return WOLFSSL_SUCCESS on success.
* @return BAD_FUNC_ARG when cm is NULL.
*/
int wolfSSL_CertManagerSetCRLUpdate_Cb(WOLFSSL_CERT_MANAGER* cm, CbUpdateCRL cb)
{
int ret = WOLFSSL_SUCCESS;

WOLFSSL_ENTER("wolfSSL_CertManagerSetCRLUpdate_Cb");

/* Validate parameters. */
if (cm == NULL) {
ret = BAD_FUNC_ARG;
}
if (ret == WOLFSSL_SUCCESS) {
/* Store callback. */
cm->cbUpdateCRL = cb;
}

return ret;
}
#endif

#ifdef HAVE_CRL_IO
/* Set the CRL I/O callback.
*
Expand Down
Loading

0 comments on commit 261ddc1

Please sign in to comment.