source: azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/src/ocsp.c

Last change on this file was 464, checked in by coas-nagasima, 3 years ago

WolfSSLとAzure IoT SDKを更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 34.4 KB
Line 
1/* ocsp.c
2 *
3 * Copyright (C) 2006-2020 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22
23 /* Name change compatibility layer no longer needs to be included here */
24
25#ifdef HAVE_CONFIG_H
26 #include <config.h>
27#endif
28
29#include <wolfssl/wolfcrypt/settings.h>
30
31#ifndef WOLFCRYPT_ONLY
32#ifdef HAVE_OCSP
33
34#include <wolfssl/error-ssl.h>
35#include <wolfssl/ocsp.h>
36#include <wolfssl/internal.h>
37
38#ifdef NO_INLINE
39 #include <wolfssl/wolfcrypt/misc.h>
40#else
41 #define WOLFSSL_MISC_INCLUDED
42 #include <wolfcrypt/src/misc.c>
43#endif
44
45
46int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
47{
48 WOLFSSL_ENTER("InitOCSP");
49
50 ForceZero(ocsp, sizeof(WOLFSSL_OCSP));
51
52 if (wc_InitMutex(&ocsp->ocspLock) != 0)
53 return BAD_MUTEX_E;
54
55 ocsp->cm = cm;
56
57 return 0;
58}
59
60
61static int InitOcspEntry(OcspEntry* entry, OcspRequest* request)
62{
63 WOLFSSL_ENTER("InitOcspEntry");
64
65 ForceZero(entry, sizeof(OcspEntry));
66
67 XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE);
68 XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE);
69
70 return 0;
71}
72
73
74static void FreeOcspEntry(OcspEntry* entry, void* heap)
75{
76 CertStatus *status, *next;
77
78 if (entry == NULL)
79 return;
80
81 WOLFSSL_ENTER("FreeOcspEntry");
82
83 for (status = entry->status; status; status = next) {
84 next = status->next;
85
86 if (status->rawOcspResponse)
87 XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS);
88
89#ifdef OPENSSL_EXTRA
90 if (status->serialInt) {
91 if (status->serialInt->isDynamic) {
92 XFREE(status->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL);
93 }
94 XFREE(status->serialInt, NULL, DYNAMIC_TYPE_OPENSSL);
95 }
96 status->serialInt = NULL;
97#endif
98
99 XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS);
100 }
101
102 (void)heap;
103}
104
105
106void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
107{
108 OcspEntry *entry, *next;
109
110 WOLFSSL_ENTER("FreeOCSP");
111
112 for (entry = ocsp->ocspList; entry; entry = next) {
113 next = entry->next;
114 FreeOcspEntry(entry, ocsp->cm->heap);
115 XFREE(entry, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
116 }
117
118 wc_FreeMutex(&ocsp->ocspLock);
119
120 if (dynamic)
121 XFREE(ocsp, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
122
123}
124
125
126static int xstat2err(int st)
127{
128 switch (st) {
129 case CERT_GOOD:
130 return 0;
131 case CERT_REVOKED:
132 return OCSP_CERT_REVOKED;
133 default:
134 return OCSP_CERT_UNKNOWN;
135 }
136}
137
138int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl)
139{
140 int ret = OCSP_LOOKUP_FAIL;
141
142#ifdef WOLFSSL_SMALL_STACK
143 OcspRequest* ocspRequest;
144#else
145 OcspRequest ocspRequest[1];
146#endif
147
148 WOLFSSL_ENTER("CheckCertOCSP");
149
150
151#ifdef WOLFSSL_SMALL_STACK
152 ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
153 DYNAMIC_TYPE_TMP_BUFFER);
154 if (ocspRequest == NULL) {
155 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
156 return MEMORY_E;
157 }
158#endif
159
160 if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
161 ocsp->cm->heap) == 0) {
162 ocspRequest->ssl = ssl;
163 ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer);
164
165 FreeOcspRequest(ocspRequest);
166 }
167
168#ifdef WOLFSSL_SMALL_STACK
169 XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
170#endif
171
172 WOLFSSL_LEAVE("CheckCertOCSP", ret);
173 return ret;
174}
175int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer)
176{
177 return CheckCertOCSP_ex(ocsp, cert, responseBuffer, NULL);
178}
179
180static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
181 OcspEntry** entry)
182{
183 WOLFSSL_ENTER("GetOcspEntry");
184
185 *entry = NULL;
186
187 if (wc_LockMutex(&ocsp->ocspLock) != 0) {
188 WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
189 return BAD_MUTEX_E;
190 }
191
192 for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next)
193 if (XMEMCMP((*entry)->issuerHash, request->issuerHash,
194 OCSP_DIGEST_SIZE) == 0
195 && XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash,
196 OCSP_DIGEST_SIZE) == 0)
197 break;
198
199 if (*entry == NULL) {
200 *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry),
201 ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
202 if (*entry) {
203 InitOcspEntry(*entry, request);
204 (*entry)->next = ocsp->ocspList;
205 ocsp->ocspList = *entry;
206 }
207 }
208
209 wc_UnLockMutex(&ocsp->ocspLock);
210
211 return *entry ? 0 : MEMORY_ERROR;
212}
213
214
215/* Mallocs responseBuffer->buffer and is up to caller to free on success
216 *
217 * Returns OCSP status
218 */
219static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
220 OcspEntry* entry, CertStatus** status, buffer* responseBuffer)
221{
222 int ret = OCSP_INVALID_STATUS;
223
224 WOLFSSL_ENTER("GetOcspStatus");
225
226 *status = NULL;
227
228 if (wc_LockMutex(&ocsp->ocspLock) != 0) {
229 WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E);
230 return BAD_MUTEX_E;
231 }
232
233 for (*status = entry->status; *status; *status = (*status)->next)
234 if ((*status)->serialSz == request->serialSz
235 && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz))
236 break;
237
238 if (responseBuffer && *status && !(*status)->rawOcspResponse) {
239 /* force fetching again */
240 ret = OCSP_INVALID_STATUS;
241 }
242 else if (*status) {
243#ifndef NO_ASN_TIME
244 if (XVALIDATE_DATE((*status)->thisDate,
245 (*status)->thisDateFormat, BEFORE)
246 && ((*status)->nextDate[0] != 0)
247 && XVALIDATE_DATE((*status)->nextDate,
248 (*status)->nextDateFormat, AFTER))
249#endif
250 {
251 ret = xstat2err((*status)->status);
252
253 if (responseBuffer) {
254 responseBuffer->buffer = (byte*)XMALLOC(
255 (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
256
257 if (responseBuffer->buffer) {
258 responseBuffer->length = (*status)->rawOcspResponseSz;
259 XMEMCPY(responseBuffer->buffer,
260 (*status)->rawOcspResponse,
261 (*status)->rawOcspResponseSz);
262 }
263 }
264 }
265 }
266
267 wc_UnLockMutex(&ocsp->ocspLock);
268
269 return ret;
270}
271
272/* Check that the response for validity. Store result in status.
273 *
274 * ocsp Context object for OCSP status.
275 * response OCSP response message data.
276 * responseSz Length of OCSP response message data.
277 * reponseBuffer Buffer object to return the response with.
278 * status The certificate status object.
279 * entry The OCSP entry for this certificate.
280 * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise.
281 */
282WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
283 WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status,
284 OcspEntry *entry, OcspRequest *ocspRequest)
285{
286#ifdef WOLFSSL_SMALL_STACK
287 CertStatus* newStatus;
288 OcspEntry* newSingle;
289 OcspResponse* ocspResponse;
290#else
291 CertStatus newStatus[1];
292 OcspEntry newSingle[1];
293 OcspResponse ocspResponse[1];
294#endif
295 int ret;
296 int validated = 0; /* ocsp validation flag */
297
298#ifdef WOLFSSL_SMALL_STACK
299 newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
300 DYNAMIC_TYPE_OCSP_STATUS);
301 newSingle = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
302 DYNAMIC_TYPE_OCSP_ENTRY);
303 ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
304 DYNAMIC_TYPE_OCSP_REQUEST);
305
306 if (newStatus == NULL || newSingle == NULL || ocspResponse == NULL) {
307 if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS);
308 if (newSingle) XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
309 if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
310
311 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
312 return MEMORY_E;
313 }
314#endif
315 InitOcspResponse(ocspResponse, newSingle, newStatus, response, responseSz,
316 ocsp->cm->heap);
317
318 ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
319 if (ret != 0) {
320 ocsp->error = ret;
321 WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error);
322 goto end;
323 }
324
325 if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) {
326 WOLFSSL_MSG("OcspResponse status bad");
327 goto end;
328 }
329 if (ocspRequest != NULL) {
330 ret = CompareOcspReqResp(ocspRequest, ocspResponse);
331 if (ret != 0) {
332 goto end;
333 }
334 }
335
336 if (responseBuffer) {
337 responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap,
338 DYNAMIC_TYPE_TMP_BUFFER);
339
340 if (responseBuffer->buffer) {
341 responseBuffer->length = responseSz;
342 XMEMCPY(responseBuffer->buffer, response, responseSz);
343 }
344 }
345
346 ret = xstat2err(ocspResponse->single->status->status);
347 if (ret == 0) {
348 validated = 1;
349 }
350
351 if (wc_LockMutex(&ocsp->ocspLock) != 0) {
352 ret = BAD_MUTEX_E;
353 goto end;
354 }
355
356 if (status != NULL) {
357 if (status->rawOcspResponse) {
358 XFREE(status->rawOcspResponse, ocsp->cm->heap,
359 DYNAMIC_TYPE_OCSP_STATUS);
360 }
361
362 /* Replace existing certificate entry with updated */
363 newSingle->status->next = status->next;
364 XMEMCPY(status, newSingle->status, sizeof(CertStatus));
365 }
366 else {
367 /* Save new certificate entry */
368 status = (CertStatus*)XMALLOC(sizeof(CertStatus),
369 ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
370 if (status != NULL) {
371 XMEMCPY(status, newSingle->status, sizeof(CertStatus));
372 status->next = entry->status;
373 entry->status = status;
374 entry->totalStatus++;
375 }
376 }
377
378 if (status && responseBuffer && responseBuffer->buffer) {
379 status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length,
380 ocsp->cm->heap,
381 DYNAMIC_TYPE_OCSP_STATUS);
382
383 if (status->rawOcspResponse) {
384 status->rawOcspResponseSz = responseBuffer->length;
385 XMEMCPY(status->rawOcspResponse, responseBuffer->buffer,
386 responseBuffer->length);
387 }
388 }
389
390 wc_UnLockMutex(&ocsp->ocspLock);
391
392end:
393 if (ret == 0 && validated == 1) {
394 WOLFSSL_MSG("New OcspResponse validated");
395 } else if (ret != OCSP_CERT_REVOKED) {
396 ret = OCSP_LOOKUP_FAIL;
397 }
398
399#ifdef WOLFSSL_SMALL_STACK
400 XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS);
401 XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
402 XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
403#endif
404 return ret;
405}
406
407/* 0 on success */
408int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
409 buffer* responseBuffer)
410{
411 OcspEntry* entry = NULL;
412 CertStatus* status = NULL;
413 byte* request = NULL;
414 int requestSz = 2048;
415 int responseSz = 0;
416 byte* response = NULL;
417 const char* url = NULL;
418 int urlSz = 0;
419 int ret = -1;
420 WOLFSSL* ssl;
421 void* ioCtx;
422
423 WOLFSSL_ENTER("CheckOcspRequest");
424
425 if (ocsp == NULL || ocspRequest == NULL)
426 return BAD_FUNC_ARG;
427
428 if (responseBuffer) {
429 responseBuffer->buffer = NULL;
430 responseBuffer->length = 0;
431 }
432
433 ret = GetOcspEntry(ocsp, ocspRequest, &entry);
434 if (ret != 0)
435 return ret;
436
437 ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer);
438 if (ret != OCSP_INVALID_STATUS)
439 return ret;
440
441 /* get SSL and IOCtx */
442 ssl = (WOLFSSL*)ocspRequest->ssl;
443 ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
444 ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
445
446#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
447 if (ocsp->statusCb != NULL && ssl != NULL) {
448 ret = ocsp->statusCb(ssl, ioCtx);
449 if (ret == 0) {
450 ret = wolfSSL_get_ocsp_response(ssl, &response);
451 ret = CheckOcspResponse(ocsp, response, ret, responseBuffer, status,
452 entry, NULL);
453 if (response != NULL)
454 XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
455 return ret;
456 }
457 WOLFSSL_LEAVE("CheckOcspRequest", ocsp->error);
458 return OCSP_LOOKUP_FAIL;
459 }
460#endif
461
462 if (ocsp->cm->ocspUseOverrideURL) {
463 url = ocsp->cm->ocspOverrideURL;
464 if (url != NULL && url[0] != '\0')
465 urlSz = (int)XSTRLEN(url);
466 else
467 return OCSP_NEED_URL;
468 }
469 else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) {
470 url = (const char *)ocspRequest->url;
471 urlSz = ocspRequest->urlSz;
472 }
473 else {
474 /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
475 WOLFSSL_MSG("Cert has no OCSP URL, assuming CERT_GOOD");
476 return 0;
477 }
478
479 request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
480 if (request == NULL) {
481 WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
482 if (responseBuffer) {
483 XFREE(responseBuffer->buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
484 responseBuffer->buffer = NULL;
485 }
486 return MEMORY_ERROR;
487 }
488
489 requestSz = EncodeOcspRequest(ocspRequest, request, requestSz);
490 if (requestSz > 0 && ocsp->cm->ocspIOCb) {
491 responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz,
492 request, requestSz, &response);
493 }
494 if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) {
495 ret = OCSP_WANT_READ;
496 }
497
498 XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
499
500 if (responseSz >= 0 && response) {
501 ret = CheckOcspResponse(ocsp, response, responseSz, responseBuffer, status,
502 entry, ocspRequest);
503 }
504
505 if (response != NULL && ocsp->cm->ocspRespFreeCb)
506 ocsp->cm->ocspRespFreeCb(ioCtx, response);
507
508 /* Keep responseBuffer in the case of getting to response check. Caller
509 * should free responseBuffer after checking OCSP return value in "ret" */
510 WOLFSSL_LEAVE("CheckOcspRequest", ret);
511 return ret;
512}
513
514#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
515 defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIGHTY)
516
517int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
518 WOLFSSL_OCSP_CERTID* id, int* status, int* reason,
519 WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd,
520 WOLFSSL_ASN1_TIME** nextupd)
521{
522 WOLFSSL_OCSP_SINGLERESP* single;
523
524 if (bs == NULL || id == NULL)
525 return WOLFSSL_FAILURE;
526
527 single = bs->single;
528 while (single != NULL) {
529 if ((XMEMCMP(single->status->serial, id->status->serial, single->status->serialSz) == 0)
530 && (XMEMCMP(single->issuerHash, id->issuerHash, OCSP_DIGEST_SIZE) == 0)
531 && (XMEMCMP(single->issuerKeyHash, id->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) {
532 break;
533 }
534 single = single->next;
535 }
536
537 if (single == NULL)
538 return WOLFSSL_FAILURE;
539
540 if (status != NULL)
541 *status = single->status->status;
542 if (thisupd != NULL)
543 *thisupd = &single->status->thisDateParsed;
544 if (nextupd != NULL)
545 *nextupd = &single->status->nextDateParsed;
546
547 /* TODO: Not needed for Nginx or httpd */
548 if (reason != NULL)
549 *reason = 0;
550 if (revtime != NULL)
551 *revtime = NULL;
552
553 return WOLFSSL_SUCCESS;
554}
555
556const char *wolfSSL_OCSP_cert_status_str(long s)
557{
558 switch (s) {
559 case CERT_GOOD:
560 return "good";
561 case CERT_REVOKED:
562 return "revoked";
563 case CERT_UNKNOWN:
564 return "unknown";
565 default:
566 return "(UNKNOWN)";
567 }
568}
569
570int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd,
571 WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec)
572{
573 (void)thisupd;
574 (void)nextupd;
575 (void)sec;
576 (void)maxsec;
577 /* Dates validated in DecodeSingleResponse. */
578 return WOLFSSL_SUCCESS;
579}
580
581void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId)
582{
583 FreeOcspEntry(certId, NULL);
584 XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
585}
586
587WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
588 const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject,
589 const WOLFSSL_X509 *issuer)
590{
591 WOLFSSL_OCSP_CERTID* certId;
592 CertStatus* certStatus;
593 DecodedCert cert;
594 WOLFSSL_CERT_MANAGER* cm;
595 int ret;
596 DerBuffer* derCert = NULL;
597
598 (void)dgst;
599
600 cm = wolfSSL_CertManagerNew();
601 if (cm == NULL)
602 return NULL;
603
604 ret = AllocDer(&derCert, issuer->derCert->length,
605 issuer->derCert->type, NULL);
606 if (ret == 0) {
607 /* AddCA() frees the buffer. */
608 XMEMCPY(derCert->buffer, issuer->derCert->buffer,
609 issuer->derCert->length);
610 AddCA(cm, &derCert, WOLFSSL_USER_CA, 1);
611 }
612
613 certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL,
614 DYNAMIC_TYPE_OPENSSL);
615 certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
616 DYNAMIC_TYPE_OPENSSL);
617
618 if (certId == NULL || certStatus == NULL) {
619 if (certId)
620 XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
621 if (certStatus)
622 XFREE(certStatus, NULL, DYNAMIC_TYPE_OPENSSL);
623
624 return NULL;
625 }
626
627 XMEMSET(certId, 0, sizeof(WOLFSSL_OCSP_CERTID));
628 XMEMSET(certStatus, 0, sizeof(CertStatus));
629
630 certId->status = certStatus;
631
632 InitDecodedCert(&cert, subject->derCert->buffer,
633 subject->derCert->length, NULL);
634 if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) {
635 XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
636 certId = NULL;
637 }
638 else {
639 XMEMCPY(certId->issuerHash, cert.issuerHash, OCSP_DIGEST_SIZE);
640 XMEMCPY(certId->issuerKeyHash, cert.issuerKeyHash, OCSP_DIGEST_SIZE);
641 XMEMCPY(certId->status->serial, cert.serial, cert.serialSz);
642 certId->status->serialSz = cert.serialSz;
643 }
644 FreeDecodedCert(&cert);
645
646 wolfSSL_CertManagerFree(cm);
647
648 return certId;
649}
650
651void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
652{
653 wolfSSL_OCSP_RESPONSE_free(basicResponse);
654}
655
656/* Signature verified in DecodeBasicOcspResponse.
657 * But no store available to verify certificate. */
658int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs,
659 WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags)
660{
661 DecodedCert cert;
662 int ret = WOLFSSL_SUCCESS;
663
664 (void)certs;
665
666 if (flags & OCSP_NOVERIFY)
667 return WOLFSSL_SUCCESS;
668
669#ifdef OPENSSL_EXTRA
670 if (bs->verifyError != OCSP_VERIFY_ERROR_NONE)
671 return WOLFSSL_FAILURE;
672#endif
673
674 InitDecodedCert(&cert, bs->cert, bs->certSz, NULL);
675 if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0)
676 ret = WOLFSSL_FAILURE;
677 FreeDecodedCert(&cert);
678
679 return ret;
680}
681
682void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
683{
684 if (response == NULL)
685 return;
686
687 if (response->single != NULL) {
688 FreeOcspEntry(response->single, NULL);
689 XFREE(response->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
690 }
691
692 if (response->source != NULL)
693 XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
694
695 XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
696}
697
698#ifndef NO_BIO
699OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
700 OcspResponse** response)
701{
702 byte* data;
703 byte* p;
704 int len;
705 int dataAlloced = 0;
706 OcspResponse* ret = NULL;
707
708 if (bio == NULL)
709 return NULL;
710
711 if (bio->type == WOLFSSL_BIO_MEMORY) {
712 len = wolfSSL_BIO_get_mem_data(bio, &data);
713 if (len <= 0 || data == NULL) {
714 return NULL;
715 }
716 }
717#ifndef NO_FILESYSTEM
718 else if (bio->type == WOLFSSL_BIO_FILE) {
719 long fcur;
720 long flen;
721
722 if (bio->ptr == NULL)
723 return NULL;
724
725 fcur = XFTELL((XFILE)bio->ptr);
726 if (fcur < 0)
727 return NULL;
728 if(XFSEEK((XFILE)bio->ptr, 0, SEEK_END) != 0)
729 return NULL;
730 flen = XFTELL((XFILE)bio->ptr);
731 if (flen < 0)
732 return NULL;
733 if (XFSEEK((XFILE)bio->ptr, fcur, SEEK_SET) != 0)
734 return NULL;
735
736 /* check calculated length */
737 fcur = flen - fcur;
738 if (fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0)
739 return NULL;
740
741 data = (byte*)XMALLOC(fcur, 0, DYNAMIC_TYPE_TMP_BUFFER);
742 if (data == NULL)
743 return NULL;
744 dataAlloced = 1;
745
746 len = wolfSSL_BIO_read(bio, (char *)data, (int)flen);
747 }
748#endif
749 else
750 return NULL;
751
752 if (len > 0) {
753 p = data;
754 ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p,
755 len);
756 }
757
758 if (dataAlloced)
759 XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER);
760
761 return ret;
762}
763#endif /* !NO_BIO */
764
765OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
766 const unsigned char** data, int len)
767{
768 OcspResponse *resp = NULL;
769 word32 idx = 0;
770 int length = 0;
771
772 if (data == NULL)
773 return NULL;
774
775 if (response != NULL)
776 resp = *response;
777 if (resp == NULL) {
778 resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
779 DYNAMIC_TYPE_OCSP_REQUEST);
780 if (resp == NULL)
781 return NULL;
782 XMEMSET(resp, 0, sizeof(OcspResponse));
783 }
784
785 resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
786 if (resp->source == NULL) {
787 XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
788 return NULL;
789 }
790 resp->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
791 DYNAMIC_TYPE_OCSP_ENTRY);
792 if (resp->single == NULL) {
793 XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
794 XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
795 return NULL;
796 }
797 XMEMSET(resp->single, 0, sizeof(OcspEntry));
798 resp->single->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
799 DYNAMIC_TYPE_OCSP_STATUS);
800 if (resp->single->status == NULL) {
801 XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
802 XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
803 XFREE(resp->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
804 return NULL;
805 }
806 XMEMSET(resp->single->status, 0, sizeof(CertStatus));
807
808 XMEMCPY(resp->source, *data, len);
809 resp->maxIdx = len;
810
811 if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) {
812 wolfSSL_OCSP_RESPONSE_free(resp);
813 return NULL;
814 }
815
816 if (GetSequence(*data, &idx, &length, len) >= 0)
817 (*data) += idx + length;
818
819 return resp;
820}
821
822int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response,
823 unsigned char** data)
824{
825 if (data == NULL)
826 return response->maxIdx;
827
828 XMEMCPY(*data, response->source, response->maxIdx);
829 return response->maxIdx;
830}
831
832int wolfSSL_OCSP_response_status(OcspResponse *response)
833{
834 return response->responseStatus;
835}
836
837const char *wolfSSL_OCSP_response_status_str(long s)
838{
839 switch (s) {
840 case OCSP_SUCCESSFUL:
841 return "successful";
842 case OCSP_MALFORMED_REQUEST:
843 return "malformedrequest";
844 case OCSP_INTERNAL_ERROR:
845 return "internalerror";
846 case OCSP_TRY_LATER:
847 return "trylater";
848 case OCSP_SIG_REQUIRED:
849 return "sigrequired";
850 case OCSP_UNAUTHROIZED:
851 return "unauthorized";
852 default:
853 return "(UNKNOWN)";
854 }
855}
856
857WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
858{
859 WOLFSSL_OCSP_BASICRESP* bs;
860
861 bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL,
862 DYNAMIC_TYPE_OCSP_REQUEST);
863 if (bs == NULL)
864 return NULL;
865
866 XMEMCPY(bs, response, sizeof(OcspResponse));
867 bs->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
868 DYNAMIC_TYPE_OCSP_ENTRY);
869 bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
870 if (bs->single == NULL || bs->source == NULL) {
871 if (bs->single) XFREE(bs->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
872 if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
873 wolfSSL_OCSP_RESPONSE_free(bs);
874 bs = NULL;
875 }
876 else {
877 XMEMCPY(bs->single, response->single, sizeof(OcspEntry));
878 XMEMCPY(bs->source, response->source, response->maxIdx);
879 }
880 return bs;
881}
882
883OcspRequest* wolfSSL_OCSP_REQUEST_new(void)
884{
885 OcspRequest* request;
886
887 request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
888 DYNAMIC_TYPE_OPENSSL);
889 if (request != NULL)
890 XMEMSET(request, 0, sizeof(OcspRequest));
891
892 return request;
893}
894
895void wolfSSL_OCSP_REQUEST_free(OcspRequest* request)
896{
897 FreeOcspRequest(request);
898 XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL);
899}
900
901int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data)
902{
903 int size;
904
905 size = EncodeOcspRequest(request, NULL, 0);
906 if (size <= 0 || data == NULL)
907 return size;
908
909 return EncodeOcspRequest(request, *data, size);
910}
911
912WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
913 WOLFSSL_OCSP_CERTID *cid)
914{
915 if (req == NULL || cid == NULL)
916 return NULL;
917
918 XMEMCPY(req->issuerHash, cid->issuerHash, KEYID_SIZE);
919 XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, KEYID_SIZE);
920 XMEMCPY(req->serial, cid->status->serial, cid->status->serialSz);
921 req->serialSz = cid->status->serialSz;
922
923 return req;
924}
925
926WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID* id)
927{
928 WOLFSSL_OCSP_CERTID* certId;
929
930 if (id == NULL)
931 return NULL;
932
933 certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID),
934 NULL, DYNAMIC_TYPE_OPENSSL);
935 if (certId) {
936 XMEMCPY(certId, id, sizeof(WOLFSSL_OCSP_CERTID));
937 }
938 return certId;
939}
940#endif
941
942#if defined(OPENSSL_ALL) || defined(APACHE_HTTPD)
943#ifndef NO_BIO
944int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out,
945 WOLFSSL_OCSP_REQUEST *req)
946{
947 int size = -1;
948 unsigned char* data = NULL;
949
950 WOLFSSL_ENTER("wolfSSL_i2d_OCSP_REQUEST_bio");
951 if (out == NULL || req == NULL)
952 return WOLFSSL_FAILURE;
953
954 size = wolfSSL_i2d_OCSP_REQUEST(req, NULL);
955 if (size > 0) {
956 data = (unsigned char*) XMALLOC(size, out->heap,
957 DYNAMIC_TYPE_TMP_BUFFER);
958 }
959
960 if (data != NULL) {
961 size = wolfSSL_i2d_OCSP_REQUEST(req, &data);
962 }
963
964 if (size <= 0) {
965 XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER);
966 return WOLFSSL_FAILURE;
967 }
968
969 if (wolfSSL_BIO_write(out, data, size) == (int)size) {
970 XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER);
971 return WOLFSSL_SUCCESS;
972 }
973
974 XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER);
975 return WOLFSSL_FAILURE;
976}
977#endif /* !NO_BIO */
978
979int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID* id, unsigned char** data)
980{
981 if (id == NULL || data == NULL)
982 return WOLFSSL_FAILURE;
983
984 if (*data != NULL) {
985 XMEMCPY(*data, id->rawCertId, id->rawCertIdSize);
986 *data = *data + id->rawCertIdSize;
987 }
988 else {
989 *data = (unsigned char*)XMALLOC(id->rawCertIdSize, NULL, DYNAMIC_TYPE_OPENSSL);
990 if (*data == NULL) {
991 return WOLFSSL_FAILURE;
992 }
993 XMEMCPY(*data, id->rawCertId, id->rawCertIdSize);
994 }
995
996 return id->rawCertIdSize;
997}
998
999const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id(const WOLFSSL_OCSP_SINGLERESP *single)
1000{
1001 return single;
1002}
1003
1004int wolfSSL_OCSP_single_get0_status(WOLFSSL_OCSP_SINGLERESP *single,
1005 int *reason,
1006 WOLFSSL_ASN1_TIME **revtime,
1007 WOLFSSL_ASN1_TIME **thisupd,
1008 WOLFSSL_ASN1_TIME **nextupd)
1009{
1010 if (single == NULL)
1011 return WOLFSSL_FAILURE;
1012
1013 if (thisupd != NULL)
1014 *thisupd = &single->status->thisDateParsed;
1015 if (nextupd != NULL)
1016 *nextupd = &single->status->nextDateParsed;
1017
1018 if (reason != NULL)
1019 *reason = 0;
1020 if (revtime != NULL)
1021 *revtime = NULL;
1022
1023 return single->status->status;
1024}
1025
1026int wolfSSL_OCSP_resp_count(WOLFSSL_OCSP_BASICRESP *bs)
1027{
1028 WOLFSSL_OCSP_SINGLERESP* single;
1029 int count = 0;
1030
1031 if (bs == NULL)
1032 return WOLFSSL_FAILURE;
1033
1034 single = bs->single;
1035 while(single != NULL)
1036 {
1037 ++count;
1038 single = single->next;
1039 }
1040
1041 return count;
1042}
1043
1044WOLFSSL_OCSP_SINGLERESP* wolfSSL_OCSP_resp_get0(WOLFSSL_OCSP_BASICRESP *bs, int idx)
1045{
1046 WOLFSSL_OCSP_SINGLERESP* single;
1047 int currIdx = 0;
1048
1049 if (bs == NULL)
1050 return NULL;
1051
1052 single = bs->single;
1053 while(single != NULL && currIdx != idx)
1054 {
1055 single = single->next;
1056 ++currIdx;
1057 }
1058
1059 return single;
1060}
1061
1062#endif /* OPENSSL_ALL || APACHE_HTTPD */
1063
1064#ifdef OPENSSL_EXTRA
1065#ifndef NO_WOLFSSL_STUB
1066int wolfSSL_OCSP_REQUEST_add_ext(OcspRequest* req, WOLFSSL_X509_EXTENSION* ext,
1067 int idx)
1068{
1069 WOLFSSL_STUB("wolfSSL_OCSP_REQUEST_add_ext");
1070 (void)req;
1071 (void)ext;
1072 (void)idx;
1073 return WOLFSSL_FATAL_ERROR;
1074}
1075#endif
1076
1077#ifndef NO_WOLFSSL_STUB
1078OcspResponse* wolfSSL_OCSP_response_create(int status,
1079 WOLFSSL_OCSP_BASICRESP* bs)
1080{
1081 WOLFSSL_STUB("wolfSSL_OCSP_response_create");
1082 (void)status;
1083 (void)bs;
1084 return NULL;
1085}
1086#endif
1087
1088#ifndef NO_WOLFSSL_STUB
1089const char* wolfSSL_OCSP_crl_reason_str(long s)
1090{
1091 WOLFSSL_STUB("wolfSSL_OCSP_crl_reason_str");
1092 (void)s;
1093 return NULL;
1094}
1095#endif
1096
1097/* Returns elements of an OCSP_CERTID struct. Currently only supports
1098 * returning the serial number, and returns an error if user requests
1099 * any of name, pmd, and/or keyHash.
1100 * Return 1 on success, 0 on failure */
1101int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name,
1102 WOLFSSL_ASN1_OBJECT **pmd, WOLFSSL_ASN1_STRING **keyHash,
1103 WOLFSSL_ASN1_INTEGER **serial, WOLFSSL_OCSP_CERTID *cid)
1104{
1105 int i = 0;
1106 WOLFSSL_ASN1_INTEGER* ser;
1107
1108 WOLFSSL_ENTER("wolfSSL_OCSP_id_get0_info");
1109
1110 if (cid == NULL)
1111 return 0;
1112
1113 /* build up ASN1_INTEGER for serial */
1114 if (serial != NULL) {
1115 ser = wolfSSL_ASN1_INTEGER_new();
1116 if (ser == NULL)
1117 return 0;
1118
1119 if (cid->status->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
1120 /* allocate data buffer, +2 for type and length */
1121 ser->data = (unsigned char*)XMALLOC(cid->status->serialSz + 2, NULL,
1122 DYNAMIC_TYPE_OPENSSL);
1123 if (ser->data == NULL) {
1124 wolfSSL_ASN1_INTEGER_free(ser);
1125 return 0;
1126 }
1127 ser->dataMax = cid->status->serialSz + 2;
1128 ser->isDynamic = 1;
1129 } else {
1130 /* Use array instead of dynamic memory */
1131 ser->data = ser->intData;
1132 ser->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
1133 }
1134
1135 #ifdef WOLFSSL_QT
1136 /* Serial number starts at 0 index of ser->data */
1137 XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz);
1138 ser->length = cid->status->serialSz;
1139 #else
1140 ser->data[i++] = ASN_INTEGER;
1141 i += SetLength(cid->status->serialSz, ser->data + i);
1142 XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz);
1143 #endif
1144
1145 cid->status->serialInt = ser;
1146 *serial = ser;
1147 }
1148
1149 /* Not needed for Apache, return error if user is requesting */
1150 if (name != NULL || pmd != NULL || keyHash != NULL) {
1151 if (name != NULL)
1152 *name = NULL;
1153
1154 if (pmd != NULL)
1155 *pmd = NULL;
1156
1157 if (keyHash != NULL)
1158 *keyHash = NULL;
1159 return 0;
1160 }
1161
1162 return 1;
1163}
1164
1165#ifndef NO_WOLFSSL_STUB
1166int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val,
1167 int sz)
1168{
1169 WOLFSSL_STUB("wolfSSL_OCSP_request_add1_nonce");
1170 (void)req;
1171 (void)val;
1172 (void)sz;
1173 return WOLFSSL_FATAL_ERROR;
1174}
1175#endif
1176
1177/* Returns result of OCSP nonce comparison. Return values:
1178 * 1 - nonces are both present and equal
1179 * 2 - both nonces are absent
1180 * 3 - nonce only present in response
1181 * -1 - nonce only present in request
1182 * 0 - both nonces present and equal
1183 */
1184int wolfSSL_OCSP_check_nonce(OcspRequest* req, WOLFSSL_OCSP_BASICRESP* bs)
1185{
1186 byte* reqNonce = NULL;
1187 byte* rspNonce = NULL;
1188 int reqNonceSz = 0;
1189 int rspNonceSz = 0;
1190
1191 WOLFSSL_ENTER("wolfSSL_OCSP_check_nonce");
1192
1193 if (req != NULL) {
1194 reqNonce = req->nonce;
1195 reqNonceSz = req->nonceSz;
1196 }
1197
1198 if (bs != NULL) {
1199 rspNonce = bs->nonce;
1200 rspNonceSz = bs->nonceSz;
1201 }
1202
1203 /* nonce absent in both req and rsp */
1204 if (reqNonce == NULL && rspNonce == NULL)
1205 return 2;
1206
1207 /* nonce present in rsp only */
1208 if (reqNonce == NULL && rspNonce != NULL)
1209 return 3;
1210
1211 /* nonce present in req only */
1212 if (reqNonce != NULL && rspNonce == NULL)
1213 return -1;
1214
1215 /* nonces are present and equal, return 1. Extra NULL check for fixing
1216 scan-build warning. */
1217 if (reqNonceSz == rspNonceSz && reqNonce && rspNonce) {
1218 if (XMEMCMP(reqNonce, rspNonce, reqNonceSz) == 0)
1219 return 1;
1220 }
1221
1222 /* nonces are present but not equal */
1223 return 0;
1224}
1225#endif /* OPENSSL_EXTRA */
1226
1227#else /* HAVE_OCSP */
1228
1229
1230#ifdef _MSC_VER
1231 /* 4206 warning for blank file */
1232 #pragma warning(disable: 4206)
1233#endif
1234
1235
1236#endif /* HAVE_OCSP */
1237#endif /* WOLFCRYPT_ONLY */
Note: See TracBrowser for help on using the repository browser.