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.
ocsp.c
00001 /* ocsp.c 00002 * 00003 * Copyright (C) 2006-2016 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 to be 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_OCSP 00033 00034 #include <wolfssl/error-ssl.h> 00035 #include <wolfssl/ocsp.h> 00036 #include <wolfssl/internal.h> 00037 00038 #ifdef NO_INLINE 00039 #include <wolfssl/wolfcrypt/misc.h> 00040 #else 00041 #include <wolfcrypt/src/misc.c> 00042 #endif 00043 00044 00045 int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm) 00046 { 00047 WOLFSSL_ENTER("InitOCSP"); 00048 00049 ForceZero(ocsp, sizeof(WOLFSSL_OCSP)); 00050 00051 if (InitMutex(&ocsp->ocspLock) != 0) 00052 return BAD_MUTEX_E; 00053 00054 ocsp->cm = cm; 00055 00056 return 0; 00057 } 00058 00059 00060 static int InitOcspEntry(OcspEntry* entry, OcspRequest* request) 00061 { 00062 WOLFSSL_ENTER("InitOcspEntry"); 00063 00064 ForceZero(entry, sizeof(OcspEntry)); 00065 00066 XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE); 00067 XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE); 00068 00069 return 0; 00070 } 00071 00072 00073 static void FreeOcspEntry(OcspEntry* entry) 00074 { 00075 CertStatus *status, *next; 00076 00077 WOLFSSL_ENTER("FreeOcspEntry"); 00078 00079 for (status = entry->status; status; status = next) { 00080 next = status->next; 00081 00082 if (status->rawOcspResponse) 00083 XFREE(status->rawOcspResponse, NULL, DYNAMIC_TYPE_OCSP_STATUS); 00084 00085 XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); 00086 } 00087 } 00088 00089 00090 void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic) 00091 { 00092 OcspEntry *entry, *next; 00093 00094 WOLFSSL_ENTER("FreeOCSP"); 00095 00096 for (entry = ocsp->ocspList; entry; entry = next) { 00097 next = entry->next; 00098 FreeOcspEntry(entry); 00099 XFREE(entry, NULL, DYNAMIC_TYPE_OCSP_ENTRY); 00100 } 00101 00102 FreeMutex(&ocsp->ocspLock); 00103 00104 if (dynamic) 00105 XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP); 00106 } 00107 00108 00109 static int xstat2err(int stat) 00110 { 00111 switch (stat) { 00112 case CERT_GOOD: 00113 return 0; 00114 case CERT_REVOKED: 00115 return OCSP_CERT_REVOKED; 00116 default: 00117 return OCSP_CERT_UNKNOWN; 00118 } 00119 } 00120 00121 00122 int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer) 00123 { 00124 int ret = OCSP_LOOKUP_FAIL; 00125 00126 #ifdef WOLFSSL_SMALL_STACK 00127 OcspRequest* ocspRequest; 00128 #else 00129 OcspRequest ocspRequest[1]; 00130 #endif 00131 00132 WOLFSSL_ENTER("CheckCertOCSP"); 00133 00134 00135 #ifdef WOLFSSL_SMALL_STACK 00136 ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, 00137 DYNAMIC_TYPE_TMP_BUFFER); 00138 if (ocspRequest == NULL) { 00139 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); 00140 return MEMORY_E; 00141 } 00142 #endif 00143 00144 if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce) == 0) { 00145 ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer); 00146 00147 FreeOcspRequest(ocspRequest); 00148 } 00149 00150 #ifdef WOLFSSL_SMALL_STACK 00151 XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00152 #endif 00153 00154 WOLFSSL_LEAVE("CheckCertOCSP", ret); 00155 return ret; 00156 } 00157 00158 static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request, 00159 OcspEntry** entry) 00160 { 00161 WOLFSSL_ENTER("GetOcspEntry"); 00162 00163 *entry = NULL; 00164 00165 if (LockMutex(&ocsp->ocspLock) != 0) { 00166 WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); 00167 return BAD_MUTEX_E; 00168 } 00169 00170 for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next) 00171 if (XMEMCMP((*entry)->issuerHash, request->issuerHash, 00172 OCSP_DIGEST_SIZE) == 0 00173 && XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash, 00174 OCSP_DIGEST_SIZE) == 0) 00175 break; 00176 00177 if (*entry == NULL) { 00178 *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry), 00179 NULL, DYNAMIC_TYPE_OCSP_ENTRY); 00180 if (*entry) { 00181 InitOcspEntry(*entry, request); 00182 (*entry)->next = ocsp->ocspList; 00183 ocsp->ocspList = *entry; 00184 } 00185 } 00186 00187 UnLockMutex(&ocsp->ocspLock); 00188 00189 return *entry ? 0 : MEMORY_ERROR; 00190 } 00191 00192 00193 static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, 00194 OcspEntry* entry, CertStatus** status, buffer* responseBuffer) 00195 { 00196 int ret = OCSP_INVALID_STATUS; 00197 00198 WOLFSSL_ENTER("GetOcspStatus"); 00199 00200 *status = NULL; 00201 00202 if (LockMutex(&ocsp->ocspLock) != 0) { 00203 WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); 00204 return BAD_MUTEX_E; 00205 } 00206 00207 for (*status = entry->status; *status; *status = (*status)->next) 00208 if ((*status)->serialSz == request->serialSz 00209 && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz)) 00210 break; 00211 00212 if (responseBuffer && *status && !(*status)->rawOcspResponse) { 00213 /* force fetching again */ 00214 ret = OCSP_INVALID_STATUS; 00215 } 00216 else if (*status) { 00217 if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE) 00218 && ((*status)->nextDate[0] != 0) 00219 && ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER)) 00220 { 00221 ret = xstat2err((*status)->status); 00222 00223 if (responseBuffer) { 00224 responseBuffer->buffer = (byte*)XMALLOC( 00225 (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00226 00227 if (responseBuffer->buffer) { 00228 responseBuffer->length = (*status)->rawOcspResponseSz; 00229 XMEMCPY(responseBuffer->buffer, 00230 (*status)->rawOcspResponse, 00231 (*status)->rawOcspResponseSz); 00232 } 00233 } 00234 } 00235 } 00236 00237 UnLockMutex(&ocsp->ocspLock); 00238 00239 return ret; 00240 } 00241 00242 int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, 00243 buffer* responseBuffer) 00244 { 00245 OcspEntry* entry = NULL; 00246 CertStatus* status = NULL; 00247 byte* request = NULL; 00248 int requestSz = 2048; 00249 byte* response = NULL; 00250 const char* url = NULL; 00251 int urlSz = 0; 00252 int ret = -1; 00253 00254 #ifdef WOLFSSL_SMALL_STACK 00255 CertStatus* newStatus; 00256 OcspResponse* ocspResponse; 00257 #else 00258 CertStatus newStatus[1]; 00259 OcspResponse ocspResponse[1]; 00260 #endif 00261 00262 WOLFSSL_ENTER("CheckOcspRequest"); 00263 00264 if (responseBuffer) { 00265 responseBuffer->buffer = NULL; 00266 responseBuffer->length = 0; 00267 } 00268 00269 ret = GetOcspEntry(ocsp, ocspRequest, &entry); 00270 if (ret != 0) 00271 return ret; 00272 00273 ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer); 00274 if (ret != OCSP_INVALID_STATUS) 00275 return ret; 00276 00277 if (ocsp->cm->ocspUseOverrideURL) { 00278 url = ocsp->cm->ocspOverrideURL; 00279 if (url != NULL && url[0] != '\0') 00280 urlSz = (int)XSTRLEN(url); 00281 else 00282 return OCSP_NEED_URL; 00283 } 00284 else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) { 00285 url = (const char *)ocspRequest->url; 00286 urlSz = ocspRequest->urlSz; 00287 } 00288 else { 00289 /* cert doesn't have extAuthInfo, assuming CERT_GOOD */ 00290 return 0; 00291 } 00292 00293 request = (byte*)XMALLOC(requestSz, NULL, DYNAMIC_TYPE_OCSP); 00294 if (request == NULL) { 00295 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); 00296 return MEMORY_ERROR; 00297 } 00298 00299 #ifdef WOLFSSL_SMALL_STACK 00300 newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, 00301 DYNAMIC_TYPE_TMP_BUFFER); 00302 ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, 00303 DYNAMIC_TYPE_TMP_BUFFER); 00304 00305 if (newStatus == NULL || ocspResponse == NULL) { 00306 if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00307 if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00308 00309 XFREE(request, NULL, DYNAMIC_TYPE_OCSP); 00310 00311 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); 00312 return MEMORY_E; 00313 } 00314 #endif 00315 00316 requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); 00317 00318 if (ocsp->cm->ocspIOCb) 00319 ret = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, 00320 request, requestSz, &response); 00321 00322 if (ret >= 0 && response) { 00323 XMEMSET(newStatus, 0, sizeof(CertStatus)); 00324 00325 InitOcspResponse(ocspResponse, newStatus, response, ret); 00326 OcspResponseDecode(ocspResponse, ocsp->cm); 00327 00328 if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) 00329 ret = OCSP_LOOKUP_FAIL; 00330 else { 00331 if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { 00332 if (responseBuffer) { 00333 responseBuffer->buffer = (byte*)XMALLOC(ret, NULL, 00334 DYNAMIC_TYPE_TMP_BUFFER); 00335 00336 if (responseBuffer->buffer) { 00337 responseBuffer->length = ret; 00338 XMEMCPY(responseBuffer->buffer, response, ret); 00339 } 00340 } 00341 00342 ret = xstat2err(ocspResponse->status->status); 00343 00344 if (LockMutex(&ocsp->ocspLock) != 0) 00345 ret = BAD_MUTEX_E; 00346 else { 00347 if (status != NULL) { 00348 if (status->rawOcspResponse) 00349 XFREE(status->rawOcspResponse, NULL, 00350 DYNAMIC_TYPE_OCSP_STATUS); 00351 00352 /* Replace existing certificate entry with updated */ 00353 XMEMCPY(status, newStatus, sizeof(CertStatus)); 00354 } 00355 else { 00356 /* Save new certificate entry */ 00357 status = (CertStatus*)XMALLOC(sizeof(CertStatus), 00358 NULL, DYNAMIC_TYPE_OCSP_STATUS); 00359 if (status != NULL) { 00360 XMEMCPY(status, newStatus, sizeof(CertStatus)); 00361 status->next = entry->status; 00362 entry->status = status; 00363 entry->totalStatus++; 00364 } 00365 } 00366 00367 if (status && responseBuffer && responseBuffer->buffer) { 00368 status->rawOcspResponse = (byte*)XMALLOC( 00369 responseBuffer->length, NULL, 00370 DYNAMIC_TYPE_OCSP_STATUS); 00371 00372 if (status->rawOcspResponse) { 00373 status->rawOcspResponseSz = responseBuffer->length; 00374 XMEMCPY(status->rawOcspResponse, 00375 responseBuffer->buffer, 00376 responseBuffer->length); 00377 } 00378 } 00379 00380 UnLockMutex(&ocsp->ocspLock); 00381 } 00382 } 00383 else 00384 ret = OCSP_LOOKUP_FAIL; 00385 } 00386 } 00387 else 00388 ret = OCSP_LOOKUP_FAIL; 00389 00390 #ifdef WOLFSSL_SMALL_STACK 00391 XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00392 XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00393 #endif 00394 00395 if (response != NULL && ocsp->cm->ocspRespFreeCb) 00396 ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response); 00397 00398 WOLFSSL_LEAVE("CheckOcspRequest", ret); 00399 return ret; 00400 } 00401 00402 00403 #else /* HAVE_OCSP */ 00404 00405 00406 #ifdef _MSC_VER 00407 /* 4206 warning for blank file */ 00408 #pragma warning(disable: 4206) 00409 #endif 00410 00411 00412 #endif /* HAVE_OCSP */ 00413 #endif /* WOLFCRYPT_ONLY */ 00414 00415
Generated on Tue Jul 12 2022 15:55:20 by
 1.7.2
 1.7.2