Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more
crl.c
00001 /* crl.c 00002 * 00003 * Copyright (C) 2006-2020 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 /* Name change compatibility layer no longer needs included here */ 00024 00025 #ifdef HAVE_CONFIG_H 00026 #include <config.h> 00027 #endif 00028 00029 #include <wolfssl/wolfcrypt/settings.h> 00030 00031 #ifndef WOLFCRYPT_ONLY 00032 #ifdef HAVE_CRL 00033 00034 #include <wolfssl/internal.h> 00035 #include <wolfssl/error-ssl.h> 00036 00037 #include <string.h> 00038 00039 #ifdef HAVE_CRL_MONITOR 00040 #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__)) 00041 static int StopMonitor(int mfd); 00042 #else 00043 #error "CRL monitor only currently supported on linux or mach" 00044 #endif 00045 #endif /* HAVE_CRL_MONITOR */ 00046 00047 00048 /* Initialize CRL members */ 00049 int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm) 00050 { 00051 WOLFSSL_ENTER("InitCRL"); 00052 if(cm != NULL) 00053 crl->heap = cm->heap; 00054 else 00055 crl->heap = NULL; 00056 crl->cm = cm; 00057 crl->crlList = NULL; 00058 crl->monitors[0].path = NULL; 00059 crl->monitors[1].path = NULL; 00060 #ifdef HAVE_CRL_MONITOR 00061 crl->tid = 0; 00062 crl->mfd = -1; /* mfd for bsd is kqueue fd, eventfd for linux */ 00063 crl->setup = 0; /* thread setup done predicate */ 00064 if (pthread_cond_init(&crl->cond, 0) != 0) { 00065 WOLFSSL_MSG("Pthread condition init failed"); 00066 return BAD_COND_E; 00067 } 00068 #endif 00069 if (wc_InitMutex(&crl->crlLock) != 0) { 00070 WOLFSSL_MSG("Init Mutex failed"); 00071 return BAD_MUTEX_E; 00072 } 00073 00074 return 0; 00075 } 00076 00077 00078 /* Initialize CRL Entry */ 00079 static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, 00080 int verified, void* heap) 00081 { 00082 WOLFSSL_ENTER("InitCRL_Entry"); 00083 00084 XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE); 00085 /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE); 00086 * copy the hash here if needed for optimized comparisons */ 00087 XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE); 00088 XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE); 00089 crle->lastDateFormat = dcrl->lastDateFormat; 00090 crle->nextDateFormat = dcrl->nextDateFormat; 00091 00092 crle->certs = dcrl->certs; /* take ownsership */ 00093 dcrl->certs = NULL; 00094 crle->totalCerts = dcrl->totalCerts; 00095 crle->verified = verified; 00096 if (!verified) { 00097 crle->tbsSz = dcrl->sigIndex - dcrl->certBegin; 00098 crle->signatureSz = dcrl->sigLength; 00099 crle->signatureOID = dcrl->signatureOID; 00100 crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap, 00101 DYNAMIC_TYPE_CRL_ENTRY); 00102 if (crle->toBeSigned == NULL) 00103 return -1; 00104 crle->signature = (byte*)XMALLOC(crle->signatureSz, heap, 00105 DYNAMIC_TYPE_CRL_ENTRY); 00106 if (crle->signature == NULL) { 00107 XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY); 00108 return -1; 00109 } 00110 XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz); 00111 XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz); 00112 #ifndef NO_SKID 00113 crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; 00114 if (crle->extAuthKeyIdSet) 00115 XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); 00116 #endif 00117 } 00118 else { 00119 crle->toBeSigned = NULL; 00120 crle->signature = NULL; 00121 } 00122 00123 (void)verified; 00124 (void)heap; 00125 00126 return 0; 00127 } 00128 00129 00130 /* Free all CRL Entry resources */ 00131 static void FreeCRL_Entry(CRL_Entry* crle, void* heap) 00132 { 00133 RevokedCert* tmp = crle->certs; 00134 RevokedCert* next; 00135 00136 WOLFSSL_ENTER("FreeCRL_Entry"); 00137 00138 while (tmp) { 00139 next = tmp->next; 00140 XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED); 00141 tmp = next; 00142 } 00143 if (crle->signature != NULL) 00144 XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED); 00145 if (crle->toBeSigned != NULL) 00146 XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED); 00147 00148 (void)heap; 00149 } 00150 00151 00152 00153 /* Free all CRL resources */ 00154 void FreeCRL(WOLFSSL_CRL* crl, int dynamic) 00155 { 00156 CRL_Entry* tmp = crl->crlList; 00157 00158 WOLFSSL_ENTER("FreeCRL"); 00159 if (crl->monitors[0].path) 00160 XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR); 00161 00162 if (crl->monitors[1].path) 00163 XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR); 00164 00165 while(tmp) { 00166 CRL_Entry* next = tmp->next; 00167 FreeCRL_Entry(tmp, crl->heap); 00168 XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00169 tmp = next; 00170 } 00171 00172 #ifdef HAVE_CRL_MONITOR 00173 if (crl->tid != 0) { 00174 WOLFSSL_MSG("stopping monitor thread"); 00175 if (StopMonitor(crl->mfd) == 0) 00176 pthread_join(crl->tid, NULL); 00177 else { 00178 WOLFSSL_MSG("stop monitor failed"); 00179 } 00180 } 00181 pthread_cond_destroy(&crl->cond); 00182 #endif 00183 wc_FreeMutex(&crl->crlLock); 00184 if (dynamic) /* free self */ 00185 XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL); 00186 } 00187 00188 00189 static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry) 00190 { 00191 CRL_Entry* crle; 00192 int foundEntry = 0; 00193 int ret = 0; 00194 00195 if (wc_LockMutex(&crl->crlLock) != 0) { 00196 WOLFSSL_MSG("wc_LockMutex failed"); 00197 return BAD_MUTEX_E; 00198 } 00199 00200 crle = crl->crlList; 00201 00202 while (crle) { 00203 if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) { 00204 WOLFSSL_MSG("Found CRL Entry on list"); 00205 00206 if (crle->verified == 0) { 00207 Signer* ca = NULL; 00208 #ifndef NO_SKID 00209 byte extAuthKeyId[KEYID_SIZE]; 00210 #endif 00211 byte issuerHash[CRL_DIGEST_SIZE]; 00212 byte* tbs; 00213 word32 tbsSz = crle->tbsSz; 00214 byte* sig = NULL; 00215 word32 sigSz = crle->signatureSz; 00216 word32 sigOID = crle->signatureOID; 00217 SignatureCtx sigCtx; 00218 00219 tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00220 if (tbs == NULL) { 00221 wc_UnLockMutex(&crl->crlLock); 00222 return MEMORY_E; 00223 } 00224 sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00225 if (sig == NULL) { 00226 XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00227 wc_UnLockMutex(&crl->crlLock); 00228 return MEMORY_E; 00229 } 00230 00231 XMEMCPY(tbs, crle->toBeSigned, tbsSz); 00232 XMEMCPY(sig, crle->signature, sigSz); 00233 #ifndef NO_SKID 00234 XMEMCPY(extAuthKeyId, crle->extAuthKeyId, 00235 sizeof(extAuthKeyId)); 00236 #endif 00237 XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash)); 00238 00239 wc_UnLockMutex(&crl->crlLock); 00240 00241 #ifndef NO_SKID 00242 if (crle->extAuthKeyIdSet) 00243 ca = GetCA(crl->cm, extAuthKeyId); 00244 if (ca == NULL) 00245 ca = GetCAByName(crl->cm, issuerHash); 00246 #else /* NO_SKID */ 00247 ca = GetCA(crl->cm, issuerHash); 00248 #endif /* NO_SKID */ 00249 if (ca == NULL) { 00250 XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00251 XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00252 WOLFSSL_MSG("Did NOT find CRL issuer CA"); 00253 return ASN_CRL_NO_SIGNER_E; 00254 } 00255 00256 ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz, 00257 sigOID, ca, crl->heap); 00258 00259 XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00260 XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00261 00262 if (wc_LockMutex(&crl->crlLock) != 0) { 00263 WOLFSSL_MSG("wc_LockMutex failed"); 00264 return BAD_MUTEX_E; 00265 } 00266 00267 crle = crl->crlList; 00268 while (crle) { 00269 if (XMEMCMP(crle->issuerHash, cert->issuerHash, 00270 CRL_DIGEST_SIZE) == 0) { 00271 00272 if (ret == 0) 00273 crle->verified = 1; 00274 else 00275 crle->verified = ret; 00276 00277 XFREE(crle->toBeSigned, crl->heap, 00278 DYNAMIC_TYPE_CRL_ENTRY); 00279 crle->toBeSigned = NULL; 00280 XFREE(crle->signature, crl->heap, 00281 DYNAMIC_TYPE_CRL_ENTRY); 00282 crle->signature = NULL; 00283 break; 00284 } 00285 crle = crle->next; 00286 } 00287 if (crle == NULL || crle->verified < 0) 00288 break; 00289 } 00290 else if (crle->verified < 0) { 00291 WOLFSSL_MSG("Cannot use CRL as it didn't verify"); 00292 ret = crle->verified; 00293 break; 00294 } 00295 00296 WOLFSSL_MSG("Checking next date validity"); 00297 00298 #ifdef WOLFSSL_NO_CRL_NEXT_DATE 00299 if (crle->nextDateFormat != ASN_OTHER_TYPE) 00300 #endif 00301 { 00302 #ifndef NO_ASN_TIME 00303 if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, AFTER)) { 00304 WOLFSSL_MSG("CRL next date is no longer valid"); 00305 ret = ASN_AFTER_DATE_E; 00306 } 00307 #endif 00308 } 00309 if (ret == 0) { 00310 foundEntry = 1; 00311 } 00312 break; 00313 } 00314 crle = crle->next; 00315 } 00316 00317 if (foundEntry) { 00318 RevokedCert* rc = crle->certs; 00319 00320 while (rc) { 00321 if (rc->serialSz == cert->serialSz && 00322 XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) { 00323 WOLFSSL_MSG("Cert revoked"); 00324 ret = CRL_CERT_REVOKED; 00325 break; 00326 } 00327 rc = rc->next; 00328 } 00329 } 00330 00331 wc_UnLockMutex(&crl->crlLock); 00332 00333 *pFoundEntry = foundEntry; 00334 00335 return ret; 00336 } 00337 00338 /* Is the cert ok with CRL, return 0 on success */ 00339 int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) 00340 { 00341 int foundEntry = 0; 00342 int ret = 0; 00343 00344 WOLFSSL_ENTER("CheckCertCRL"); 00345 00346 ret = CheckCertCRLList(crl, cert, &foundEntry); 00347 00348 #ifdef HAVE_CRL_IO 00349 if (foundEntry == 0) { 00350 /* perform embedded lookup */ 00351 if (crl->crlIOCb) { 00352 ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo, 00353 cert->extCrlInfoSz); 00354 if (ret == WOLFSSL_CBIO_ERR_WANT_READ) { 00355 ret = WANT_READ; 00356 } 00357 else if (ret >= 0) { 00358 /* try again */ 00359 ret = CheckCertCRLList(crl, cert, &foundEntry); 00360 } 00361 } 00362 } 00363 #endif 00364 00365 if (foundEntry == 0) { 00366 WOLFSSL_MSG("Couldn't find CRL for status check"); 00367 ret = CRL_MISSING; 00368 00369 if (crl->cm->cbMissingCRL) { 00370 char url[256]; 00371 00372 WOLFSSL_MSG("Issuing missing CRL callback"); 00373 url[0] = '\0'; 00374 if (cert->extCrlInfo) { 00375 if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) { 00376 XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz); 00377 url[cert->extCrlInfoSz] = '\0'; 00378 } 00379 else { 00380 WOLFSSL_MSG("CRL url too long"); 00381 } 00382 } 00383 00384 crl->cm->cbMissingCRL(url); 00385 } 00386 } 00387 00388 return ret; 00389 } 00390 00391 00392 /* Add Decoded CRL, 0 on success */ 00393 static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, 00394 int verified) 00395 { 00396 CRL_Entry* crle; 00397 00398 WOLFSSL_ENTER("AddCRL"); 00399 00400 crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00401 if (crle == NULL) { 00402 WOLFSSL_MSG("alloc CRL Entry failed"); 00403 return -1; 00404 } 00405 00406 if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) { 00407 WOLFSSL_MSG("Init CRL Entry failed"); 00408 XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00409 return -1; 00410 } 00411 00412 if (wc_LockMutex(&crl->crlLock) != 0) { 00413 WOLFSSL_MSG("wc_LockMutex failed"); 00414 FreeCRL_Entry(crle, crl->heap); 00415 XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); 00416 return BAD_MUTEX_E; 00417 } 00418 crle->next = crl->crlList; 00419 crl->crlList = crle; 00420 wc_UnLockMutex(&crl->crlLock); 00421 00422 return 0; 00423 } 00424 00425 00426 /* Load CRL File of type, WOLFSSL_SUCCESS on ok */ 00427 int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type, 00428 int verify) 00429 { 00430 int ret = WOLFSSL_SUCCESS; 00431 const byte* myBuffer = buff; /* if DER ok, otherwise switch */ 00432 DerBuffer* der = NULL; 00433 #ifdef WOLFSSL_SMALL_STACK 00434 DecodedCRL* dcrl; 00435 #else 00436 DecodedCRL dcrl[1]; 00437 #endif 00438 00439 WOLFSSL_ENTER("BufferLoadCRL"); 00440 00441 if (crl == NULL || buff == NULL || sz == 0) 00442 return BAD_FUNC_ARG; 00443 00444 if (type == WOLFSSL_FILETYPE_PEM) { 00445 #ifdef WOLFSSL_PEM_TO_DER 00446 ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL); 00447 if (ret == 0) { 00448 myBuffer = der->buffer; 00449 sz = der->length; 00450 } 00451 else { 00452 WOLFSSL_MSG("Pem to Der failed"); 00453 FreeDer(&der); 00454 return -1; 00455 } 00456 #else 00457 ret = NOT_COMPILED_IN; 00458 #endif 00459 } 00460 00461 #ifdef WOLFSSL_SMALL_STACK 00462 dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); 00463 if (dcrl == NULL) { 00464 FreeDer(&der); 00465 return MEMORY_E; 00466 } 00467 #endif 00468 00469 InitDecodedCRL(dcrl, crl->heap); 00470 ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm); 00471 if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) { 00472 WOLFSSL_MSG("ParseCRL error"); 00473 } 00474 else { 00475 ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E); 00476 if (ret != 0) { 00477 WOLFSSL_MSG("AddCRL error"); 00478 } 00479 } 00480 00481 FreeDecodedCRL(dcrl); 00482 00483 #ifdef WOLFSSL_SMALL_STACK 00484 XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00485 #endif 00486 00487 FreeDer(&der); 00488 00489 return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */ 00490 } 00491 00492 #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) 00493 int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl) 00494 { 00495 CRL_Entry *crle; 00496 WOLFSSL_CRL *crl; 00497 00498 WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl"); 00499 if (store == NULL || newcrl == NULL) 00500 return BAD_FUNC_ARG; 00501 00502 crl = store->crl; 00503 crle = newcrl->crlList; 00504 00505 if (wc_LockMutex(&crl->crlLock) != 0) 00506 { 00507 WOLFSSL_MSG("wc_LockMutex failed"); 00508 return BAD_MUTEX_E; 00509 } 00510 crle->next = crl->crlList; 00511 crl->crlList = crle; 00512 newcrl->crlList = NULL; 00513 wc_UnLockMutex(&crl->crlLock); 00514 00515 WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS); 00516 00517 return WOLFSSL_SUCCESS; 00518 } 00519 #endif 00520 00521 #ifdef HAVE_CRL_MONITOR 00522 00523 00524 /* Signal Monitor thread is setup, save status to setup flag, 0 on success */ 00525 static int SignalSetup(WOLFSSL_CRL* crl, int status) 00526 { 00527 int ret; 00528 00529 /* signal to calling thread we're setup */ 00530 if (wc_LockMutex(&crl->crlLock) != 0) { 00531 WOLFSSL_MSG("wc_LockMutex crlLock failed"); 00532 return BAD_MUTEX_E; 00533 } 00534 00535 crl->setup = status; 00536 ret = pthread_cond_signal(&crl->cond); 00537 00538 wc_UnLockMutex(&crl->crlLock); 00539 00540 if (ret != 0) 00541 return BAD_COND_E; 00542 00543 return 0; 00544 } 00545 00546 00547 /* read in new CRL entries and save new list */ 00548 static int SwapLists(WOLFSSL_CRL* crl) 00549 { 00550 int ret; 00551 CRL_Entry* newList; 00552 #ifdef WOLFSSL_SMALL_STACK 00553 WOLFSSL_CRL* tmp; 00554 #else 00555 WOLFSSL_CRL tmp[1]; 00556 #endif 00557 00558 #ifdef WOLFSSL_SMALL_STACK 00559 tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); 00560 if (tmp == NULL) 00561 return MEMORY_E; 00562 #endif 00563 00564 if (InitCRL(tmp, crl->cm) < 0) { 00565 WOLFSSL_MSG("Init tmp CRL failed"); 00566 #ifdef WOLFSSL_SMALL_STACK 00567 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00568 #endif 00569 return -1; 00570 } 00571 00572 if (crl->monitors[0].path) { 00573 ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0); 00574 if (ret != WOLFSSL_SUCCESS) { 00575 WOLFSSL_MSG("PEM LoadCRL on dir change failed"); 00576 FreeCRL(tmp, 0); 00577 #ifdef WOLFSSL_SMALL_STACK 00578 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00579 #endif 00580 return -1; 00581 } 00582 } 00583 00584 if (crl->monitors[1].path) { 00585 ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0); 00586 if (ret != WOLFSSL_SUCCESS) { 00587 WOLFSSL_MSG("DER LoadCRL on dir change failed"); 00588 FreeCRL(tmp, 0); 00589 #ifdef WOLFSSL_SMALL_STACK 00590 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00591 #endif 00592 return -1; 00593 } 00594 } 00595 00596 if (wc_LockMutex(&crl->crlLock) != 0) { 00597 WOLFSSL_MSG("wc_LockMutex failed"); 00598 FreeCRL(tmp, 0); 00599 #ifdef WOLFSSL_SMALL_STACK 00600 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00601 #endif 00602 return -1; 00603 } 00604 00605 newList = tmp->crlList; 00606 00607 /* swap lists */ 00608 tmp->crlList = crl->crlList; 00609 crl->crlList = newList; 00610 00611 wc_UnLockMutex(&crl->crlLock); 00612 00613 FreeCRL(tmp, 0); 00614 00615 #ifdef WOLFSSL_SMALL_STACK 00616 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00617 #endif 00618 00619 return 0; 00620 } 00621 00622 00623 #if (defined(__MACH__) || defined(__FreeBSD__)) 00624 00625 #include <sys/types.h> 00626 #include <sys/event.h> 00627 #include <sys/time.h> 00628 #include <fcntl.h> 00629 #include <unistd.h> 00630 00631 #ifdef __MACH__ 00632 #define XEVENT_MODE O_EVTONLY 00633 #elif defined(__FreeBSD__) 00634 #define XEVENT_MODE EVFILT_VNODE 00635 #endif 00636 00637 00638 /* we need a unique kqueue user filter fd for crl in case user is doing custom 00639 * events too */ 00640 #ifndef CRL_CUSTOM_FD 00641 #define CRL_CUSTOM_FD 123456 00642 #endif 00643 00644 00645 /* shutdown monitor thread, 0 on success */ 00646 static int StopMonitor(int mfd) 00647 { 00648 struct kevent change; 00649 00650 /* trigger custom shutdown */ 00651 EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); 00652 if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) { 00653 WOLFSSL_MSG("kevent trigger customer event failed"); 00654 return -1; 00655 } 00656 00657 return 0; 00658 } 00659 00660 00661 /* OS X monitoring */ 00662 static void* DoMonitor(void* arg) 00663 { 00664 int fPEM, fDER; 00665 struct kevent change; 00666 00667 WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg; 00668 00669 WOLFSSL_ENTER("DoMonitor"); 00670 00671 crl->mfd = kqueue(); 00672 if (crl->mfd == -1) { 00673 WOLFSSL_MSG("kqueue failed"); 00674 SignalSetup(crl, MONITOR_SETUP_E); 00675 return NULL; 00676 } 00677 00678 /* listen for custom shutdown event */ 00679 EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL); 00680 if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) { 00681 WOLFSSL_MSG("kevent monitor customer event failed"); 00682 SignalSetup(crl, MONITOR_SETUP_E); 00683 close(crl->mfd); 00684 return NULL; 00685 } 00686 00687 fPEM = -1; 00688 fDER = -1; 00689 00690 if (crl->monitors[0].path) { 00691 fPEM = open(crl->monitors[0].path, XEVENT_MODE); 00692 if (fPEM == -1) { 00693 WOLFSSL_MSG("PEM event dir open failed"); 00694 SignalSetup(crl, MONITOR_SETUP_E); 00695 close(crl->mfd); 00696 return NULL; 00697 } 00698 } 00699 00700 if (crl->monitors[1].path) { 00701 fDER = open(crl->monitors[1].path, XEVENT_MODE); 00702 if (fDER == -1) { 00703 WOLFSSL_MSG("DER event dir open failed"); 00704 if (fPEM != -1) 00705 close(fPEM); 00706 close(crl->mfd); 00707 SignalSetup(crl, MONITOR_SETUP_E); 00708 return NULL; 00709 } 00710 } 00711 00712 if (fPEM != -1) 00713 EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, 00714 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0); 00715 00716 if (fDER != -1) 00717 EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, 00718 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0); 00719 00720 /* signal to calling thread we're setup */ 00721 if (SignalSetup(crl, 1) != 0) { 00722 if (fPEM != -1) 00723 close(fPEM); 00724 if (fDER != -1) 00725 close(fDER); 00726 close(crl->mfd); 00727 return NULL; 00728 } 00729 00730 for (;;) { 00731 struct kevent event; 00732 int numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL); 00733 00734 WOLFSSL_MSG("Got kevent"); 00735 00736 if (numEvents == -1) { 00737 WOLFSSL_MSG("kevent problem, continue"); 00738 continue; 00739 } 00740 00741 if (event.filter == EVFILT_USER) { 00742 WOLFSSL_MSG("Got user shutdown event, breaking out"); 00743 break; 00744 } 00745 00746 if (SwapLists(crl) < 0) { 00747 WOLFSSL_MSG("SwapLists problem, continue"); 00748 } 00749 } 00750 00751 if (fPEM != -1) 00752 close(fPEM); 00753 if (fDER != -1) 00754 close(fDER); 00755 00756 close(crl->mfd); 00757 00758 return NULL; 00759 } 00760 00761 00762 #elif defined(__linux__) 00763 00764 #include <sys/types.h> 00765 #include <sys/inotify.h> 00766 #include <sys/eventfd.h> 00767 #include <unistd.h> 00768 00769 00770 #ifndef max 00771 static WC_INLINE int max(int a, int b) 00772 { 00773 return a > b ? a : b; 00774 } 00775 #endif /* max */ 00776 00777 00778 /* shutdown monitor thread, 0 on success */ 00779 static int StopMonitor(int mfd) 00780 { 00781 word64 w64 = 1; 00782 00783 /* write to our custom event */ 00784 if (write(mfd, &w64, sizeof(w64)) < 0) { 00785 WOLFSSL_MSG("StopMonitor write failed"); 00786 return -1; 00787 } 00788 00789 return 0; 00790 } 00791 00792 00793 /* linux monitoring */ 00794 static void* DoMonitor(void* arg) 00795 { 00796 int notifyFd; 00797 int wd = -1; 00798 WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg; 00799 #ifdef WOLFSSL_SMALL_STACK 00800 char* buff; 00801 #else 00802 char buff[8192]; 00803 #endif 00804 00805 WOLFSSL_ENTER("DoMonitor"); 00806 00807 crl->mfd = eventfd(0, 0); /* our custom shutdown event */ 00808 if (crl->mfd < 0) { 00809 WOLFSSL_MSG("eventfd failed"); 00810 SignalSetup(crl, MONITOR_SETUP_E); 00811 return NULL; 00812 } 00813 00814 notifyFd = inotify_init(); 00815 if (notifyFd < 0) { 00816 WOLFSSL_MSG("inotify failed"); 00817 close(crl->mfd); 00818 SignalSetup(crl, MONITOR_SETUP_E); 00819 return NULL; 00820 } 00821 00822 if (crl->monitors[0].path) { 00823 wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE | 00824 IN_DELETE); 00825 if (wd < 0) { 00826 WOLFSSL_MSG("PEM notify add watch failed"); 00827 close(crl->mfd); 00828 close(notifyFd); 00829 SignalSetup(crl, MONITOR_SETUP_E); 00830 return NULL; 00831 } 00832 } 00833 00834 if (crl->monitors[1].path) { 00835 wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE | 00836 IN_DELETE); 00837 if (wd < 0) { 00838 WOLFSSL_MSG("DER notify add watch failed"); 00839 close(crl->mfd); 00840 close(notifyFd); 00841 SignalSetup(crl, MONITOR_SETUP_E); 00842 return NULL; 00843 } 00844 } 00845 00846 #ifdef WOLFSSL_SMALL_STACK 00847 buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00848 if (buff == NULL) 00849 return NULL; 00850 #endif 00851 00852 /* signal to calling thread we're setup */ 00853 if (SignalSetup(crl, 1) != 0) { 00854 #ifdef WOLFSSL_SMALL_STACK 00855 XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00856 #endif 00857 00858 if (wd > 0) 00859 inotify_rm_watch(notifyFd, wd); 00860 close(crl->mfd); 00861 close(notifyFd); 00862 return NULL; 00863 } 00864 00865 for (;;) { 00866 fd_set readfds; 00867 int result; 00868 int length; 00869 00870 FD_ZERO(&readfds); 00871 FD_SET(notifyFd, &readfds); 00872 FD_SET(crl->mfd, &readfds); 00873 00874 result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL); 00875 00876 WOLFSSL_MSG("Got notify event"); 00877 00878 if (result < 0) { 00879 WOLFSSL_MSG("select problem, continue"); 00880 continue; 00881 } 00882 00883 if (FD_ISSET(crl->mfd, &readfds)) { 00884 WOLFSSL_MSG("got custom shutdown event, breaking out"); 00885 break; 00886 } 00887 00888 length = (int) read(notifyFd, buff, 8192); 00889 if (length < 0) { 00890 WOLFSSL_MSG("notify read problem, continue"); 00891 continue; 00892 } 00893 00894 if (SwapLists(crl) < 0) { 00895 WOLFSSL_MSG("SwapLists problem, continue"); 00896 } 00897 } 00898 00899 #ifdef WOLFSSL_SMALL_STACK 00900 XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00901 #endif 00902 00903 if (wd > 0) 00904 inotify_rm_watch(notifyFd, wd); 00905 close(crl->mfd); 00906 close(notifyFd); 00907 00908 return NULL; 00909 } 00910 00911 #endif /* MACH or linux */ 00912 00913 00914 /* Start Monitoring the CRL path(s) in a thread */ 00915 static int StartMonitorCRL(WOLFSSL_CRL* crl) 00916 { 00917 int ret = WOLFSSL_SUCCESS; 00918 00919 WOLFSSL_ENTER("StartMonitorCRL"); 00920 00921 if (crl == NULL) 00922 return BAD_FUNC_ARG; 00923 00924 if (crl->tid != 0) { 00925 WOLFSSL_MSG("Monitor thread already running"); 00926 return ret; /* that's ok, someone already started */ 00927 } 00928 00929 if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) { 00930 WOLFSSL_MSG("Thread creation error"); 00931 return THREAD_CREATE_E; 00932 } 00933 00934 /* wait for setup to complete */ 00935 if (wc_LockMutex(&crl->crlLock) != 0) { 00936 WOLFSSL_MSG("wc_LockMutex crlLock error"); 00937 return BAD_MUTEX_E; 00938 } 00939 00940 while (crl->setup == 0) { 00941 if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) { 00942 ret = BAD_COND_E; 00943 break; 00944 } 00945 } 00946 00947 if (crl->setup < 0) 00948 ret = crl->setup; /* store setup error */ 00949 00950 wc_UnLockMutex(&crl->crlLock); 00951 00952 if (ret < 0) { 00953 WOLFSSL_MSG("DoMonitor setup failure"); 00954 crl->tid = 0; /* thread already done */ 00955 } 00956 00957 return ret; 00958 } 00959 00960 00961 #else /* HAVE_CRL_MONITOR */ 00962 00963 #ifndef NO_FILESYSTEM 00964 00965 static int StartMonitorCRL(WOLFSSL_CRL* crl) 00966 { 00967 (void)crl; 00968 00969 WOLFSSL_ENTER("StartMonitorCRL"); 00970 WOLFSSL_MSG("Not compiled in"); 00971 00972 return NOT_COMPILED_IN; 00973 } 00974 00975 #endif /* NO_FILESYSTEM */ 00976 00977 #endif /* HAVE_CRL_MONITOR */ 00978 00979 #if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) 00980 00981 /* Load CRL path files of type, WOLFSSL_SUCCESS on ok */ 00982 int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) 00983 { 00984 int ret = WOLFSSL_SUCCESS; 00985 char* name = NULL; 00986 #ifdef WOLFSSL_SMALL_STACK 00987 ReadDirCtx* readCtx = NULL; 00988 #else 00989 ReadDirCtx readCtx[1]; 00990 #endif 00991 00992 WOLFSSL_ENTER("LoadCRL"); 00993 if (crl == NULL) 00994 return BAD_FUNC_ARG; 00995 00996 #ifdef WOLFSSL_SMALL_STACK 00997 readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap, 00998 DYNAMIC_TYPE_TMP_BUFFER); 00999 if (readCtx == NULL) 01000 return MEMORY_E; 01001 #endif 01002 01003 /* try to load each regular file in path */ 01004 ret = wc_ReadDirFirst(readCtx, path, &name); 01005 while (ret == 0 && name) { 01006 int skip = 0; 01007 if (type == WOLFSSL_FILETYPE_PEM) { 01008 if (XSTRSTR(name, ".pem") == NULL) { 01009 WOLFSSL_MSG("not .pem file, skipping"); 01010 skip = 1; 01011 } 01012 } 01013 else { 01014 if (XSTRSTR(name, ".der") == NULL && 01015 XSTRSTR(name, ".crl") == NULL) 01016 { 01017 WOLFSSL_MSG("not .der or .crl file, skipping"); 01018 skip = 1; 01019 } 01020 } 01021 01022 if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl, 01023 VERIFY) != WOLFSSL_SUCCESS) { 01024 WOLFSSL_MSG("CRL file load failed, continuing"); 01025 } 01026 01027 ret = wc_ReadDirNext(readCtx, path, &name); 01028 } 01029 wc_ReadDirClose(readCtx); 01030 ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */ 01031 01032 #ifdef WOLFSSL_SMALL_STACK 01033 XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); 01034 #endif 01035 01036 if (monitor & WOLFSSL_CRL_MONITOR) { 01037 word32 pathLen; 01038 char* pathBuf; 01039 01040 WOLFSSL_MSG("monitor path requested"); 01041 01042 pathLen = (word32)XSTRLEN(path); 01043 pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR); 01044 if (pathBuf) { 01045 XSTRNCPY(pathBuf, path, pathLen+1); 01046 01047 if (type == WOLFSSL_FILETYPE_PEM) { 01048 /* free old path before setting a new one */ 01049 if (crl->monitors[0].path) { 01050 XFREE(crl->monitors[0].path, crl->heap, 01051 DYNAMIC_TYPE_CRL_MONITOR); 01052 } 01053 crl->monitors[0].path = pathBuf; 01054 crl->monitors[0].type = WOLFSSL_FILETYPE_PEM; 01055 } else { 01056 /* free old path before setting a new one */ 01057 if (crl->monitors[1].path) { 01058 XFREE(crl->monitors[1].path, crl->heap, 01059 DYNAMIC_TYPE_CRL_MONITOR); 01060 } 01061 crl->monitors[1].path = pathBuf; 01062 crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1; 01063 } 01064 01065 if (monitor & WOLFSSL_CRL_START_MON) { 01066 WOLFSSL_MSG("start monitoring requested"); 01067 01068 ret = StartMonitorCRL(crl); 01069 } 01070 } 01071 else { 01072 ret = MEMORY_E; 01073 } 01074 } 01075 01076 return ret; 01077 } 01078 01079 #else 01080 int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) 01081 { 01082 (void)crl; 01083 (void)path; 01084 (void)type; 01085 (void)monitor; 01086 01087 /* stub for scenario where file system is not supported */ 01088 return NOT_COMPILED_IN; 01089 } 01090 #endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ 01091 01092 #endif /* HAVE_CRL */ 01093 #endif /* !WOLFCRYPT_ONLY */ 01094
Generated on Tue Jul 12 2022 20:58:34 by
1.7.2