3 * Copyright (C) 2006-2015 wolfSSL Inc.
5 * This file is part of wolfSSL. (formerly known as CyaSSL)
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 /* Name change compatibility layer no longer needs to be included here */
28 #include <wolfssl/wolfcrypt/settings.h>
32 #include <wolfssl/error-ssl.h>
33 #include <wolfssl/ocsp.h>
34 #include <wolfssl/internal.h>
37 int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
39 WOLFSSL_ENTER("InitOCSP");
40 XMEMSET(ocsp, 0, sizeof(*ocsp));
42 if (InitMutex(&ocsp->ocspLock) != 0)
49 static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert)
51 WOLFSSL_ENTER("InitOCSP_Entry");
53 XMEMSET(ocspe, 0, sizeof(*ocspe));
54 XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE);
55 XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE);
61 static void FreeOCSP_Entry(OCSP_Entry* ocspe)
63 CertStatus* tmp = ocspe->status;
65 WOLFSSL_ENTER("FreeOCSP_Entry");
68 CertStatus* next = tmp->next;
69 XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
75 void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
77 OCSP_Entry* tmp = ocsp->ocspList;
79 WOLFSSL_ENTER("FreeOCSP");
82 OCSP_Entry* next = tmp->next;
84 XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
88 FreeMutex(&ocsp->ocspLock);
90 XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP);
94 static int xstat2err(int stat)
100 return OCSP_CERT_REVOKED;
102 return OCSP_CERT_UNKNOWN;
107 int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
109 byte* ocspReqBuf = NULL;
110 int ocspReqSz = 2048;
111 byte* ocspRespBuf = NULL;
114 CertStatus* certStatus = NULL;
117 #ifdef WOLFSSL_SMALL_STACK
118 CertStatus* newStatus;
119 OcspRequest* ocspRequest;
120 OcspResponse* ocspResponse;
122 CertStatus newStatus[1];
123 OcspRequest ocspRequest[1];
124 OcspResponse ocspResponse[1];
127 WOLFSSL_ENTER("CheckCertOCSP");
129 if (LockMutex(&ocsp->ocspLock) != 0) {
130 WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
134 ocspe = ocsp->ocspList;
136 if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
137 && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash,
138 SHA_DIGEST_SIZE) == 0)
145 ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
146 NULL, DYNAMIC_TYPE_OCSP_ENTRY);
148 InitOCSP_Entry(ocspe, cert);
149 ocspe->next = ocsp->ocspList;
150 ocsp->ocspList = ocspe;
153 UnLockMutex(&ocsp->ocspLock);
154 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
159 certStatus = ocspe->status;
161 if (certStatus->serialSz == cert->serialSz &&
162 XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0)
165 certStatus = certStatus->next;
169 if (certStatus != NULL) {
170 if (!ValidateDate(certStatus->thisDate,
171 certStatus->thisDateFormat, BEFORE) ||
172 (certStatus->nextDate[0] == 0) ||
173 !ValidateDate(certStatus->nextDate,
174 certStatus->nextDateFormat, AFTER)) {
175 WOLFSSL_MSG("\tinvalid status date, looking up cert");
178 result = xstat2err(certStatus->status);
179 UnLockMutex(&ocsp->ocspLock);
180 WOLFSSL_LEAVE("CheckCertOCSP", result);
185 UnLockMutex(&ocsp->ocspLock);
187 if (ocsp->cm->ocspUseOverrideURL) {
188 url = ocsp->cm->ocspOverrideURL;
189 if (url != NULL && url[0] != '\0')
190 urlSz = (int)XSTRLEN(url);
192 return OCSP_NEED_URL;
194 else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
195 url = (const char *)cert->extAuthInfo;
196 urlSz = cert->extAuthInfoSz;
199 /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
203 ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
204 if (ocspReqBuf == NULL) {
205 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
209 #ifdef WOLFSSL_SMALL_STACK
210 newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
211 DYNAMIC_TYPE_TMP_BUFFER);
212 ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
213 DYNAMIC_TYPE_TMP_BUFFER);
214 ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
215 DYNAMIC_TYPE_TMP_BUFFER);
217 if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) {
218 if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
219 if (ocspRequest) XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
220 if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
222 XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
224 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
229 InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
230 ocspReqBuf, ocspReqSz);
231 ocspReqSz = EncodeOcspRequest(ocspRequest);
233 if (ocsp->cm->ocspIOCb)
234 result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
235 ocspReqBuf, ocspReqSz, &ocspRespBuf);
237 if (result >= 0 && ocspRespBuf) {
238 XMEMSET(newStatus, 0, sizeof(CertStatus));
240 InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result);
241 OcspResponseDecode(ocspResponse);
243 if (ocspResponse->responseStatus != OCSP_SUCCESSFUL)
244 result = OCSP_LOOKUP_FAIL;
246 if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) {
247 result = xstat2err(ocspResponse->status->status);
249 if (LockMutex(&ocsp->ocspLock) != 0)
250 result = BAD_MUTEX_E;
252 if (certStatus != NULL)
253 /* Replace existing certificate entry with updated */
254 XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
256 /* Save new certificate entry */
257 certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus),
258 NULL, DYNAMIC_TYPE_OCSP_STATUS);
259 if (certStatus != NULL) {
260 XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
261 certStatus->next = ocspe->status;
262 ocspe->status = certStatus;
263 ocspe->totalStatus++;
267 UnLockMutex(&ocsp->ocspLock);
271 result = OCSP_LOOKUP_FAIL;
275 result = OCSP_LOOKUP_FAIL;
277 XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
279 #ifdef WOLFSSL_SMALL_STACK
280 XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
281 XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
282 XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
285 if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb)
286 ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf);
288 WOLFSSL_LEAVE("CheckCertOCSP", result);
293 #else /* HAVE_OCSP */
297 /* 4206 warning for blank file */
298 #pragma warning(disable: 4206)
302 #endif /* HAVE_OCSP */