source: azure_iot_hub_riscv/trunk/wolfssl-4.4.0/src/crl.c@ 453

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

ファイルを追加

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