Francois Berder / cyassl-lib

Dependents:   TLS_cyassl TLS_cyassl

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-2013 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 #ifdef EBSNET
00031     #include "rtip.h"
00032     #include "socket.h"
00033 #endif
00034 
00035 #include <cyassl/ctaoerror.h>
00036 #include <cyassl/ocsp.h>
00037 #include <cyassl/internal.h>
00038 #include <ctype.h>
00039 
00040 #include <string.h>
00041 
00042 #ifndef EBSNET
00043     #include <unistd.h>
00044     #include <netdb.h>
00045     #include <netinet/in.h>
00046     #include <netinet/tcp.h>
00047     #include <arpa/inet.h>
00048     #include <sys/ioctl.h>
00049     #include <sys/time.h>
00050     #include <sys/types.h>
00051     #include <sys/socket.h>
00052 #endif
00053 
00054 
00055 CYASSL_API int ocsp_test(unsigned char* buf, int sz);
00056 #define CYASSL_OCSP_ENABLE       0x0001 /* Enable OCSP lookups */
00057 #define CYASSL_OCSP_URL_OVERRIDE 0x0002 /* Use the override URL instead of URL
00058                                          * in certificate */
00059 #define CYASSL_OCSP_NO_NONCE     0x0004 /* Disables the request nonce */
00060 
00061 typedef struct sockaddr_in  SOCKADDR_IN_T;
00062 #define AF_INET_V    AF_INET
00063 #define SOCKET_T unsigned int
00064    
00065 
00066 int CyaSSL_OCSP_Init(CYASSL_OCSP* ocsp)
00067 {
00068     if (ocsp != NULL) {
00069         XMEMSET(ocsp, 0, sizeof(*ocsp));
00070         ocsp->useNonce = 1;
00071         #ifndef CYASSL_USER_IO
00072             ocsp->CBIOOcsp = EmbedOcspLookup;
00073             ocsp->CBIOOcspRespFree = EmbedOcspRespFree;
00074         #endif
00075         return 0;
00076     }
00077 
00078     return -1;
00079 }
00080 
00081 
00082 static void FreeOCSP_Entry(OCSP_Entry* ocspe)
00083 {
00084     CertStatus* tmp = ocspe->status;
00085 
00086     CYASSL_ENTER("FreeOCSP_Entry");
00087 
00088     while (tmp) {
00089         CertStatus* next = tmp->next;
00090         XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
00091         tmp = next;
00092     }
00093 }
00094 
00095 
00096 void CyaSSL_OCSP_Cleanup(CYASSL_OCSP* ocsp)
00097 {
00098     OCSP_Entry* tmp = ocsp->ocspList;
00099 
00100     ocsp->enabled = 0;
00101     while (tmp) {
00102         OCSP_Entry* next = tmp->next;
00103         FreeOCSP_Entry(tmp);
00104         XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
00105         tmp = next;
00106     }
00107 }
00108 
00109 
00110 int CyaSSL_OCSP_set_override_url(CYASSL_OCSP* ocsp, const char* url)
00111 {
00112     if (ocsp != NULL) {
00113         int urlSz = (int)XSTRLEN(url);
00114         if (urlSz < (int)sizeof(ocsp->overrideUrl)) {
00115             XSTRNCPY(ocsp->overrideUrl, url, urlSz);
00116             return 1;
00117         }
00118     }
00119 
00120     return 0;
00121 }
00122 
00123 
00124 static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert)
00125 {
00126     CYASSL_ENTER("InitOCSP_Entry");
00127 
00128     ocspe->next = NULL;
00129     XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE);
00130     XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE);
00131     ocspe->status = NULL;
00132     ocspe->totalStatus = 0;
00133 
00134     return 0;
00135 }
00136 
00137 
00138 static OCSP_Entry* find_ocsp_entry(CYASSL_OCSP* ocsp, DecodedCert* cert)
00139 {
00140     OCSP_Entry* entry = ocsp->ocspList;
00141 
00142     while (entry)
00143     {
00144         if (XMEMCMP(entry->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
00145             && XMEMCMP(entry->issuerKeyHash, cert->issuerKeyHash,
00146                                                         SHA_DIGEST_SIZE) == 0)
00147         {
00148             CYASSL_MSG("Found OCSP responder");
00149             break;
00150         }
00151         else
00152         {
00153             entry = entry->next;
00154         }
00155     }
00156 
00157     if (entry == NULL)
00158     {
00159         CYASSL_MSG("Add a new OCSP entry");
00160         entry = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
00161                                                 NULL, DYNAMIC_TYPE_OCSP_ENTRY);
00162         if (entry != NULL)
00163         {
00164             InitOCSP_Entry(entry, cert);
00165             entry->next = ocsp->ocspList;
00166             ocsp->ocspList = entry;
00167         }
00168     }
00169 
00170     return entry;
00171 }
00172 
00173 
00174 static CertStatus* find_cert_status(OCSP_Entry* ocspe, DecodedCert* cert)
00175 {
00176     CertStatus* stat = ocspe->status;
00177 
00178     while (stat)
00179     {
00180         if(stat->serialSz == cert->serialSz &&
00181             (XMEMCMP(stat->serial, cert->serial, cert->serialSz) == 0))
00182         {
00183             break;
00184         }
00185         else
00186         {
00187             stat = stat->next;
00188         }
00189     }
00190     if (stat == NULL)
00191     {
00192         stat = (CertStatus*)XMALLOC(sizeof(CertStatus),
00193                                             NULL, DYNAMIC_TYPE_OCSP_STATUS);
00194         if (stat != NULL)
00195         {
00196             XMEMCPY(stat->serial, cert->serial, cert->serialSz);
00197             stat->serialSz = cert->serialSz;
00198             stat->status = -1;
00199             stat->nextDate[0] = 0;
00200             ocspe->totalStatus++;
00201 
00202             stat->next = ocspe->status;
00203             ocspe->status = stat;
00204         }
00205     }
00206 
00207     return stat;
00208 }
00209 
00210 
00211 static int xstat2err(int stat)
00212 {
00213     switch (stat) {
00214         case CERT_GOOD:
00215             return 0;
00216             break;
00217         case CERT_REVOKED:
00218             return OCSP_CERT_REVOKED;
00219             break;
00220         default:
00221             return OCSP_CERT_UNKNOWN;
00222             break;
00223     }
00224 }
00225 
00226 
00227 int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert)
00228 {
00229     byte* ocspReqBuf = NULL;
00230     int ocspReqSz = 2048;
00231     byte* ocspRespBuf = NULL;
00232     OcspRequest ocspRequest;
00233     OcspResponse ocspResponse;
00234     int result = 0;
00235     OCSP_Entry* ocspe;
00236     CertStatus* certStatus;
00237     const char *url;
00238     int urlSz;
00239 
00240     /* If OCSP lookups are disabled, return success. */
00241     if (!ocsp->enabled) {
00242         CYASSL_MSG("OCSP lookup disabled, assuming CERT_GOOD");
00243         return 0;
00244     }
00245 
00246     ocspe = find_ocsp_entry(ocsp, cert);
00247     if (ocspe == NULL) {
00248         CYASSL_MSG("alloc OCSP entry failed");
00249         return MEMORY_ERROR;
00250     }
00251 
00252     certStatus = find_cert_status(ocspe, cert);
00253     if (certStatus == NULL)
00254     {
00255         CYASSL_MSG("alloc OCSP cert status failed");
00256         return MEMORY_ERROR;
00257     }
00258 
00259     if (certStatus->status != -1)
00260     {
00261         if (!ValidateDate(certStatus->thisDate,
00262                                         certStatus->thisDateFormat, BEFORE) ||
00263             (certStatus->nextDate[0] == 0) ||
00264             !ValidateDate(certStatus->nextDate,
00265                                         certStatus->nextDateFormat, AFTER))
00266         {
00267             CYASSL_MSG("\tinvalid status date, looking up cert");
00268             certStatus->status = -1;
00269         }
00270         else
00271         {
00272             CYASSL_MSG("\tusing cached status");
00273             result = xstat2err(certStatus->status);
00274             return result;
00275         }
00276     }
00277 
00278     if (ocsp->useOverrideUrl) {
00279         if (ocsp->overrideUrl[0] != '\0') {
00280             url = ocsp->overrideUrl;
00281             urlSz = (int)XSTRLEN(url);
00282         }
00283         else
00284             return OCSP_NEED_URL;
00285     }
00286     else if (cert->extAuthInfoSz == 0 || cert->extAuthInfo == NULL) {
00287         url = (const char *)cert->extAuthInfo;
00288         urlSz = cert->extAuthInfoSz;
00289     }
00290     else {
00291         CYASSL_MSG("\tcert doesn't have extAuthInfo, assuming CERT_GOOD");
00292         return 0;
00293     }
00294 
00295     ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
00296     if (ocspReqBuf == NULL) {
00297         CYASSL_MSG("\talloc OCSP request buffer failed");
00298         return MEMORY_ERROR;
00299     }
00300     InitOcspRequest(&ocspRequest, cert, ocsp->useNonce, ocspReqBuf, ocspReqSz);
00301     ocspReqSz = EncodeOcspRequest(&ocspRequest);
00302     
00303     if (ocsp->CBIOOcsp) {
00304         result = ocsp->CBIOOcsp(ocsp->IOCB_OcspCtx, url, urlSz,
00305                                           ocspReqBuf, ocspReqSz, &ocspRespBuf);
00306     }
00307 
00308     if (result >= 0 && ocspRespBuf) {
00309         InitOcspResponse(&ocspResponse, certStatus, ocspRespBuf, result);
00310         OcspResponseDecode(&ocspResponse);
00311     
00312         if (ocspResponse.responseStatus != OCSP_SUCCESSFUL) {
00313             CYASSL_MSG("OCSP Responder failure");
00314             result = OCSP_LOOKUP_FAIL;
00315         } else {
00316             if (CompareOcspReqResp(&ocspRequest, &ocspResponse) == 0)
00317             {
00318                 result = xstat2err(ocspResponse.status->status);
00319             }
00320             else
00321             {
00322                 CYASSL_MSG("OCSP Response incorrect for Request");
00323                 result = OCSP_LOOKUP_FAIL;
00324             }
00325         }
00326     }
00327     else {
00328         result = OCSP_LOOKUP_FAIL;
00329     }
00330 
00331     if (ocspReqBuf != NULL) {
00332         XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
00333     }
00334     if (ocspRespBuf != NULL && ocsp->CBIOOcspRespFree) {
00335         ocsp->CBIOOcspRespFree(ocsp->IOCB_OcspCtx, ocspRespBuf);
00336     }
00337 
00338     return result;
00339 }
00340 
00341 
00342 #endif /* HAVE_OCSP */
00343