MultiTech / CyaSSL

Dependents:   HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL

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-2014 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL 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  * CyaSSL 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-1301, USA
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023     #include <config.h>
00024 #endif
00025 
00026 #include <cyassl/ctaocrypt/settings.h>
00027 
00028 #ifdef HAVE_OCSP
00029 
00030 #include <cyassl/error-ssl.h>
00031 #include <cyassl/ocsp.h>
00032 #include <cyassl/internal.h>
00033 
00034 
00035 int InitOCSP(CYASSL_OCSP* ocsp, CYASSL_CERT_MANAGER* cm)
00036 {
00037     CYASSL_ENTER("InitOCSP");
00038     XMEMSET(ocsp, 0, sizeof(*ocsp));
00039     ocsp->cm = cm;
00040     if (InitMutex(&ocsp->ocspLock) != 0)
00041         return BAD_MUTEX_E;
00042 
00043     return 0;
00044 }
00045 
00046 
00047 static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert)
00048 {
00049     CYASSL_ENTER("InitOCSP_Entry");
00050 
00051     XMEMSET(ocspe, 0, sizeof(*ocspe));
00052     XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE);
00053     XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE);
00054 
00055     return 0;
00056 }
00057 
00058 
00059 static void FreeOCSP_Entry(OCSP_Entry* ocspe)
00060 {
00061     CertStatus* tmp = ocspe->status;
00062 
00063     CYASSL_ENTER("FreeOCSP_Entry");
00064 
00065     while (tmp) {
00066         CertStatus* next = tmp->next;
00067         XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
00068         tmp = next;
00069     }
00070 }
00071 
00072 
00073 void FreeOCSP(CYASSL_OCSP* ocsp, int dynamic)
00074 {
00075     OCSP_Entry* tmp = ocsp->ocspList;
00076 
00077     CYASSL_ENTER("FreeOCSP");
00078 
00079     while (tmp) {
00080         OCSP_Entry* next = tmp->next;
00081         FreeOCSP_Entry(tmp);
00082         XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
00083         tmp = next;
00084     }
00085 
00086     FreeMutex(&ocsp->ocspLock);
00087     if (dynamic)
00088         XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP);
00089 }
00090 
00091 
00092 static int xstat2err(int stat)
00093 {
00094     switch (stat) {
00095         case CERT_GOOD:
00096             return 0;
00097         case CERT_REVOKED:
00098             return OCSP_CERT_REVOKED;
00099         default:
00100             return OCSP_CERT_UNKNOWN;
00101     }
00102 }
00103 
00104 
00105 int CheckCertOCSP(CYASSL_OCSP* ocsp, DecodedCert* cert)
00106 {
00107     byte* ocspReqBuf = NULL;
00108     int ocspReqSz = 2048;
00109     byte* ocspRespBuf = NULL;
00110     int result = -1;
00111     OCSP_Entry* ocspe;
00112     CertStatus* certStatus = NULL;
00113     const char *url;
00114     int urlSz;
00115 #ifdef CYASSL_SMALL_STACK
00116     CertStatus* newStatus;
00117     OcspRequest* ocspRequest;
00118     OcspResponse* ocspResponse;
00119 #else
00120     CertStatus newStatus[1];
00121     OcspRequest ocspRequest[1];
00122     OcspResponse ocspResponse[1];
00123 #endif
00124 
00125     CYASSL_ENTER("CheckCertOCSP");
00126 
00127     if (LockMutex(&ocsp->ocspLock) != 0) {
00128         CYASSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
00129         return BAD_MUTEX_E;
00130     }
00131 
00132     ocspe = ocsp->ocspList;
00133     while (ocspe) {
00134         if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
00135             && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash,
00136                                                         SHA_DIGEST_SIZE) == 0)
00137             break;
00138         else
00139             ocspe = ocspe->next;
00140     }
00141 
00142     if (ocspe == NULL) {
00143         ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
00144                                                 NULL, DYNAMIC_TYPE_OCSP_ENTRY);
00145         if (ocspe != NULL) {
00146             InitOCSP_Entry(ocspe, cert);
00147             ocspe->next = ocsp->ocspList;
00148             ocsp->ocspList = ocspe;
00149         }
00150         else {
00151             UnLockMutex(&ocsp->ocspLock);
00152             CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
00153             return MEMORY_ERROR;
00154         }
00155     }
00156     else {
00157         certStatus = ocspe->status;
00158         while (certStatus) {
00159             if (certStatus->serialSz == cert->serialSz &&
00160                  XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0)
00161                 break;
00162             else
00163                 certStatus = certStatus->next;
00164         }
00165     }
00166 
00167     if (certStatus != NULL) {
00168         if (!ValidateDate(certStatus->thisDate,
00169                                         certStatus->thisDateFormat, BEFORE) ||
00170             (certStatus->nextDate[0] == 0) ||
00171             !ValidateDate(certStatus->nextDate,
00172                                         certStatus->nextDateFormat, AFTER)) {
00173             CYASSL_MSG("\tinvalid status date, looking up cert");
00174         }
00175         else {
00176             result = xstat2err(certStatus->status);
00177             UnLockMutex(&ocsp->ocspLock);
00178             CYASSL_LEAVE("CheckCertOCSP", result);
00179             return result;
00180         }
00181     }
00182 
00183     UnLockMutex(&ocsp->ocspLock);
00184 
00185     if (ocsp->cm->ocspUseOverrideURL) {
00186         url = ocsp->cm->ocspOverrideURL;
00187         if (url != NULL && url[0] != '\0')
00188             urlSz = (int)XSTRLEN(url);
00189         else
00190             return OCSP_NEED_URL;
00191     }
00192     else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
00193         url = (const char *)cert->extAuthInfo;
00194         urlSz = cert->extAuthInfoSz;
00195     }
00196     else {
00197         /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
00198         return 0;
00199     }
00200 
00201     ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
00202     if (ocspReqBuf == NULL) {
00203         CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
00204         return MEMORY_ERROR;
00205     }
00206 
00207 #ifdef CYASSL_SMALL_STACK
00208     newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
00209                                                        DYNAMIC_TYPE_TMP_BUFFER);
00210     ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
00211                                                        DYNAMIC_TYPE_TMP_BUFFER);
00212     ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
00213                                                        DYNAMIC_TYPE_TMP_BUFFER);
00214 
00215     if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) {
00216         if (newStatus)    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
00217         if (ocspRequest)  XFREE(ocspRequest,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
00218         if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00219 
00220         XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00221 
00222         CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
00223         return MEMORY_E;
00224     }
00225 #endif
00226 
00227     InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
00228                                                          ocspReqBuf, ocspReqSz);
00229     ocspReqSz = EncodeOcspRequest(ocspRequest);
00230     
00231     if (ocsp->cm->ocspIOCb)
00232         result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
00233                                            ocspReqBuf, ocspReqSz, &ocspRespBuf);
00234 
00235     if (result >= 0 && ocspRespBuf) {
00236         XMEMSET(newStatus, 0, sizeof(CertStatus));
00237 
00238         InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result);
00239         OcspResponseDecode(ocspResponse);
00240     
00241         if (ocspResponse->responseStatus != OCSP_SUCCESSFUL)
00242             result = OCSP_LOOKUP_FAIL;
00243         else {
00244             if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) {
00245                 result = xstat2err(ocspResponse->status->status);
00246 
00247                 if (LockMutex(&ocsp->ocspLock) != 0)
00248                     result = BAD_MUTEX_E;
00249                 else {
00250                     if (certStatus != NULL)
00251                         /* Replace existing certificate entry with updated */
00252                         XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
00253                     else {
00254                         /* Save new certificate entry */
00255                         certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus),
00256                                           NULL, DYNAMIC_TYPE_OCSP_STATUS);
00257                         if (certStatus != NULL) {
00258                             XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
00259                             certStatus->next = ocspe->status;
00260                             ocspe->status = certStatus;
00261                             ocspe->totalStatus++;
00262                         }
00263                     }
00264 
00265                     UnLockMutex(&ocsp->ocspLock);
00266                 }
00267             }
00268             else
00269                 result = OCSP_LOOKUP_FAIL;
00270         }
00271     }
00272     else
00273         result = OCSP_LOOKUP_FAIL;
00274 
00275     XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
00276 
00277 #ifdef CYASSL_SMALL_STACK
00278     XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
00279     XFREE(ocspRequest,  NULL, DYNAMIC_TYPE_TMP_BUFFER);
00280     XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00281 #endif
00282 
00283     if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb)
00284         ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf);
00285 
00286     CYASSL_LEAVE("CheckCertOCSP", result);
00287     return result;
00288 }
00289 
00290 
00291 #else /* HAVE_OCSP */
00292 
00293 
00294 #ifdef _MSC_VER
00295     /* 4206 warning for blank file */
00296     #pragma warning(disable: 4206)
00297 #endif
00298 
00299 
00300 #endif /* HAVE_OCSP */
00301