Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRL improvements and update callback #8006

Merged
merged 6 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
153 changes: 150 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)
SparkiDev marked this conversation as resolved.
Show resolved Hide resolved
{
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 new;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here with g++:

[quantum-safe-wolfssl-all-g++-latest-debug] [6 of 36] [55be5035a0-dirty]
    autogen.sh 55be5035a0-dirty...   real 0m10.586s  user 0m8.680s  sys 0m1.088s
    configure...   real 0m25.038s  user 0m13.907s  sys 0m13.286s
    build...src/crl.c: In function ‘int AddCRL(WOLFSSL_CRL*, DecodedCRL*, const byte*, int)’:
src/crl.c:599:13: error: expected unqualified-id before ‘new’
  599 |     CrlInfo new;

#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, &new);
crl->cm->cbUpdateCRL(&old, &new);
}
#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,86 @@ 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: This line is over 80 characters.

overlong lines added:
src/crl.c:794     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 @@ -1878,6 +1878,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
ColtonWilley marked this conversation as resolved.
Show resolved Hide resolved
* 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