cyassl re-port with cellular comms, PSK test

Dependencies:   VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src

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