wolfSSL SSL/TLS library, support up to TLS1.3

Dependents:   OS

Committer:
sPymbed
Date:
Wed Nov 20 13:27:48 2019 +0000
Revision:
17:ff9d1e86ad5f
Parent:
15:117db924cf7c
removed: wolfcrypt

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sPymbed 17:ff9d1e86ad5f 1 /* ocsp.c
sPymbed 17:ff9d1e86ad5f 2 *
sPymbed 17:ff9d1e86ad5f 3 * Copyright (C) 2006-2017 wolfSSL Inc.
sPymbed 17:ff9d1e86ad5f 4 *
sPymbed 17:ff9d1e86ad5f 5 * This file is part of wolfSSL.
sPymbed 17:ff9d1e86ad5f 6 *
sPymbed 17:ff9d1e86ad5f 7 * wolfSSL is free software; you can redistribute it and/or modify
sPymbed 17:ff9d1e86ad5f 8 * it under the terms of the GNU General Public License as published by
sPymbed 17:ff9d1e86ad5f 9 * the Free Software Foundation; either version 2 of the License, or
sPymbed 17:ff9d1e86ad5f 10 * (at your option) any later version.
sPymbed 17:ff9d1e86ad5f 11 *
sPymbed 17:ff9d1e86ad5f 12 * wolfSSL is distributed in the hope that it will be useful,
sPymbed 17:ff9d1e86ad5f 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
sPymbed 17:ff9d1e86ad5f 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
sPymbed 17:ff9d1e86ad5f 15 * GNU General Public License for more details.
sPymbed 17:ff9d1e86ad5f 16 *
sPymbed 17:ff9d1e86ad5f 17 * You should have received a copy of the GNU General Public License
sPymbed 17:ff9d1e86ad5f 18 * along with this program; if not, write to the Free Software
sPymbed 17:ff9d1e86ad5f 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
sPymbed 17:ff9d1e86ad5f 20 */
sPymbed 17:ff9d1e86ad5f 21
sPymbed 17:ff9d1e86ad5f 22
sPymbed 17:ff9d1e86ad5f 23 /* Name change compatibility layer no longer needs to be included here */
sPymbed 17:ff9d1e86ad5f 24
sPymbed 17:ff9d1e86ad5f 25 #ifdef HAVE_CONFIG_H
sPymbed 17:ff9d1e86ad5f 26 #include <config.h>
sPymbed 17:ff9d1e86ad5f 27 #endif
sPymbed 17:ff9d1e86ad5f 28
sPymbed 17:ff9d1e86ad5f 29 #include <wolfcrypt/settings.h>
sPymbed 17:ff9d1e86ad5f 30
sPymbed 17:ff9d1e86ad5f 31 #ifndef WOLFCRYPT_ONLY
sPymbed 17:ff9d1e86ad5f 32 #ifdef HAVE_OCSP
sPymbed 17:ff9d1e86ad5f 33
sPymbed 17:ff9d1e86ad5f 34 #include <wolfssl/error-ssl.h>
sPymbed 17:ff9d1e86ad5f 35 #include <wolfssl/ocsp.h>
sPymbed 17:ff9d1e86ad5f 36 #include <wolfssl/internal.h>
sPymbed 17:ff9d1e86ad5f 37
sPymbed 17:ff9d1e86ad5f 38 #ifdef NO_INLINE
sPymbed 17:ff9d1e86ad5f 39 #include <wolfcrypt/misc.h>
sPymbed 17:ff9d1e86ad5f 40 #else
sPymbed 17:ff9d1e86ad5f 41 #define WOLFSSL_MISC_INCLUDED
sPymbed 17:ff9d1e86ad5f 42 #include <wolfcrypt/src/misc.c>
sPymbed 17:ff9d1e86ad5f 43 #endif
sPymbed 17:ff9d1e86ad5f 44
sPymbed 17:ff9d1e86ad5f 45
sPymbed 17:ff9d1e86ad5f 46 int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
sPymbed 17:ff9d1e86ad5f 47 {
sPymbed 17:ff9d1e86ad5f 48 WOLFSSL_ENTER("InitOCSP");
sPymbed 17:ff9d1e86ad5f 49
sPymbed 17:ff9d1e86ad5f 50 ForceZero(ocsp, sizeof(WOLFSSL_OCSP));
sPymbed 17:ff9d1e86ad5f 51
sPymbed 17:ff9d1e86ad5f 52 if (wc_InitMutex(&ocsp->ocspLock) != 0)
sPymbed 17:ff9d1e86ad5f 53 return BAD_MUTEX_E;
sPymbed 17:ff9d1e86ad5f 54
sPymbed 17:ff9d1e86ad5f 55 ocsp->cm = cm;
sPymbed 17:ff9d1e86ad5f 56
sPymbed 17:ff9d1e86ad5f 57 return 0;
sPymbed 17:ff9d1e86ad5f 58 }
sPymbed 17:ff9d1e86ad5f 59
sPymbed 17:ff9d1e86ad5f 60
sPymbed 17:ff9d1e86ad5f 61 static int InitOcspEntry(OcspEntry* entry, OcspRequest* request)
sPymbed 17:ff9d1e86ad5f 62 {
sPymbed 17:ff9d1e86ad5f 63 WOLFSSL_ENTER("InitOcspEntry");
sPymbed 17:ff9d1e86ad5f 64
sPymbed 17:ff9d1e86ad5f 65 ForceZero(entry, sizeof(OcspEntry));
sPymbed 17:ff9d1e86ad5f 66
sPymbed 17:ff9d1e86ad5f 67 XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE);
sPymbed 17:ff9d1e86ad5f 68 XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE);
sPymbed 17:ff9d1e86ad5f 69
sPymbed 17:ff9d1e86ad5f 70 return 0;
sPymbed 17:ff9d1e86ad5f 71 }
sPymbed 17:ff9d1e86ad5f 72
sPymbed 17:ff9d1e86ad5f 73
sPymbed 17:ff9d1e86ad5f 74 static void FreeOcspEntry(OcspEntry* entry, void* heap)
sPymbed 17:ff9d1e86ad5f 75 {
sPymbed 17:ff9d1e86ad5f 76 CertStatus *status, *next;
sPymbed 17:ff9d1e86ad5f 77
sPymbed 17:ff9d1e86ad5f 78 WOLFSSL_ENTER("FreeOcspEntry");
sPymbed 17:ff9d1e86ad5f 79
sPymbed 17:ff9d1e86ad5f 80 for (status = entry->status; status; status = next) {
sPymbed 17:ff9d1e86ad5f 81 next = status->next;
sPymbed 17:ff9d1e86ad5f 82
sPymbed 17:ff9d1e86ad5f 83 if (status->rawOcspResponse)
sPymbed 17:ff9d1e86ad5f 84 XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS);
sPymbed 17:ff9d1e86ad5f 85
sPymbed 17:ff9d1e86ad5f 86 XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS);
sPymbed 17:ff9d1e86ad5f 87 }
sPymbed 17:ff9d1e86ad5f 88
sPymbed 17:ff9d1e86ad5f 89 (void)heap;
sPymbed 17:ff9d1e86ad5f 90 }
sPymbed 17:ff9d1e86ad5f 91
sPymbed 17:ff9d1e86ad5f 92
sPymbed 17:ff9d1e86ad5f 93 void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
sPymbed 17:ff9d1e86ad5f 94 {
sPymbed 17:ff9d1e86ad5f 95 OcspEntry *entry, *next;
sPymbed 17:ff9d1e86ad5f 96
sPymbed 17:ff9d1e86ad5f 97 WOLFSSL_ENTER("FreeOCSP");
sPymbed 17:ff9d1e86ad5f 98
sPymbed 17:ff9d1e86ad5f 99 for (entry = ocsp->ocspList; entry; entry = next) {
sPymbed 17:ff9d1e86ad5f 100 next = entry->next;
sPymbed 17:ff9d1e86ad5f 101 FreeOcspEntry(entry, ocsp->cm->heap);
sPymbed 17:ff9d1e86ad5f 102 XFREE(entry, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
sPymbed 17:ff9d1e86ad5f 103 }
sPymbed 17:ff9d1e86ad5f 104
sPymbed 17:ff9d1e86ad5f 105 wc_FreeMutex(&ocsp->ocspLock);
sPymbed 17:ff9d1e86ad5f 106
sPymbed 17:ff9d1e86ad5f 107 if (dynamic)
sPymbed 17:ff9d1e86ad5f 108 XFREE(ocsp, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
sPymbed 17:ff9d1e86ad5f 109
sPymbed 17:ff9d1e86ad5f 110 }
sPymbed 17:ff9d1e86ad5f 111
sPymbed 17:ff9d1e86ad5f 112
sPymbed 17:ff9d1e86ad5f 113 static int xstat2err(int st)
sPymbed 17:ff9d1e86ad5f 114 {
sPymbed 17:ff9d1e86ad5f 115 switch (st) {
sPymbed 17:ff9d1e86ad5f 116 case CERT_GOOD:
sPymbed 17:ff9d1e86ad5f 117 return 0;
sPymbed 17:ff9d1e86ad5f 118 case CERT_REVOKED:
sPymbed 17:ff9d1e86ad5f 119 return OCSP_CERT_REVOKED;
sPymbed 17:ff9d1e86ad5f 120 default:
sPymbed 17:ff9d1e86ad5f 121 return OCSP_CERT_UNKNOWN;
sPymbed 17:ff9d1e86ad5f 122 }
sPymbed 17:ff9d1e86ad5f 123 }
sPymbed 17:ff9d1e86ad5f 124
sPymbed 17:ff9d1e86ad5f 125 int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl)
sPymbed 17:ff9d1e86ad5f 126 {
sPymbed 17:ff9d1e86ad5f 127 int ret = OCSP_LOOKUP_FAIL;
sPymbed 17:ff9d1e86ad5f 128
sPymbed 17:ff9d1e86ad5f 129 #ifdef WOLFSSL_SMALL_STACK
sPymbed 17:ff9d1e86ad5f 130 OcspRequest* ocspRequest;
sPymbed 17:ff9d1e86ad5f 131 #else
sPymbed 17:ff9d1e86ad5f 132 OcspRequest ocspRequest[1];
sPymbed 17:ff9d1e86ad5f 133 #endif
sPymbed 17:ff9d1e86ad5f 134
sPymbed 17:ff9d1e86ad5f 135 WOLFSSL_ENTER("CheckCertOCSP");
sPymbed 17:ff9d1e86ad5f 136
sPymbed 17:ff9d1e86ad5f 137
sPymbed 17:ff9d1e86ad5f 138 #ifdef WOLFSSL_SMALL_STACK
sPymbed 17:ff9d1e86ad5f 139 ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
sPymbed 17:ff9d1e86ad5f 140 DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 141 if (ocspRequest == NULL) {
sPymbed 17:ff9d1e86ad5f 142 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
sPymbed 17:ff9d1e86ad5f 143 return MEMORY_E;
sPymbed 17:ff9d1e86ad5f 144 }
sPymbed 17:ff9d1e86ad5f 145 #endif
sPymbed 17:ff9d1e86ad5f 146
sPymbed 17:ff9d1e86ad5f 147 if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
sPymbed 17:ff9d1e86ad5f 148 ocsp->cm->heap) == 0) {
sPymbed 17:ff9d1e86ad5f 149 ocspRequest->ssl = ssl;
sPymbed 17:ff9d1e86ad5f 150 ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer);
sPymbed 17:ff9d1e86ad5f 151
sPymbed 17:ff9d1e86ad5f 152 FreeOcspRequest(ocspRequest);
sPymbed 17:ff9d1e86ad5f 153 }
sPymbed 17:ff9d1e86ad5f 154
sPymbed 17:ff9d1e86ad5f 155 #ifdef WOLFSSL_SMALL_STACK
sPymbed 17:ff9d1e86ad5f 156 XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 157 #endif
sPymbed 17:ff9d1e86ad5f 158
sPymbed 17:ff9d1e86ad5f 159 WOLFSSL_LEAVE("CheckCertOCSP", ret);
sPymbed 17:ff9d1e86ad5f 160 return ret;
sPymbed 17:ff9d1e86ad5f 161 }
sPymbed 17:ff9d1e86ad5f 162 int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer)
sPymbed 17:ff9d1e86ad5f 163 {
sPymbed 17:ff9d1e86ad5f 164 return CheckCertOCSP_ex(ocsp, cert, responseBuffer, NULL);
sPymbed 17:ff9d1e86ad5f 165 }
sPymbed 17:ff9d1e86ad5f 166
sPymbed 17:ff9d1e86ad5f 167 static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
sPymbed 17:ff9d1e86ad5f 168 OcspEntry** entry)
sPymbed 17:ff9d1e86ad5f 169 {
sPymbed 17:ff9d1e86ad5f 170 WOLFSSL_ENTER("GetOcspEntry");
sPymbed 17:ff9d1e86ad5f 171
sPymbed 17:ff9d1e86ad5f 172 *entry = NULL;
sPymbed 17:ff9d1e86ad5f 173
sPymbed 17:ff9d1e86ad5f 174 if (wc_LockMutex(&ocsp->ocspLock) != 0) {
sPymbed 17:ff9d1e86ad5f 175 WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
sPymbed 17:ff9d1e86ad5f 176 return BAD_MUTEX_E;
sPymbed 17:ff9d1e86ad5f 177 }
sPymbed 17:ff9d1e86ad5f 178
sPymbed 17:ff9d1e86ad5f 179 for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next)
sPymbed 17:ff9d1e86ad5f 180 if (XMEMCMP((*entry)->issuerHash, request->issuerHash,
sPymbed 17:ff9d1e86ad5f 181 OCSP_DIGEST_SIZE) == 0
sPymbed 17:ff9d1e86ad5f 182 && XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash,
sPymbed 17:ff9d1e86ad5f 183 OCSP_DIGEST_SIZE) == 0)
sPymbed 17:ff9d1e86ad5f 184 break;
sPymbed 17:ff9d1e86ad5f 185
sPymbed 17:ff9d1e86ad5f 186 if (*entry == NULL) {
sPymbed 17:ff9d1e86ad5f 187 *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry),
sPymbed 17:ff9d1e86ad5f 188 ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
sPymbed 17:ff9d1e86ad5f 189 if (*entry) {
sPymbed 17:ff9d1e86ad5f 190 InitOcspEntry(*entry, request);
sPymbed 17:ff9d1e86ad5f 191 (*entry)->next = ocsp->ocspList;
sPymbed 17:ff9d1e86ad5f 192 ocsp->ocspList = *entry;
sPymbed 17:ff9d1e86ad5f 193 }
sPymbed 17:ff9d1e86ad5f 194 }
sPymbed 17:ff9d1e86ad5f 195
sPymbed 17:ff9d1e86ad5f 196 wc_UnLockMutex(&ocsp->ocspLock);
sPymbed 17:ff9d1e86ad5f 197
sPymbed 17:ff9d1e86ad5f 198 return *entry ? 0 : MEMORY_ERROR;
sPymbed 17:ff9d1e86ad5f 199 }
sPymbed 17:ff9d1e86ad5f 200
sPymbed 17:ff9d1e86ad5f 201
sPymbed 17:ff9d1e86ad5f 202 static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
sPymbed 17:ff9d1e86ad5f 203 OcspEntry* entry, CertStatus** status, buffer* responseBuffer)
sPymbed 17:ff9d1e86ad5f 204 {
sPymbed 17:ff9d1e86ad5f 205 int ret = OCSP_INVALID_STATUS;
sPymbed 17:ff9d1e86ad5f 206
sPymbed 17:ff9d1e86ad5f 207 WOLFSSL_ENTER("GetOcspStatus");
sPymbed 17:ff9d1e86ad5f 208
sPymbed 17:ff9d1e86ad5f 209 *status = NULL;
sPymbed 17:ff9d1e86ad5f 210
sPymbed 17:ff9d1e86ad5f 211 if (wc_LockMutex(&ocsp->ocspLock) != 0) {
sPymbed 17:ff9d1e86ad5f 212 WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
sPymbed 17:ff9d1e86ad5f 213 return BAD_MUTEX_E;
sPymbed 17:ff9d1e86ad5f 214 }
sPymbed 17:ff9d1e86ad5f 215
sPymbed 17:ff9d1e86ad5f 216 for (*status = entry->status; *status; *status = (*status)->next)
sPymbed 17:ff9d1e86ad5f 217 if ((*status)->serialSz == request->serialSz
sPymbed 17:ff9d1e86ad5f 218 && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz))
sPymbed 17:ff9d1e86ad5f 219 break;
sPymbed 17:ff9d1e86ad5f 220
sPymbed 17:ff9d1e86ad5f 221 if (responseBuffer && *status && !(*status)->rawOcspResponse) {
sPymbed 17:ff9d1e86ad5f 222 /* force fetching again */
sPymbed 17:ff9d1e86ad5f 223 ret = OCSP_INVALID_STATUS;
sPymbed 17:ff9d1e86ad5f 224 }
sPymbed 17:ff9d1e86ad5f 225 else if (*status) {
sPymbed 17:ff9d1e86ad5f 226 #ifndef NO_ASN_TIME
sPymbed 17:ff9d1e86ad5f 227 if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE)
sPymbed 17:ff9d1e86ad5f 228 && ((*status)->nextDate[0] != 0)
sPymbed 17:ff9d1e86ad5f 229 && ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER))
sPymbed 17:ff9d1e86ad5f 230 #endif
sPymbed 17:ff9d1e86ad5f 231 {
sPymbed 17:ff9d1e86ad5f 232 ret = xstat2err((*status)->status);
sPymbed 17:ff9d1e86ad5f 233
sPymbed 17:ff9d1e86ad5f 234 if (responseBuffer) {
sPymbed 17:ff9d1e86ad5f 235 responseBuffer->buffer = (byte*)XMALLOC(
sPymbed 17:ff9d1e86ad5f 236 (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 237
sPymbed 17:ff9d1e86ad5f 238 if (responseBuffer->buffer) {
sPymbed 17:ff9d1e86ad5f 239 responseBuffer->length = (*status)->rawOcspResponseSz;
sPymbed 17:ff9d1e86ad5f 240 XMEMCPY(responseBuffer->buffer,
sPymbed 17:ff9d1e86ad5f 241 (*status)->rawOcspResponse,
sPymbed 17:ff9d1e86ad5f 242 (*status)->rawOcspResponseSz);
sPymbed 17:ff9d1e86ad5f 243 }
sPymbed 17:ff9d1e86ad5f 244 }
sPymbed 17:ff9d1e86ad5f 245 }
sPymbed 17:ff9d1e86ad5f 246 }
sPymbed 17:ff9d1e86ad5f 247
sPymbed 17:ff9d1e86ad5f 248 wc_UnLockMutex(&ocsp->ocspLock);
sPymbed 17:ff9d1e86ad5f 249
sPymbed 17:ff9d1e86ad5f 250 return ret;
sPymbed 17:ff9d1e86ad5f 251 }
sPymbed 17:ff9d1e86ad5f 252
sPymbed 17:ff9d1e86ad5f 253 /* Check that the response for validity. Store result in status.
sPymbed 17:ff9d1e86ad5f 254 *
sPymbed 17:ff9d1e86ad5f 255 * ocsp Context object for OCSP status.
sPymbed 17:ff9d1e86ad5f 256 * response OCSP response message data.
sPymbed 17:ff9d1e86ad5f 257 * responseSz Length of OCSP response message data.
sPymbed 17:ff9d1e86ad5f 258 * reponseBuffer Buffer object to return the response with.
sPymbed 17:ff9d1e86ad5f 259 * status The certificate status object.
sPymbed 17:ff9d1e86ad5f 260 * entry The OCSP entry for this certificate.
sPymbed 17:ff9d1e86ad5f 261 * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise.
sPymbed 17:ff9d1e86ad5f 262 */
sPymbed 17:ff9d1e86ad5f 263 static int CheckResponse(WOLFSSL_OCSP* ocsp, byte* response, int responseSz,
sPymbed 17:ff9d1e86ad5f 264 buffer* responseBuffer, CertStatus* status,
sPymbed 17:ff9d1e86ad5f 265 OcspEntry* entry, OcspRequest* ocspRequest)
sPymbed 17:ff9d1e86ad5f 266 {
sPymbed 17:ff9d1e86ad5f 267 #ifdef WOLFSSL_SMALL_STACK
sPymbed 17:ff9d1e86ad5f 268 CertStatus* newStatus;
sPymbed 17:ff9d1e86ad5f 269 OcspResponse* ocspResponse;
sPymbed 17:ff9d1e86ad5f 270 #else
sPymbed 17:ff9d1e86ad5f 271 CertStatus newStatus[1];
sPymbed 17:ff9d1e86ad5f 272 OcspResponse ocspResponse[1];
sPymbed 17:ff9d1e86ad5f 273 #endif
sPymbed 17:ff9d1e86ad5f 274 int ret;
sPymbed 17:ff9d1e86ad5f 275 int validated = 0; /* ocsp validation flag */
sPymbed 17:ff9d1e86ad5f 276
sPymbed 17:ff9d1e86ad5f 277 #ifdef WOLFSSL_SMALL_STACK
sPymbed 17:ff9d1e86ad5f 278 newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
sPymbed 17:ff9d1e86ad5f 279 DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 280 ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
sPymbed 17:ff9d1e86ad5f 281 DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 282
sPymbed 17:ff9d1e86ad5f 283 if (newStatus == NULL || ocspResponse == NULL) {
sPymbed 17:ff9d1e86ad5f 284 if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 285 if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 286
sPymbed 17:ff9d1e86ad5f 287 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
sPymbed 17:ff9d1e86ad5f 288 return MEMORY_E;
sPymbed 17:ff9d1e86ad5f 289 }
sPymbed 17:ff9d1e86ad5f 290 #endif
sPymbed 17:ff9d1e86ad5f 291 XMEMSET(newStatus, 0, sizeof(CertStatus));
sPymbed 17:ff9d1e86ad5f 292
sPymbed 17:ff9d1e86ad5f 293 InitOcspResponse(ocspResponse, newStatus, response, responseSz);
sPymbed 17:ff9d1e86ad5f 294 ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
sPymbed 17:ff9d1e86ad5f 295 if (ret != 0) {
sPymbed 17:ff9d1e86ad5f 296 WOLFSSL_MSG("OcspResponseDecode failed");
sPymbed 17:ff9d1e86ad5f 297 goto end;
sPymbed 17:ff9d1e86ad5f 298 }
sPymbed 17:ff9d1e86ad5f 299
sPymbed 17:ff9d1e86ad5f 300 if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) {
sPymbed 17:ff9d1e86ad5f 301 WOLFSSL_MSG("OcspResponse status bad");
sPymbed 17:ff9d1e86ad5f 302 goto end;
sPymbed 17:ff9d1e86ad5f 303 }
sPymbed 17:ff9d1e86ad5f 304 if (ocspRequest != NULL) {
sPymbed 17:ff9d1e86ad5f 305 ret = CompareOcspReqResp(ocspRequest, ocspResponse);
sPymbed 17:ff9d1e86ad5f 306 if (ret != 0) {
sPymbed 17:ff9d1e86ad5f 307 goto end;
sPymbed 17:ff9d1e86ad5f 308 }
sPymbed 17:ff9d1e86ad5f 309 }
sPymbed 17:ff9d1e86ad5f 310
sPymbed 17:ff9d1e86ad5f 311 if (responseBuffer) {
sPymbed 17:ff9d1e86ad5f 312 responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap,
sPymbed 17:ff9d1e86ad5f 313 DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 314
sPymbed 17:ff9d1e86ad5f 315 if (responseBuffer->buffer) {
sPymbed 17:ff9d1e86ad5f 316 responseBuffer->length = responseSz;
sPymbed 17:ff9d1e86ad5f 317 XMEMCPY(responseBuffer->buffer, response, responseSz);
sPymbed 17:ff9d1e86ad5f 318 }
sPymbed 17:ff9d1e86ad5f 319 }
sPymbed 17:ff9d1e86ad5f 320
sPymbed 17:ff9d1e86ad5f 321 ret = xstat2err(ocspResponse->status->status);
sPymbed 17:ff9d1e86ad5f 322 if (ret == 0) {
sPymbed 17:ff9d1e86ad5f 323 validated = 1;
sPymbed 17:ff9d1e86ad5f 324 }
sPymbed 17:ff9d1e86ad5f 325
sPymbed 17:ff9d1e86ad5f 326 if (wc_LockMutex(&ocsp->ocspLock) != 0) {
sPymbed 17:ff9d1e86ad5f 327 ret = BAD_MUTEX_E;
sPymbed 17:ff9d1e86ad5f 328 goto end;
sPymbed 17:ff9d1e86ad5f 329 }
sPymbed 17:ff9d1e86ad5f 330
sPymbed 17:ff9d1e86ad5f 331 if (status != NULL) {
sPymbed 17:ff9d1e86ad5f 332 if (status->rawOcspResponse) {
sPymbed 17:ff9d1e86ad5f 333 XFREE(status->rawOcspResponse, ocsp->cm->heap,
sPymbed 17:ff9d1e86ad5f 334 DYNAMIC_TYPE_OCSP_STATUS);
sPymbed 17:ff9d1e86ad5f 335 }
sPymbed 17:ff9d1e86ad5f 336
sPymbed 17:ff9d1e86ad5f 337 /* Replace existing certificate entry with updated */
sPymbed 17:ff9d1e86ad5f 338 XMEMCPY(status, newStatus, sizeof(CertStatus));
sPymbed 17:ff9d1e86ad5f 339 }
sPymbed 17:ff9d1e86ad5f 340 else {
sPymbed 17:ff9d1e86ad5f 341 /* Save new certificate entry */
sPymbed 17:ff9d1e86ad5f 342 status = (CertStatus*)XMALLOC(sizeof(CertStatus),
sPymbed 17:ff9d1e86ad5f 343 ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
sPymbed 17:ff9d1e86ad5f 344 if (status != NULL) {
sPymbed 17:ff9d1e86ad5f 345 XMEMCPY(status, newStatus, sizeof(CertStatus));
sPymbed 17:ff9d1e86ad5f 346 status->next = entry->status;
sPymbed 17:ff9d1e86ad5f 347 entry->status = status;
sPymbed 17:ff9d1e86ad5f 348 entry->totalStatus++;
sPymbed 17:ff9d1e86ad5f 349 }
sPymbed 17:ff9d1e86ad5f 350 }
sPymbed 17:ff9d1e86ad5f 351
sPymbed 17:ff9d1e86ad5f 352 if (status && responseBuffer && responseBuffer->buffer) {
sPymbed 17:ff9d1e86ad5f 353 status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length,
sPymbed 17:ff9d1e86ad5f 354 ocsp->cm->heap,
sPymbed 17:ff9d1e86ad5f 355 DYNAMIC_TYPE_OCSP_STATUS);
sPymbed 17:ff9d1e86ad5f 356
sPymbed 17:ff9d1e86ad5f 357 if (status->rawOcspResponse) {
sPymbed 17:ff9d1e86ad5f 358 status->rawOcspResponseSz = responseBuffer->length;
sPymbed 17:ff9d1e86ad5f 359 XMEMCPY(status->rawOcspResponse, responseBuffer->buffer,
sPymbed 17:ff9d1e86ad5f 360 responseBuffer->length);
sPymbed 17:ff9d1e86ad5f 361 }
sPymbed 17:ff9d1e86ad5f 362 }
sPymbed 17:ff9d1e86ad5f 363
sPymbed 17:ff9d1e86ad5f 364 wc_UnLockMutex(&ocsp->ocspLock);
sPymbed 17:ff9d1e86ad5f 365
sPymbed 17:ff9d1e86ad5f 366 end:
sPymbed 17:ff9d1e86ad5f 367 if (ret == 0 && validated == 1) {
sPymbed 17:ff9d1e86ad5f 368 WOLFSSL_MSG("New OcspResponse validated");
sPymbed 17:ff9d1e86ad5f 369 } else if (ret != OCSP_CERT_REVOKED) {
sPymbed 17:ff9d1e86ad5f 370 ret = OCSP_LOOKUP_FAIL;
sPymbed 17:ff9d1e86ad5f 371 }
sPymbed 17:ff9d1e86ad5f 372
sPymbed 17:ff9d1e86ad5f 373 #ifdef WOLFSSL_SMALL_STACK
sPymbed 17:ff9d1e86ad5f 374 XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 375 XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 376 #endif
sPymbed 17:ff9d1e86ad5f 377 return ret;
sPymbed 17:ff9d1e86ad5f 378 }
sPymbed 17:ff9d1e86ad5f 379
sPymbed 17:ff9d1e86ad5f 380 /* 0 on success */
sPymbed 17:ff9d1e86ad5f 381 int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
sPymbed 17:ff9d1e86ad5f 382 buffer* responseBuffer)
sPymbed 17:ff9d1e86ad5f 383 {
sPymbed 17:ff9d1e86ad5f 384 OcspEntry* entry = NULL;
sPymbed 17:ff9d1e86ad5f 385 CertStatus* status = NULL;
sPymbed 17:ff9d1e86ad5f 386 byte* request = NULL;
sPymbed 17:ff9d1e86ad5f 387 int requestSz = 2048;
sPymbed 17:ff9d1e86ad5f 388 int responseSz = 0;
sPymbed 17:ff9d1e86ad5f 389 byte* response = NULL;
sPymbed 17:ff9d1e86ad5f 390 const char* url = NULL;
sPymbed 17:ff9d1e86ad5f 391 int urlSz = 0;
sPymbed 17:ff9d1e86ad5f 392 int ret = -1;
sPymbed 17:ff9d1e86ad5f 393 WOLFSSL* ssl;
sPymbed 17:ff9d1e86ad5f 394 void* ioCtx;
sPymbed 17:ff9d1e86ad5f 395
sPymbed 17:ff9d1e86ad5f 396 WOLFSSL_ENTER("CheckOcspRequest");
sPymbed 17:ff9d1e86ad5f 397
sPymbed 17:ff9d1e86ad5f 398 if (ocsp == NULL || ocspRequest == NULL)
sPymbed 17:ff9d1e86ad5f 399 return BAD_FUNC_ARG;
sPymbed 17:ff9d1e86ad5f 400
sPymbed 17:ff9d1e86ad5f 401 if (responseBuffer) {
sPymbed 17:ff9d1e86ad5f 402 responseBuffer->buffer = NULL;
sPymbed 17:ff9d1e86ad5f 403 responseBuffer->length = 0;
sPymbed 17:ff9d1e86ad5f 404 }
sPymbed 17:ff9d1e86ad5f 405
sPymbed 17:ff9d1e86ad5f 406 ret = GetOcspEntry(ocsp, ocspRequest, &entry);
sPymbed 17:ff9d1e86ad5f 407 if (ret != 0)
sPymbed 17:ff9d1e86ad5f 408 return ret;
sPymbed 17:ff9d1e86ad5f 409
sPymbed 17:ff9d1e86ad5f 410 ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer);
sPymbed 17:ff9d1e86ad5f 411 if (ret != OCSP_INVALID_STATUS)
sPymbed 17:ff9d1e86ad5f 412 return ret;
sPymbed 17:ff9d1e86ad5f 413
sPymbed 17:ff9d1e86ad5f 414 /* get SSL and IOCtx */
sPymbed 17:ff9d1e86ad5f 415 ssl = (WOLFSSL*)ocspRequest->ssl;
sPymbed 17:ff9d1e86ad5f 416 ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
sPymbed 17:ff9d1e86ad5f 417 ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
sPymbed 17:ff9d1e86ad5f 418
sPymbed 17:ff9d1e86ad5f 419 #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
sPymbed 17:ff9d1e86ad5f 420 if (ocsp->statusCb != NULL && ssl != NULL) {
sPymbed 17:ff9d1e86ad5f 421 ret = ocsp->statusCb(ssl, ioCtx);
sPymbed 17:ff9d1e86ad5f 422 if (ret == 0) {
sPymbed 17:ff9d1e86ad5f 423 ret = wolfSSL_get_ocsp_response(ssl, &response);
sPymbed 17:ff9d1e86ad5f 424 ret = CheckResponse(ocsp, response, ret, responseBuffer, status,
sPymbed 17:ff9d1e86ad5f 425 entry, NULL);
sPymbed 17:ff9d1e86ad5f 426 if (response != NULL)
sPymbed 17:ff9d1e86ad5f 427 XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 428 return ret;
sPymbed 17:ff9d1e86ad5f 429 }
sPymbed 17:ff9d1e86ad5f 430 return OCSP_LOOKUP_FAIL;
sPymbed 17:ff9d1e86ad5f 431 }
sPymbed 17:ff9d1e86ad5f 432 #endif
wolfSSL 15:117db924cf7c 433
sPymbed 17:ff9d1e86ad5f 434 if (ocsp->cm->ocspUseOverrideURL) {
sPymbed 17:ff9d1e86ad5f 435 url = ocsp->cm->ocspOverrideURL;
sPymbed 17:ff9d1e86ad5f 436 if (url != NULL && url[0] != '\0')
sPymbed 17:ff9d1e86ad5f 437 urlSz = (int)XSTRLEN(url);
sPymbed 17:ff9d1e86ad5f 438 else
sPymbed 17:ff9d1e86ad5f 439 return OCSP_NEED_URL;
sPymbed 17:ff9d1e86ad5f 440 }
sPymbed 17:ff9d1e86ad5f 441 else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) {
sPymbed 17:ff9d1e86ad5f 442 url = (const char *)ocspRequest->url;
sPymbed 17:ff9d1e86ad5f 443 urlSz = ocspRequest->urlSz;
sPymbed 17:ff9d1e86ad5f 444 }
sPymbed 17:ff9d1e86ad5f 445 else {
sPymbed 17:ff9d1e86ad5f 446 /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
sPymbed 17:ff9d1e86ad5f 447 return 0;
sPymbed 17:ff9d1e86ad5f 448 }
sPymbed 17:ff9d1e86ad5f 449
sPymbed 17:ff9d1e86ad5f 450 request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
sPymbed 17:ff9d1e86ad5f 451 if (request == NULL) {
sPymbed 17:ff9d1e86ad5f 452 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
sPymbed 17:ff9d1e86ad5f 453 return MEMORY_ERROR;
sPymbed 17:ff9d1e86ad5f 454 }
sPymbed 17:ff9d1e86ad5f 455
sPymbed 17:ff9d1e86ad5f 456 requestSz = EncodeOcspRequest(ocspRequest, request, requestSz);
sPymbed 17:ff9d1e86ad5f 457 if (requestSz > 0 && ocsp->cm->ocspIOCb) {
sPymbed 17:ff9d1e86ad5f 458 responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz,
sPymbed 17:ff9d1e86ad5f 459 request, requestSz, &response);
sPymbed 17:ff9d1e86ad5f 460 }
sPymbed 17:ff9d1e86ad5f 461 if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) {
sPymbed 17:ff9d1e86ad5f 462 ret = OCSP_WANT_READ;
sPymbed 17:ff9d1e86ad5f 463 }
sPymbed 17:ff9d1e86ad5f 464
sPymbed 17:ff9d1e86ad5f 465 XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
sPymbed 17:ff9d1e86ad5f 466
sPymbed 17:ff9d1e86ad5f 467 if (responseSz >= 0 && response) {
sPymbed 17:ff9d1e86ad5f 468 ret = CheckResponse(ocsp, response, responseSz, responseBuffer, status,
sPymbed 17:ff9d1e86ad5f 469 entry, ocspRequest);
sPymbed 17:ff9d1e86ad5f 470 }
sPymbed 17:ff9d1e86ad5f 471
sPymbed 17:ff9d1e86ad5f 472 if (response != NULL && ocsp->cm->ocspRespFreeCb)
sPymbed 17:ff9d1e86ad5f 473 ocsp->cm->ocspRespFreeCb(ioCtx, response);
sPymbed 17:ff9d1e86ad5f 474
sPymbed 17:ff9d1e86ad5f 475 WOLFSSL_LEAVE("CheckOcspRequest", ret);
sPymbed 17:ff9d1e86ad5f 476 return ret;
sPymbed 17:ff9d1e86ad5f 477 }
sPymbed 17:ff9d1e86ad5f 478
sPymbed 17:ff9d1e86ad5f 479 #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
sPymbed 17:ff9d1e86ad5f 480
sPymbed 17:ff9d1e86ad5f 481 int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
sPymbed 17:ff9d1e86ad5f 482 WOLFSSL_OCSP_CERTID* id, int* status, int* reason,
sPymbed 17:ff9d1e86ad5f 483 WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd,
sPymbed 17:ff9d1e86ad5f 484 WOLFSSL_ASN1_TIME** nextupd)
sPymbed 17:ff9d1e86ad5f 485 {
sPymbed 17:ff9d1e86ad5f 486 if (bs == NULL || id == NULL)
sPymbed 17:ff9d1e86ad5f 487 return WOLFSSL_FAILURE;
sPymbed 17:ff9d1e86ad5f 488
sPymbed 17:ff9d1e86ad5f 489 /* Only supporting one certificate status in asn.c. */
sPymbed 17:ff9d1e86ad5f 490 if (CompareOcspReqResp(id, bs) != 0)
sPymbed 17:ff9d1e86ad5f 491 return WOLFSSL_FAILURE;
sPymbed 17:ff9d1e86ad5f 492
sPymbed 17:ff9d1e86ad5f 493 if (status != NULL)
sPymbed 17:ff9d1e86ad5f 494 *status = bs->status->status;
sPymbed 17:ff9d1e86ad5f 495 if (thisupd != NULL)
sPymbed 17:ff9d1e86ad5f 496 *thisupd = (WOLFSSL_ASN1_TIME*)bs->status->thisDateAsn;
sPymbed 17:ff9d1e86ad5f 497 if (nextupd != NULL)
sPymbed 17:ff9d1e86ad5f 498 *nextupd = (WOLFSSL_ASN1_TIME*)bs->status->nextDateAsn;
sPymbed 17:ff9d1e86ad5f 499
sPymbed 17:ff9d1e86ad5f 500 /* TODO: Not needed for Nginx. */
sPymbed 17:ff9d1e86ad5f 501 if (reason != NULL)
sPymbed 17:ff9d1e86ad5f 502 *reason = 0;
sPymbed 17:ff9d1e86ad5f 503 if (revtime != NULL)
sPymbed 17:ff9d1e86ad5f 504 *revtime = NULL;
sPymbed 17:ff9d1e86ad5f 505
sPymbed 17:ff9d1e86ad5f 506 return WOLFSSL_SUCCESS;
sPymbed 17:ff9d1e86ad5f 507 }
sPymbed 17:ff9d1e86ad5f 508
sPymbed 17:ff9d1e86ad5f 509 const char *wolfSSL_OCSP_cert_status_str(long s)
sPymbed 17:ff9d1e86ad5f 510 {
sPymbed 17:ff9d1e86ad5f 511 switch (s) {
sPymbed 17:ff9d1e86ad5f 512 case CERT_GOOD:
sPymbed 17:ff9d1e86ad5f 513 return "good";
sPymbed 17:ff9d1e86ad5f 514 case CERT_REVOKED:
sPymbed 17:ff9d1e86ad5f 515 return "revoked";
sPymbed 17:ff9d1e86ad5f 516 case CERT_UNKNOWN:
sPymbed 17:ff9d1e86ad5f 517 return "unknown";
sPymbed 17:ff9d1e86ad5f 518 default:
sPymbed 17:ff9d1e86ad5f 519 return "(UNKNOWN)";
sPymbed 17:ff9d1e86ad5f 520 }
sPymbed 17:ff9d1e86ad5f 521 }
sPymbed 17:ff9d1e86ad5f 522
sPymbed 17:ff9d1e86ad5f 523 int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd,
sPymbed 17:ff9d1e86ad5f 524 WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec)
sPymbed 17:ff9d1e86ad5f 525 {
sPymbed 17:ff9d1e86ad5f 526 (void)thisupd;
sPymbed 17:ff9d1e86ad5f 527 (void)nextupd;
sPymbed 17:ff9d1e86ad5f 528 (void)sec;
sPymbed 17:ff9d1e86ad5f 529 (void)maxsec;
sPymbed 17:ff9d1e86ad5f 530 /* Dates validated in DecodeSingleResponse. */
sPymbed 17:ff9d1e86ad5f 531 return WOLFSSL_SUCCESS;
sPymbed 17:ff9d1e86ad5f 532 }
sPymbed 17:ff9d1e86ad5f 533
sPymbed 17:ff9d1e86ad5f 534 void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId)
sPymbed 17:ff9d1e86ad5f 535 {
sPymbed 17:ff9d1e86ad5f 536 FreeOcspRequest(certId);
sPymbed 17:ff9d1e86ad5f 537 XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 538 }
sPymbed 17:ff9d1e86ad5f 539
sPymbed 17:ff9d1e86ad5f 540 WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
sPymbed 17:ff9d1e86ad5f 541 const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject,
sPymbed 17:ff9d1e86ad5f 542 const WOLFSSL_X509 *issuer)
sPymbed 17:ff9d1e86ad5f 543 {
sPymbed 17:ff9d1e86ad5f 544 WOLFSSL_OCSP_CERTID* certId;
sPymbed 17:ff9d1e86ad5f 545 DecodedCert cert;
sPymbed 17:ff9d1e86ad5f 546 WOLFSSL_CERT_MANAGER* cm;
sPymbed 17:ff9d1e86ad5f 547 int ret;
sPymbed 17:ff9d1e86ad5f 548 DerBuffer* derCert = NULL;
sPymbed 17:ff9d1e86ad5f 549
sPymbed 17:ff9d1e86ad5f 550 (void)dgst;
sPymbed 17:ff9d1e86ad5f 551
sPymbed 17:ff9d1e86ad5f 552 cm = wolfSSL_CertManagerNew();
sPymbed 17:ff9d1e86ad5f 553 if (cm == NULL)
sPymbed 17:ff9d1e86ad5f 554 return NULL;
sPymbed 17:ff9d1e86ad5f 555
sPymbed 17:ff9d1e86ad5f 556 ret = AllocDer(&derCert, issuer->derCert->length,
sPymbed 17:ff9d1e86ad5f 557 issuer->derCert->type, NULL);
sPymbed 17:ff9d1e86ad5f 558 if (ret == 0) {
sPymbed 17:ff9d1e86ad5f 559 /* AddCA() frees the buffer. */
sPymbed 17:ff9d1e86ad5f 560 XMEMCPY(derCert->buffer, issuer->derCert->buffer,
sPymbed 17:ff9d1e86ad5f 561 issuer->derCert->length);
sPymbed 17:ff9d1e86ad5f 562 AddCA(cm, &derCert, WOLFSSL_USER_CA, 1);
sPymbed 17:ff9d1e86ad5f 563 }
sPymbed 17:ff9d1e86ad5f 564
sPymbed 17:ff9d1e86ad5f 565 certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL,
sPymbed 17:ff9d1e86ad5f 566 DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 567 if (certId != NULL) {
sPymbed 17:ff9d1e86ad5f 568 InitDecodedCert(&cert, subject->derCert->buffer,
sPymbed 17:ff9d1e86ad5f 569 subject->derCert->length, NULL);
sPymbed 17:ff9d1e86ad5f 570 if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) {
sPymbed 17:ff9d1e86ad5f 571 XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 572 certId = NULL;
sPymbed 17:ff9d1e86ad5f 573 }
sPymbed 17:ff9d1e86ad5f 574 else {
sPymbed 17:ff9d1e86ad5f 575 ret = InitOcspRequest(certId, &cert, 0, NULL);
sPymbed 17:ff9d1e86ad5f 576 if (ret != 0) {
sPymbed 17:ff9d1e86ad5f 577 XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 578 certId = NULL;
sPymbed 17:ff9d1e86ad5f 579 }
sPymbed 17:ff9d1e86ad5f 580 }
sPymbed 17:ff9d1e86ad5f 581 FreeDecodedCert(&cert);
sPymbed 17:ff9d1e86ad5f 582 }
sPymbed 17:ff9d1e86ad5f 583
sPymbed 17:ff9d1e86ad5f 584 wolfSSL_CertManagerFree(cm);
sPymbed 17:ff9d1e86ad5f 585
sPymbed 17:ff9d1e86ad5f 586 return certId;
sPymbed 17:ff9d1e86ad5f 587 }
sPymbed 17:ff9d1e86ad5f 588
sPymbed 17:ff9d1e86ad5f 589 void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
sPymbed 17:ff9d1e86ad5f 590 {
sPymbed 17:ff9d1e86ad5f 591 wolfSSL_OCSP_RESPONSE_free(basicResponse);
sPymbed 17:ff9d1e86ad5f 592 }
sPymbed 17:ff9d1e86ad5f 593
sPymbed 17:ff9d1e86ad5f 594 /* Signature verified in DecodeBasicOcspResponse.
sPymbed 17:ff9d1e86ad5f 595 * But no store available to verify certificate. */
sPymbed 17:ff9d1e86ad5f 596 int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs,
sPymbed 17:ff9d1e86ad5f 597 WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags)
sPymbed 17:ff9d1e86ad5f 598 {
sPymbed 17:ff9d1e86ad5f 599 DecodedCert cert;
sPymbed 17:ff9d1e86ad5f 600 int ret = WOLFSSL_SUCCESS;
sPymbed 17:ff9d1e86ad5f 601
sPymbed 17:ff9d1e86ad5f 602 (void)certs;
sPymbed 17:ff9d1e86ad5f 603
sPymbed 17:ff9d1e86ad5f 604 if (flags & OCSP_NOVERIFY)
sPymbed 17:ff9d1e86ad5f 605 return WOLFSSL_SUCCESS;
sPymbed 17:ff9d1e86ad5f 606
sPymbed 17:ff9d1e86ad5f 607 #ifdef OPENSSL_EXTRA
sPymbed 17:ff9d1e86ad5f 608 if (bs->verifyError != OCSP_VERIFY_ERROR_NONE)
sPymbed 17:ff9d1e86ad5f 609 return WOLFSSL_FAILURE;
sPymbed 17:ff9d1e86ad5f 610 #endif
sPymbed 17:ff9d1e86ad5f 611
sPymbed 17:ff9d1e86ad5f 612 InitDecodedCert(&cert, bs->cert, bs->certSz, NULL);
sPymbed 17:ff9d1e86ad5f 613 if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0)
sPymbed 17:ff9d1e86ad5f 614 ret = WOLFSSL_FAILURE;
sPymbed 17:ff9d1e86ad5f 615 FreeDecodedCert(&cert);
sPymbed 17:ff9d1e86ad5f 616
sPymbed 17:ff9d1e86ad5f 617 return ret;
sPymbed 17:ff9d1e86ad5f 618 }
sPymbed 17:ff9d1e86ad5f 619
sPymbed 17:ff9d1e86ad5f 620 void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
sPymbed 17:ff9d1e86ad5f 621 {
sPymbed 17:ff9d1e86ad5f 622 if (response->status != NULL)
sPymbed 17:ff9d1e86ad5f 623 XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 624 if (response->source != NULL)
sPymbed 17:ff9d1e86ad5f 625 XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 626 XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 627 }
sPymbed 17:ff9d1e86ad5f 628
sPymbed 17:ff9d1e86ad5f 629 OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
sPymbed 17:ff9d1e86ad5f 630 OcspResponse** response)
sPymbed 17:ff9d1e86ad5f 631 {
sPymbed 17:ff9d1e86ad5f 632 byte* data;
sPymbed 17:ff9d1e86ad5f 633 byte* p;
sPymbed 17:ff9d1e86ad5f 634 int len;
sPymbed 17:ff9d1e86ad5f 635 int dataAlloced = 0;
sPymbed 17:ff9d1e86ad5f 636 OcspResponse* ret = NULL;
sPymbed 17:ff9d1e86ad5f 637
sPymbed 17:ff9d1e86ad5f 638 if (bio == NULL)
sPymbed 17:ff9d1e86ad5f 639 return NULL;
sPymbed 17:ff9d1e86ad5f 640
sPymbed 17:ff9d1e86ad5f 641 if (bio->type == WOLFSSL_BIO_MEMORY) {
sPymbed 17:ff9d1e86ad5f 642 len = wolfSSL_BIO_get_mem_data(bio, &data);
sPymbed 17:ff9d1e86ad5f 643 if (len <= 0 || data == NULL) {
sPymbed 17:ff9d1e86ad5f 644 return NULL;
sPymbed 17:ff9d1e86ad5f 645 }
sPymbed 17:ff9d1e86ad5f 646 }
sPymbed 17:ff9d1e86ad5f 647 #ifndef NO_FILESYSTEM
sPymbed 17:ff9d1e86ad5f 648 else if (bio->type == WOLFSSL_BIO_FILE) {
sPymbed 17:ff9d1e86ad5f 649 long i;
sPymbed 17:ff9d1e86ad5f 650 long l;
sPymbed 17:ff9d1e86ad5f 651
sPymbed 17:ff9d1e86ad5f 652 i = XFTELL(bio->file);
sPymbed 17:ff9d1e86ad5f 653 if (i < 0)
sPymbed 17:ff9d1e86ad5f 654 return NULL;
sPymbed 17:ff9d1e86ad5f 655 XFSEEK(bio->file, 0, SEEK_END);
sPymbed 17:ff9d1e86ad5f 656 l = XFTELL(bio->file);
sPymbed 17:ff9d1e86ad5f 657 if (l < 0)
sPymbed 17:ff9d1e86ad5f 658 return NULL;
sPymbed 17:ff9d1e86ad5f 659 if (XFSEEK(bio->file, i, SEEK_SET) != 0)
sPymbed 17:ff9d1e86ad5f 660 return NULL;
sPymbed 17:ff9d1e86ad5f 661
sPymbed 17:ff9d1e86ad5f 662 /* check calculated length */
sPymbed 17:ff9d1e86ad5f 663 if (l - i <= 0)
sPymbed 17:ff9d1e86ad5f 664 return NULL;
sPymbed 17:ff9d1e86ad5f 665
sPymbed 17:ff9d1e86ad5f 666 data = (byte*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 667 if (data == NULL)
sPymbed 17:ff9d1e86ad5f 668 return NULL;
sPymbed 17:ff9d1e86ad5f 669 dataAlloced = 1;
sPymbed 17:ff9d1e86ad5f 670
sPymbed 17:ff9d1e86ad5f 671 len = wolfSSL_BIO_read(bio, (char *)data, (int)l);
sPymbed 17:ff9d1e86ad5f 672 }
sPymbed 17:ff9d1e86ad5f 673 #endif
sPymbed 17:ff9d1e86ad5f 674 else
sPymbed 17:ff9d1e86ad5f 675 return NULL;
sPymbed 17:ff9d1e86ad5f 676
sPymbed 17:ff9d1e86ad5f 677 if (len > 0) {
sPymbed 17:ff9d1e86ad5f 678 p = data;
sPymbed 17:ff9d1e86ad5f 679 ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, len);
sPymbed 17:ff9d1e86ad5f 680 }
sPymbed 17:ff9d1e86ad5f 681
sPymbed 17:ff9d1e86ad5f 682 if (dataAlloced)
sPymbed 17:ff9d1e86ad5f 683 XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 684
sPymbed 17:ff9d1e86ad5f 685 return ret;
sPymbed 17:ff9d1e86ad5f 686 }
sPymbed 17:ff9d1e86ad5f 687
sPymbed 17:ff9d1e86ad5f 688 OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
sPymbed 17:ff9d1e86ad5f 689 const unsigned char** data, int len)
sPymbed 17:ff9d1e86ad5f 690 {
sPymbed 17:ff9d1e86ad5f 691 OcspResponse *resp = NULL;
sPymbed 17:ff9d1e86ad5f 692 word32 idx = 0;
sPymbed 17:ff9d1e86ad5f 693 int length = 0;
sPymbed 17:ff9d1e86ad5f 694
sPymbed 17:ff9d1e86ad5f 695 if (data == NULL)
sPymbed 17:ff9d1e86ad5f 696 return NULL;
sPymbed 17:ff9d1e86ad5f 697
sPymbed 17:ff9d1e86ad5f 698 if (response != NULL)
sPymbed 17:ff9d1e86ad5f 699 resp = *response;
sPymbed 17:ff9d1e86ad5f 700 if (resp == NULL) {
sPymbed 17:ff9d1e86ad5f 701 resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
sPymbed 17:ff9d1e86ad5f 702 DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 703 if (resp == NULL)
sPymbed 17:ff9d1e86ad5f 704 return NULL;
sPymbed 17:ff9d1e86ad5f 705 XMEMSET(resp, 0, sizeof(OcspResponse));
sPymbed 17:ff9d1e86ad5f 706 }
sPymbed 17:ff9d1e86ad5f 707
sPymbed 17:ff9d1e86ad5f 708 resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 709 if (resp->source == NULL) {
sPymbed 17:ff9d1e86ad5f 710 XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 711 return NULL;
sPymbed 17:ff9d1e86ad5f 712 }
sPymbed 17:ff9d1e86ad5f 713 resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
sPymbed 17:ff9d1e86ad5f 714 DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 715 if (resp->status == NULL) {
sPymbed 17:ff9d1e86ad5f 716 XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 717 XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 718 return NULL;
sPymbed 17:ff9d1e86ad5f 719 }
sPymbed 17:ff9d1e86ad5f 720
sPymbed 17:ff9d1e86ad5f 721 XMEMCPY(resp->source, *data, len);
sPymbed 17:ff9d1e86ad5f 722 resp->maxIdx = len;
sPymbed 17:ff9d1e86ad5f 723
sPymbed 17:ff9d1e86ad5f 724 if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) {
sPymbed 17:ff9d1e86ad5f 725 wolfSSL_OCSP_RESPONSE_free(resp);
sPymbed 17:ff9d1e86ad5f 726 return NULL;
sPymbed 17:ff9d1e86ad5f 727 }
sPymbed 17:ff9d1e86ad5f 728
sPymbed 17:ff9d1e86ad5f 729 if (GetSequence(*data, &idx, &length, len) >= 0)
sPymbed 17:ff9d1e86ad5f 730 (*data) += idx + length;
sPymbed 17:ff9d1e86ad5f 731
sPymbed 17:ff9d1e86ad5f 732 return resp;
sPymbed 17:ff9d1e86ad5f 733 }
sPymbed 17:ff9d1e86ad5f 734
sPymbed 17:ff9d1e86ad5f 735 int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response,
sPymbed 17:ff9d1e86ad5f 736 unsigned char** data)
sPymbed 17:ff9d1e86ad5f 737 {
sPymbed 17:ff9d1e86ad5f 738 if (data == NULL)
sPymbed 17:ff9d1e86ad5f 739 return response->maxIdx;
sPymbed 17:ff9d1e86ad5f 740
sPymbed 17:ff9d1e86ad5f 741 XMEMCPY(*data, response->source, response->maxIdx);
sPymbed 17:ff9d1e86ad5f 742 return response->maxIdx;
sPymbed 17:ff9d1e86ad5f 743 }
sPymbed 17:ff9d1e86ad5f 744
sPymbed 17:ff9d1e86ad5f 745 int wolfSSL_OCSP_response_status(OcspResponse *response)
sPymbed 17:ff9d1e86ad5f 746 {
sPymbed 17:ff9d1e86ad5f 747 return response->responseStatus;
sPymbed 17:ff9d1e86ad5f 748 }
sPymbed 17:ff9d1e86ad5f 749
sPymbed 17:ff9d1e86ad5f 750 const char *wolfSSL_OCSP_response_status_str(long s)
sPymbed 17:ff9d1e86ad5f 751 {
sPymbed 17:ff9d1e86ad5f 752 switch (s) {
sPymbed 17:ff9d1e86ad5f 753 case OCSP_SUCCESSFUL:
sPymbed 17:ff9d1e86ad5f 754 return "successful";
sPymbed 17:ff9d1e86ad5f 755 case OCSP_MALFORMED_REQUEST:
sPymbed 17:ff9d1e86ad5f 756 return "malformedrequest";
sPymbed 17:ff9d1e86ad5f 757 case OCSP_INTERNAL_ERROR:
sPymbed 17:ff9d1e86ad5f 758 return "internalerror";
sPymbed 17:ff9d1e86ad5f 759 case OCSP_TRY_LATER:
sPymbed 17:ff9d1e86ad5f 760 return "trylater";
sPymbed 17:ff9d1e86ad5f 761 case OCSP_SIG_REQUIRED:
sPymbed 17:ff9d1e86ad5f 762 return "sigrequired";
sPymbed 17:ff9d1e86ad5f 763 case OCSP_UNAUTHROIZED:
sPymbed 17:ff9d1e86ad5f 764 return "unauthorized";
sPymbed 17:ff9d1e86ad5f 765 default:
sPymbed 17:ff9d1e86ad5f 766 return "(UNKNOWN)";
sPymbed 17:ff9d1e86ad5f 767 }
sPymbed 17:ff9d1e86ad5f 768 }
sPymbed 17:ff9d1e86ad5f 769
sPymbed 17:ff9d1e86ad5f 770 WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
sPymbed 17:ff9d1e86ad5f 771 {
sPymbed 17:ff9d1e86ad5f 772 WOLFSSL_OCSP_BASICRESP* bs;
sPymbed 17:ff9d1e86ad5f 773
sPymbed 17:ff9d1e86ad5f 774 bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL,
sPymbed 17:ff9d1e86ad5f 775 DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 776 if (bs == NULL)
sPymbed 17:ff9d1e86ad5f 777 return NULL;
sPymbed 17:ff9d1e86ad5f 778
sPymbed 17:ff9d1e86ad5f 779 XMEMCPY(bs, response, sizeof(OcspResponse));
sPymbed 17:ff9d1e86ad5f 780 bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
sPymbed 17:ff9d1e86ad5f 781 DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 782 bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 783 if (bs->status == NULL || bs->source == NULL) {
sPymbed 17:ff9d1e86ad5f 784 if (bs->status) XFREE(bs->status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 785 if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
sPymbed 17:ff9d1e86ad5f 786 wolfSSL_OCSP_RESPONSE_free(bs);
sPymbed 17:ff9d1e86ad5f 787 bs = NULL;
sPymbed 17:ff9d1e86ad5f 788 }
sPymbed 17:ff9d1e86ad5f 789 else {
sPymbed 17:ff9d1e86ad5f 790 XMEMCPY(bs->status, response->status, sizeof(CertStatus));
sPymbed 17:ff9d1e86ad5f 791 XMEMCPY(bs->source, response->source, response->maxIdx);
sPymbed 17:ff9d1e86ad5f 792 }
sPymbed 17:ff9d1e86ad5f 793 return bs;
sPymbed 17:ff9d1e86ad5f 794 }
sPymbed 17:ff9d1e86ad5f 795
sPymbed 17:ff9d1e86ad5f 796 OcspRequest* wolfSSL_OCSP_REQUEST_new(void)
sPymbed 17:ff9d1e86ad5f 797 {
sPymbed 17:ff9d1e86ad5f 798 OcspRequest* request;
sPymbed 17:ff9d1e86ad5f 799
sPymbed 17:ff9d1e86ad5f 800 request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
sPymbed 17:ff9d1e86ad5f 801 DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 802 if (request != NULL)
sPymbed 17:ff9d1e86ad5f 803 XMEMSET(request, 0, sizeof(OcspRequest));
sPymbed 17:ff9d1e86ad5f 804
sPymbed 17:ff9d1e86ad5f 805 return request;
sPymbed 17:ff9d1e86ad5f 806 }
sPymbed 17:ff9d1e86ad5f 807
sPymbed 17:ff9d1e86ad5f 808 void wolfSSL_OCSP_REQUEST_free(OcspRequest* request)
sPymbed 17:ff9d1e86ad5f 809 {
sPymbed 17:ff9d1e86ad5f 810 FreeOcspRequest(request);
sPymbed 17:ff9d1e86ad5f 811 XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL);
sPymbed 17:ff9d1e86ad5f 812 }
sPymbed 17:ff9d1e86ad5f 813
sPymbed 17:ff9d1e86ad5f 814 int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data)
sPymbed 17:ff9d1e86ad5f 815 {
sPymbed 17:ff9d1e86ad5f 816 word32 size;
sPymbed 17:ff9d1e86ad5f 817
sPymbed 17:ff9d1e86ad5f 818 size = EncodeOcspRequest(request, NULL, 0);
sPymbed 17:ff9d1e86ad5f 819 if (size <= 0 || data == NULL)
sPymbed 17:ff9d1e86ad5f 820 return size;
sPymbed 17:ff9d1e86ad5f 821
sPymbed 17:ff9d1e86ad5f 822 return EncodeOcspRequest(request, *data, size);
sPymbed 17:ff9d1e86ad5f 823 }
sPymbed 17:ff9d1e86ad5f 824
sPymbed 17:ff9d1e86ad5f 825 WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
sPymbed 17:ff9d1e86ad5f 826 WOLFSSL_OCSP_CERTID *cid)
sPymbed 17:ff9d1e86ad5f 827 {
sPymbed 17:ff9d1e86ad5f 828 if (req == NULL || cid == NULL)
sPymbed 17:ff9d1e86ad5f 829 return NULL;
sPymbed 17:ff9d1e86ad5f 830
sPymbed 17:ff9d1e86ad5f 831 FreeOcspRequest(req);
sPymbed 17:ff9d1e86ad5f 832 XMEMCPY(req, cid, sizeof(OcspRequest));
sPymbed 17:ff9d1e86ad5f 833
sPymbed 17:ff9d1e86ad5f 834 if (cid->serial != NULL) {
sPymbed 17:ff9d1e86ad5f 835 req->serial = (byte*)XMALLOC(cid->serialSz, NULL,
sPymbed 17:ff9d1e86ad5f 836 DYNAMIC_TYPE_OCSP_REQUEST);
sPymbed 17:ff9d1e86ad5f 837 req->url = (byte*)XMALLOC(cid->urlSz, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
sPymbed 17:ff9d1e86ad5f 838 if (req->serial == NULL || req->url == NULL) {
sPymbed 17:ff9d1e86ad5f 839 FreeOcspRequest(req);
sPymbed 17:ff9d1e86ad5f 840 return NULL;
sPymbed 17:ff9d1e86ad5f 841 }
sPymbed 17:ff9d1e86ad5f 842
sPymbed 17:ff9d1e86ad5f 843 XMEMCPY(req->serial, cid->serial, cid->serialSz);
sPymbed 17:ff9d1e86ad5f 844 XMEMCPY(req->url, cid->url, cid->urlSz);
sPymbed 17:ff9d1e86ad5f 845 }
sPymbed 17:ff9d1e86ad5f 846
sPymbed 17:ff9d1e86ad5f 847 wolfSSL_OCSP_REQUEST_free(cid);
sPymbed 17:ff9d1e86ad5f 848
sPymbed 17:ff9d1e86ad5f 849 return req;
sPymbed 17:ff9d1e86ad5f 850 }
sPymbed 17:ff9d1e86ad5f 851
sPymbed 17:ff9d1e86ad5f 852 #endif
sPymbed 17:ff9d1e86ad5f 853
sPymbed 17:ff9d1e86ad5f 854 #else /* HAVE_OCSP */
sPymbed 17:ff9d1e86ad5f 855
sPymbed 17:ff9d1e86ad5f 856
sPymbed 17:ff9d1e86ad5f 857 #ifdef _MSC_VER
sPymbed 17:ff9d1e86ad5f 858 /* 4206 warning for blank file */
sPymbed 17:ff9d1e86ad5f 859 #pragma warning(disable: 4206)
sPymbed 17:ff9d1e86ad5f 860 #endif
sPymbed 17:ff9d1e86ad5f 861
sPymbed 17:ff9d1e86ad5f 862
sPymbed 17:ff9d1e86ad5f 863 #endif /* HAVE_OCSP */
sPymbed 17:ff9d1e86ad5f 864 #endif /* WOLFCRYPT_ONLY */
sPymbed 17:ff9d1e86ad5f 865
sPymbed 17:ff9d1e86ad5f 866