瀏覽代碼

Merge pull request #5559 from tmael/crl_bs_p

Hayden Roche 1 年之前
父節點
當前提交
12bfa24ecc
共有 4 個文件被更改,包括 178 次插入50 次删除
  1. 106 24
      src/crl.c
  2. 58 23
      wolfcrypt/src/asn.c
  3. 12 1
      wolfssl/internal.h
  4. 2 2
      wolfssl/wolfcrypt/asn.h

+ 106 - 24
src/crl.c

@@ -20,8 +20,15 @@
  */
 
 
-  /* Name change compatibility layer no longer needs included here */
-
+/*
+CRL Options:
+ * CRL_STATIC_REVOKED_LIST:                                        default: off
+ *                         Enables fixed static list of RevokedCerts to allow
+ *                         for a binary search.
+ * CRL_MAX_REVOKED_CERTS:                                          default: 4
+ *                         Specifies the number of buffers to hold RevokedCerts.
+ *                         The default value is set to 4.
+*/
 #ifdef HAVE_CONFIG_H
     #include <config.h>
 #endif
@@ -56,7 +63,8 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
     else
         crl->heap = NULL;
     crl->cm = cm;
-    crl->crlList = NULL;
+    crl->crlList  = NULL;
+    crl->currentEntry = NULL;
     crl->monitors[0].path = NULL;
     crl->monitors[1].path = NULL;
 #ifdef HAVE_CRL_MONITOR
@@ -99,7 +107,12 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
         return WOLFSSL_FAILURE;
     }
 #endif
-    crle->certs = dcrl->certs;   /* take ownsership */
+#ifdef CRL_STATIC_REVOKED_LIST
+    /* ParseCRL_CertList() has already cached the Revoked certs into
+       the crle->certs array */
+#else
+    crle->certs = dcrl->certs;   /* take ownership */
+#endif
     dcrl->certs = NULL;
     crle->totalCerts = dcrl->totalCerts;
     crle->crlNumber = dcrl->crlNumber;
@@ -141,6 +154,11 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
 /* Free all CRL Entry resources */
 static void FreeCRL_Entry(CRL_Entry* crle, void* heap)
 {
+#ifdef CRL_STATIC_REVOKED_LIST
+    if (crle != NULL) {
+        XMEMSET(crle->certs, 0, CRL_MAX_REVOKED_CERTS*sizeof(RevokedCert));
+    }
+#else
     RevokedCert* tmp = crle->certs;
     RevokedCert* next;
 
@@ -151,6 +169,7 @@ static void FreeCRL_Entry(CRL_Entry* crle, void* heap)
         XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED);
         tmp = next;
     }
+#endif
     if (crle->signature != NULL)
         XFREE(crle->signature, heap, DYNAMIC_TYPE_CRL_ENTRY);
     if (crle->toBeSigned != NULL)
@@ -178,6 +197,8 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
     if (crl->monitors[1].path)
         XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
 
+    XFREE(crl->currentEntry, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+    crl->currentEntry = NULL;
     while(tmp) {
         CRL_Entry* next = tmp->next;
         FreeCRL_Entry(tmp, crl->heap);
@@ -208,7 +229,48 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
         XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL);
 }
 
+static int FindRevokedSerial(DecodedCert* cert, RevokedCert* rc, int totalCerts)
+{
+    int ret = 0;
+#ifdef CRL_STATIC_REVOKED_LIST
+    /* do binary search */
+    int low, high, mid;
 
+    low = 0;
+    high = totalCerts - 1;
+
+    while (low <= high) {
+        mid = (low + high) / 2;
+
+        if (XMEMCMP(rc[mid].serialNumber, cert->serial, rc->serialSz) < 0) {
+            low = mid + 1;
+        }
+        else if (XMEMCMP(rc[mid].serialNumber, cert->serial,
+                                                        rc->serialSz) > 0) {
+            high = mid - 1;
+        }
+        else {
+            WOLFSSL_MSG("Cert revoked");
+            ret = CRL_CERT_REVOKED;
+            break;
+        }
+    }
+#else
+    (void)totalCerts;
+    /* search in the linked list*/
+
+    while (rc) {
+        if (rc->serialSz == cert->serialSz &&
+               XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
+            WOLFSSL_MSG("Cert revoked");
+            ret = CRL_CERT_REVOKED;
+            break;
+        }
+        rc = rc->next;
+    }
+#endif
+    return ret;
+}
 static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry)
 {
     CRL_Entry* crle;
@@ -338,17 +400,7 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntr
     }
 
     if (foundEntry) {
-        RevokedCert* rc = crle->certs;
-
-        while (rc) {
-            if (rc->serialSz == cert->serialSz &&
-                   XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
-                WOLFSSL_MSG("Cert revoked");
-                ret = CRL_CERT_REVOKED;
-                break;
-            }
-            rc = rc->next;
-        }
+        ret = FindRevokedSerial(cert, crle->certs, crle->totalCerts);
     }
 
     wc_UnLockMutex(&crl->crlLock);
@@ -444,14 +496,22 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
 static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
                   int verified)
 {
-    CRL_Entry* crle;
+    CRL_Entry* crle = NULL;
 
     WOLFSSL_ENTER("AddCRL");
 
-    crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
-    if (crle == NULL) {
-        WOLFSSL_MSG("alloc CRL Entry failed");
+    if (crl == NULL)
         return -1;
+
+    crle = crl->currentEntry;
+
+    if (crle == NULL) {
+        crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap,
+                                   DYNAMIC_TYPE_CRL_ENTRY);
+        if (crle == NULL) {
+            WOLFSSL_MSG("alloc CRL Entry failed");
+            return MEMORY_E;
+        }
     }
 
     if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) {
@@ -466,9 +526,12 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
         XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
         return BAD_MUTEX_E;
     }
+
     crle->next = crl->crlList;
     crl->crlList = crle;
     wc_UnLockMutex(&crl->crlLock);
+    /* Avoid heap-use-after-free after crl->crlList is released */
+    crl->currentEntry = NULL;
 
     return 0;
 }
@@ -517,10 +580,21 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
     }
 #endif
 
+    crl->currentEntry = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap,
+                                        DYNAMIC_TYPE_CRL_ENTRY);
+    if (crl->currentEntry == NULL) {
+        WOLFSSL_MSG("alloc CRL Entry failed");
+        return MEMORY_E;
+    }
+    XMEMSET(crl->currentEntry, 0, sizeof(CRL_Entry));
+
     InitDecodedCRL(dcrl, crl->heap);
-    ret = ParseCRL(dcrl, myBuffer, (word32)sz, verify, crl->cm);
+    ret = ParseCRL(crl->currentEntry->certs, dcrl, myBuffer, (word32)sz,
+                   verify, crl->cm);
     if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) {
         WOLFSSL_MSG("ParseCRL error");
+        XFREE(crl->currentEntry, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
+        crl->currentEntry = NULL;
     }
     else {
         ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E);
@@ -558,7 +632,7 @@ static WOLFSSL_X509_CRL* wolfSSL_X509_crl_new(WOLFSSL_CERT_MANAGER* cm)
     return ret;
 }
 
-
+#ifndef CRL_STATIC_REVOKED_LIST
 /* returns head of copied list that was alloc'd */
 static RevokedCert *DupRevokedCertList(RevokedCert* in, void* heap)
 {
@@ -599,12 +673,16 @@ static RevokedCert *DupRevokedCertList(RevokedCert* in, void* heap)
     return head;
 }
 
-
+#endif /* CRL_STATIC_REVOKED_LIST */
 /* returns a deep copy of ent on success and null on fail */
 static CRL_Entry* DupCRL_Entry(const CRL_Entry* ent, void* heap)
 {
     CRL_Entry *dupl;
-
+#ifdef CRL_STATIC_REVOKED_LIST
+    if (ent->totalCerts > CRL_MAX_REVOKED_CERTS) {
+        return NULL;
+    }
+#endif
     dupl = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), heap, DYNAMIC_TYPE_CRL_ENTRY);
     if (dupl == NULL) {
         WOLFSSL_MSG("alloc CRL Entry failed");
@@ -617,8 +695,12 @@ static CRL_Entry* DupCRL_Entry(const CRL_Entry* ent, void* heap)
     XMEMCPY(dupl->nextDate, ent->nextDate, MAX_DATE_SIZE);
     dupl->lastDateFormat = ent->lastDateFormat;
     dupl->nextDateFormat = ent->nextDateFormat;
-    dupl->certs = DupRevokedCertList(ent->certs, heap);
 
+#ifdef CRL_STATIC_REVOKED_LIST
+    XMEMCPY(dupl->certs, ent->certs, ent->totalCerts*sizeof(RevokedCert));
+#else
+    dupl->certs = DupRevokedCertList(ent->certs, heap);
+#endif
     dupl->totalCerts = ent->totalCerts;
     dupl->verified = ent->verified;
 

+ 58 - 23
wolfcrypt/src/asn.c

@@ -33475,7 +33475,7 @@ int wc_Curve448PublicKeyToDer(curve448_key* key, byte* output, word32 inLen,
 
 
 #ifndef WOLFSSL_ASN_TEMPLATE
-#if defined(HAVE_OCSP) || defined(HAVE_CRL)
+#if (defined(HAVE_OCSP) || defined(HAVE_CRL)) && !defined(WOLFCRYPT_ONLY)
 
 /* Get raw Date only, no processing, 0 on success */
 static int GetBasicDate(const byte* source, word32* idx, byte* date,
@@ -33499,7 +33499,7 @@ static int GetBasicDate(const byte* source, word32* idx, byte* date,
 #endif /* WOLFSSL_ASN_TEMPLATE */
 
 
-#ifdef HAVE_OCSP
+#if defined(HAVE_OCSP) && !defined(WOLFCRYPT_ONLY)
 
 #ifndef WOLFSSL_ASN_TEMPLATE
 static int GetEnumerated(const byte* input, word32* inOutIdx, int *value,
@@ -35391,7 +35391,7 @@ int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx)
 #endif /* WOLFSSL_ASN_TEMPLATE */
 }
 
-#ifdef HAVE_CRL
+#if defined(HAVE_CRL) && !defined(WOLFCRYPT_ONLY)
 
 #ifdef OPENSSL_EXTRA
 static char* GetNameFromDer(const byte* source, int sz)
@@ -35469,8 +35469,8 @@ enum {
 #endif
 
 /* Get Revoked Cert list, 0 on success */
-static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
-                      int maxIdx)
+static int GetRevoked(RevokedCert* rcert, const byte* buff, word32* idx,
+                      DecodedCRL* dcrl, int maxIdx)
 {
 #ifndef WOLFSSL_ASN_TEMPLATE
 #ifndef NO_ASN_TIME
@@ -35479,7 +35479,9 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
     int len;
     word32 end;
     RevokedCert* rc;
-
+#ifdef CRL_STATIC_REVOKED_LIST
+    int totalCerts = 0;
+#endif
     WOLFSSL_ENTER("GetRevoked");
 
     if (GetSequence(buff, idx, &len, maxIdx) < 0)
@@ -35487,24 +35489,39 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
 
     end = *idx + len;
 
+#ifdef CRL_STATIC_REVOKED_LIST
+    totalCerts = dcrl->totalCerts;
+
+    if (totalCerts >= CRL_MAX_REVOKED_CERTS) {
+        return MEMORY_E;
+    }
+
+    rc = &rcert[totalCerts];
+    ret = wc_GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz,maxIdx);
+    if (ret < 0) {
+        WOLFSSL_MSG("wc_GetSerialNumber error");
+        return ret;
+    }
+#else
+
     rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), dcrl->heap,
                                                           DYNAMIC_TYPE_REVOKED);
     if (rc == NULL) {
         WOLFSSL_MSG("Alloc Revoked Cert failed");
         return MEMORY_E;
     }
-
-    if (wc_GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz,
-                                                                maxIdx) < 0) {
-        XFREE(rc, dcrl->heap, DYNAMIC_TYPE_REVOKED);
-        return ASN_PARSE_E;
+    ret = wc_GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz,maxIdx);
+    if (ret < 0) {
+        WOLFSSL_MSG("wc_GetSerialNumber error");
+        return ret;
     }
-
     /* add to list */
     rc->next = dcrl->certs;
     dcrl->certs = rc;
-    dcrl->totalCerts++;
 
+    (void)rcert;
+#endif /* CRL_STATIC_REVOKED_LIST */
+    dcrl->totalCerts++;
     /* get date */
 #ifndef NO_ASN_TIME
     ret = GetBasicDate(buff, idx, rc->revDate, &rc->revDateFormat, maxIdx);
@@ -35523,13 +35540,23 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
     word32 serialSz = EXTERNAL_SERIAL_SIZE;
     word32 revDateSz = MAX_DATE_SIZE;
     RevokedCert* rc;
+#ifdef CRL_STATIC_REVOKED_LIST
+    int totalCerts = dcrl->totalCerts;
+
+    if (totalCerts >= CRL_MAX_REVOKED_CERTS) {
+        return MEMORY_E;
+    }
 
+    rc = &rcert[totalCerts];
+
+#else
     /* Allocate a new revoked certificate object. */
     rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), dcrl->heap,
             DYNAMIC_TYPE_CRL);
     if (rc == NULL) {
         ret = MEMORY_E;
     }
+#endif /* CRL_STATIC_REVOKED_LIST */
 
     CALLOC_ASNGETDATA(dataASN, revokedASN_Length, ret, dcrl->heap);
 
@@ -35555,15 +35582,20 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
 
         /* TODO: use extensions, only v2 */
         /* Add revoked certificate to chain. */
+#ifndef CRL_STATIC_REVOKED_LIST
         rc->next = dcrl->certs;
         dcrl->certs = rc;
+#endif
         dcrl->totalCerts++;
     }
 
     FREE_ASNGETDATA(dataASN, dcrl->heap);
+#ifndef CRL_STATIC_REVOKED_LIST
     if ((ret != 0) && (rc != NULL)) {
         XFREE(rc, dcrl->heap, DYNAMIC_TYPE_CRL);
     }
+    (void)rcert;
+#endif
     return ret;
 #endif /* WOLFSSL_ASN_TEMPLATE */
 }
@@ -35578,15 +35610,15 @@ static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
  * @return  0 on success.
  * @return  ASN_PARSE_E on failure.
  */
-static int ParseCRL_RevokedCerts(DecodedCRL* dcrl, const byte* buff, word32 idx,
-    word32 maxIdx)
+static int ParseCRL_RevokedCerts(RevokedCert* rcert, DecodedCRL* dcrl,
+                                 const byte* buff, word32 idx, word32 maxIdx)
 {
     int ret = 0;
 
     /* Parse each revoked cerificate. */
     while ((ret == 0) && (idx < maxIdx)) {
         /* Parse a revoked certificate. */
-        if (GetRevoked(buff, &idx, dcrl, maxIdx) < 0) {
+        if (GetRevoked(rcert, buff, &idx, dcrl, maxIdx) < 0) {
             ret = ASN_PARSE_E;
         }
     }
@@ -35704,8 +35736,8 @@ static int PaseCRL_CheckSignature(DecodedCRL* dcrl, const byte* buff, void* cm)
 #endif
 
 #ifndef WOLFSSL_ASN_TEMPLATE
-static int ParseCRL_CertList(DecodedCRL* dcrl, const byte* buf,
-        word32* inOutIdx, int sz, int verify)
+static int ParseCRL_CertList(RevokedCert* rcert, DecodedCRL* dcrl,
+                           const byte* buf,word32* inOutIdx, int sz, int verify)
 {
     word32 oid, dateIdx, idx, checkIdx;
     int length;
@@ -35787,7 +35819,7 @@ static int ParseCRL_CertList(DecodedCRL* dcrl, const byte* buf,
         len += idx;
 
         while (idx < (word32)len) {
-            if (GetRevoked(buf, &idx, dcrl, len) < 0)
+            if (GetRevoked(rcert, buf, &idx, dcrl, len) < 0)
                 return ASN_PARSE_E;
         }
     }
@@ -36137,8 +36169,8 @@ enum {
 #endif
 
 /* parse crl buffer into decoded state, 0 on success */
-int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, int verify,
-        void* cm)
+int ParseCRL(RevokedCert* rcert, DecodedCRL* dcrl, const byte* buff, word32 sz,
+             int verify, void* cm)
 {
 #ifndef WOLFSSL_ASN_TEMPLATE
     Signer*      ca = NULL;
@@ -36167,7 +36199,7 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, int verify,
         return ASN_PARSE_E;
     dcrl->sigIndex = len + idx;
 
-    if (ParseCRL_CertList(dcrl, buff, &idx, dcrl->sigIndex, verify) < 0)
+    if (ParseCRL_CertList(rcert, dcrl, buff, &idx, dcrl->sigIndex, verify) < 0)
         return ASN_PARSE_E;
 
     if (ParseCRL_Extensions(dcrl, buff, &idx, dcrl->sigIndex) < 0)
@@ -36303,6 +36335,7 @@ end:
     }
     if (ret == 0) {
     #endif
+#if defined(OPENSSL_EXTRA)
         /* Parse and store the issuer name. */
         dcrl->issuerSz = GetASNItem_Length(dataASN[CRLASN_IDX_TBS_ISSUER],
                             buff);
@@ -36315,10 +36348,12 @@ end:
         if (ret < 0) {
             ret = ASN_PARSE_E;
         }
+#endif
     }
+
     if ((ret == 0) && (dataASN[CRLASN_IDX_TBS_REVOKEDCERTS].tag != 0)) {
         /* Parse revoked cerificates - starting after SEQUENCE OF. */
-        ret = ParseCRL_RevokedCerts(dcrl, buff,
+        ret = ParseCRL_RevokedCerts(rcert, dcrl, buff,
             GetASNItem_DataIdx(dataASN[CRLASN_IDX_TBS_REVOKEDCERTS], buff),
             GetASNItem_EndIdx(dataASN[CRLASN_IDX_TBS_REVOKEDCERTS], buff));
     }

+ 12 - 1
wolfssl/internal.h

@@ -2198,7 +2198,13 @@ typedef struct CRL_Entry CRL_Entry;
 #ifdef NO_ASN
     typedef struct RevokedCert RevokedCert;
 #endif
-
+#ifdef CRL_STATIC_REVOKED_LIST
+    #ifndef CRL_MAX_REVOKED_CERTS
+        #define CRL_MAX_REVOKED_CERTS 4
+    #elif CRL_MAX_REVOKED_CERTS > 22000
+        #error CRL_MAX_REVOKED_CERTS too big, max is 22000
+    #endif
+#endif
 /* Complete CRL */
 struct CRL_Entry {
     CRL_Entry* next;                      /* next entry */
@@ -2209,7 +2215,11 @@ struct CRL_Entry {
     byte    nextDate[MAX_DATE_SIZE]; /* next update date   */
     byte    lastDateFormat;          /* last date format */
     byte    nextDateFormat;          /* next date format */
+#ifdef CRL_STATIC_REVOKED_LIST
+    RevokedCert certs[CRL_MAX_REVOKED_CERTS];
+#else
     RevokedCert* certs;              /* revoked cert list  */
+#endif
     int          totalCerts;         /* number on list     */
     int     version;                 /* version of certficate */
     int     verified;
@@ -2245,6 +2255,7 @@ struct CRL_Monitor {
 /* wolfSSL CRL controller */
 struct WOLFSSL_CRL {
     WOLFSSL_CERT_MANAGER* cm;            /* pointer back to cert manager */
+    CRL_Entry*            currentEntry;  /* Current CRL entry being processed */
     CRL_Entry*            crlList;       /* our CRL list */
 #ifdef HAVE_CRL_IO
     CbCrlIO               crlIOCb;

+ 2 - 2
wolfssl/wolfcrypt/asn.h

@@ -2472,8 +2472,8 @@ WOLFSSL_LOCAL int VerifyCRL_Signature(SignatureCtx* sigCtx,
                                       const byte* signature, word32 sigSz,
                                       word32 signatureOID, Signer *ca,
                                       void* heap);
-WOLFSSL_LOCAL int  ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz,
-                            int verify, void* cm);
+WOLFSSL_LOCAL int ParseCRL(RevokedCert* rcert, DecodedCRL* dcrl,
+                           const byte* buff, word32 sz, int verify, void* cm);
 WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL* dcrl);