source: azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/src/crl.c@ 464

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

WolfSSLとAzure IoT SDKを更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 36.1 KB
RevLine 
[457]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
[464]37#ifndef WOLFSSL_LINUXKM
38 #include <string.h>
39#endif
[457]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 */
51int 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 */
81static 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 */
133static 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 */
156void 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
191static 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 */
341int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
342{
343 int foundEntry = 0;
344 int ret = 0;
345
346 WOLFSSL_ENTER("CheckCertCRL");
347
348 ret = CheckCertCRLList(crl, cert, &foundEntry);
349
350#ifdef HAVE_CRL_IO
351 if (foundEntry == 0) {
352 /* perform embedded lookup */
353 if (crl->crlIOCb) {
354 ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo,
355 cert->extCrlInfoSz);
356 if (ret == WOLFSSL_CBIO_ERR_WANT_READ) {
357 ret = WANT_READ;
358 }
359 else if (ret >= 0) {
360 /* try again */
361 ret = CheckCertCRLList(crl, cert, &foundEntry);
362 }
363 }
364 }
365#endif
366
367 if (foundEntry == 0) {
368 WOLFSSL_MSG("Couldn't find CRL for status check");
369 ret = CRL_MISSING;
370
371 if (crl->cm->cbMissingCRL) {
372 char url[256];
373
374 WOLFSSL_MSG("Issuing missing CRL callback");
375 url[0] = '\0';
376 if (cert->extCrlInfo) {
377 if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
378 XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
379 url[cert->extCrlInfoSz] = '\0';
380 }
381 else {
382 WOLFSSL_MSG("CRL url too long");
383 }
384 }
385
386 crl->cm->cbMissingCRL(url);
387 }
388 }
389
390 return ret;
391}
392
393
394/* Add Decoded CRL, 0 on success */
395static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff,
396 int verified)
397{
398 CRL_Entry* crle;
399
400 WOLFSSL_ENTER("AddCRL");
401
402 crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
403 if (crle == NULL) {
404 WOLFSSL_MSG("alloc CRL Entry failed");
405 return -1;
406 }
407
408 if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) {
409 WOLFSSL_MSG("Init CRL Entry failed");
410 XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
411 return -1;
412 }
413
414 if (wc_LockMutex(&crl->crlLock) != 0) {
415 WOLFSSL_MSG("wc_LockMutex failed");
416 FreeCRL_Entry(crle, crl->heap);
417 XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY);
418 return BAD_MUTEX_E;
419 }
420 crle->next = crl->crlList;
421 crl->crlList = crle;
422 wc_UnLockMutex(&crl->crlLock);
423
424 return 0;
425}
426
427
428/* Load CRL File of type, WOLFSSL_SUCCESS on ok */
429int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type,
430 int verify)
431{
432 int ret = WOLFSSL_SUCCESS;
433 const byte* myBuffer = buff; /* if DER ok, otherwise switch */
434 DerBuffer* der = NULL;
435#ifdef WOLFSSL_SMALL_STACK
436 DecodedCRL* dcrl;
437#else
438 DecodedCRL dcrl[1];
439#endif
440
441 WOLFSSL_ENTER("BufferLoadCRL");
442
443 if (crl == NULL || buff == NULL || sz == 0)
444 return BAD_FUNC_ARG;
445
446 if (type == WOLFSSL_FILETYPE_PEM) {
447 #ifdef WOLFSSL_PEM_TO_DER
448 ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL);
449 if (ret == 0) {
450 myBuffer = der->buffer;
451 sz = der->length;
452 }
453 else {
454 WOLFSSL_MSG("Pem to Der failed");
455 FreeDer(&der);
456 return -1;
457 }
458 #else
459 ret = NOT_COMPILED_IN;
460 #endif
461 }
462
463#ifdef WOLFSSL_SMALL_STACK
464 dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
465 if (dcrl == NULL) {
466 FreeDer(&der);
467 return MEMORY_E;
468 }
469#endif
470
471 InitDecodedCRL(dcrl, crl->heap);
472 ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm);
473 if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) {
474 WOLFSSL_MSG("ParseCRL error");
475 }
476 else {
477 ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E);
478 if (ret != 0) {
479 WOLFSSL_MSG("AddCRL error");
480 }
481 }
482
483 FreeDecodedCRL(dcrl);
484
485#ifdef WOLFSSL_SMALL_STACK
486 XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
487#endif
488
489 FreeDer(&der);
490
491 return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */
492}
493
494#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL)
[464]495/* helper function to create a new dynamic WOLFSSL_X509_CRL structure */
496static WOLFSSL_X509_CRL* wolfSSL_X509_crl_new(WOLFSSL_CERT_MANAGER* cm)
497{
498 WOLFSSL_X509_CRL* ret;
499
500 ret = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), cm->heap,
501 DYNAMIC_TYPE_CRL);
502 if (ret != NULL) {
503 if (InitCRL(ret, cm) < 0) {
504 WOLFSSL_MSG("Unable to initialize new CRL structure");
505 XFREE(ret, cm->heap, DYNAMIC_TYPE_CRL);
506 ret = NULL;
507 }
508 }
509 return ret;
510}
511
512
513/* returns head of copied list that was alloc'd */
514static RevokedCert *DupRevokedCertList(RevokedCert* in, void* heap)
515{
516 RevokedCert* head = NULL;
517 RevokedCert* current = in;
518 RevokedCert* prev = NULL;
519 while (current) {
520 RevokedCert* tmp = (RevokedCert*)XMALLOC(sizeof(RevokedCert), heap,
521 DYNAMIC_TYPE_REVOKED);
522 if (tmp != NULL) {
523 XMEMCPY(tmp->serialNumber, current->serialNumber,
524 EXTERNAL_SERIAL_SIZE);
525 tmp->serialSz = current->serialSz;
526 tmp->next = NULL;
527 if (prev != NULL)
528 prev->next = tmp;
529 if (head == NULL)
530 head = tmp;
531 prev = tmp;
532 }
533 else {
534 WOLFSSL_MSG("Failed to allocate new RevokedCert structure");
535 /* free up any existing list */
536 while (head != NULL) {
537 current = head;
538 head = head->next;
539 XFREE(current, heap, DYNAMIC_TYPE_REVOKED);
540 }
541 return NULL;
542 }
543 current = current->next;
544 }
545
546 (void)heap;
547 return head;
548}
549
550
551/* returns a deep copy of ent on success and null on fail */
552static CRL_Entry* DupCRL_Entry(const CRL_Entry* ent, void* heap)
553{
554 CRL_Entry *dupl;
555
556 dupl = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), heap, DYNAMIC_TYPE_CRL_ENTRY);
557 if (dupl == NULL) {
558 WOLFSSL_MSG("alloc CRL Entry failed");
559 return NULL;
560 }
561 XMEMSET(dupl, 0, sizeof(CRL_Entry));
562
563 XMEMCPY(dupl->issuerHash, ent->issuerHash, CRL_DIGEST_SIZE);
564 XMEMCPY(dupl->lastDate, ent->lastDate, MAX_DATE_SIZE);
565 XMEMCPY(dupl->nextDate, ent->nextDate, MAX_DATE_SIZE);
566 dupl->lastDateFormat = ent->lastDateFormat;
567 dupl->nextDateFormat = ent->nextDateFormat;
568 dupl->certs = DupRevokedCertList(ent->certs, heap);
569
570 dupl->totalCerts = ent->totalCerts;
571 dupl->verified = ent->verified;
572
573 if (!ent->verified) {
574 dupl->tbsSz = ent->tbsSz;
575 dupl->signatureSz = ent->signatureSz;
576 dupl->signatureOID = ent->signatureOID;
577 dupl->toBeSigned = (byte*)XMALLOC(dupl->tbsSz, heap,
578 DYNAMIC_TYPE_CRL_ENTRY);
579 if (dupl->toBeSigned == NULL) {
580 FreeCRL_Entry(dupl, heap);
581 XFREE(dupl, heap, DYNAMIC_TYPE_CRL_ENTRY);
582 return NULL;
583 }
584
585 dupl->signature = (byte*)XMALLOC(dupl->signatureSz, heap,
586 DYNAMIC_TYPE_CRL_ENTRY);
587 if (dupl->signature == NULL) {
588 FreeCRL_Entry(dupl, heap);
589 XFREE(dupl, heap, DYNAMIC_TYPE_CRL_ENTRY);
590 return NULL;
591 }
592 XMEMCPY(dupl->toBeSigned, ent->toBeSigned, dupl->tbsSz);
593 XMEMCPY(dupl->signature, ent->signature, dupl->signatureSz);
594 #ifndef NO_SKID
595 dupl->extAuthKeyIdSet = ent->extAuthKeyIdSet;
596 if (dupl->extAuthKeyIdSet)
597 XMEMCPY(dupl->extAuthKeyId, ent->extAuthKeyId, KEYID_SIZE);
598 #endif
599 }
600 else {
601 dupl->toBeSigned = NULL;
602 dupl->tbsSz = 0;
603 dupl->signature = NULL;
604 dupl->signatureSz = 0;
605 }
606
607 return dupl;
608}
609
610
611/* returns the head of a deep copy of the list on success and null on fail */
612static CRL_Entry* DupCRL_list(CRL_Entry* crl, void* heap)
613{
614 CRL_Entry* current;
615 CRL_Entry* head = NULL;
616 CRL_Entry* prev = NULL;
617
618 current = crl;
619 while (current != NULL) {
620 CRL_Entry* tmp = DupCRL_Entry(current, heap);
621 if (tmp != NULL) {
622 tmp->next = NULL;
623 if (head == NULL)
624 head = tmp;
625 if (prev != NULL)
626 prev->next = tmp;
627 prev = tmp;
628 }
629 else {
630 WOLFSSL_MSG("Failed to allocate new CRL_Entry structure");
631 /* free up any existing list */
632 while (head != NULL) {
633 current = head;
634 head = head->next;
635 FreeCRL_Entry(current, heap);
636 }
637
638 return NULL;
639 }
640 current = current->next;
641 }
642 return head;
643}
644
645
646/* Duplicates everything except the parent cm pointed to.
647 * Expects that Init has already been done to 'dupl'
648 * return 0 on success */
649static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl)
650{
651 if (dupl == NULL || crl == NULL) {
652 return BAD_FUNC_ARG;
653 }
654
655 if (crl->monitors[0].path) {
656 int pathSz = (int)XSTRLEN(crl->monitors[0].path) + 1;
657 dupl->monitors[0].path = (char*)XMALLOC(pathSz, dupl->heap,
658 DYNAMIC_TYPE_CRL_MONITOR);
659 if (dupl->monitors[0].path != NULL) {
660 XSTRNCPY(dupl->monitors[0].path, crl->monitors[0].path, pathSz);
661 }
662 else {
663 return MEMORY_E;
664 }
665 }
666
667 if (crl->monitors[1].path) {
668 int pathSz = (int)XSTRLEN(crl->monitors[1].path) + 1;
669 dupl->monitors[1].path = (char*)XMALLOC(pathSz, dupl->heap,
670 DYNAMIC_TYPE_CRL_MONITOR);
671 if (dupl->monitors[1].path != NULL) {
672 XSTRNCPY(dupl->monitors[1].path, crl->monitors[1].path, pathSz);
673 }
674 else {
675 if (dupl->monitors[0].path != NULL) {
676 XFREE(dupl->monitors[0].path, dupl->heap,
677 DYNAMIC_TYPE_CRL_MONITOR);
678 }
679 return MEMORY_E;
680 }
681 }
682
683 dupl->crlList = DupCRL_list(crl->crlList, dupl->heap);
684#ifdef HAVE_CRL_IO
685 dupl->crlIOCb = crl->crlIOCb;
686#endif
687
688 return 0;
689}
690
691/* returns WOLFSSL_SUCCESS on success. Does not take ownership of newcrl */
[457]692int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl)
693{
694 CRL_Entry *crle;
[464]695 WOLFSSL_X509_CRL *crl;
[457]696
697 WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl");
[464]698 if (store == NULL || newcrl == NULL || store->cm == NULL)
[457]699 return BAD_FUNC_ARG;
700
[464]701 if (store->cm->crl == NULL) {
702 crl = wolfSSL_X509_crl_new(store->cm);
703 if (DupX509_CRL(crl, newcrl) != 0) {
704 FreeCRL(crl, 1);
705 return WOLFSSL_FAILURE;
706 }
707 store->crl = store->cm->crl = crl;
708 if (wolfSSL_CertManagerEnableCRL(store->cm, WOLFSSL_CRL_CHECKALL)
709 != WOLFSSL_SUCCESS) {
710 WOLFSSL_MSG("wolfSSL_CertManagerEnableCRL error");
711 return WOLFSSL_FAILURE;
712 }
713 return WOLFSSL_SUCCESS;
714 }
[457]715
[464]716 /* find tail of current list and add new list */
717 crl = store->cm->crl;
718 crle = crl->crlList;
719 if (newcrl->crlList != NULL) {
720 CRL_Entry *tail = crle;
721 CRL_Entry *toAdd;
722
723 if (wc_LockMutex(&crl->crlLock) != 0)
724 {
725 WOLFSSL_MSG("wc_LockMutex failed");
726 return BAD_MUTEX_E;
727 }
728
729 toAdd = DupCRL_list(newcrl->crlList, crl->heap);
730 if (tail == NULL) {
731 crl->crlList = toAdd;
732 }
733 else {
734 while (tail->next != NULL) tail = tail->next;
735 tail->next = toAdd;
736 }
737 wc_UnLockMutex(&crl->crlLock);
[457]738 }
739
[464]740 if (wolfSSL_CertManagerEnableCRL(store->cm, WOLFSSL_CRL_CHECKALL)
741 != WOLFSSL_SUCCESS) {
742 WOLFSSL_MSG("wolfSSL_CertManagerEnableCRL error");
743 return WOLFSSL_FAILURE;
744 }
745
[457]746 WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS);
747
748 return WOLFSSL_SUCCESS;
749}
750#endif
751
752#ifdef HAVE_CRL_MONITOR
753
754
755/* Signal Monitor thread is setup, save status to setup flag, 0 on success */
756static int SignalSetup(WOLFSSL_CRL* crl, int status)
757{
758 int ret;
759
760 /* signal to calling thread we're setup */
761 if (wc_LockMutex(&crl->crlLock) != 0) {
762 WOLFSSL_MSG("wc_LockMutex crlLock failed");
763 return BAD_MUTEX_E;
764 }
765
766 crl->setup = status;
767 ret = pthread_cond_signal(&crl->cond);
768
769 wc_UnLockMutex(&crl->crlLock);
770
771 if (ret != 0)
772 return BAD_COND_E;
773
774 return 0;
775}
776
777
778/* read in new CRL entries and save new list */
779static int SwapLists(WOLFSSL_CRL* crl)
780{
781 int ret;
782 CRL_Entry* newList;
783#ifdef WOLFSSL_SMALL_STACK
784 WOLFSSL_CRL* tmp;
785#else
786 WOLFSSL_CRL tmp[1];
787#endif
788
789#ifdef WOLFSSL_SMALL_STACK
790 tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
791 if (tmp == NULL)
792 return MEMORY_E;
793#endif
794
795 if (InitCRL(tmp, crl->cm) < 0) {
796 WOLFSSL_MSG("Init tmp CRL failed");
797#ifdef WOLFSSL_SMALL_STACK
798 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
799#endif
800 return -1;
801 }
802
803 if (crl->monitors[0].path) {
804 ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0);
805 if (ret != WOLFSSL_SUCCESS) {
806 WOLFSSL_MSG("PEM LoadCRL on dir change failed");
807 FreeCRL(tmp, 0);
808#ifdef WOLFSSL_SMALL_STACK
809 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
810#endif
811 return -1;
812 }
813 }
814
815 if (crl->monitors[1].path) {
816 ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0);
817 if (ret != WOLFSSL_SUCCESS) {
818 WOLFSSL_MSG("DER LoadCRL on dir change failed");
819 FreeCRL(tmp, 0);
820#ifdef WOLFSSL_SMALL_STACK
821 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
822#endif
823 return -1;
824 }
825 }
826
827 if (wc_LockMutex(&crl->crlLock) != 0) {
828 WOLFSSL_MSG("wc_LockMutex failed");
829 FreeCRL(tmp, 0);
830#ifdef WOLFSSL_SMALL_STACK
831 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
832#endif
833 return -1;
834 }
835
836 newList = tmp->crlList;
837
838 /* swap lists */
839 tmp->crlList = crl->crlList;
840 crl->crlList = newList;
841
842 wc_UnLockMutex(&crl->crlLock);
843
844 FreeCRL(tmp, 0);
845
846#ifdef WOLFSSL_SMALL_STACK
847 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
848#endif
849
850 return 0;
851}
852
853
854#if (defined(__MACH__) || defined(__FreeBSD__))
855
856#include <sys/types.h>
857#include <sys/event.h>
858#include <sys/time.h>
859#include <fcntl.h>
860#include <unistd.h>
861
862#ifdef __MACH__
863 #define XEVENT_MODE O_EVTONLY
864#elif defined(__FreeBSD__)
865 #define XEVENT_MODE EVFILT_VNODE
866#endif
867
868
869/* we need a unique kqueue user filter fd for crl in case user is doing custom
870 * events too */
871#ifndef CRL_CUSTOM_FD
872 #define CRL_CUSTOM_FD 123456
873#endif
874
875
876/* shutdown monitor thread, 0 on success */
877static int StopMonitor(int mfd)
878{
879 struct kevent change;
880
881 /* trigger custom shutdown */
882 EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
883 if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
884 WOLFSSL_MSG("kevent trigger customer event failed");
885 return -1;
886 }
887
888 return 0;
889}
890
891
892/* OS X monitoring */
893static void* DoMonitor(void* arg)
894{
895 int fPEM, fDER;
896 struct kevent change;
897
898 WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
899
900 WOLFSSL_ENTER("DoMonitor");
901
902 crl->mfd = kqueue();
903 if (crl->mfd == -1) {
904 WOLFSSL_MSG("kqueue failed");
905 SignalSetup(crl, MONITOR_SETUP_E);
906 return NULL;
907 }
908
909 /* listen for custom shutdown event */
910 EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
911 if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) {
912 WOLFSSL_MSG("kevent monitor customer event failed");
913 SignalSetup(crl, MONITOR_SETUP_E);
914 close(crl->mfd);
915 return NULL;
916 }
917
918 fPEM = -1;
919 fDER = -1;
920
921 if (crl->monitors[0].path) {
922 fPEM = open(crl->monitors[0].path, XEVENT_MODE);
923 if (fPEM == -1) {
924 WOLFSSL_MSG("PEM event dir open failed");
925 SignalSetup(crl, MONITOR_SETUP_E);
926 close(crl->mfd);
927 return NULL;
928 }
929 }
930
931 if (crl->monitors[1].path) {
932 fDER = open(crl->monitors[1].path, XEVENT_MODE);
933 if (fDER == -1) {
934 WOLFSSL_MSG("DER event dir open failed");
935 if (fPEM != -1)
936 close(fPEM);
937 close(crl->mfd);
938 SignalSetup(crl, MONITOR_SETUP_E);
939 return NULL;
940 }
941 }
942
943 if (fPEM != -1)
944 EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
945 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
946
947 if (fDER != -1)
948 EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
949 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
950
951 /* signal to calling thread we're setup */
952 if (SignalSetup(crl, 1) != 0) {
953 if (fPEM != -1)
954 close(fPEM);
955 if (fDER != -1)
956 close(fDER);
957 close(crl->mfd);
958 return NULL;
959 }
960
961 for (;;) {
962 struct kevent event;
963 int numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL);
964
965 WOLFSSL_MSG("Got kevent");
966
967 if (numEvents == -1) {
968 WOLFSSL_MSG("kevent problem, continue");
969 continue;
970 }
971
972 if (event.filter == EVFILT_USER) {
973 WOLFSSL_MSG("Got user shutdown event, breaking out");
974 break;
975 }
976
977 if (SwapLists(crl) < 0) {
978 WOLFSSL_MSG("SwapLists problem, continue");
979 }
980 }
981
982 if (fPEM != -1)
983 close(fPEM);
984 if (fDER != -1)
985 close(fDER);
986
987 close(crl->mfd);
988
989 return NULL;
990}
991
992
993#elif defined(__linux__)
994
995#include <sys/types.h>
996#include <sys/inotify.h>
997#include <sys/eventfd.h>
998#include <unistd.h>
999
1000
1001#ifndef max
1002 static WC_INLINE int max(int a, int b)
1003 {
1004 return a > b ? a : b;
1005 }
1006#endif /* max */
1007
1008
1009/* shutdown monitor thread, 0 on success */
1010static int StopMonitor(int mfd)
1011{
1012 word64 w64 = 1;
1013
1014 /* write to our custom event */
1015 if (write(mfd, &w64, sizeof(w64)) < 0) {
1016 WOLFSSL_MSG("StopMonitor write failed");
1017 return -1;
1018 }
1019
1020 return 0;
1021}
1022
1023
1024/* linux monitoring */
1025static void* DoMonitor(void* arg)
1026{
1027 int notifyFd;
1028 int wd = -1;
1029 WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
1030#ifdef WOLFSSL_SMALL_STACK
1031 char* buff;
1032#else
1033 char buff[8192];
1034#endif
1035
1036 WOLFSSL_ENTER("DoMonitor");
1037
1038 crl->mfd = eventfd(0, 0); /* our custom shutdown event */
1039 if (crl->mfd < 0) {
1040 WOLFSSL_MSG("eventfd failed");
1041 SignalSetup(crl, MONITOR_SETUP_E);
1042 return NULL;
1043 }
1044
1045 notifyFd = inotify_init();
1046 if (notifyFd < 0) {
1047 WOLFSSL_MSG("inotify failed");
1048 close(crl->mfd);
1049 SignalSetup(crl, MONITOR_SETUP_E);
1050 return NULL;
1051 }
1052
1053 if (crl->monitors[0].path) {
1054 wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
1055 IN_DELETE);
1056 if (wd < 0) {
1057 WOLFSSL_MSG("PEM notify add watch failed");
1058 close(crl->mfd);
1059 close(notifyFd);
1060 SignalSetup(crl, MONITOR_SETUP_E);
1061 return NULL;
1062 }
1063 }
1064
1065 if (crl->monitors[1].path) {
1066 wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
1067 IN_DELETE);
1068 if (wd < 0) {
1069 WOLFSSL_MSG("DER notify add watch failed");
1070 close(crl->mfd);
1071 close(notifyFd);
1072 SignalSetup(crl, MONITOR_SETUP_E);
1073 return NULL;
1074 }
1075 }
1076
1077#ifdef WOLFSSL_SMALL_STACK
1078 buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1079 if (buff == NULL)
1080 return NULL;
1081#endif
1082
1083 /* signal to calling thread we're setup */
1084 if (SignalSetup(crl, 1) != 0) {
1085 #ifdef WOLFSSL_SMALL_STACK
1086 XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1087 #endif
1088
1089 if (wd > 0)
1090 inotify_rm_watch(notifyFd, wd);
1091 close(crl->mfd);
1092 close(notifyFd);
1093 return NULL;
1094 }
1095
1096 for (;;) {
1097 fd_set readfds;
1098 int result;
1099 int length;
1100
1101 FD_ZERO(&readfds);
1102 FD_SET(notifyFd, &readfds);
1103 FD_SET(crl->mfd, &readfds);
1104
1105 result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL);
1106
1107 WOLFSSL_MSG("Got notify event");
1108
1109 if (result < 0) {
1110 WOLFSSL_MSG("select problem, continue");
1111 continue;
1112 }
1113
1114 if (FD_ISSET(crl->mfd, &readfds)) {
[464]1115 word64 r64;
1116 int rlen;
1117
[457]1118 WOLFSSL_MSG("got custom shutdown event, breaking out");
[464]1119
1120 /* read out the bytes written to the event to clean up */
1121 rlen = (int) read(crl->mfd, &r64, sizeof(r64));
1122 if (rlen < 0) {
1123 WOLFSSL_MSG("read custom event failure");
1124 }
1125
[457]1126 break;
1127 }
1128
1129 length = (int) read(notifyFd, buff, 8192);
1130 if (length < 0) {
1131 WOLFSSL_MSG("notify read problem, continue");
1132 continue;
1133 }
1134
1135 if (SwapLists(crl) < 0) {
1136 WOLFSSL_MSG("SwapLists problem, continue");
1137 }
1138 }
1139
1140#ifdef WOLFSSL_SMALL_STACK
1141 XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1142#endif
1143
1144 if (wd > 0)
1145 inotify_rm_watch(notifyFd, wd);
1146 close(crl->mfd);
1147 close(notifyFd);
1148
1149 return NULL;
1150}
1151
1152#endif /* MACH or linux */
1153
1154
1155/* Start Monitoring the CRL path(s) in a thread */
1156static int StartMonitorCRL(WOLFSSL_CRL* crl)
1157{
1158 int ret = WOLFSSL_SUCCESS;
1159
1160 WOLFSSL_ENTER("StartMonitorCRL");
1161
1162 if (crl == NULL)
1163 return BAD_FUNC_ARG;
1164
1165 if (crl->tid != 0) {
1166 WOLFSSL_MSG("Monitor thread already running");
1167 return ret; /* that's ok, someone already started */
1168 }
1169
1170 if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) {
1171 WOLFSSL_MSG("Thread creation error");
1172 return THREAD_CREATE_E;
1173 }
1174
1175 /* wait for setup to complete */
1176 if (wc_LockMutex(&crl->crlLock) != 0) {
1177 WOLFSSL_MSG("wc_LockMutex crlLock error");
1178 return BAD_MUTEX_E;
1179 }
1180
1181 while (crl->setup == 0) {
1182 if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) {
1183 ret = BAD_COND_E;
1184 break;
1185 }
1186 }
1187
1188 if (crl->setup < 0)
1189 ret = crl->setup; /* store setup error */
1190
1191 wc_UnLockMutex(&crl->crlLock);
1192
1193 if (ret < 0) {
1194 WOLFSSL_MSG("DoMonitor setup failure");
1195 crl->tid = 0; /* thread already done */
1196 }
1197
1198 return ret;
1199}
1200
1201
1202#else /* HAVE_CRL_MONITOR */
1203
[464]1204#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
[457]1205
1206static int StartMonitorCRL(WOLFSSL_CRL* crl)
1207{
1208 (void)crl;
1209
1210 WOLFSSL_ENTER("StartMonitorCRL");
1211 WOLFSSL_MSG("Not compiled in");
1212
1213 return NOT_COMPILED_IN;
1214}
1215
[464]1216#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
[457]1217
1218#endif /* HAVE_CRL_MONITOR */
1219
1220#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
1221
1222/* Load CRL path files of type, WOLFSSL_SUCCESS on ok */
1223int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
1224{
1225 int ret = WOLFSSL_SUCCESS;
1226 char* name = NULL;
1227#ifdef WOLFSSL_SMALL_STACK
1228 ReadDirCtx* readCtx = NULL;
1229#else
1230 ReadDirCtx readCtx[1];
1231#endif
1232
1233 WOLFSSL_ENTER("LoadCRL");
1234 if (crl == NULL)
1235 return BAD_FUNC_ARG;
1236
1237#ifdef WOLFSSL_SMALL_STACK
1238 readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap,
1239 DYNAMIC_TYPE_TMP_BUFFER);
1240 if (readCtx == NULL)
1241 return MEMORY_E;
1242#endif
1243
1244 /* try to load each regular file in path */
1245 ret = wc_ReadDirFirst(readCtx, path, &name);
1246 while (ret == 0 && name) {
1247 int skip = 0;
1248 if (type == WOLFSSL_FILETYPE_PEM) {
1249 if (XSTRSTR(name, ".pem") == NULL) {
1250 WOLFSSL_MSG("not .pem file, skipping");
1251 skip = 1;
1252 }
1253 }
1254 else {
1255 if (XSTRSTR(name, ".der") == NULL &&
1256 XSTRSTR(name, ".crl") == NULL)
1257 {
1258 WOLFSSL_MSG("not .der or .crl file, skipping");
1259 skip = 1;
1260 }
1261 }
1262
1263 if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl,
1264 VERIFY) != WOLFSSL_SUCCESS) {
1265 WOLFSSL_MSG("CRL file load failed, continuing");
1266 }
1267
1268 ret = wc_ReadDirNext(readCtx, path, &name);
1269 }
1270 wc_ReadDirClose(readCtx);
1271 ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */
1272
1273#ifdef WOLFSSL_SMALL_STACK
1274 XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
1275#endif
1276
1277 if (monitor & WOLFSSL_CRL_MONITOR) {
1278 word32 pathLen;
1279 char* pathBuf;
1280
1281 WOLFSSL_MSG("monitor path requested");
1282
1283 pathLen = (word32)XSTRLEN(path);
1284 pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR);
1285 if (pathBuf) {
1286 XSTRNCPY(pathBuf, path, pathLen+1);
1287
1288 if (type == WOLFSSL_FILETYPE_PEM) {
1289 /* free old path before setting a new one */
1290 if (crl->monitors[0].path) {
1291 XFREE(crl->monitors[0].path, crl->heap,
1292 DYNAMIC_TYPE_CRL_MONITOR);
1293 }
1294 crl->monitors[0].path = pathBuf;
1295 crl->monitors[0].type = WOLFSSL_FILETYPE_PEM;
1296 } else {
1297 /* free old path before setting a new one */
1298 if (crl->monitors[1].path) {
1299 XFREE(crl->monitors[1].path, crl->heap,
1300 DYNAMIC_TYPE_CRL_MONITOR);
1301 }
1302 crl->monitors[1].path = pathBuf;
1303 crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1;
1304 }
1305
1306 if (monitor & WOLFSSL_CRL_START_MON) {
1307 WOLFSSL_MSG("start monitoring requested");
1308
1309 ret = StartMonitorCRL(crl);
1310 }
1311 }
1312 else {
1313 ret = MEMORY_E;
1314 }
1315 }
1316
1317 return ret;
1318}
1319
1320#else
1321int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
1322{
1323 (void)crl;
1324 (void)path;
1325 (void)type;
1326 (void)monitor;
1327
1328 /* stub for scenario where file system is not supported */
1329 return NOT_COMPILED_IN;
1330}
1331#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
1332
1333#endif /* HAVE_CRL */
1334#endif /* !WOLFCRYPT_ONLY */
Note: See TracBrowser for help on using the repository browser.