Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ocsp.c Source File

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