123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /* ocsp.c
- *
- * Copyright (C) 2006-2014 wolfSSL Inc.
- *
- * This file is part of CyaSSL.
- *
- * CyaSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * CyaSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <cyassl/ctaocrypt/settings.h>
- #ifdef HAVE_OCSP
- #include <cyassl/error-ssl.h>
- #include <cyassl/ocsp.h>
- #include <cyassl/internal.h>
- int InitOCSP(CYASSL_OCSP* ocsp, CYASSL_CERT_MANAGER* cm)
- {
- CYASSL_ENTER("InitOCSP");
- XMEMSET(ocsp, 0, sizeof(*ocsp));
- ocsp->cm = cm;
- if (InitMutex(&ocsp->ocspLock) != 0)
- return BAD_MUTEX_E;
- return 0;
- }
- static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert)
- {
- CYASSL_ENTER("InitOCSP_Entry");
- XMEMSET(ocspe, 0, sizeof(*ocspe));
- XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE);
- XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE);
- return 0;
- }
- static void FreeOCSP_Entry(OCSP_Entry* ocspe)
- {
- CertStatus* tmp = ocspe->status;
- CYASSL_ENTER("FreeOCSP_Entry");
- while (tmp) {
- CertStatus* next = tmp->next;
- XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
- tmp = next;
- }
- }
- void FreeOCSP(CYASSL_OCSP* ocsp, int dynamic)
- {
- OCSP_Entry* tmp = ocsp->ocspList;
- CYASSL_ENTER("FreeOCSP");
- while (tmp) {
- OCSP_Entry* next = tmp->next;
- FreeOCSP_Entry(tmp);
- XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
- tmp = next;
- }
- FreeMutex(&ocsp->ocspLock);
- if (dynamic)
- XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP);
- }
- static int xstat2err(int stat)
- {
- switch (stat) {
- case CERT_GOOD:
- return 0;
- case CERT_REVOKED:
- return OCSP_CERT_REVOKED;
- default:
- return OCSP_CERT_UNKNOWN;
- }
- }
- int CheckCertOCSP(CYASSL_OCSP* ocsp, DecodedCert* cert)
- {
- byte* ocspReqBuf = NULL;
- int ocspReqSz = 2048;
- byte* ocspRespBuf = NULL;
- int result = -1;
- OCSP_Entry* ocspe;
- CertStatus* certStatus = NULL;
- const char *url;
- int urlSz;
- #ifdef CYASSL_SMALL_STACK
- CertStatus* newStatus;
- OcspRequest* ocspRequest;
- OcspResponse* ocspResponse;
- #else
- CertStatus newStatus[1];
- OcspRequest ocspRequest[1];
- OcspResponse ocspResponse[1];
- #endif
- CYASSL_ENTER("CheckCertOCSP");
- if (LockMutex(&ocsp->ocspLock) != 0) {
- CYASSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
- return BAD_MUTEX_E;
- }
- ocspe = ocsp->ocspList;
- while (ocspe) {
- if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
- && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash,
- SHA_DIGEST_SIZE) == 0)
- break;
- else
- ocspe = ocspe->next;
- }
- if (ocspe == NULL) {
- ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
- NULL, DYNAMIC_TYPE_OCSP_ENTRY);
- if (ocspe != NULL) {
- InitOCSP_Entry(ocspe, cert);
- ocspe->next = ocsp->ocspList;
- ocsp->ocspList = ocspe;
- }
- else {
- UnLockMutex(&ocsp->ocspLock);
- CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
- return MEMORY_ERROR;
- }
- }
- else {
- certStatus = ocspe->status;
- while (certStatus) {
- if (certStatus->serialSz == cert->serialSz &&
- XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0)
- break;
- else
- certStatus = certStatus->next;
- }
- }
- if (certStatus != NULL) {
- if (!ValidateDate(certStatus->thisDate,
- certStatus->thisDateFormat, BEFORE) ||
- (certStatus->nextDate[0] == 0) ||
- !ValidateDate(certStatus->nextDate,
- certStatus->nextDateFormat, AFTER)) {
- CYASSL_MSG("\tinvalid status date, looking up cert");
- }
- else {
- result = xstat2err(certStatus->status);
- UnLockMutex(&ocsp->ocspLock);
- CYASSL_LEAVE("CheckCertOCSP", result);
- return result;
- }
- }
- UnLockMutex(&ocsp->ocspLock);
- if (ocsp->cm->ocspUseOverrideURL) {
- url = ocsp->cm->ocspOverrideURL;
- if (url != NULL && url[0] != '\0')
- urlSz = (int)XSTRLEN(url);
- else
- return OCSP_NEED_URL;
- }
- else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
- url = (const char *)cert->extAuthInfo;
- urlSz = cert->extAuthInfoSz;
- }
- else {
- /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
- return 0;
- }
- ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
- if (ocspReqBuf == NULL) {
- CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
- return MEMORY_ERROR;
- }
- #ifdef CYASSL_SMALL_STACK
- newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
- DYNAMIC_TYPE_TMP_BUFFER);
- if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) {
- if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (ocspRequest) XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- CYASSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
- return MEMORY_E;
- }
- #endif
- InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
- ocspReqBuf, ocspReqSz);
- ocspReqSz = EncodeOcspRequest(ocspRequest);
-
- if (ocsp->cm->ocspIOCb)
- result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz,
- ocspReqBuf, ocspReqSz, &ocspRespBuf);
- if (result >= 0 && ocspRespBuf) {
- XMEMSET(newStatus, 0, sizeof(CertStatus));
- InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result);
- OcspResponseDecode(ocspResponse);
-
- if (ocspResponse->responseStatus != OCSP_SUCCESSFUL)
- result = OCSP_LOOKUP_FAIL;
- else {
- if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) {
- result = xstat2err(ocspResponse->status->status);
- if (LockMutex(&ocsp->ocspLock) != 0)
- result = BAD_MUTEX_E;
- else {
- if (certStatus != NULL)
- /* Replace existing certificate entry with updated */
- XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
- else {
- /* Save new certificate entry */
- certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus),
- NULL, DYNAMIC_TYPE_OCSP_STATUS);
- if (certStatus != NULL) {
- XMEMCPY(certStatus, newStatus, sizeof(CertStatus));
- certStatus->next = ocspe->status;
- ocspe->status = certStatus;
- ocspe->totalStatus++;
- }
- }
- UnLockMutex(&ocsp->ocspLock);
- }
- }
- else
- result = OCSP_LOOKUP_FAIL;
- }
- }
- else
- result = OCSP_LOOKUP_FAIL;
- XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
- #ifdef CYASSL_SMALL_STACK
- XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
- #endif
- if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb)
- ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf);
- CYASSL_LEAVE("CheckCertOCSP", result);
- return result;
- }
- #else /* HAVE_OCSP */
- #ifdef _MSC_VER
- /* 4206 warning for blank file */
- #pragma warning(disable: 4206)
- #endif
- #endif /* HAVE_OCSP */
|