source: azure_iot_hub/trunk/wolfssl-3.15.7/src/crl.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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