CyaSSL 3.0.0

Dependents:   HTTPClient-SSL HTTPClient HTTPClient-SSL http_access ... more

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     OcspRequest ocspRequest;
00111     OcspResponse ocspResponse;
00112     int result = -1;
00113     OCSP_Entry* ocspe;
00114     CertStatus* certStatus = NULL;
00115     CertStatus newStatus;
00116     const char *url;
00117     int urlSz;
00118 
00119     CYASSL_ENTER("CheckCertOCSP");
00120 
00121     if (LockMutex(&ocsp->ocspLock) != 0) {
00122         CYASSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
00123         return BAD_MUTEX_E;
00124     }
00125 
00126     ocspe = ocsp->ocspList;
00127     while (ocspe) {
00128         if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
00129             && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash,
00130                                                         SHA_DIGEST_SIZE) == 0)
00131             break;
00132         else
00133             ocspe = ocspe->next;
00134     }
00135 
00136     if (ocspe == NULL) {
00137         ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
00138                                                 NULL, DYNAMIC_TYPE_OCSP_ENTRY);
00139         if (ocspe != NULL) {
00140             InitOCSP_Entry(ocspe, cert);
00141             ocspe->next = ocsp->ocspList;
00142             ocsp->ocspList = ocspe;
00143         }
00144         else {
00145             UnLockMutex(&ocsp->ocspLock);
00146             CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
00147             return MEMORY_ERROR;
00148         }
00149     }
00150     else {
00151         certStatus = ocspe->status;
00152         while (certStatus) {
00153             if (certStatus->serialSz == cert->serialSz &&
00154                  XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0)
00155                 break;
00156             else
00157                 certStatus = certStatus->next;
00158         }
00159     }
00160 
00161     if (certStatus != NULL) {
00162         if (!ValidateDate(certStatus->thisDate,
00163                                         certStatus->thisDateFormat, BEFORE) ||
00164             (certStatus->nextDate[0] == 0) ||
00165             !ValidateDate(certStatus->nextDate,
00166                                         certStatus->nextDateFormat, AFTER)) {
00167             CYASSL_MSG("\tinvalid status date, looking up cert");
00168         }
00169         else {
00170             result = xstat2err(certStatus->status);
00171             UnLockMutex(&ocsp->ocspLock);
00172             CYASSL_LEAVE("CheckCertOCSP", result);
00173             return result;
00174         }
00175     }
00176 
00177     UnLockMutex(&ocsp->ocspLock);
00178 
00179     if (ocsp->cm->ocspUseOverrideURL) {
00180         url = ocsp->cm->ocspOverrideURL;
00181         if (url != NULL && url[0] != '\0')
00182             urlSz = (int)XSTRLEN(url);
00183         else
00184             return OCSP_NEED_URL;
00185     }
00186     else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
00187         url = (const char *)cert->extAuthInfo;
00188         urlSz = cert->extAuthInfoSz;
00189     }
00190     else {
00191         /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
00192         return 0;
00193     }
00194 
00195     ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
00196     if (ocspReqBuf == NULL) {
00197         CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
00198         return MEMORY_ERROR;
00199     }
00200     InitOcspRequest(&ocspRequest, cert, ocsp->cm->ocspSendNonce,
00201                                                          ocspReqBuf, ocspReqSz);
00202     ocspReqSz = EncodeOcspRequest(&ocspRequest);
00203     
00204     if (ocsp->cm->ocspIOCb)
00205         result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
00206                                            ocspReqBuf, ocspReqSz, &ocspRespBuf);
00207 
00208     if (result >= 0 && ocspRespBuf) {
00209         XMEMSET(&newStatus, 0, sizeof(CertStatus));
00210 
00211         InitOcspResponse(&ocspResponse, &newStatus, ocspRespBuf, result);
00212         OcspResponseDecode(&ocspResponse);
00213     
00214         if (ocspResponse.responseStatus != OCSP_SUCCESSFUL)
00215             result = OCSP_LOOKUP_FAIL;
00216         else {
00217             if (CompareOcspReqResp(&ocspRequest, &ocspResponse) == 0) {
00218                 result = xstat2err(ocspResponse.status->status);
00219 
00220                 if (LockMutex(&ocsp->ocspLock) != 0)
00221                     result = BAD_MUTEX_E;
00222                 else {
00223                     if (certStatus != NULL)
00224                         /* Replace existing certificate entry with updated */
00225                         XMEMCPY(certStatus, &newStatus, sizeof(CertStatus));
00226                     else {
00227                         /* Save new certificate entry */
00228                         certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus),
00229                                           NULL, DYNAMIC_TYPE_OCSP_STATUS);
00230                         if (certStatus != NULL) {
00231                             XMEMCPY(certStatus, &newStatus, sizeof(CertStatus));
00232                             certStatus->next = ocspe->status;
00233                             ocspe->status = certStatus;
00234                             ocspe->totalStatus++;
00235                         }
00236                     }
00237 
00238                     UnLockMutex(&ocsp->ocspLock);
00239                 }
00240             }
00241             else
00242                 result = OCSP_LOOKUP_FAIL;
00243         }
00244     }
00245     else
00246         result = OCSP_LOOKUP_FAIL;
00247 
00248     if (ocspReqBuf != NULL)
00249         XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
00250 
00251     if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb)
00252         ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf);
00253 
00254     CYASSL_LEAVE("CheckCertOCSP", result);
00255     return result;
00256 }
00257 
00258 
00259 #else /* HAVE_OCSP */
00260 
00261 
00262 #ifdef _MSC_VER
00263     /* 4206 warning for blank file */
00264     #pragma warning(disable: 4206)
00265 #endif
00266 
00267 
00268 #endif /* HAVE_OCSP */
00269 
00270