fork of cyassl-lib

Dependents:   TLS_cyassl TLS_cyassl

Committer:
feb11
Date:
Mon Sep 16 09:53:35 2013 +0000
Revision:
4:f377303c41be
Parent:
0:714293de3836
changed settings

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:714293de3836 1 /* ocsp.c
ashleymills 0:714293de3836 2 *
ashleymills 0:714293de3836 3 * Copyright (C) 2006-2013 wolfSSL Inc.
ashleymills 0:714293de3836 4 *
ashleymills 0:714293de3836 5 * This file is part of CyaSSL.
ashleymills 0:714293de3836 6 *
ashleymills 0:714293de3836 7 * CyaSSL is free software; you can redistribute it and/or modify
ashleymills 0:714293de3836 8 * it under the terms of the GNU General Public License as published by
ashleymills 0:714293de3836 9 * the Free Software Foundation; either version 2 of the License, or
ashleymills 0:714293de3836 10 * (at your option) any later version.
ashleymills 0:714293de3836 11 *
ashleymills 0:714293de3836 12 * CyaSSL is distributed in the hope that it will be useful,
ashleymills 0:714293de3836 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ashleymills 0:714293de3836 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ashleymills 0:714293de3836 15 * GNU General Public License for more details.
ashleymills 0:714293de3836 16 *
ashleymills 0:714293de3836 17 * You should have received a copy of the GNU General Public License
ashleymills 0:714293de3836 18 * along with this program; if not, write to the Free Software
ashleymills 0:714293de3836 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
ashleymills 0:714293de3836 20 */
ashleymills 0:714293de3836 21
ashleymills 0:714293de3836 22 #ifdef HAVE_CONFIG_H
ashleymills 0:714293de3836 23 #include <config.h>
ashleymills 0:714293de3836 24 #endif
ashleymills 0:714293de3836 25
ashleymills 0:714293de3836 26 #include <cyassl/ctaocrypt/settings.h>
ashleymills 0:714293de3836 27
ashleymills 0:714293de3836 28 #ifdef HAVE_OCSP
ashleymills 0:714293de3836 29
ashleymills 0:714293de3836 30 #ifdef EBSNET
ashleymills 0:714293de3836 31 #include "rtip.h"
ashleymills 0:714293de3836 32 #include "socket.h"
ashleymills 0:714293de3836 33 #endif
ashleymills 0:714293de3836 34
ashleymills 0:714293de3836 35 #include <cyassl/ctaoerror.h>
ashleymills 0:714293de3836 36 #include <cyassl/ocsp.h>
ashleymills 0:714293de3836 37 #include <cyassl/internal.h>
ashleymills 0:714293de3836 38 #include <ctype.h>
ashleymills 0:714293de3836 39
ashleymills 0:714293de3836 40 #include <string.h>
ashleymills 0:714293de3836 41
ashleymills 0:714293de3836 42 #ifndef EBSNET
ashleymills 0:714293de3836 43 #include <unistd.h>
ashleymills 0:714293de3836 44 #include <netdb.h>
ashleymills 0:714293de3836 45 #include <netinet/in.h>
ashleymills 0:714293de3836 46 #include <netinet/tcp.h>
ashleymills 0:714293de3836 47 #include <arpa/inet.h>
ashleymills 0:714293de3836 48 #include <sys/ioctl.h>
ashleymills 0:714293de3836 49 #include <sys/time.h>
ashleymills 0:714293de3836 50 #include <sys/types.h>
ashleymills 0:714293de3836 51 #include <sys/socket.h>
ashleymills 0:714293de3836 52 #endif
ashleymills 0:714293de3836 53
ashleymills 0:714293de3836 54
ashleymills 0:714293de3836 55 CYASSL_API int ocsp_test(unsigned char* buf, int sz);
ashleymills 0:714293de3836 56 #define CYASSL_OCSP_ENABLE 0x0001 /* Enable OCSP lookups */
ashleymills 0:714293de3836 57 #define CYASSL_OCSP_URL_OVERRIDE 0x0002 /* Use the override URL instead of URL
ashleymills 0:714293de3836 58 * in certificate */
ashleymills 0:714293de3836 59 #define CYASSL_OCSP_NO_NONCE 0x0004 /* Disables the request nonce */
ashleymills 0:714293de3836 60
ashleymills 0:714293de3836 61 typedef struct sockaddr_in SOCKADDR_IN_T;
ashleymills 0:714293de3836 62 #define AF_INET_V AF_INET
ashleymills 0:714293de3836 63 #define SOCKET_T unsigned int
ashleymills 0:714293de3836 64
ashleymills 0:714293de3836 65
ashleymills 0:714293de3836 66 int CyaSSL_OCSP_Init(CYASSL_OCSP* ocsp)
ashleymills 0:714293de3836 67 {
ashleymills 0:714293de3836 68 if (ocsp != NULL) {
ashleymills 0:714293de3836 69 XMEMSET(ocsp, 0, sizeof(*ocsp));
ashleymills 0:714293de3836 70 ocsp->useNonce = 1;
ashleymills 0:714293de3836 71 #ifndef CYASSL_USER_IO
ashleymills 0:714293de3836 72 ocsp->CBIOOcsp = EmbedOcspLookup;
ashleymills 0:714293de3836 73 ocsp->CBIOOcspRespFree = EmbedOcspRespFree;
ashleymills 0:714293de3836 74 #endif
ashleymills 0:714293de3836 75 return 0;
ashleymills 0:714293de3836 76 }
ashleymills 0:714293de3836 77
ashleymills 0:714293de3836 78 return -1;
ashleymills 0:714293de3836 79 }
ashleymills 0:714293de3836 80
ashleymills 0:714293de3836 81
ashleymills 0:714293de3836 82 static void FreeOCSP_Entry(OCSP_Entry* ocspe)
ashleymills 0:714293de3836 83 {
ashleymills 0:714293de3836 84 CertStatus* tmp = ocspe->status;
ashleymills 0:714293de3836 85
ashleymills 0:714293de3836 86 CYASSL_ENTER("FreeOCSP_Entry");
ashleymills 0:714293de3836 87
ashleymills 0:714293de3836 88 while (tmp) {
ashleymills 0:714293de3836 89 CertStatus* next = tmp->next;
ashleymills 0:714293de3836 90 XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS);
ashleymills 0:714293de3836 91 tmp = next;
ashleymills 0:714293de3836 92 }
ashleymills 0:714293de3836 93 }
ashleymills 0:714293de3836 94
ashleymills 0:714293de3836 95
ashleymills 0:714293de3836 96 void CyaSSL_OCSP_Cleanup(CYASSL_OCSP* ocsp)
ashleymills 0:714293de3836 97 {
ashleymills 0:714293de3836 98 OCSP_Entry* tmp = ocsp->ocspList;
ashleymills 0:714293de3836 99
ashleymills 0:714293de3836 100 ocsp->enabled = 0;
ashleymills 0:714293de3836 101 while (tmp) {
ashleymills 0:714293de3836 102 OCSP_Entry* next = tmp->next;
ashleymills 0:714293de3836 103 FreeOCSP_Entry(tmp);
ashleymills 0:714293de3836 104 XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
ashleymills 0:714293de3836 105 tmp = next;
ashleymills 0:714293de3836 106 }
ashleymills 0:714293de3836 107 }
ashleymills 0:714293de3836 108
ashleymills 0:714293de3836 109
ashleymills 0:714293de3836 110 int CyaSSL_OCSP_set_override_url(CYASSL_OCSP* ocsp, const char* url)
ashleymills 0:714293de3836 111 {
ashleymills 0:714293de3836 112 if (ocsp != NULL) {
ashleymills 0:714293de3836 113 int urlSz = (int)XSTRLEN(url);
ashleymills 0:714293de3836 114 if (urlSz < (int)sizeof(ocsp->overrideUrl)) {
ashleymills 0:714293de3836 115 XSTRNCPY(ocsp->overrideUrl, url, urlSz);
ashleymills 0:714293de3836 116 return 1;
ashleymills 0:714293de3836 117 }
ashleymills 0:714293de3836 118 }
ashleymills 0:714293de3836 119
ashleymills 0:714293de3836 120 return 0;
ashleymills 0:714293de3836 121 }
ashleymills 0:714293de3836 122
ashleymills 0:714293de3836 123
ashleymills 0:714293de3836 124 static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert)
ashleymills 0:714293de3836 125 {
ashleymills 0:714293de3836 126 CYASSL_ENTER("InitOCSP_Entry");
ashleymills 0:714293de3836 127
ashleymills 0:714293de3836 128 ocspe->next = NULL;
ashleymills 0:714293de3836 129 XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE);
ashleymills 0:714293de3836 130 XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE);
ashleymills 0:714293de3836 131 ocspe->status = NULL;
ashleymills 0:714293de3836 132 ocspe->totalStatus = 0;
ashleymills 0:714293de3836 133
ashleymills 0:714293de3836 134 return 0;
ashleymills 0:714293de3836 135 }
ashleymills 0:714293de3836 136
ashleymills 0:714293de3836 137
ashleymills 0:714293de3836 138 static OCSP_Entry* find_ocsp_entry(CYASSL_OCSP* ocsp, DecodedCert* cert)
ashleymills 0:714293de3836 139 {
ashleymills 0:714293de3836 140 OCSP_Entry* entry = ocsp->ocspList;
ashleymills 0:714293de3836 141
ashleymills 0:714293de3836 142 while (entry)
ashleymills 0:714293de3836 143 {
ashleymills 0:714293de3836 144 if (XMEMCMP(entry->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0
ashleymills 0:714293de3836 145 && XMEMCMP(entry->issuerKeyHash, cert->issuerKeyHash,
ashleymills 0:714293de3836 146 SHA_DIGEST_SIZE) == 0)
ashleymills 0:714293de3836 147 {
ashleymills 0:714293de3836 148 CYASSL_MSG("Found OCSP responder");
ashleymills 0:714293de3836 149 break;
ashleymills 0:714293de3836 150 }
ashleymills 0:714293de3836 151 else
ashleymills 0:714293de3836 152 {
ashleymills 0:714293de3836 153 entry = entry->next;
ashleymills 0:714293de3836 154 }
ashleymills 0:714293de3836 155 }
ashleymills 0:714293de3836 156
ashleymills 0:714293de3836 157 if (entry == NULL)
ashleymills 0:714293de3836 158 {
ashleymills 0:714293de3836 159 CYASSL_MSG("Add a new OCSP entry");
ashleymills 0:714293de3836 160 entry = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry),
ashleymills 0:714293de3836 161 NULL, DYNAMIC_TYPE_OCSP_ENTRY);
ashleymills 0:714293de3836 162 if (entry != NULL)
ashleymills 0:714293de3836 163 {
ashleymills 0:714293de3836 164 InitOCSP_Entry(entry, cert);
ashleymills 0:714293de3836 165 entry->next = ocsp->ocspList;
ashleymills 0:714293de3836 166 ocsp->ocspList = entry;
ashleymills 0:714293de3836 167 }
ashleymills 0:714293de3836 168 }
ashleymills 0:714293de3836 169
ashleymills 0:714293de3836 170 return entry;
ashleymills 0:714293de3836 171 }
ashleymills 0:714293de3836 172
ashleymills 0:714293de3836 173
ashleymills 0:714293de3836 174 static CertStatus* find_cert_status(OCSP_Entry* ocspe, DecodedCert* cert)
ashleymills 0:714293de3836 175 {
ashleymills 0:714293de3836 176 CertStatus* stat = ocspe->status;
ashleymills 0:714293de3836 177
ashleymills 0:714293de3836 178 while (stat)
ashleymills 0:714293de3836 179 {
ashleymills 0:714293de3836 180 if(stat->serialSz == cert->serialSz &&
ashleymills 0:714293de3836 181 (XMEMCMP(stat->serial, cert->serial, cert->serialSz) == 0))
ashleymills 0:714293de3836 182 {
ashleymills 0:714293de3836 183 break;
ashleymills 0:714293de3836 184 }
ashleymills 0:714293de3836 185 else
ashleymills 0:714293de3836 186 {
ashleymills 0:714293de3836 187 stat = stat->next;
ashleymills 0:714293de3836 188 }
ashleymills 0:714293de3836 189 }
ashleymills 0:714293de3836 190 if (stat == NULL)
ashleymills 0:714293de3836 191 {
ashleymills 0:714293de3836 192 stat = (CertStatus*)XMALLOC(sizeof(CertStatus),
ashleymills 0:714293de3836 193 NULL, DYNAMIC_TYPE_OCSP_STATUS);
ashleymills 0:714293de3836 194 if (stat != NULL)
ashleymills 0:714293de3836 195 {
ashleymills 0:714293de3836 196 XMEMCPY(stat->serial, cert->serial, cert->serialSz);
ashleymills 0:714293de3836 197 stat->serialSz = cert->serialSz;
ashleymills 0:714293de3836 198 stat->status = -1;
ashleymills 0:714293de3836 199 stat->nextDate[0] = 0;
ashleymills 0:714293de3836 200 ocspe->totalStatus++;
ashleymills 0:714293de3836 201
ashleymills 0:714293de3836 202 stat->next = ocspe->status;
ashleymills 0:714293de3836 203 ocspe->status = stat;
ashleymills 0:714293de3836 204 }
ashleymills 0:714293de3836 205 }
ashleymills 0:714293de3836 206
ashleymills 0:714293de3836 207 return stat;
ashleymills 0:714293de3836 208 }
ashleymills 0:714293de3836 209
ashleymills 0:714293de3836 210
ashleymills 0:714293de3836 211 static int xstat2err(int stat)
ashleymills 0:714293de3836 212 {
ashleymills 0:714293de3836 213 switch (stat) {
ashleymills 0:714293de3836 214 case CERT_GOOD:
ashleymills 0:714293de3836 215 return 0;
ashleymills 0:714293de3836 216 break;
ashleymills 0:714293de3836 217 case CERT_REVOKED:
ashleymills 0:714293de3836 218 return OCSP_CERT_REVOKED;
ashleymills 0:714293de3836 219 break;
ashleymills 0:714293de3836 220 default:
ashleymills 0:714293de3836 221 return OCSP_CERT_UNKNOWN;
ashleymills 0:714293de3836 222 break;
ashleymills 0:714293de3836 223 }
ashleymills 0:714293de3836 224 }
ashleymills 0:714293de3836 225
ashleymills 0:714293de3836 226
ashleymills 0:714293de3836 227 int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert)
ashleymills 0:714293de3836 228 {
ashleymills 0:714293de3836 229 byte* ocspReqBuf = NULL;
ashleymills 0:714293de3836 230 int ocspReqSz = 2048;
ashleymills 0:714293de3836 231 byte* ocspRespBuf = NULL;
ashleymills 0:714293de3836 232 OcspRequest ocspRequest;
ashleymills 0:714293de3836 233 OcspResponse ocspResponse;
ashleymills 0:714293de3836 234 int result = 0;
ashleymills 0:714293de3836 235 OCSP_Entry* ocspe;
ashleymills 0:714293de3836 236 CertStatus* certStatus;
ashleymills 0:714293de3836 237 const char *url;
ashleymills 0:714293de3836 238 int urlSz;
ashleymills 0:714293de3836 239
ashleymills 0:714293de3836 240 /* If OCSP lookups are disabled, return success. */
ashleymills 0:714293de3836 241 if (!ocsp->enabled) {
ashleymills 0:714293de3836 242 CYASSL_MSG("OCSP lookup disabled, assuming CERT_GOOD");
ashleymills 0:714293de3836 243 return 0;
ashleymills 0:714293de3836 244 }
ashleymills 0:714293de3836 245
ashleymills 0:714293de3836 246 ocspe = find_ocsp_entry(ocsp, cert);
ashleymills 0:714293de3836 247 if (ocspe == NULL) {
ashleymills 0:714293de3836 248 CYASSL_MSG("alloc OCSP entry failed");
ashleymills 0:714293de3836 249 return MEMORY_ERROR;
ashleymills 0:714293de3836 250 }
ashleymills 0:714293de3836 251
ashleymills 0:714293de3836 252 certStatus = find_cert_status(ocspe, cert);
ashleymills 0:714293de3836 253 if (certStatus == NULL)
ashleymills 0:714293de3836 254 {
ashleymills 0:714293de3836 255 CYASSL_MSG("alloc OCSP cert status failed");
ashleymills 0:714293de3836 256 return MEMORY_ERROR;
ashleymills 0:714293de3836 257 }
ashleymills 0:714293de3836 258
ashleymills 0:714293de3836 259 if (certStatus->status != -1)
ashleymills 0:714293de3836 260 {
ashleymills 0:714293de3836 261 if (!ValidateDate(certStatus->thisDate,
ashleymills 0:714293de3836 262 certStatus->thisDateFormat, BEFORE) ||
ashleymills 0:714293de3836 263 (certStatus->nextDate[0] == 0) ||
ashleymills 0:714293de3836 264 !ValidateDate(certStatus->nextDate,
ashleymills 0:714293de3836 265 certStatus->nextDateFormat, AFTER))
ashleymills 0:714293de3836 266 {
ashleymills 0:714293de3836 267 CYASSL_MSG("\tinvalid status date, looking up cert");
ashleymills 0:714293de3836 268 certStatus->status = -1;
ashleymills 0:714293de3836 269 }
ashleymills 0:714293de3836 270 else
ashleymills 0:714293de3836 271 {
ashleymills 0:714293de3836 272 CYASSL_MSG("\tusing cached status");
ashleymills 0:714293de3836 273 result = xstat2err(certStatus->status);
ashleymills 0:714293de3836 274 return result;
ashleymills 0:714293de3836 275 }
ashleymills 0:714293de3836 276 }
ashleymills 0:714293de3836 277
ashleymills 0:714293de3836 278 if (ocsp->useOverrideUrl) {
ashleymills 0:714293de3836 279 if (ocsp->overrideUrl[0] != '\0') {
ashleymills 0:714293de3836 280 url = ocsp->overrideUrl;
ashleymills 0:714293de3836 281 urlSz = (int)XSTRLEN(url);
ashleymills 0:714293de3836 282 }
ashleymills 0:714293de3836 283 else
ashleymills 0:714293de3836 284 return OCSP_NEED_URL;
ashleymills 0:714293de3836 285 }
ashleymills 0:714293de3836 286 else if (cert->extAuthInfoSz == 0 || cert->extAuthInfo == NULL) {
ashleymills 0:714293de3836 287 url = (const char *)cert->extAuthInfo;
ashleymills 0:714293de3836 288 urlSz = cert->extAuthInfoSz;
ashleymills 0:714293de3836 289 }
ashleymills 0:714293de3836 290 else {
ashleymills 0:714293de3836 291 CYASSL_MSG("\tcert doesn't have extAuthInfo, assuming CERT_GOOD");
ashleymills 0:714293de3836 292 return 0;
ashleymills 0:714293de3836 293 }
ashleymills 0:714293de3836 294
ashleymills 0:714293de3836 295 ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
ashleymills 0:714293de3836 296 if (ocspReqBuf == NULL) {
ashleymills 0:714293de3836 297 CYASSL_MSG("\talloc OCSP request buffer failed");
ashleymills 0:714293de3836 298 return MEMORY_ERROR;
ashleymills 0:714293de3836 299 }
ashleymills 0:714293de3836 300 InitOcspRequest(&ocspRequest, cert, ocsp->useNonce, ocspReqBuf, ocspReqSz);
ashleymills 0:714293de3836 301 ocspReqSz = EncodeOcspRequest(&ocspRequest);
ashleymills 0:714293de3836 302
ashleymills 0:714293de3836 303 if (ocsp->CBIOOcsp) {
ashleymills 0:714293de3836 304 result = ocsp->CBIOOcsp(ocsp->IOCB_OcspCtx, url, urlSz,
ashleymills 0:714293de3836 305 ocspReqBuf, ocspReqSz, &ocspRespBuf);
ashleymills 0:714293de3836 306 }
ashleymills 0:714293de3836 307
ashleymills 0:714293de3836 308 if (result >= 0 && ocspRespBuf) {
ashleymills 0:714293de3836 309 InitOcspResponse(&ocspResponse, certStatus, ocspRespBuf, result);
ashleymills 0:714293de3836 310 OcspResponseDecode(&ocspResponse);
ashleymills 0:714293de3836 311
ashleymills 0:714293de3836 312 if (ocspResponse.responseStatus != OCSP_SUCCESSFUL) {
ashleymills 0:714293de3836 313 CYASSL_MSG("OCSP Responder failure");
ashleymills 0:714293de3836 314 result = OCSP_LOOKUP_FAIL;
ashleymills 0:714293de3836 315 } else {
ashleymills 0:714293de3836 316 if (CompareOcspReqResp(&ocspRequest, &ocspResponse) == 0)
ashleymills 0:714293de3836 317 {
ashleymills 0:714293de3836 318 result = xstat2err(ocspResponse.status->status);
ashleymills 0:714293de3836 319 }
ashleymills 0:714293de3836 320 else
ashleymills 0:714293de3836 321 {
ashleymills 0:714293de3836 322 CYASSL_MSG("OCSP Response incorrect for Request");
ashleymills 0:714293de3836 323 result = OCSP_LOOKUP_FAIL;
ashleymills 0:714293de3836 324 }
ashleymills 0:714293de3836 325 }
ashleymills 0:714293de3836 326 }
ashleymills 0:714293de3836 327 else {
ashleymills 0:714293de3836 328 result = OCSP_LOOKUP_FAIL;
ashleymills 0:714293de3836 329 }
ashleymills 0:714293de3836 330
ashleymills 0:714293de3836 331 if (ocspReqBuf != NULL) {
ashleymills 0:714293de3836 332 XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
ashleymills 0:714293de3836 333 }
ashleymills 0:714293de3836 334 if (ocspRespBuf != NULL && ocsp->CBIOOcspRespFree) {
ashleymills 0:714293de3836 335 ocsp->CBIOOcspRespFree(ocsp->IOCB_OcspCtx, ocspRespBuf);
ashleymills 0:714293de3836 336 }
ashleymills 0:714293de3836 337
ashleymills 0:714293de3836 338 return result;
ashleymills 0:714293de3836 339 }
ashleymills 0:714293de3836 340
ashleymills 0:714293de3836 341
ashleymills 0:714293de3836 342 #endif /* HAVE_OCSP */
ashleymills 0:714293de3836 343