source: asp3_tinet_ecnl_rx/trunk/wolfssl-3.12.2/src/crl.c@ 337

Last change on this file since 337 was 337, checked in by coas-nagasima, 6 years ago

ASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 28.1 KB
Line 
1/* crl.c
2 *
3 * Copyright (C) 2006-2017 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#include <string.h>
38
39#ifdef HAVE_CRL_MONITOR
40 #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__))
41 static int StopMonitor(int mfd);
42 #else
43 #error "CRL monitor only currently supported on linux or mach"
44 #endif
45#endif /* HAVE_CRL_MONITOR */
46
47
48/* Initialize CRL members */
49int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
50{
51 WOLFSSL_ENTER("InitCRL");
52
53 crl->heap = cm->heap;
54 crl->cm = cm;
55 crl->crlList = NULL;
56 crl->monitors[0].path = NULL;
57 crl->monitors[1].path = NULL;
58#ifdef HAVE_CRL_MONITOR
59 crl->tid = 0;
60 crl->mfd = -1; /* mfd for bsd is kqueue fd, eventfd for linux */
61 crl->setup = 0; /* thread setup done predicate */
62 if (pthread_cond_init(&crl->cond, 0) != 0) {
63 WOLFSSL_MSG("Pthread condition init failed");
64 return BAD_COND_E;
65 }
66#endif
67 if (wc_InitMutex(&crl->crlLock) != 0) {
68 WOLFSSL_MSG("Init Mutex failed");
69 return BAD_MUTEX_E;
70 }
71
72 return 0;
73}
74
75
76/* Initialize CRL Entry */
77static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff,
78 int verified, void* heap)
79{
80 WOLFSSL_ENTER("InitCRL_Entry");
81
82 XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE);
83 /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE);
84 * copy the hash here if needed for optimized comparisons */
85 XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
86 XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
87 crle->lastDateFormat = dcrl->lastDateFormat;
88 crle->nextDateFormat = dcrl->nextDateFormat;
89
90 crle->certs = dcrl->certs; /* take ownsership */
91 dcrl->certs = NULL;
92 crle->totalCerts = dcrl->totalCerts;
93 crle->verified = verified;
94 if (!verified) {
95 crle->tbsSz = dcrl->sigIndex - dcrl->certBegin;
96 crle->signatureSz = dcrl->sigLength;
97 crle->signatureOID = dcrl->signatureOID;
98 crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap,
99 DYNAMIC_TYPE_CRL_ENTRY);
100 if (crle->toBeSigned == NULL)
101 return -1;
102 crle->signature = (byte*)XMALLOC(crle->signatureSz, heap,
103 DYNAMIC_TYPE_CRL_ENTRY);
104 if (crle->signature == NULL) {
105 XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY);
106 return -1;
107 }
108 XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz);
109 XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz);
110 #if !defined(NO_SKID) && defined(CRL_SKID_READY)
111 crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet;
112 if (crle->extAuthKeyIdSet)
113 XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE);
114 #endif
115 }
116 else {
117 crle->toBeSigned = NULL;
118 crle->signature = NULL;
119 }
120
121 (void)verified;
122
123 return 0;
124}
125
126
127/* Free all CRL Entry resources */
128static void FreeCRL_Entry(CRL_Entry* crle, void* heap)
129{
130 RevokedCert* tmp = crle->certs;
131 RevokedCert* next;
132
133 WOLFSSL_ENTER("FreeCRL_Entry");
134
135 while (tmp) {
136 next = tmp->next;
137 XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED);
138 tmp = next;
139 }
140 if (crle->signature != NULL)
141 XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED);
142 if (crle->toBeSigned != NULL)
143 XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED);
144
145 (void)heap;
146}
147
148
149
150/* Free all CRL resources */
151void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
152{
153 CRL_Entry* tmp = crl->crlList;
154
155 WOLFSSL_ENTER("FreeCRL");
156
157 if (crl->monitors[0].path)
158 XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
159
160 if (crl->monitors[1].path)
161 XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR);
162
163 while(tmp) {
164 CRL_Entry* next = tmp->next;
165 FreeCRL_Entry(tmp, crl->heap);
166 XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
167 tmp = next;
168 }
169
170#ifdef HAVE_CRL_MONITOR
171 if (crl->tid != 0) {
172 WOLFSSL_MSG("stopping monitor thread");
173 if (StopMonitor(crl->mfd) == 0)
174 pthread_join(crl->tid, NULL);
175 else {
176 WOLFSSL_MSG("stop monitor failed");
177 }
178 }
179 pthread_cond_destroy(&crl->cond);
180#endif
181 wc_FreeMutex(&crl->crlLock);
182 if (dynamic) /* free self */
183 XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL);
184}
185
186
187static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry)
188{
189 CRL_Entry* crle;
190 int foundEntry = 0;
191 int ret = 0;
192
193 if (wc_LockMutex(&crl->crlLock) != 0) {
194 WOLFSSL_MSG("wc_LockMutex failed");
195 return BAD_MUTEX_E;
196 }
197
198 crle = crl->crlList;
199
200 while (crle) {
201 if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) {
202 int doNextDate = 1;
203
204 WOLFSSL_MSG("Found CRL Entry on list");
205
206 if (crle->verified == 0) {
207 Signer* ca;
208 #if !defined(NO_SKID) && defined(CRL_SKID_READY)
209 byte extAuthKeyId[KEYID_SIZE]
210 #endif
211 byte issuerHash[CRL_DIGEST_SIZE];
212 byte* tbs = NULL;
213 word32 tbsSz = crle->tbsSz;
214 byte* sig = NULL;
215 word32 sigSz = crle->signatureSz;
216 word32 sigOID = crle->signatureOID;
217 SignatureCtx sigCtx;
218
219 tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
220 if (tbs == NULL) {
221 wc_UnLockMutex(&crl->crlLock);
222 return MEMORY_E;
223 }
224 sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
225 if (sig == NULL) {
226 XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
227 wc_UnLockMutex(&crl->crlLock);
228 return MEMORY_E;
229 }
230
231 XMEMCPY(tbs, crle->toBeSigned, tbsSz);
232 XMEMCPY(sig, crle->signature, sigSz);
233 #if !defined(NO_SKID) && defined(CRL_SKID_READY)
234 XMEMCMPY(extAuthKeyId, crle->extAuthKeyId,
235 sizeof(extAuthKeyId));
236 #endif
237 XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash));
238
239 wc_UnLockMutex(&crl->crlLock);
240
241 #if !defined(NO_SKID) && defined(CRL_SKID_READY)
242 if (crle->extAuthKeyIdSet)
243 ca = GetCA(crl->cm, extAuthKeyId);
244 if (ca == NULL)
245 ca = GetCAByName(crl->cm, issuerHash);
246 #else /* NO_SKID */
247 ca = GetCA(crl->cm, issuerHash);
248 #endif /* NO_SKID */
249 if (ca == NULL) {
250 WOLFSSL_MSG("Did NOT find CRL issuer CA");
251 return ASN_CRL_NO_SIGNER_E;
252 }
253
254 ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz,
255 sigOID, ca, crl->heap);
256
257 XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
258 XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
259
260 if (wc_LockMutex(&crl->crlLock) != 0) {
261 WOLFSSL_MSG("wc_LockMutex failed");
262 return BAD_MUTEX_E;
263 }
264
265 crle = crl->crlList;
266 while (crle) {
267 if (XMEMCMP(crle->issuerHash, cert->issuerHash,
268 CRL_DIGEST_SIZE) == 0) {
269
270 if (ret == 0)
271 crle->verified = 1;
272 else
273 crle->verified = ret;
274
275 XFREE(crle->toBeSigned, crl->heap,
276 DYNAMIC_TYPE_CRL_ENTRY);
277 crle->toBeSigned = NULL;
278 XFREE(crle->signature, crl->heap,
279 DYNAMIC_TYPE_CRL_ENTRY);
280 crle->signature = NULL;
281 break;
282 }
283 crle = crle->next;
284 }
285 if (crle == NULL || crle->verified < 0)
286 break;
287 }
288 else if (crle->verified < 0) {
289 WOLFSSL_MSG("Cannot use CRL as it didn't verify");
290 ret = crle->verified;
291 break;
292 }
293
294 WOLFSSL_MSG("Checking next date validity");
295
296 #ifdef WOLFSSL_NO_CRL_NEXT_DATE
297 if (crle->nextDateFormat == ASN_OTHER_TYPE)
298 doNextDate = 0; /* skip */
299 #endif
300
301 if (doNextDate) {
302 #ifndef NO_ASN_TIME
303 if (!ValidateDate(crle->nextDate,crle->nextDateFormat, AFTER)) {
304 WOLFSSL_MSG("CRL next date is no longer valid");
305 ret = ASN_AFTER_DATE_E;
306 }
307 #endif
308 }
309 if (ret == 0) {
310 foundEntry = 1;
311 }
312 break;
313 }
314 crle = crle->next;
315 }
316
317 if (foundEntry) {
318 RevokedCert* rc = crle->certs;
319
320 while (rc) {
321 if (rc->serialSz == cert->serialSz &&
322 XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
323 WOLFSSL_MSG("Cert revoked");
324 ret = CRL_CERT_REVOKED;
325 break;
326 }
327 rc = rc->next;
328 }
329 }
330
331 wc_UnLockMutex(&crl->crlLock);
332
333 *pFoundEntry = foundEntry;
334
335 return ret;
336}
337
338/* Is the cert ok with CRL, return 0 on success */
339int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
340{
341 int foundEntry = 0;
342 int ret = 0;
343
344 WOLFSSL_ENTER("CheckCertCRL");
345
346 ret = CheckCertCRLList(crl, cert, &foundEntry);
347
348#ifdef HAVE_CRL_IO
349 if (foundEntry == 0) {
350 /* perform embedded lookup */
351 if (crl->crlIOCb) {
352 ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo,
353 cert->extCrlInfoSz);
354 if (ret == WOLFSSL_CBIO_ERR_WANT_READ) {
355 ret = WANT_READ;
356 }
357 else if (ret >= 0) {
358 /* try again */
359 ret = CheckCertCRLList(crl, cert, &foundEntry);
360 }
361 }
362 }
363#endif
364
365 if (foundEntry == 0) {
366 WOLFSSL_MSG("Couldn't find CRL for status check");
367 ret = CRL_MISSING;
368
369 if (crl->cm->cbMissingCRL) {
370 char url[256];
371
372 WOLFSSL_MSG("Issuing missing CRL callback");
373 url[0] = '\0';
374 if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
375 XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
376 url[cert->extCrlInfoSz] = '\0';
377 }
378 else {
379 WOLFSSL_MSG("CRL url too long");
380 }
381
382 crl->cm->cbMissingCRL(url);
383 }
384 }
385
386 return ret;
387}
388
389
390/* Add Decoded CRL, 0 on success */
391static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
392 int verified)
393{
394 CRL_Entry* crle;
395
396 WOLFSSL_ENTER("AddCRL");
397
398 crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
399 if (crle == NULL) {
400 WOLFSSL_MSG("alloc CRL Entry failed");
401 return -1;
402 }
403
404 if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) {
405 WOLFSSL_MSG("Init CRL Entry failed");
406 XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
407 return -1;
408 }
409
410 if (wc_LockMutex(&crl->crlLock) != 0) {
411 WOLFSSL_MSG("wc_LockMutex failed");
412 FreeCRL_Entry(crle, crl->heap);
413 XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
414 return BAD_MUTEX_E;
415 }
416 crle->next = crl->crlList;
417 crl->crlList = crle;
418 wc_UnLockMutex(&crl->crlLock);
419
420 return 0;
421}
422
423
424/* Load CRL File of type, WOLFSSL_SUCCESS on ok */
425int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
426 int noVerify)
427{
428 int ret = WOLFSSL_SUCCESS;
429 const byte* myBuffer = buff; /* if DER ok, otherwise switch */
430 DerBuffer* der = NULL;
431#ifdef WOLFSSL_SMALL_STACK
432 DecodedCRL* dcrl;
433#else
434 DecodedCRL dcrl[1];
435#endif
436
437 WOLFSSL_ENTER("BufferLoadCRL");
438
439 if (crl == NULL || buff == NULL || sz == 0)
440 return BAD_FUNC_ARG;
441
442 if (type == WOLFSSL_FILETYPE_PEM) {
443 int eccKey = 0; /* not used */
444 EncryptedInfo info;
445 info.ctx = NULL;
446
447 ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey);
448 if (ret == 0) {
449 myBuffer = der->buffer;
450 sz = der->length;
451 }
452 else {
453 WOLFSSL_MSG("Pem to Der failed");
454 FreeDer(&der);
455 return -1;
456 }
457 }
458
459#ifdef WOLFSSL_SMALL_STACK
460 dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
461 if (dcrl == NULL) {
462 FreeDer(&der);
463 return MEMORY_E;
464 }
465#endif
466
467 InitDecodedCRL(dcrl, crl->heap);
468 ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm);
469 if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && noVerify)) {
470 WOLFSSL_MSG("ParseCRL error");
471 }
472 else {
473 ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E);
474 if (ret != 0) {
475 WOLFSSL_MSG("AddCRL error");
476 }
477 }
478
479 FreeDecodedCRL(dcrl);
480
481#ifdef WOLFSSL_SMALL_STACK
482 XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
483#endif
484
485 FreeDer(&der);
486
487 return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
488}
489
490
491#ifdef HAVE_CRL_MONITOR
492
493
494/* Signal Monitor thread is setup, save status to setup flag, 0 on success */
495static int SignalSetup(WOLFSSL_CRL* crl, int status)
496{
497 int ret;
498
499 /* signal to calling thread we're setup */
500 if (wc_LockMutex(&crl->crlLock) != 0) {
501 WOLFSSL_MSG("wc_LockMutex crlLock failed");
502 return BAD_MUTEX_E;
503 }
504
505 crl->setup = status;
506 ret = pthread_cond_signal(&crl->cond);
507
508 wc_UnLockMutex(&crl->crlLock);
509
510 if (ret != 0)
511 return BAD_COND_E;
512
513 return 0;
514}
515
516
517/* read in new CRL entries and save new list */
518static int SwapLists(WOLFSSL_CRL* crl)
519{
520 int ret;
521 CRL_Entry* newList;
522#ifdef WOLFSSL_SMALL_STACK
523 WOLFSSL_CRL* tmp;
524#else
525 WOLFSSL_CRL tmp[1];
526#endif
527
528#ifdef WOLFSSL_SMALL_STACK
529 tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
530 if (tmp == NULL)
531 return MEMORY_E;
532#endif
533
534 if (InitCRL(tmp, crl->cm) < 0) {
535 WOLFSSL_MSG("Init tmp CRL failed");
536#ifdef WOLFSSL_SMALL_STACK
537 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
538#endif
539 return -1;
540 }
541
542 if (crl->monitors[0].path) {
543 ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0);
544 if (ret != WOLFSSL_SUCCESS) {
545 WOLFSSL_MSG("PEM LoadCRL on dir change failed");
546 FreeCRL(tmp, 0);
547#ifdef WOLFSSL_SMALL_STACK
548 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
549#endif
550 return -1;
551 }
552 }
553
554 if (crl->monitors[1].path) {
555 ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0);
556 if (ret != WOLFSSL_SUCCESS) {
557 WOLFSSL_MSG("DER LoadCRL on dir change failed");
558 FreeCRL(tmp, 0);
559#ifdef WOLFSSL_SMALL_STACK
560 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
561#endif
562 return -1;
563 }
564 }
565
566 if (wc_LockMutex(&crl->crlLock) != 0) {
567 WOLFSSL_MSG("wc_LockMutex failed");
568 FreeCRL(tmp, 0);
569#ifdef WOLFSSL_SMALL_STACK
570 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
571#endif
572 return -1;
573 }
574
575 newList = tmp->crlList;
576
577 /* swap lists */
578 tmp->crlList = crl->crlList;
579 crl->crlList = newList;
580
581 wc_UnLockMutex(&crl->crlLock);
582
583 FreeCRL(tmp, 0);
584
585#ifdef WOLFSSL_SMALL_STACK
586 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
587#endif
588
589 return 0;
590}
591
592
593#if (defined(__MACH__) || defined(__FreeBSD__))
594
595#include <sys/types.h>
596#include <sys/event.h>
597#include <sys/time.h>
598#include <fcntl.h>
599#include <unistd.h>
600
601#ifdef __MACH__
602 #define XEVENT_MODE O_EVTONLY
603#elif defined(__FreeBSD__)
604 #define XEVENT_MODE EVFILT_VNODE
605#endif
606
607
608/* we need a unique kqueue user filter fd for crl in case user is doing custom
609 * events too */
610#ifndef CRL_CUSTOM_FD
611 #define CRL_CUSTOM_FD 123456
612#endif
613
614
615/* shutdown monitor thread, 0 on success */
616static int StopMonitor(int mfd)
617{
618 struct kevent change;
619
620 /* trigger custom shutdown */
621 EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
622 if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
623 WOLFSSL_MSG("kevent trigger customer event failed");
624 return -1;
625 }
626
627 return 0;
628}
629
630
631/* OS X monitoring */
632static void* DoMonitor(void* arg)
633{
634 int fPEM, fDER;
635 struct kevent change;
636
637 WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
638
639 WOLFSSL_ENTER("DoMonitor");
640
641 crl->mfd = kqueue();
642 if (crl->mfd == -1) {
643 WOLFSSL_MSG("kqueue failed");
644 SignalSetup(crl, MONITOR_SETUP_E);
645 return NULL;
646 }
647
648 /* listen for custom shutdown event */
649 EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
650 if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) {
651 WOLFSSL_MSG("kevent monitor customer event failed");
652 SignalSetup(crl, MONITOR_SETUP_E);
653 close(crl->mfd);
654 return NULL;
655 }
656
657 fPEM = -1;
658 fDER = -1;
659
660 if (crl->monitors[0].path) {
661 fPEM = open(crl->monitors[0].path, XEVENT_MODE);
662 if (fPEM == -1) {
663 WOLFSSL_MSG("PEM event dir open failed");
664 SignalSetup(crl, MONITOR_SETUP_E);
665 close(crl->mfd);
666 return NULL;
667 }
668 }
669
670 if (crl->monitors[1].path) {
671 fDER = open(crl->monitors[1].path, XEVENT_MODE);
672 if (fDER == -1) {
673 WOLFSSL_MSG("DER event dir open failed");
674 if (fPEM != -1)
675 close(fPEM);
676 close(crl->mfd);
677 SignalSetup(crl, MONITOR_SETUP_E);
678 return NULL;
679 }
680 }
681
682 if (fPEM != -1)
683 EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
684 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
685
686 if (fDER != -1)
687 EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
688 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
689
690 /* signal to calling thread we're setup */
691 if (SignalSetup(crl, 1) != 0) {
692 if (fPEM != -1)
693 close(fPEM);
694 if (fDER != -1)
695 close(fDER);
696 close(crl->mfd);
697 return NULL;
698 }
699
700 for (;;) {
701 struct kevent event;
702 int numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL);
703
704 WOLFSSL_MSG("Got kevent");
705
706 if (numEvents == -1) {
707 WOLFSSL_MSG("kevent problem, continue");
708 continue;
709 }
710
711 if (event.filter == EVFILT_USER) {
712 WOLFSSL_MSG("Got user shutdown event, breaking out");
713 break;
714 }
715
716 if (SwapLists(crl) < 0) {
717 WOLFSSL_MSG("SwapLists problem, continue");
718 }
719 }
720
721 if (fPEM != -1)
722 close(fPEM);
723 if (fDER != -1)
724 close(fDER);
725
726 close(crl->mfd);
727
728 return NULL;
729}
730
731
732#elif defined(__linux__)
733
734#include <sys/types.h>
735#include <sys/inotify.h>
736#include <sys/eventfd.h>
737#include <unistd.h>
738
739
740#ifndef max
741 static INLINE int max(int a, int b)
742 {
743 return a > b ? a : b;
744 }
745#endif /* max */
746
747
748/* shutdown monitor thread, 0 on success */
749static int StopMonitor(int mfd)
750{
751 word64 w64 = 1;
752
753 /* write to our custom event */
754 if (write(mfd, &w64, sizeof(w64)) < 0) {
755 WOLFSSL_MSG("StopMonitor write failed");
756 return -1;
757 }
758
759 return 0;
760}
761
762
763/* linux monitoring */
764static void* DoMonitor(void* arg)
765{
766 int notifyFd;
767 int wd = -1;
768 WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
769#ifdef WOLFSSL_SMALL_STACK
770 char* buff;
771#else
772 char buff[8192];
773#endif
774
775 WOLFSSL_ENTER("DoMonitor");
776
777 crl->mfd = eventfd(0, 0); /* our custom shutdown event */
778 if (crl->mfd < 0) {
779 WOLFSSL_MSG("eventfd failed");
780 SignalSetup(crl, MONITOR_SETUP_E);
781 return NULL;
782 }
783
784 notifyFd = inotify_init();
785 if (notifyFd < 0) {
786 WOLFSSL_MSG("inotify failed");
787 close(crl->mfd);
788 SignalSetup(crl, MONITOR_SETUP_E);
789 return NULL;
790 }
791
792 if (crl->monitors[0].path) {
793 wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
794 IN_DELETE);
795 if (wd < 0) {
796 WOLFSSL_MSG("PEM notify add watch failed");
797 close(crl->mfd);
798 close(notifyFd);
799 SignalSetup(crl, MONITOR_SETUP_E);
800 return NULL;
801 }
802 }
803
804 if (crl->monitors[1].path) {
805 wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
806 IN_DELETE);
807 if (wd < 0) {
808 WOLFSSL_MSG("DER notify add watch failed");
809 close(crl->mfd);
810 close(notifyFd);
811 SignalSetup(crl, MONITOR_SETUP_E);
812 return NULL;
813 }
814 }
815
816#ifdef WOLFSSL_SMALL_STACK
817 buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
818 if (buff == NULL)
819 return NULL;
820#endif
821
822 /* signal to calling thread we're setup */
823 if (SignalSetup(crl, 1) != 0) {
824 #ifdef WOLFSSL_SMALL_STACK
825 XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
826 #endif
827
828 if (wd > 0)
829 inotify_rm_watch(notifyFd, wd);
830 close(crl->mfd);
831 close(notifyFd);
832 return NULL;
833 }
834
835 for (;;) {
836 fd_set readfds;
837 int result;
838 int length;
839
840 FD_ZERO(&readfds);
841 FD_SET(notifyFd, &readfds);
842 FD_SET(crl->mfd, &readfds);
843
844 result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL);
845
846 WOLFSSL_MSG("Got notify event");
847
848 if (result < 0) {
849 WOLFSSL_MSG("select problem, continue");
850 continue;
851 }
852
853 if (FD_ISSET(crl->mfd, &readfds)) {
854 WOLFSSL_MSG("got custom shutdown event, breaking out");
855 break;
856 }
857
858 length = (int) read(notifyFd, buff, 8192);
859 if (length < 0) {
860 WOLFSSL_MSG("notify read problem, continue");
861 continue;
862 }
863
864 if (SwapLists(crl) < 0) {
865 WOLFSSL_MSG("SwapLists problem, continue");
866 }
867 }
868
869#ifdef WOLFSSL_SMALL_STACK
870 XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
871#endif
872
873 if (wd > 0)
874 inotify_rm_watch(notifyFd, wd);
875 close(crl->mfd);
876 close(notifyFd);
877
878 return NULL;
879}
880
881#endif /* MACH or linux */
882
883
884/* Start Monitoring the CRL path(s) in a thread */
885static int StartMonitorCRL(WOLFSSL_CRL* crl)
886{
887 int ret = WOLFSSL_SUCCESS;
888
889 WOLFSSL_ENTER("StartMonitorCRL");
890
891 if (crl == NULL)
892 return BAD_FUNC_ARG;
893
894 if (crl->tid != 0) {
895 WOLFSSL_MSG("Monitor thread already running");
896 return ret; /* that's ok, someone already started */
897 }
898
899 if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) {
900 WOLFSSL_MSG("Thread creation error");
901 return THREAD_CREATE_E;
902 }
903
904 /* wait for setup to complete */
905 if (wc_LockMutex(&crl->crlLock) != 0) {
906 WOLFSSL_MSG("wc_LockMutex crlLock error");
907 return BAD_MUTEX_E;
908 }
909
910 while (crl->setup == 0) {
911 if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) {
912 ret = BAD_COND_E;
913 break;
914 }
915 }
916
917 if (crl->setup < 0)
918 ret = crl->setup; /* store setup error */
919
920 wc_UnLockMutex(&crl->crlLock);
921
922 if (ret < 0) {
923 WOLFSSL_MSG("DoMonitor setup failure");
924 crl->tid = 0; /* thread already done */
925 }
926
927 return ret;
928}
929
930
931#else /* HAVE_CRL_MONITOR */
932
933#ifndef NO_FILESYSTEM
934
935static int StartMonitorCRL(WOLFSSL_CRL* crl)
936{
937 (void)crl;
938
939 WOLFSSL_ENTER("StartMonitorCRL");
940 WOLFSSL_MSG("Not compiled in");
941
942 return NOT_COMPILED_IN;
943}
944
945#endif /* NO_FILESYSTEM */
946
947#endif /* HAVE_CRL_MONITOR */
948
949#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
950
951/* Load CRL path files of type, WOLFSSL_SUCCESS on ok */
952int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
953{
954 int ret = WOLFSSL_SUCCESS;
955 char* name = NULL;
956#ifdef WOLFSSL_SMALL_STACK
957 ReadDirCtx* readCtx = NULL;
958#else
959 ReadDirCtx readCtx[1];
960#endif
961
962 WOLFSSL_ENTER("LoadCRL");
963 if (crl == NULL)
964 return BAD_FUNC_ARG;
965
966#ifdef WOLFSSL_SMALL_STACK
967 readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap,
968 DYNAMIC_TYPE_TMP_BUFFER);
969 if (readCtx == NULL)
970 return MEMORY_E;
971#endif
972
973 /* try to load each regular file in path */
974 ret = wc_ReadDirFirst(readCtx, path, &name);
975 while (ret == 0 && name) {
976 int skip = 0;
977 if (type == WOLFSSL_FILETYPE_PEM) {
978 if (XSTRSTR(name, ".pem") == NULL) {
979 WOLFSSL_MSG("not .pem file, skipping");
980 skip = 1;
981 }
982 }
983 else {
984 if (XSTRSTR(name, ".der") == NULL &&
985 XSTRSTR(name, ".crl") == NULL)
986 {
987 WOLFSSL_MSG("not .der or .crl file, skipping");
988 skip = 1;
989 }
990 }
991
992 if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl)
993 != WOLFSSL_SUCCESS) {
994 WOLFSSL_MSG("CRL file load failed, continuing");
995 }
996
997 ret = wc_ReadDirNext(readCtx, path, &name);
998 }
999 wc_ReadDirClose(readCtx);
1000 ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */
1001
1002#ifdef WOLFSSL_SMALL_STACK
1003 XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
1004#endif
1005
1006 if (monitor & WOLFSSL_CRL_MONITOR) {
1007 word32 pathLen;
1008 char* pathBuf;
1009
1010 WOLFSSL_MSG("monitor path requested");
1011
1012 pathLen = (word32)XSTRLEN(path);
1013 pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR);
1014 if (pathBuf) {
1015 XSTRNCPY(pathBuf, path, pathLen);
1016 pathBuf[pathLen] = '\0'; /* Null Terminate */
1017
1018 if (type == WOLFSSL_FILETYPE_PEM) {
1019 /* free old path before setting a new one */
1020 if (crl->monitors[0].path) {
1021 XFREE(crl->monitors[0].path, crl->heap,
1022 DYNAMIC_TYPE_CRL_MONITOR);
1023 }
1024 crl->monitors[0].path = pathBuf;
1025 crl->monitors[0].type = WOLFSSL_FILETYPE_PEM;
1026 } else {
1027 /* free old path before setting a new one */
1028 if (crl->monitors[1].path) {
1029 XFREE(crl->monitors[1].path, crl->heap,
1030 DYNAMIC_TYPE_CRL_MONITOR);
1031 }
1032 crl->monitors[1].path = pathBuf;
1033 crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1;
1034 }
1035
1036 if (monitor & WOLFSSL_CRL_START_MON) {
1037 WOLFSSL_MSG("start monitoring requested");
1038
1039 ret = StartMonitorCRL(crl);
1040 }
1041 }
1042 else {
1043 ret = MEMORY_E;
1044 }
1045 }
1046
1047 return ret;
1048}
1049
1050#else
1051int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
1052{
1053 (void)crl;
1054 (void)path;
1055 (void)type;
1056 (void)monitor;
1057
1058 /* stub for scenario where file system is not supported */
1059 return NOT_COMPILED_IN;
1060}
1061#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
1062
1063#endif /* HAVE_CRL */
1064#endif /* !WOLFCRYPT_ONLY */
Note: See TracBrowser for help on using the repository browser.