1 /* crl.c
2  *
3  * Copyright (C) 2006-2021 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL.
6  *
7  * wolfSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * wolfSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20  */
21 
22 
23   /* Name change compatibility layer no longer needs included here */
24 
25 #ifdef HAVE_CONFIG_H
26     #include <config.h>
27 #endif
28 
29 #include <wolfssl/wolfcrypt/settings.h>
30 
31 #ifndef WOLFCRYPT_ONLY
32 #ifdef HAVE_CRL
33 
34 #include <wolfssl/internal.h>
35 #include <wolfssl/error-ssl.h>
36 
37 #ifndef WOLFSSL_LINUXKM
38     #include <string.h>
39 #endif
40 
41 #ifdef HAVE_CRL_MONITOR
42     #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__))
43         static int StopMonitor(int mfd);
44     #else
45         #error "CRL monitor only currently supported on linux or mach"
46     #endif
47 #endif /* HAVE_CRL_MONITOR */
48 
49 
50 /* Initialize CRL members */
InitCRL(WOLFSSL_CRL * crl,WOLFSSL_CERT_MANAGER * cm)51 int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
52 {
53     WOLFSSL_ENTER("InitCRL");
54     if(cm != NULL)
55         crl->heap = cm->heap;
56     else
57         crl->heap = NULL;
58     crl->cm = cm;
59     crl->crlList = NULL;
60     crl->monitors[0].path = NULL;
61     crl->monitors[1].path = NULL;
62 #ifdef HAVE_CRL_MONITOR
63     crl->tid   =  0;
64     crl->mfd   = -1;    /* mfd for bsd is kqueue fd, eventfd for linux */
65     crl->setup = 0;     /* thread setup done predicate */
66     if (pthread_cond_init(&crl->cond, 0) != 0) {
67         WOLFSSL_MSG("Pthread condition init failed");
68         return BAD_COND_E;
69     }
70 #endif
71     if (wc_InitMutex(&crl->crlLock) != 0) {
72         WOLFSSL_MSG("Init Mutex failed");
73         return BAD_MUTEX_E;
74     }
75 
76     return 0;
77 }
78 
79 
80 /* Initialize CRL Entry */
InitCRL_Entry(CRL_Entry * crle,DecodedCRL * dcrl,const byte * buff,int verified,void * heap)81 static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
82                          int verified, void* heap)
83 {
84     WOLFSSL_ENTER("InitCRL_Entry");
85 
86     XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE);
87     /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE);
88      * copy the hash here if needed for optimized comparisons */
89     XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
90     XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
91     crle->lastDateFormat = dcrl->lastDateFormat;
92     crle->nextDateFormat = dcrl->nextDateFormat;
93 
94     crle->certs = dcrl->certs;   /* take ownsership */
95     dcrl->certs = NULL;
96     crle->totalCerts = dcrl->totalCerts;
97     crle->verified = verified;
98     if (!verified) {
99         crle->tbsSz = dcrl->sigIndex - dcrl->certBegin;
100         crle->signatureSz = dcrl->sigLength;
101         crle->signatureOID = dcrl->signatureOID;
102         crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap,
103                                           DYNAMIC_TYPE_CRL_ENTRY);
104         if (crle->toBeSigned == NULL)
105             return -1;
106         crle->signature = (byte*)XMALLOC(crle->signatureSz, heap,
107                                          DYNAMIC_TYPE_CRL_ENTRY);
108         if (crle->signature == NULL) {
109             XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY);
110             return -1;
111         }
112         XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz);
113         XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz);
114     #ifndef NO_SKID
115         crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet;
116         if (crle->extAuthKeyIdSet)
117             XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE);
118     #endif
119     }
120     else {
121         crle->toBeSigned = NULL;
122         crle->signature = NULL;
123     }
124 
125     (void)verified;
126     (void)heap;
127 
128     return 0;
129 }
130 
131 
132 /* Free all CRL Entry resources */
FreeCRL_Entry(CRL_Entry * crle,void * heap)133 static void FreeCRL_Entry(CRL_Entry* crle, void* heap)
134 {
135     RevokedCert* tmp = crle->certs;
136     RevokedCert* next;
137 
138     WOLFSSL_ENTER("FreeCRL_Entry");
139 
140     while (tmp) {
141         next = tmp->next;
142         XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED);
143         tmp = next;
144     }
145     if (crle->signature != NULL)
146         XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED);
147     if (crle->toBeSigned != NULL)
148         XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED);
149 
150     (void)heap;
151 }
152 
153 
154 
155 /* Free all CRL resources */
FreeCRL(WOLFSSL_CRL * crl,int dynamic)156 void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
157 {
158     CRL_Entry* tmp = crl->crlList;
159 
160     WOLFSSL_ENTER("FreeCRL");
161     if (crl->monitors[0].path)
162         XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
163 
164     if (crl->monitors[1].path)
165         XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
166 
167     while(tmp) {
168         CRL_Entry* next = tmp->next;
169         FreeCRL_Entry(tmp, crl->heap);
170         XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
171         tmp = next;
172     }
173 
174 #ifdef HAVE_CRL_MONITOR
175     if (crl->tid != 0) {
176         WOLFSSL_MSG("stopping monitor thread");
177         if (StopMonitor(crl->mfd) == 0)
178             pthread_join(crl->tid, NULL);
179         else {
180             WOLFSSL_MSG("stop monitor failed");
181         }
182     }
183     pthread_cond_destroy(&crl->cond);
184 #endif
185     wc_FreeMutex(&crl->crlLock);
186     if (dynamic)   /* free self */
187         XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL);
188 }
189 
190 
CheckCertCRLList(WOLFSSL_CRL * crl,DecodedCert * cert,int * pFoundEntry)191 static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry)
192 {
193     CRL_Entry* crle;
194     int        foundEntry = 0;
195     int        ret = 0;
196 
197     if (wc_LockMutex(&crl->crlLock) != 0) {
198         WOLFSSL_MSG("wc_LockMutex failed");
199         return BAD_MUTEX_E;
200     }
201 
202     crle = crl->crlList;
203 
204     while (crle) {
205         if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) {
206             WOLFSSL_MSG("Found CRL Entry on list");
207 
208             if (crle->verified == 0) {
209                 Signer* ca = NULL;
210             #ifndef NO_SKID
211                 byte extAuthKeyId[KEYID_SIZE];
212             #endif
213                 byte issuerHash[CRL_DIGEST_SIZE];
214                 byte* tbs;
215                 word32 tbsSz = crle->tbsSz;
216                 byte* sig = NULL;
217                 word32 sigSz = crle->signatureSz;
218                 word32 sigOID = crle->signatureOID;
219                 SignatureCtx sigCtx;
220 
221                 tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
222                 if (tbs == NULL) {
223                     wc_UnLockMutex(&crl->crlLock);
224                     return MEMORY_E;
225                 }
226                 sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
227                 if (sig == NULL) {
228                     XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
229                     wc_UnLockMutex(&crl->crlLock);
230                     return MEMORY_E;
231                 }
232 
233                 XMEMCPY(tbs, crle->toBeSigned, tbsSz);
234                 XMEMCPY(sig, crle->signature, sigSz);
235             #ifndef NO_SKID
236                 XMEMCPY(extAuthKeyId, crle->extAuthKeyId,
237                                                           sizeof(extAuthKeyId));
238             #endif
239                 XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash));
240 
241                 wc_UnLockMutex(&crl->crlLock);
242 
243             #ifndef NO_SKID
244                 if (crle->extAuthKeyIdSet)
245                     ca = GetCA(crl->cm, extAuthKeyId);
246                 if (ca == NULL)
247                     ca = GetCAByName(crl->cm, issuerHash);
248             #else /* NO_SKID */
249                 ca = GetCA(crl->cm, issuerHash);
250             #endif /* NO_SKID */
251                 if (ca == NULL) {
252                     XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
253                     XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
254                     WOLFSSL_MSG("Did NOT find CRL issuer CA");
255                     return ASN_CRL_NO_SIGNER_E;
256                 }
257 
258                 ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz,
259                                           sigOID, ca, crl->heap);
260 
261                 XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
262                 XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
263 
264                 if (wc_LockMutex(&crl->crlLock) != 0) {
265                     WOLFSSL_MSG("wc_LockMutex failed");
266                     return BAD_MUTEX_E;
267                 }
268 
269                 crle = crl->crlList;
270                 while (crle) {
271                     if (XMEMCMP(crle->issuerHash, cert->issuerHash,
272                         CRL_DIGEST_SIZE) == 0) {
273 
274                         if (ret == 0)
275                             crle->verified = 1;
276                         else
277                             crle->verified = ret;
278 
279                         XFREE(crle->toBeSigned, crl->heap,
280                                                         DYNAMIC_TYPE_CRL_ENTRY);
281                         crle->toBeSigned = NULL;
282                         XFREE(crle->signature, crl->heap,
283                                                         DYNAMIC_TYPE_CRL_ENTRY);
284                         crle->signature = NULL;
285                         break;
286                     }
287                     crle = crle->next;
288                 }
289                 if (crle == NULL || crle->verified < 0)
290                     break;
291             }
292             else if (crle->verified < 0) {
293                 WOLFSSL_MSG("Cannot use CRL as it didn't verify");
294                 ret = crle->verified;
295                 break;
296             }
297 
298             WOLFSSL_MSG("Checking next date validity");
299 
300         #ifdef WOLFSSL_NO_CRL_NEXT_DATE
301             if (crle->nextDateFormat != ASN_OTHER_TYPE)
302         #endif
303             {
304             #ifndef NO_ASN_TIME
305                 if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, AFTER)) {
306                     WOLFSSL_MSG("CRL next date is no longer valid");
307                     ret = ASN_AFTER_DATE_E;
308                 }
309             #endif
310             }
311             if (ret == 0) {
312                 foundEntry = 1;
313             }
314             break;
315         }
316         crle = crle->next;
317     }
318 
319     if (foundEntry) {
320         RevokedCert* rc = crle->certs;
321 
322         while (rc) {
323             if (rc->serialSz == cert->serialSz &&
324                    XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
325                 WOLFSSL_MSG("Cert revoked");
326                 ret = CRL_CERT_REVOKED;
327                 break;
328             }
329             rc = rc->next;
330         }
331     }
332 
333     wc_UnLockMutex(&crl->crlLock);
334 
335     *pFoundEntry = foundEntry;
336 
337     return ret;
338 }
339 
340 /* Is the cert ok with CRL, return 0 on success */
CheckCertCRL(WOLFSSL_CRL * crl,DecodedCert * cert)341 int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
342 {
343     int        foundEntry = 0;
344     int        ret = 0;
345 
346     WOLFSSL_ENTER("CheckCertCRL");
347 
348 #ifdef WOLFSSL_CRL_ALLOW_MISSING_CDP
349     /* Skip CRL verification in case no CDP in peer cert */
350     if (!cert->extCrlInfo) {
351         return ret;
352     }
353 #endif
354 
355     ret = CheckCertCRLList(crl, cert, &foundEntry);
356 
357 #ifdef HAVE_CRL_IO
358     if (foundEntry == 0) {
359         /* perform embedded lookup */
360         if (crl->crlIOCb) {
361             ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo,
362                                                         cert->extCrlInfoSz);
363             if (ret == WOLFSSL_CBIO_ERR_WANT_READ) {
364                 ret = OCSP_WANT_READ;
365             }
366             else if (ret >= 0) {
367                 /* try again */
368                 ret = CheckCertCRLList(crl, cert, &foundEntry);
369             }
370         }
371     }
372 #endif
373 
374 #if defined(OPENSSL_ALL) && defined(WOLFSSL_CERT_GEN) && \
375     (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \
376     !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
377     /* if not find entry in the CRL list, it looks at the folder that sets  */
378     /* by LOOKUP_ctrl because user would want to use hash_dir.              */
379     /* Loading <issuer-hash>.rN form CRL file if find at the folder,        */
380     /* and try again checking Cert in the CRL list.                         */
381     /* When not set the folder or not use hash_dir, do nothing.             */
382     if ((foundEntry == 0) && (ret != OCSP_WANT_READ)) {
383         if (crl->cm->x509_store_p != NULL) {
384             ret = LoadCertByIssuer(crl->cm->x509_store_p,
385                           (WOLFSSL_X509_NAME*)cert->issuerName, X509_LU_CRL);
386             if (ret == WOLFSSL_SUCCESS) {
387                 /* try again */
388                 ret = CheckCertCRLList(crl, cert, &foundEntry);
389             }
390         }
391     }
392 #endif
393     if (foundEntry == 0) {
394         WOLFSSL_MSG("Couldn't find CRL for status check");
395         if (ret != CRL_CERT_DATE_ERR) {
396             ret = CRL_MISSING;
397         }
398 
399         if (crl->cm->cbMissingCRL) {
400             char url[256];
401 
402             WOLFSSL_MSG("Issuing missing CRL callback");
403             url[0] = '\0';
404             if (cert->extCrlInfo) {
405                 if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
406                     XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
407                     url[cert->extCrlInfoSz] = '\0';
408                 }
409                 else  {
410                     WOLFSSL_MSG("CRL url too long");
411                 }
412             }
413 
414             crl->cm->cbMissingCRL(url);
415         }
416     }
417 
418     return ret;
419 }
420 
421 
422 /* Add Decoded CRL, 0 on success */
AddCRL(WOLFSSL_CRL * crl,DecodedCRL * dcrl,const byte * buff,int verified)423 static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
424                   int verified)
425 {
426     CRL_Entry* crle;
427 
428     WOLFSSL_ENTER("AddCRL");
429 
430     crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
431     if (crle == NULL) {
432         WOLFSSL_MSG("alloc CRL Entry failed");
433         return -1;
434     }
435 
436     if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) {
437         WOLFSSL_MSG("Init CRL Entry failed");
438         XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
439         return -1;
440     }
441 
442     if (wc_LockMutex(&crl->crlLock) != 0) {
443         WOLFSSL_MSG("wc_LockMutex failed");
444         FreeCRL_Entry(crle, crl->heap);
445         XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
446         return BAD_MUTEX_E;
447     }
448     crle->next = crl->crlList;
449     crl->crlList = crle;
450     wc_UnLockMutex(&crl->crlLock);
451 
452     return 0;
453 }
454 
455 
456 /* Load CRL File of type, WOLFSSL_SUCCESS on ok */
BufferLoadCRL(WOLFSSL_CRL * crl,const byte * buff,long sz,int type,int verify)457 int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
458                   int verify)
459 {
460     int          ret = WOLFSSL_SUCCESS;
461     const byte*  myBuffer = buff;    /* if DER ok, otherwise switch */
462     DerBuffer*   der = NULL;
463 #ifdef WOLFSSL_SMALL_STACK
464     DecodedCRL*  dcrl;
465 #else
466     DecodedCRL   dcrl[1];
467 #endif
468 
469     WOLFSSL_ENTER("BufferLoadCRL");
470 
471     if (crl == NULL || buff == NULL || sz == 0)
472         return BAD_FUNC_ARG;
473 
474     if (type == WOLFSSL_FILETYPE_PEM) {
475     #ifdef WOLFSSL_PEM_TO_DER
476         ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL);
477         if (ret == 0) {
478             myBuffer = der->buffer;
479             sz = der->length;
480         }
481         else {
482             WOLFSSL_MSG("Pem to Der failed");
483             FreeDer(&der);
484             return -1;
485         }
486     #else
487         ret = NOT_COMPILED_IN;
488     #endif
489     }
490 
491 #ifdef WOLFSSL_SMALL_STACK
492     dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
493     if (dcrl == NULL) {
494         FreeDer(&der);
495         return MEMORY_E;
496     }
497 #endif
498 
499     InitDecodedCRL(dcrl, crl->heap);
500     ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm);
501     if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) {
502         WOLFSSL_MSG("ParseCRL error");
503     }
504     else {
505         ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E);
506         if (ret != 0) {
507             WOLFSSL_MSG("AddCRL error");
508         }
509     }
510 
511     FreeDecodedCRL(dcrl);
512 
513 #ifdef WOLFSSL_SMALL_STACK
514     XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
515 #endif
516 
517     FreeDer(&der);
518 
519     return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
520 }
521 
522 #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
523 /* helper function to create a new dynamic WOLFSSL_X509_CRL structure */
wolfSSL_X509_crl_new(WOLFSSL_CERT_MANAGER * cm)524 static WOLFSSL_X509_CRL* wolfSSL_X509_crl_new(WOLFSSL_CERT_MANAGER* cm)
525 {
526     WOLFSSL_X509_CRL* ret;
527 
528     ret = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), cm->heap,
529                 DYNAMIC_TYPE_CRL);
530     if (ret != NULL) {
531         if (InitCRL(ret, cm) < 0) {
532             WOLFSSL_MSG("Unable to initialize new CRL structure");
533             XFREE(ret, cm->heap, DYNAMIC_TYPE_CRL);
534             ret = NULL;
535         }
536     }
537     return ret;
538 }
539 
540 
541 /* returns head of copied list that was alloc'd */
DupRevokedCertList(RevokedCert * in,void * heap)542 static RevokedCert *DupRevokedCertList(RevokedCert* in, void* heap)
543 {
544     RevokedCert* head = NULL;
545     RevokedCert* current = in;
546     RevokedCert* prev = NULL;
547     while (current) {
548         RevokedCert* tmp = (RevokedCert*)XMALLOC(sizeof(RevokedCert), heap,
549                 DYNAMIC_TYPE_REVOKED);
550         if (tmp != NULL) {
551             XMEMCPY(tmp->serialNumber, current->serialNumber,
552                     EXTERNAL_SERIAL_SIZE);
553             tmp->serialSz = current->serialSz;
554             tmp->next = NULL;
555             if (prev != NULL)
556                 prev->next = tmp;
557             if (head == NULL)
558                 head = tmp;
559             prev = tmp;
560         }
561         else {
562             WOLFSSL_MSG("Failed to allocate new RevokedCert structure");
563             /* free up any existing list */
564             while (head != NULL) {
565                 current = head;
566                 head = head->next;
567                 XFREE(current, heap, DYNAMIC_TYPE_REVOKED);
568             }
569             return NULL;
570         }
571         current = current->next;
572     }
573 
574     (void)heap;
575     return head;
576 }
577 
578 
579 /* returns a deep copy of ent on success and null on fail */
DupCRL_Entry(const CRL_Entry * ent,void * heap)580 static CRL_Entry* DupCRL_Entry(const CRL_Entry* ent, void* heap)
581 {
582     CRL_Entry *dupl;
583 
584     dupl = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), heap, DYNAMIC_TYPE_CRL_ENTRY);
585     if (dupl == NULL) {
586         WOLFSSL_MSG("alloc CRL Entry failed");
587         return NULL;
588     }
589     XMEMSET(dupl, 0, sizeof(CRL_Entry));
590 
591     XMEMCPY(dupl->issuerHash, ent->issuerHash, CRL_DIGEST_SIZE);
592     XMEMCPY(dupl->lastDate, ent->lastDate, MAX_DATE_SIZE);
593     XMEMCPY(dupl->nextDate, ent->nextDate, MAX_DATE_SIZE);
594     dupl->lastDateFormat = ent->lastDateFormat;
595     dupl->nextDateFormat = ent->nextDateFormat;
596     dupl->certs = DupRevokedCertList(ent->certs, heap);
597 
598     dupl->totalCerts = ent->totalCerts;
599     dupl->verified = ent->verified;
600 
601     if (!ent->verified) {
602         dupl->tbsSz = ent->tbsSz;
603         dupl->signatureSz = ent->signatureSz;
604         dupl->signatureOID = ent->signatureOID;
605         dupl->toBeSigned = (byte*)XMALLOC(dupl->tbsSz, heap,
606                                           DYNAMIC_TYPE_CRL_ENTRY);
607         if (dupl->toBeSigned == NULL) {
608             FreeCRL_Entry(dupl, heap);
609             XFREE(dupl, heap, DYNAMIC_TYPE_CRL_ENTRY);
610             return NULL;
611         }
612 
613         dupl->signature = (byte*)XMALLOC(dupl->signatureSz, heap,
614                                          DYNAMIC_TYPE_CRL_ENTRY);
615         if (dupl->signature == NULL) {
616             FreeCRL_Entry(dupl, heap);
617             XFREE(dupl, heap, DYNAMIC_TYPE_CRL_ENTRY);
618             return NULL;
619         }
620         XMEMCPY(dupl->toBeSigned, ent->toBeSigned, dupl->tbsSz);
621         XMEMCPY(dupl->signature, ent->signature, dupl->signatureSz);
622     #ifndef NO_SKID
623         dupl->extAuthKeyIdSet = ent->extAuthKeyIdSet;
624         if (dupl->extAuthKeyIdSet)
625             XMEMCPY(dupl->extAuthKeyId, ent->extAuthKeyId, KEYID_SIZE);
626     #endif
627     }
628     else {
629         dupl->toBeSigned = NULL;
630         dupl->tbsSz = 0;
631         dupl->signature = NULL;
632         dupl->signatureSz = 0;
633     }
634 
635     return dupl;
636 }
637 
638 
639 /* returns the head of a deep copy of the list on success and null on fail */
DupCRL_list(CRL_Entry * crl,void * heap)640 static CRL_Entry* DupCRL_list(CRL_Entry* crl, void* heap)
641 {
642     CRL_Entry* current;
643     CRL_Entry* head = NULL;
644     CRL_Entry* prev = NULL;
645 
646     current = crl;
647     while (current != NULL) {
648         CRL_Entry* tmp = DupCRL_Entry(current, heap);
649         if (tmp != NULL) {
650             tmp->next = NULL;
651             if (head == NULL)
652                 head = tmp;
653             if (prev != NULL)
654                 prev->next = tmp;
655             prev = tmp;
656         }
657         else {
658             WOLFSSL_MSG("Failed to allocate new CRL_Entry structure");
659             /* free up any existing list */
660             while (head != NULL) {
661                 current = head;
662                 head = head->next;
663                 FreeCRL_Entry(current, heap);
664                 XFREE(current, heap, DYNAMIC_TYPE_CRL_ENTRY);
665             }
666 
667             return NULL;
668         }
669         current = current->next;
670     }
671     return head;
672 }
673 
674 
675 /* Duplicates everything except the parent cm pointed to.
676  * Expects that Init has already been done to 'dupl'
677  * return 0 on success */
DupX509_CRL(WOLFSSL_X509_CRL * dupl,const WOLFSSL_X509_CRL * crl)678 static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl)
679 {
680     if (dupl == NULL || crl == NULL) {
681         return BAD_FUNC_ARG;
682     }
683 
684     if (crl->monitors[0].path) {
685         int pathSz = (int)XSTRLEN(crl->monitors[0].path) + 1;
686         dupl->monitors[0].path = (char*)XMALLOC(pathSz, dupl->heap,
687                 DYNAMIC_TYPE_CRL_MONITOR);
688         if (dupl->monitors[0].path != NULL) {
689             XSTRNCPY(dupl->monitors[0].path, crl->monitors[0].path, pathSz);
690         }
691         else {
692             return MEMORY_E;
693         }
694     }
695 
696     if (crl->monitors[1].path) {
697         int pathSz = (int)XSTRLEN(crl->monitors[1].path) + 1;
698         dupl->monitors[1].path = (char*)XMALLOC(pathSz, dupl->heap,
699                 DYNAMIC_TYPE_CRL_MONITOR);
700         if (dupl->monitors[1].path != NULL) {
701             XSTRNCPY(dupl->monitors[1].path, crl->monitors[1].path, pathSz);
702         }
703         else {
704             if (dupl->monitors[0].path != NULL) {
705                 XFREE(dupl->monitors[0].path, dupl->heap,
706                         DYNAMIC_TYPE_CRL_MONITOR);
707             }
708             return MEMORY_E;
709         }
710     }
711 
712     dupl->crlList = DupCRL_list(crl->crlList, dupl->heap);
713 #ifdef HAVE_CRL_IO
714     dupl->crlIOCb = crl->crlIOCb;
715 #endif
716 
717     return 0;
718 }
719 
720 /* returns WOLFSSL_SUCCESS on success. Does not take ownership of newcrl */
wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE * store,WOLFSSL_X509_CRL * newcrl)721 int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl)
722 {
723     CRL_Entry   *crle;
724     WOLFSSL_X509_CRL *crl;
725 
726     WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl");
727     if (store == NULL || newcrl == NULL || store->cm == NULL)
728         return BAD_FUNC_ARG;
729 
730     if (store->cm->crl == NULL) {
731         crl = wolfSSL_X509_crl_new(store->cm);
732         if (DupX509_CRL(crl, newcrl) != 0) {
733             if (crl != NULL)
734                 FreeCRL(crl, 1);
735             return WOLFSSL_FAILURE;
736         }
737         store->crl = store->cm->crl = crl;
738         if (wolfSSL_CertManagerEnableCRL(store->cm, WOLFSSL_CRL_CHECKALL)
739                 != WOLFSSL_SUCCESS) {
740             WOLFSSL_MSG("wolfSSL_CertManagerEnableCRL error");
741             return WOLFSSL_FAILURE;
742         }
743         return WOLFSSL_SUCCESS;
744     }
745 
746     /* find tail of current list and add new list */
747     crl  = store->cm->crl;
748     crle = crl->crlList;
749     if (newcrl->crlList != NULL) {
750         CRL_Entry *tail = crle;
751         CRL_Entry *toAdd;
752 
753         if (wc_LockMutex(&crl->crlLock) != 0)
754         {
755             WOLFSSL_MSG("wc_LockMutex failed");
756             return BAD_MUTEX_E;
757         }
758 
759         toAdd = DupCRL_list(newcrl->crlList, crl->heap);
760         if (tail == NULL) {
761             crl->crlList = toAdd;
762         }
763         else {
764             while (tail->next != NULL) tail = tail->next;
765             tail->next = toAdd;
766         }
767         wc_UnLockMutex(&crl->crlLock);
768     }
769 
770     if (wolfSSL_CertManagerEnableCRL(store->cm, WOLFSSL_CRL_CHECKALL)
771             != WOLFSSL_SUCCESS) {
772         WOLFSSL_MSG("wolfSSL_CertManagerEnableCRL error");
773         return WOLFSSL_FAILURE;
774     }
775 
776     WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS);
777 
778     return WOLFSSL_SUCCESS;
779 }
780 #endif
781 
782 #ifdef HAVE_CRL_MONITOR
783 
784 
785 /* Signal Monitor thread is setup, save status to setup flag, 0 on success */
SignalSetup(WOLFSSL_CRL * crl,int status)786 static int SignalSetup(WOLFSSL_CRL* crl, int status)
787 {
788     int ret;
789 
790     /* signal to calling thread we're setup */
791     if (wc_LockMutex(&crl->crlLock) != 0) {
792         WOLFSSL_MSG("wc_LockMutex crlLock failed");
793         return BAD_MUTEX_E;
794     }
795 
796         crl->setup = status;
797         ret = pthread_cond_signal(&crl->cond);
798 
799     wc_UnLockMutex(&crl->crlLock);
800 
801     if (ret != 0)
802         return BAD_COND_E;
803 
804     return 0;
805 }
806 
807 
808 /* read in new CRL entries and save new list */
SwapLists(WOLFSSL_CRL * crl)809 static int SwapLists(WOLFSSL_CRL* crl)
810 {
811     int        ret;
812     CRL_Entry* newList;
813 #ifdef WOLFSSL_SMALL_STACK
814     WOLFSSL_CRL* tmp;
815 #else
816     WOLFSSL_CRL tmp[1];
817 #endif
818 
819 #ifdef WOLFSSL_SMALL_STACK
820     tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
821     if (tmp == NULL)
822         return MEMORY_E;
823 #endif
824 
825     if (InitCRL(tmp, crl->cm) < 0) {
826         WOLFSSL_MSG("Init tmp CRL failed");
827 #ifdef WOLFSSL_SMALL_STACK
828         XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
829 #endif
830         return -1;
831     }
832 
833     if (crl->monitors[0].path) {
834         ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0);
835         if (ret != WOLFSSL_SUCCESS) {
836             WOLFSSL_MSG("PEM LoadCRL on dir change failed");
837             FreeCRL(tmp, 0);
838 #ifdef WOLFSSL_SMALL_STACK
839             XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
840 #endif
841             return -1;
842         }
843     }
844 
845     if (crl->monitors[1].path) {
846         ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0);
847         if (ret != WOLFSSL_SUCCESS) {
848             WOLFSSL_MSG("DER LoadCRL on dir change failed");
849             FreeCRL(tmp, 0);
850 #ifdef WOLFSSL_SMALL_STACK
851             XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
852 #endif
853             return -1;
854         }
855     }
856 
857     if (wc_LockMutex(&crl->crlLock) != 0) {
858         WOLFSSL_MSG("wc_LockMutex failed");
859         FreeCRL(tmp, 0);
860 #ifdef WOLFSSL_SMALL_STACK
861         XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
862 #endif
863         return -1;
864     }
865 
866     newList = tmp->crlList;
867 
868     /* swap lists */
869     tmp->crlList  = crl->crlList;
870     crl->crlList = newList;
871 
872     wc_UnLockMutex(&crl->crlLock);
873 
874     FreeCRL(tmp, 0);
875 
876 #ifdef WOLFSSL_SMALL_STACK
877     XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
878 #endif
879 
880     return 0;
881 }
882 
883 
884 #if (defined(__MACH__) || defined(__FreeBSD__))
885 
886 #include <sys/types.h>
887 #include <sys/event.h>
888 #include <sys/time.h>
889 #include <fcntl.h>
890 #include <unistd.h>
891 
892 #ifdef __MACH__
893     #define XEVENT_MODE O_EVTONLY
894 #elif defined(__FreeBSD__)
895     #define XEVENT_MODE EVFILT_VNODE
896 #endif
897 
898 
899 /* we need a unique kqueue user filter fd for crl in case user is doing custom
900  * events too */
901 #ifndef CRL_CUSTOM_FD
902     #define CRL_CUSTOM_FD 123456
903 #endif
904 
905 
906 /* shutdown monitor thread, 0 on success */
StopMonitor(int mfd)907 static int StopMonitor(int mfd)
908 {
909     struct kevent change;
910 
911     /* trigger custom shutdown */
912     EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
913     if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
914         WOLFSSL_MSG("kevent trigger customer event failed");
915         return -1;
916     }
917 
918     return 0;
919 }
920 
921 
922 /* OS X  monitoring */
DoMonitor(void * arg)923 static void* DoMonitor(void* arg)
924 {
925     int fPEM, fDER;
926     struct kevent change;
927 
928     WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
929 
930     WOLFSSL_ENTER("DoMonitor");
931 
932     crl->mfd = kqueue();
933     if (crl->mfd == -1) {
934         WOLFSSL_MSG("kqueue failed");
935         SignalSetup(crl, MONITOR_SETUP_E);
936         return NULL;
937     }
938 
939     /* listen for custom shutdown event */
940     EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
941     if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) {
942         WOLFSSL_MSG("kevent monitor customer event failed");
943         SignalSetup(crl, MONITOR_SETUP_E);
944         (void)close(crl->mfd);
945         return NULL;
946     }
947 
948     fPEM = -1;
949     fDER = -1;
950 
951     if (crl->monitors[0].path) {
952         fPEM = open(crl->monitors[0].path, XEVENT_MODE);
953         if (fPEM == -1) {
954             WOLFSSL_MSG("PEM event dir open failed");
955             SignalSetup(crl, MONITOR_SETUP_E);
956             (void)close(crl->mfd);
957             return NULL;
958         }
959     }
960 
961     if (crl->monitors[1].path) {
962         fDER = open(crl->monitors[1].path, XEVENT_MODE);
963         if (fDER == -1) {
964             WOLFSSL_MSG("DER event dir open failed");
965             if (fPEM != -1)
966                 (void)close(fPEM);
967             (void)close(crl->mfd);
968             SignalSetup(crl, MONITOR_SETUP_E);
969             return NULL;
970         }
971     }
972 
973     if (fPEM != -1)
974         EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
975                 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
976 
977     if (fDER != -1)
978         EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
979                 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
980 
981     /* signal to calling thread we're setup */
982     if (SignalSetup(crl, 1) != 0) {
983         if (fPEM != -1)
984             (void)close(fPEM);
985         if (fDER != -1)
986             (void)close(fDER);
987         (void)close(crl->mfd);
988         return NULL;
989     }
990 
991     for (;;) {
992         struct kevent event;
993         int           numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL);
994 
995         WOLFSSL_MSG("Got kevent");
996 
997         if (numEvents == -1) {
998             WOLFSSL_MSG("kevent problem, continue");
999             continue;
1000         }
1001 
1002         if (event.filter == EVFILT_USER) {
1003             WOLFSSL_MSG("Got user shutdown event, breaking out");
1004             break;
1005         }
1006 
1007         if (SwapLists(crl) < 0) {
1008             WOLFSSL_MSG("SwapLists problem, continue");
1009         }
1010     }
1011 
1012     if (fPEM != -1)
1013         (void)close(fPEM);
1014     if (fDER != -1)
1015         (void)close(fDER);
1016 
1017     (void)close(crl->mfd);
1018 
1019     return NULL;
1020 }
1021 
1022 
1023 #elif defined(__linux__)
1024 
1025 #include <sys/types.h>
1026 #include <sys/inotify.h>
1027 #include <sys/eventfd.h>
1028 #include <unistd.h>
1029 
1030 
1031 #ifndef max
max(int a,int b)1032     static WC_INLINE int max(int a, int b)
1033     {
1034         return a > b ? a : b;
1035     }
1036 #endif /* max */
1037 
1038 
1039 /* shutdown monitor thread, 0 on success */
StopMonitor(int mfd)1040 static int StopMonitor(int mfd)
1041 {
1042     word64 w64 = 1;
1043 
1044     /* write to our custom event */
1045     if (write(mfd, &w64, sizeof(w64)) < 0) {
1046         WOLFSSL_MSG("StopMonitor write failed");
1047         return -1;
1048     }
1049 
1050     return 0;
1051 }
1052 
1053 
1054 /* linux monitoring */
DoMonitor(void * arg)1055 static void* DoMonitor(void* arg)
1056 {
1057     int         notifyFd;
1058     int         wd  = -1;
1059     WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
1060 #ifdef WOLFSSL_SMALL_STACK
1061     char*       buff;
1062 #else
1063     char        buff[8192];
1064 #endif
1065 
1066     WOLFSSL_ENTER("DoMonitor");
1067 
1068     crl->mfd = eventfd(0, 0);  /* our custom shutdown event */
1069     if (crl->mfd < 0) {
1070         WOLFSSL_MSG("eventfd failed");
1071         SignalSetup(crl, MONITOR_SETUP_E);
1072         return NULL;
1073     }
1074 
1075     notifyFd = inotify_init();
1076     if (notifyFd < 0) {
1077         WOLFSSL_MSG("inotify failed");
1078         (void)close(crl->mfd);
1079         SignalSetup(crl, MONITOR_SETUP_E);
1080         return NULL;
1081     }
1082 
1083     if (crl->monitors[0].path) {
1084         wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
1085                                                                 IN_DELETE);
1086         if (wd < 0) {
1087             WOLFSSL_MSG("PEM notify add watch failed");
1088             (void)close(crl->mfd);
1089             (void)close(notifyFd);
1090             SignalSetup(crl, MONITOR_SETUP_E);
1091             return NULL;
1092         }
1093     }
1094 
1095     if (crl->monitors[1].path) {
1096         wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
1097                                                                 IN_DELETE);
1098         if (wd < 0) {
1099             WOLFSSL_MSG("DER notify add watch failed");
1100             (void)close(crl->mfd);
1101             (void)close(notifyFd);
1102             SignalSetup(crl, MONITOR_SETUP_E);
1103             return NULL;
1104         }
1105     }
1106 
1107 #ifdef WOLFSSL_SMALL_STACK
1108     buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1109     if (buff == NULL)
1110         return NULL;
1111 #endif
1112 
1113     /* signal to calling thread we're setup */
1114     if (SignalSetup(crl, 1) != 0) {
1115         #ifdef WOLFSSL_SMALL_STACK
1116             XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1117         #endif
1118 
1119         if (wd > 0)
1120             inotify_rm_watch(notifyFd, wd);
1121         (void)close(crl->mfd);
1122         (void)close(notifyFd);
1123         return NULL;
1124     }
1125 
1126     for (;;) {
1127         fd_set readfds;
1128         int    result;
1129         int    length;
1130 
1131         FD_ZERO(&readfds);
1132         FD_SET(notifyFd, &readfds);
1133         FD_SET(crl->mfd, &readfds);
1134 
1135         result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL);
1136 
1137         WOLFSSL_MSG("Got notify event");
1138 
1139         if (result < 0) {
1140             WOLFSSL_MSG("select problem, continue");
1141             continue;
1142         }
1143 
1144         if (FD_ISSET(crl->mfd, &readfds)) {
1145             word64 r64;
1146             int    rlen;
1147 
1148             WOLFSSL_MSG("got custom shutdown event, breaking out");
1149 
1150             /* read out the bytes written to the event to clean up */
1151             rlen = (int) read(crl->mfd, &r64, sizeof(r64));
1152             if (rlen < 0) {
1153                 WOLFSSL_MSG("read custom event failure");
1154             }
1155 
1156             break;
1157         }
1158 
1159         length = (int) read(notifyFd, buff, 8192);
1160         if (length < 0) {
1161             WOLFSSL_MSG("notify read problem, continue");
1162             continue;
1163         }
1164 
1165         if (SwapLists(crl) < 0) {
1166             WOLFSSL_MSG("SwapLists problem, continue");
1167         }
1168     }
1169 
1170 #ifdef WOLFSSL_SMALL_STACK
1171     XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1172 #endif
1173 
1174     if (wd > 0)
1175         inotify_rm_watch(notifyFd, wd);
1176     (void)close(crl->mfd);
1177     (void)close(notifyFd);
1178 
1179     return NULL;
1180 }
1181 
1182 #endif /* MACH or linux */
1183 
1184 
1185 /* Start Monitoring the CRL path(s) in a thread */
StartMonitorCRL(WOLFSSL_CRL * crl)1186 static int StartMonitorCRL(WOLFSSL_CRL* crl)
1187 {
1188     int ret = WOLFSSL_SUCCESS;
1189 
1190     WOLFSSL_ENTER("StartMonitorCRL");
1191 
1192     if (crl == NULL)
1193         return BAD_FUNC_ARG;
1194 
1195     if (crl->tid != 0) {
1196         WOLFSSL_MSG("Monitor thread already running");
1197         return ret;  /* that's ok, someone already started */
1198     }
1199 
1200     if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) {
1201         WOLFSSL_MSG("Thread creation error");
1202         return THREAD_CREATE_E;
1203     }
1204 
1205     /* wait for setup to complete */
1206     if (wc_LockMutex(&crl->crlLock) != 0) {
1207         WOLFSSL_MSG("wc_LockMutex crlLock error");
1208         return BAD_MUTEX_E;
1209     }
1210 
1211         while (crl->setup == 0) {
1212             if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) {
1213                 ret = BAD_COND_E;
1214                 break;
1215             }
1216         }
1217 
1218         if (crl->setup < 0)
1219             ret = crl->setup;  /* store setup error */
1220 
1221     wc_UnLockMutex(&crl->crlLock);
1222 
1223     if (ret < 0) {
1224         WOLFSSL_MSG("DoMonitor setup failure");
1225         crl->tid = 0;  /* thread already done */
1226     }
1227 
1228     return ret;
1229 }
1230 
1231 
1232 #else /* HAVE_CRL_MONITOR */
1233 
1234 #if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
1235 
StartMonitorCRL(WOLFSSL_CRL * crl)1236 static int StartMonitorCRL(WOLFSSL_CRL* crl)
1237 {
1238     (void)crl;
1239 
1240     WOLFSSL_ENTER("StartMonitorCRL");
1241     WOLFSSL_MSG("Not compiled in");
1242 
1243     return NOT_COMPILED_IN;
1244 }
1245 
1246 #endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
1247 
1248 #endif  /* HAVE_CRL_MONITOR */
1249 
1250 #if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
1251 
1252 /* Load CRL path files of type, WOLFSSL_SUCCESS on ok */
LoadCRL(WOLFSSL_CRL * crl,const char * path,int type,int monitor)1253 int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
1254 {
1255     int         ret = WOLFSSL_SUCCESS;
1256     char*       name = NULL;
1257 #ifdef WOLFSSL_SMALL_STACK
1258     ReadDirCtx* readCtx = NULL;
1259 #else
1260     ReadDirCtx  readCtx[1];
1261 #endif
1262 
1263     WOLFSSL_ENTER("LoadCRL");
1264     if (crl == NULL)
1265         return BAD_FUNC_ARG;
1266 
1267 #ifdef WOLFSSL_SMALL_STACK
1268     readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap,
1269                                                        DYNAMIC_TYPE_TMP_BUFFER);
1270     if (readCtx == NULL)
1271         return MEMORY_E;
1272 #endif
1273 
1274     /* try to load each regular file in path */
1275     ret = wc_ReadDirFirst(readCtx, path, &name);
1276     while (ret == 0 && name) {
1277         int skip = 0;
1278         if (type == WOLFSSL_FILETYPE_PEM) {
1279             if (XSTRSTR(name, ".pem") == NULL) {
1280                 WOLFSSL_MSG("not .pem file, skipping");
1281                 skip = 1;
1282             }
1283         }
1284         else {
1285             if (XSTRSTR(name, ".der") == NULL &&
1286                 XSTRSTR(name, ".crl") == NULL)
1287             {
1288                 WOLFSSL_MSG("not .der or .crl file, skipping");
1289                 skip = 1;
1290             }
1291         }
1292 
1293         if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl,
1294                                  VERIFY) != WOLFSSL_SUCCESS) {
1295             WOLFSSL_MSG("CRL file load failed, continuing");
1296         }
1297 
1298         ret = wc_ReadDirNext(readCtx, path, &name);
1299     }
1300     wc_ReadDirClose(readCtx);
1301     ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */
1302 
1303 #ifdef WOLFSSL_SMALL_STACK
1304     XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
1305 #endif
1306 
1307     if (monitor & WOLFSSL_CRL_MONITOR) {
1308         word32 pathLen;
1309         char* pathBuf;
1310 
1311         WOLFSSL_MSG("monitor path requested");
1312 
1313         pathLen = (word32)XSTRLEN(path);
1314         pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR);
1315         if (pathBuf) {
1316             XSTRNCPY(pathBuf, path, pathLen+1);
1317 
1318             if (type == WOLFSSL_FILETYPE_PEM) {
1319                 /* free old path before setting a new one */
1320                 if (crl->monitors[0].path) {
1321                     XFREE(crl->monitors[0].path, crl->heap,
1322                             DYNAMIC_TYPE_CRL_MONITOR);
1323                 }
1324                 crl->monitors[0].path = pathBuf;
1325                 crl->monitors[0].type = WOLFSSL_FILETYPE_PEM;
1326             } else {
1327                 /* free old path before setting a new one */
1328                 if (crl->monitors[1].path) {
1329                     XFREE(crl->monitors[1].path, crl->heap,
1330                             DYNAMIC_TYPE_CRL_MONITOR);
1331                 }
1332                 crl->monitors[1].path = pathBuf;
1333                 crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1;
1334             }
1335 
1336             if (monitor & WOLFSSL_CRL_START_MON) {
1337                 WOLFSSL_MSG("start monitoring requested");
1338 
1339                 ret = StartMonitorCRL(crl);
1340             }
1341         }
1342         else {
1343             ret = MEMORY_E;
1344         }
1345     }
1346 
1347     return ret;
1348 }
1349 
1350 #else
LoadCRL(WOLFSSL_CRL * crl,const char * path,int type,int monitor)1351 int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
1352 {
1353     (void)crl;
1354     (void)path;
1355     (void)type;
1356     (void)monitor;
1357 
1358     /* stub for scenario where file system is not supported */
1359     return NOT_COMPILED_IN;
1360 }
1361 #endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
1362 
1363 #endif /* HAVE_CRL */
1364 #endif /* !WOLFCRYPT_ONLY */
1365