Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/src/ocsp.c
Line
Count
Source
1
/* ocsp.c
2
 *
3
 * Copyright (C) 2006-2026 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 3 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
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
/*
25
 * OCSP responder missing features:
26
 * - Support for multiple requests and responses in a single OCSP exchange
27
 * - Support name-based responder ID
28
 * - Support for singleExtensions
29
 */
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
/* Allocates and initializes a WOLFSSL_OCSP object. Returns pointer on success, NULL on failure. */
46
WOLFSSL_OCSP* wc_NewOCSP(WOLFSSL_CERT_MANAGER* cm)
47
0
{
48
0
    WOLFSSL_OCSP* ocsp = NULL;
49
0
    ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm ? cm->heap : NULL, DYNAMIC_TYPE_OCSP);
50
0
    if (ocsp == NULL)
51
0
        return NULL;
52
0
    if (InitOCSP(ocsp, cm) != 0) {
53
0
        XFREE(ocsp, cm ? cm->heap : NULL, DYNAMIC_TYPE_OCSP);
54
0
        return NULL;
55
0
    }
56
0
    return ocsp;
57
0
}
58
59
/* Frees a WOLFSSL_OCSP object allocated by wc_NewOCSP. */
60
void wc_FreeOCSP(WOLFSSL_OCSP* ocsp)
61
0
{
62
0
    if (ocsp) {
63
0
        FreeOCSP(ocsp, 1);
64
0
    }
65
0
}
66
67
int wc_CheckCertOcspResponse(WOLFSSL_OCSP *ocsp, DecodedCert *cert,
68
        byte *response, int responseSz, void* heap)
69
0
{
70
0
    int ret = WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E);
71
72
0
#ifdef WOLFSSL_SMALL_STACK
73
0
    OcspRequest* ocspRequest;
74
#else
75
    OcspRequest ocspRequest[1];
76
#endif
77
78
79
0
#ifdef WOLFSSL_SMALL_STACK
80
0
    ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
81
0
                                                       DYNAMIC_TYPE_TMP_BUFFER);
82
0
    if (ocspRequest == NULL) {
83
0
        WOLFSSL_LEAVE("wc_CheckCertOcspResponse", MEMORY_ERROR);
84
0
        return MEMORY_E;
85
0
    }
86
0
#endif
87
88
0
    if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
89
0
                                                         ocsp->cm->heap) == 0) {
90
0
        ret = CheckOcspResponse(ocsp, response, responseSz, NULL, NULL, NULL,
91
0
                ocspRequest, heap, NULL);
92
0
        FreeOcspRequest(ocspRequest);
93
0
    }
94
95
0
#ifdef WOLFSSL_SMALL_STACK
96
0
    XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
97
0
#endif
98
99
0
    WOLFSSL_LEAVE("wc_CheckCertOcspResponse", ret);
100
0
    return ret;
101
0
}
102
103
int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm)
104
28
{
105
28
    WOLFSSL_ENTER("InitOCSP");
106
107
28
    ForceZero(ocsp, sizeof(WOLFSSL_OCSP));
108
109
28
    if (wc_InitMutex(&ocsp->ocspLock) != 0)
110
0
        return BAD_MUTEX_E;
111
112
28
    ocsp->cm = cm;
113
114
28
    return 0;
115
28
}
116
117
118
static int InitOcspEntry(OcspEntry* entry, OcspRequest* request)
119
0
{
120
0
    WOLFSSL_ENTER("InitOcspEntry");
121
122
0
    ForceZero(entry, sizeof(OcspEntry));
123
124
0
    XMEMCPY(entry->issuerHash,    request->issuerHash,    OCSP_DIGEST_SIZE);
125
0
    XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE);
126
127
0
    return 0;
128
0
}
129
130
131
static void FreeOcspEntry(OcspEntry* entry, void* heap)
132
0
{
133
0
    CertStatus *status, *next;
134
135
0
    if (entry == NULL || !entry->ownStatus)
136
0
        return;
137
138
0
    WOLFSSL_ENTER("FreeOcspEntry");
139
140
0
    for (status = entry->status; status; status = next) {
141
0
        next = status->next;
142
143
0
        XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS);
144
145
0
#ifdef OPENSSL_EXTRA
146
0
        if (status->serialInt) {
147
0
            if (status->serialInt->isDynamic) {
148
0
                XFREE(status->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL);
149
0
            }
150
0
            XFREE(status->serialInt, NULL, DYNAMIC_TYPE_OPENSSL);
151
0
        }
152
0
        status->serialInt = NULL;
153
0
#endif
154
155
0
        XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS);
156
0
    }
157
158
0
    (void)heap;
159
0
}
160
161
162
void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic)
163
0
{
164
0
    OcspEntry *entry, *next;
165
0
    void* heap = (ocsp->cm != NULL) ? ocsp->cm->heap : NULL;
166
167
0
    WOLFSSL_ENTER("FreeOCSP");
168
169
0
    for (entry = ocsp->ocspList; entry; entry = next) {
170
0
        next = entry->next;
171
0
        FreeOcspEntry(entry, heap);
172
0
        XFREE(entry, heap, DYNAMIC_TYPE_OCSP_ENTRY);
173
0
    }
174
175
0
    wc_FreeMutex(&ocsp->ocspLock);
176
177
0
    if (dynamic)
178
0
        XFREE(ocsp, heap, DYNAMIC_TYPE_OCSP);
179
180
0
}
181
182
183
static int xstat2err(int st)
184
0
{
185
0
    switch (st) {
186
0
        case CERT_GOOD:
187
0
            return 0;
188
0
        case CERT_REVOKED:
189
0
            return OCSP_CERT_REVOKED;
190
0
        default:
191
0
            return OCSP_CERT_UNKNOWN;
192
0
    }
193
0
}
194
195
int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, WOLFSSL* ssl)
196
0
{
197
0
    int ret = WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL);
198
199
0
    WC_DECLARE_VAR(ocspRequest, OcspRequest, 1, 0);
200
201
0
    WOLFSSL_ENTER("CheckCertOCSP");
202
203
204
0
#ifdef WOLFSSL_SMALL_STACK
205
0
    ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
206
0
                                                       DYNAMIC_TYPE_TMP_BUFFER);
207
0
    if (ocspRequest == NULL) {
208
0
        WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
209
0
        return MEMORY_E;
210
0
    }
211
0
#endif
212
213
0
    if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce,
214
0
                                                         ocsp->cm->heap) == 0) {
215
0
        ret = CheckOcspRequest(ocsp, ocspRequest, NULL, ssl);
216
217
0
        FreeOcspRequest(ocspRequest);
218
0
    }
219
220
0
    WC_FREE_VAR_EX(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
221
222
0
    WOLFSSL_LEAVE("CheckCertOCSP", ret);
223
0
    return ret;
224
0
}
225
int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert)
226
0
{
227
0
    return CheckCertOCSP_ex(ocsp, cert, NULL);
228
0
}
229
230
static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request,
231
                                                              OcspEntry** entry)
232
0
{
233
0
    WOLFSSL_ENTER("GetOcspEntry");
234
235
0
    *entry = NULL;
236
237
0
    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
238
0
        WOLFSSL_LEAVE("GetOcspEntry", BAD_MUTEX_E);
239
0
        return BAD_MUTEX_E;
240
0
    }
241
242
0
    for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next)
243
0
        if (XMEMCMP((*entry)->issuerHash,    request->issuerHash,
244
0
                                                         OCSP_DIGEST_SIZE) == 0
245
0
        &&  XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash,
246
0
                                                         OCSP_DIGEST_SIZE) == 0)
247
0
            break;
248
249
0
    if (*entry == NULL) {
250
0
        *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry),
251
0
                                       ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY);
252
0
        if (*entry) {
253
0
            InitOcspEntry(*entry, request);
254
0
            (*entry)->next = ocsp->ocspList;
255
0
            ocsp->ocspList = *entry;
256
0
        }
257
0
    }
258
259
0
    wc_UnLockMutex(&ocsp->ocspLock);
260
261
0
    return *entry ? 0 : MEMORY_ERROR;
262
0
}
263
264
265
/* Mallocs responseBuffer->buffer and is up to caller to free on success
266
 *
267
 * Returns OCSP status
268
 */
269
static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request,
270
                  OcspEntry* entry, CertStatus** status, buffer* responseBuffer,
271
                  void* heap)
272
0
{
273
0
    int ret = WC_NO_ERR_TRACE(OCSP_INVALID_STATUS);
274
275
0
    WOLFSSL_ENTER("GetOcspStatus");
276
277
0
    (void)heap;
278
0
    *status = NULL;
279
280
0
    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
281
0
        WOLFSSL_LEAVE("GetOcspStatus", BAD_MUTEX_E);
282
0
        return BAD_MUTEX_E;
283
0
    }
284
285
0
    for (*status = entry->status; *status; *status = (*status)->next)
286
0
        if ((*status)->serialSz == request->serialSz
287
0
        &&  !XMEMCMP((*status)->serial, request->serial, (size_t)(*status)->serialSz))
288
0
            break;
289
290
0
    if (responseBuffer && *status && !(*status)->rawOcspResponse) {
291
        /* force fetching again */
292
0
        ret = OCSP_INVALID_STATUS;
293
0
    }
294
0
    else if (*status) {
295
0
#ifndef NO_ASN_TIME
296
0
        if (XVALIDATE_DATE((*status)->thisDate,
297
0
                           (*status)->thisDateFormat, ASN_BEFORE, MAX_DATE_SIZE)
298
0
        &&  ((*status)->nextDate[0] != 0)
299
0
        &&  XVALIDATE_DATE((*status)->nextDate,
300
0
                           (*status)->nextDateFormat, ASN_AFTER, MAX_DATE_SIZE))
301
0
#endif
302
0
        {
303
0
            ret = xstat2err((*status)->status);
304
305
0
            if (responseBuffer) {
306
0
                responseBuffer->buffer = (byte*)XMALLOC(
307
0
                   (*status)->rawOcspResponseSz, heap,
308
0
                   DYNAMIC_TYPE_TMP_BUFFER);
309
310
0
                if (responseBuffer->buffer) {
311
0
                    responseBuffer->length = (*status)->rawOcspResponseSz;
312
0
                    XMEMCPY(responseBuffer->buffer,
313
0
                            (*status)->rawOcspResponse,
314
0
                            (*status)->rawOcspResponseSz);
315
0
                }
316
0
            }
317
0
        }
318
0
    }
319
320
0
    wc_UnLockMutex(&ocsp->ocspLock);
321
322
0
    return ret;
323
0
}
324
325
/* Check that the response for validity. Store result in status.
326
 *
327
 * ocsp           Context object for OCSP status.
328
 * response       OCSP response message data.
329
 * responseSz     Length of OCSP response message data.
330
 * responseBuffer Buffer object to return the response with.
331
 * status         The certificate status object.
332
 * entry          The OCSP entry for this certificate.
333
 * ocspRequest    Request corresponding to response.
334
 * heap           Heap hint used for responseBuffer
335
 * ssl            Connection the request belongs to, may be NULL.
336
 * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise.
337
 */
338
int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz,
339
                      WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status,
340
                      OcspEntry *entry, OcspRequest *ocspRequest, void* heap,
341
                      WOLFSSL* ssl)
342
0
{
343
0
#ifdef WOLFSSL_SMALL_STACK
344
0
    CertStatus*   newStatus;
345
0
    OcspEntry*    newSingle;
346
0
    OcspResponse* ocspResponse;
347
#else
348
    CertStatus    newStatus[1];
349
    OcspEntry     newSingle[1];
350
    OcspResponse  ocspResponse[1];
351
#endif
352
0
    int           ret;
353
0
    int           validated      = 0;    /* ocsp validation flag */
354
355
0
    (void)heap;
356
357
0
#ifdef WOLFSSL_SMALL_STACK
358
0
    newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
359
0
                                                       DYNAMIC_TYPE_OCSP_STATUS);
360
0
    newSingle = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
361
0
                                                       DYNAMIC_TYPE_OCSP_ENTRY);
362
0
    ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
363
0
                                                       DYNAMIC_TYPE_OCSP_REQUEST);
364
365
0
    if (newStatus == NULL || newSingle == NULL || ocspResponse == NULL) {
366
0
        XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS);
367
0
        XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
368
0
        XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
369
370
0
        WOLFSSL_LEAVE("CheckOcspResponse", MEMORY_ERROR);
371
0
        return MEMORY_E;
372
0
    }
373
0
#endif
374
0
    InitOcspResponse(ocspResponse, newSingle, newStatus, response,
375
0
                     (word32)responseSz, ocsp->cm->heap);
376
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(NO_TLS)
377
    if (ssl != NULL && TLSX_CSR2_IsMulti(ssl->extensions)) {
378
        ocspResponse->pendingCAs = TLSX_CSR2_GetPendingSigners(ssl->extensions);
379
    }
380
#else
381
0
    (void)ssl;
382
0
#endif
383
0
    ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0, 0);
384
0
    if (ret != 0) {
385
0
        ocsp->error = ret;
386
0
        WOLFSSL_LEAVE("OcspResponseDecode failed", ocsp->error);
387
0
        goto end;
388
0
    }
389
390
0
    if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) {
391
0
        WOLFSSL_MSG("OcspResponse status bad");
392
0
        goto end;
393
0
    }
394
0
    if (ocspRequest != NULL) {
395
        /* Has the chance to bubble up response changing ocspResponse->single to
396
           no longer be pointing at newSingle */
397
0
        ret = CompareOcspReqResp(ocspRequest, ocspResponse);
398
0
        if (ret != 0) {
399
0
            goto end;
400
0
        }
401
0
    }
402
403
0
    if (responseBuffer) {
404
0
        responseBuffer->buffer = (byte*)XMALLOC((size_t)responseSz, heap,
405
0
                                                DYNAMIC_TYPE_TMP_BUFFER);
406
407
0
        if (responseBuffer->buffer) {
408
0
            responseBuffer->length = (unsigned int)responseSz;
409
0
            XMEMCPY(responseBuffer->buffer, response, (size_t)responseSz);
410
0
        }
411
0
    }
412
413
0
    ret = xstat2err(ocspResponse->single->status->status);
414
0
    if (ret == 0) {
415
0
        validated = 1;
416
0
    }
417
418
0
    if (wc_LockMutex(&ocsp->ocspLock) != 0) {
419
0
        ret = BAD_MUTEX_E;
420
0
        goto end;
421
0
    }
422
423
0
    if (status != NULL) {
424
0
        XFREE(status->rawOcspResponse, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
425
426
        /* Replace existing certificate entry with updated */
427
0
        ocspResponse->single->status->next = status->next;
428
0
        XMEMCPY(status, ocspResponse->single->status, sizeof(CertStatus));
429
0
    }
430
0
    else if (entry != NULL) {
431
        /* Save new certificate entry */
432
0
        status = (CertStatus*)XMALLOC(sizeof(CertStatus),
433
0
                                      ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
434
0
        if (status != NULL) {
435
0
            XMEMCPY(status, ocspResponse->single->status, sizeof(CertStatus));
436
0
            status->next  = entry->status;
437
0
            entry->status = status;
438
0
            entry->ownStatus = 1;
439
0
            entry->totalStatus++;
440
0
        }
441
0
    }
442
443
0
    if (status && responseBuffer && responseBuffer->buffer) {
444
0
        status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length,
445
0
                                                 ocsp->cm->heap,
446
0
                                                 DYNAMIC_TYPE_OCSP_STATUS);
447
448
0
        if (status->rawOcspResponse) {
449
0
            status->rawOcspResponseSz = responseBuffer->length;
450
0
            XMEMCPY(status->rawOcspResponse, responseBuffer->buffer,
451
0
                    responseBuffer->length);
452
0
        }
453
0
    }
454
455
0
    wc_UnLockMutex(&ocsp->ocspLock);
456
457
0
end:
458
0
    if (ret == 0 && validated == 1) {
459
0
        WOLFSSL_MSG("New OcspResponse validated");
460
0
    }
461
0
    else if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED)) {
462
0
        WOLFSSL_MSG("OCSP revoked");
463
0
    }
464
0
    else if (ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN)) {
465
0
        WOLFSSL_MSG("OCSP unknown");
466
0
    }
467
0
    else {
468
0
        WOLFSSL_MSG("OCSP lookup failure");
469
0
        ret = OCSP_LOOKUP_FAIL;
470
0
    }
471
472
0
    FreeOcspResponse(ocspResponse);
473
0
    WC_FREE_VAR_EX(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS);
474
0
    WC_FREE_VAR_EX(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
475
0
    WC_FREE_VAR_EX(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
476
0
    return ret;
477
0
}
478
479
/* 0 on success */
480
/* allow user to override the maximum request size at build-time */
481
#ifndef OCSP_MAX_REQUEST_SZ
482
0
#define OCSP_MAX_REQUEST_SZ 2048
483
#endif
484
int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
485
                     buffer* responseBuffer, WOLFSSL* ssl)
486
0
{
487
0
    OcspEntry*  entry          = NULL;
488
0
    CertStatus* status         = NULL;
489
0
    byte*       request        = NULL;
490
0
    int         requestSz      = OCSP_MAX_REQUEST_SZ;
491
0
    int         responseSz     = 0;
492
0
    byte*       response       = NULL;
493
0
    const char* url            = NULL;
494
0
    int         urlSz          = 0;
495
0
    int         ret            = -1;
496
0
    void*       ioCtx;
497
    /* Hint for responseBuffer only, which the caller frees against the same
498
     * connection, so take it from there rather than have every caller pass a
499
     * heap it has to keep in step with its own free. */
500
0
    void*       heap           = (ssl != NULL) ? ssl->heap : NULL;
501
502
0
    WOLFSSL_ENTER("CheckOcspRequest");
503
504
0
    if (ocsp == NULL || ocspRequest == NULL)
505
0
        return BAD_FUNC_ARG;
506
507
0
    if (responseBuffer) {
508
0
        responseBuffer->buffer = NULL;
509
0
        responseBuffer->length = 0;
510
0
    }
511
512
0
    ret = GetOcspEntry(ocsp, ocspRequest, &entry);
513
0
    if (ret != 0)
514
0
        return ret;
515
516
0
    ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer,
517
0
                        heap);
518
0
    if (ret != WC_NO_ERR_TRACE(OCSP_INVALID_STATUS))
519
0
        return ret;
520
521
0
    if (responseBuffer) {
522
0
        XFREE(responseBuffer->buffer, heap, DYNAMIC_TYPE_TMP_BUFFER);
523
0
        responseBuffer->buffer = NULL;
524
0
    }
525
526
    /* get IOCtx */
527
0
    ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
528
0
                                        ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
529
530
0
    if (ocsp->cm->ocspUseOverrideURL) {
531
0
        url = ocsp->cm->ocspOverrideURL;
532
0
        if (url != NULL && url[0] != '\0')
533
0
            urlSz = (int)XSTRLEN(url);
534
0
        else
535
0
            return OCSP_NEED_URL;
536
0
    }
537
0
    else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) {
538
0
        url = (const char *)ocspRequest->url;
539
0
        urlSz = ocspRequest->urlSz;
540
0
    }
541
0
    else {
542
        /* Cert advertises no OCSP responder and no override URL is set, so
543
         * OCSP has no opinion on this cert. Report that distinctly from a
544
         * failed lookup; the caller owns the policy decision. Callers wanting
545
         * the historical soft-fail run this through OcspNoUrlPolicy(). */
546
0
        WOLFSSL_MSG("Cert has no OCSP URL");
547
0
        return OCSP_NO_URL;
548
0
    }
549
550
0
    request = (byte*)XMALLOC((size_t)requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
551
0
    if (request == NULL) {
552
0
        WOLFSSL_LEAVE("CheckOcspRequest", MEMORY_ERROR);
553
0
        return MEMORY_ERROR;
554
0
    }
555
556
0
    requestSz = EncodeOcspRequest(ocspRequest, request, (word32)requestSz);
557
0
    if (requestSz > 0 && ocsp->cm->ocspIOCb) {
558
0
        responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz,
559
0
                                        request, requestSz, &response);
560
0
    }
561
0
    if (responseSz == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ)) {
562
0
        ret = OCSP_WANT_READ;
563
0
    }
564
0
    else if (responseSz == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_TIMEOUT)){
565
0
        ret = HTTP_TIMEOUT;
566
0
    }
567
568
0
    XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP);
569
570
0
    if (responseSz >= 0 && response) {
571
0
        ret = CheckOcspResponse(ocsp, response, responseSz, responseBuffer, status,
572
0
                            entry, ocspRequest, heap, ssl);
573
0
    }
574
575
0
    if (response != NULL && ocsp->cm->ocspRespFreeCb)
576
0
        ocsp->cm->ocspRespFreeCb(ioCtx, response);
577
578
    /* Keep responseBuffer in the case of getting to response check. Caller
579
     * should free responseBuffer after checking OCSP return value in "ret" */
580
0
    WOLFSSL_LEAVE("CheckOcspRequest", ret);
581
0
    return ret;
582
0
}
583
584
/* Map OCSP_NO_URL - "this cert advertises no OCSP responder" - to a
585
 * verification result.
586
 *
587
 * WOLFSSL_OCSP_CHECKALL selects which certificates get checked, not how hard
588
 * to fail when one cannot be checked, so it deliberately has no say here.
589
 * Refuse the cert only when the user explicitly asked for that with
590
 * WOLFSSL_OCSP_FAIL_IF_NOT_SUPPORTED.
591
 *
592
 * Returns OCSP_NEED_URL to refuse the cert, or 0 for the historical
593
 * soft-fail. */
594
int OcspNoUrlPolicy(WOLFSSL_CERT_MANAGER* cm)
595
0
{
596
0
    if (cm != NULL && cm->ocspFailIfNotSupported) {
597
0
        WOLFSSL_MSG("Cert has no OCSP URL and OCSP is required for every cert");
598
0
        WOLFSSL_ERROR_VERBOSE(OCSP_NEED_URL);
599
0
        return OCSP_NEED_URL;
600
0
    }
601
602
0
    WOLFSSL_MSG("Cert has no OCSP URL, assuming CERT_GOOD");
603
0
    return 0;
604
0
}
605
606
/* Enforce https://www.rfc-editor.org/rfc/rfc6960#section-4.2.2.2. Both halves
607
 * of CertID (issuerNameHash and issuerKeyHash) must match; name-only matching
608
 * would authorize a same-DN / different-key CA. issuerKeyHash may be NULL when
609
 * unavailable, which disables the delegated branch. */
610
int CheckOcspResponder(OcspResponse *bs, byte* subjectNameHash,
611
        byte* subjectKeyHash, byte extExtKeyUsage, byte* issuerNameHash,
612
        byte* issuerKeyHash)
613
0
{
614
0
    int ret = 0;
615
0
    OcspEntry* single;
616
617
    /* Both evaluate to enum values so can't use a pre-processor check */
618
0
    WOLFSSL_ASSERT_EQ(OCSP_DIGEST_SIZE, SIGNER_DIGEST_SIZE);
619
620
0
    WOLFSSL_ENTER("CheckOcspResponder");
621
622
    /* In the future if this API is used more then it could be beneficial to
623
     * implement calling InitDecodedCert and ParseCertRelative here
624
     * automatically when cert == NULL. */
625
0
    if (bs == NULL || subjectNameHash == NULL || issuerNameHash == NULL)
626
0
        return BAD_FUNC_ARG;
627
628
0
    for (single = bs->single; single != NULL; single = single->next) {
629
0
        int passed = 0;
630
631
0
        if (subjectKeyHash != NULL &&
632
0
                XMEMCMP(subjectNameHash, single->issuerHash,
633
0
                    OCSP_DIGEST_SIZE) == 0 &&
634
0
                XMEMCMP(subjectKeyHash, single->issuerKeyHash,
635
0
                    KEYID_SIZE) == 0) {
636
0
            WOLFSSL_MSG("\tOCSP Response signed by issuer");
637
0
            passed = 1;
638
0
        }
639
0
        else if ((extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) != 0) {
640
0
            if (issuerKeyHash != NULL &&
641
0
                    XMEMCMP(issuerNameHash, single->issuerHash,
642
0
                        OCSP_DIGEST_SIZE) == 0 &&
643
0
                    XMEMCMP(issuerKeyHash, single->issuerKeyHash,
644
0
                        KEYID_SIZE) == 0) {
645
0
                WOLFSSL_MSG("\tOCSP Response signed by authorized responder "
646
0
                            "delegated by issuer");
647
0
                passed = 1;
648
0
            }
649
0
        }
650
651
0
        if (!passed) {
652
0
            WOLFSSL_MSG("\tOCSP Responder not authorized");
653
0
            ret = BAD_OCSP_RESPONDER;
654
0
            break;
655
0
        }
656
0
    }
657
0
    return ret;
658
0
}
659
660
661
OcspRequest* wc_OcspRequest_new(void* heap)
662
0
{
663
0
    OcspRequest* request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), heap,
664
0
                                                 DYNAMIC_TYPE_OCSP_REQUEST);
665
0
    if (request != NULL) {
666
0
        XMEMSET(request, 0, sizeof(OcspRequest));
667
0
        request->heap = heap;
668
0
    }
669
670
0
    return request;
671
0
}
672
673
void wc_OcspRequest_free(OcspRequest* request)
674
0
{
675
0
    if (request != NULL) {
676
0
        FreeOcspRequest(request);
677
0
        XFREE(request, request->heap, DYNAMIC_TYPE_OCSP_REQUEST);
678
0
    }
679
0
}
680
681
OcspResponse* wc_OcspResponse_new(void* heap)
682
0
{
683
0
    OcspResponse* response = (OcspResponse*)XMALLOC(sizeof(OcspResponse),
684
0
                                                   heap,
685
0
                                                   DYNAMIC_TYPE_OCSP_RESPONSE);
686
0
    if (response != NULL) {
687
0
        XMEMSET(response, 0, sizeof(OcspResponse));
688
0
        response->heap = heap;
689
0
    }
690
691
0
    return response;
692
0
}
693
694
void wc_OcspResponse_free(OcspResponse* response)
695
0
{
696
0
    if (response != NULL) {
697
0
        FreeOcspResponse(response);
698
0
        XFREE(response, response->heap, DYNAMIC_TYPE_OCSP_RESPONSE);
699
0
    }
700
0
}
701
702
/* compatibility layer OCSP functions */
703
#ifdef OPENSSL_EXTRA
704
int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
705
    WOLFSSL_OCSP_CERTID* id, int* status, int* reason,
706
    WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd,
707
    WOLFSSL_ASN1_TIME** nextupd)
708
0
{
709
0
    WOLFSSL_OCSP_SINGLERESP* single;
710
711
0
    if (bs == NULL || id == NULL)
712
0
        return WOLFSSL_FAILURE;
713
714
0
    single = bs->single;
715
0
    while (single != NULL) {
716
0
        if (single->status != NULL && id->status != NULL &&
717
0
            (single->status->serialSz == id->status->serialSz)
718
0
         && (XMEMCMP(single->status->serial, id->status->serial,
719
0
                     (size_t)single->status->serialSz) == 0)
720
0
         && (XMEMCMP(single->issuerHash, id->issuerHash, OCSP_DIGEST_SIZE) == 0)
721
0
         && (XMEMCMP(single->issuerKeyHash, id->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) {
722
0
            break;
723
0
        }
724
0
        single = single->next;
725
0
    }
726
727
0
    if (single == NULL)
728
0
        return WOLFSSL_FAILURE;
729
730
0
    if (status != NULL)
731
0
        *status = single->status->status;
732
0
#ifdef WOLFSSL_OCSP_PARSE_STATUS
733
    /* NULL when the response has no such field, as with OpenSSL. */
734
0
    if (thisupd != NULL) {
735
0
        *thisupd = (single->status->thisDateParsed.length > 0) ?
736
0
            &single->status->thisDateParsed : NULL;
737
0
    }
738
0
    if (nextupd != NULL) {
739
0
        *nextupd = (single->status->nextDateParsed.length > 0) ?
740
0
            &single->status->nextDateParsed : NULL;
741
0
    }
742
#else
743
    if (thisupd != NULL)
744
        *thisupd = NULL;
745
    if (nextupd != NULL)
746
        *nextupd = NULL;
747
#endif
748
749
    /* TODO: Not needed for Nginx or httpd */
750
0
    if (reason != NULL)
751
0
        *reason = 0;
752
0
    if (revtime != NULL)
753
0
        *revtime = NULL;
754
755
0
    return WOLFSSL_SUCCESS;
756
0
}
757
758
const char *wolfSSL_OCSP_cert_status_str(long s)
759
0
{
760
0
    switch (s) {
761
0
        case CERT_GOOD:
762
0
            return "good";
763
0
        case CERT_REVOKED:
764
0
            return "revoked";
765
0
        case CERT_UNKNOWN:
766
0
            return "unknown";
767
0
        default:
768
0
            return "(UNKNOWN)";
769
0
    }
770
0
}
771
772
int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd,
773
    WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec)
774
0
{
775
0
#ifndef NO_ASN_TIME
776
0
    int ret = WOLFSSL_SUCCESS;
777
0
    time_t now = wc_Time(0);
778
0
    time_t cmp;
779
780
    /* Same semantics as OpenSSL's OCSP_check_validity: sec is the allowed
781
     * clock skew and maxsec, when non-negative, the maximum age of thisUpdate.
782
     * wolfSSL_X509_cmp_time() returns 0 for a NULL or malformed time. */
783
0
    if (sec < 0)
784
0
        sec = 0;
785
786
0
    cmp = now + sec;
787
0
    if (wolfSSL_X509_cmp_time(thisupd, &cmp) != -1) {
788
0
        WOLFSSL_MSG("OCSP thisUpdate missing, malformed or in the future");
789
0
        ret = WOLFSSL_FAILURE;
790
0
    }
791
0
    else if (maxsec >= 0) {
792
0
        cmp = now - maxsec;
793
0
        if (wolfSSL_X509_cmp_time(thisupd, &cmp) != 1) {
794
0
            WOLFSSL_MSG("OCSP thisUpdate is too old");
795
0
            ret = WOLFSSL_FAILURE;
796
0
        }
797
0
    }
798
799
0
    if ((ret == WOLFSSL_SUCCESS) && (nextupd != NULL)) {
800
0
        cmp = now - sec;
801
0
        if (wolfSSL_X509_cmp_time(nextupd, &cmp) != 1) {
802
0
            WOLFSSL_MSG("OCSP nextUpdate has passed or is malformed");
803
0
            ret = WOLFSSL_FAILURE;
804
0
        }
805
0
        else if (wolfSSL_ASN1_TIME_compare(nextupd, thisupd) < 0) {
806
0
            WOLFSSL_MSG("OCSP nextUpdate precedes thisUpdate");
807
0
            ret = WOLFSSL_FAILURE;
808
0
        }
809
0
    }
810
811
0
    return ret;
812
#else
813
    (void)thisupd;
814
    (void)nextupd;
815
    (void)sec;
816
    (void)maxsec;
817
    return WOLFSSL_SUCCESS;
818
#endif /* !NO_ASN_TIME */
819
0
}
820
821
void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId)
822
0
{
823
0
    FreeOcspEntry(certId, NULL);
824
0
    XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
825
0
}
826
827
WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id(
828
    const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject,
829
    const WOLFSSL_X509 *issuer)
830
0
{
831
0
    WOLFSSL_OCSP_CERTID* certId = NULL;
832
0
    CertStatus* certStatus = NULL;
833
0
    WOLFSSL_CERT_MANAGER* cm = NULL;
834
0
    int ret = -1;
835
0
    DerBuffer* derCert = NULL;
836
0
    int dgstType;
837
0
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
838
839
0
    if (dgst == NULL) {
840
0
        dgstType = WC_HASH_TYPE_SHA;
841
0
    }
842
0
    else if (wolfSSL_EVP_get_hashinfo(dgst, &dgstType, NULL) !=
843
0
             WOLFSSL_SUCCESS) {
844
0
        return NULL;
845
0
    }
846
847
0
    if (dgstType != OCSP_DIGEST)
848
0
        return NULL;
849
850
0
    cm = wolfSSL_CertManagerNew();
851
0
    if (cm == NULL
852
0
            || subject == NULL || subject->derCert == NULL
853
0
            || issuer  == NULL || issuer->derCert  == NULL)
854
0
        goto out;
855
856
0
    WC_ALLOC_VAR_EX(cert, DecodedCert, 1, cm->heap, DYNAMIC_TYPE_DCERT,
857
0
        goto out);
858
859
0
    ret = AllocDer(&derCert, issuer->derCert->length,
860
0
        issuer->derCert->type, NULL);
861
0
    if (ret == 0) {
862
        /* AddCA() frees the buffer. */
863
0
        XMEMCPY(derCert->buffer, issuer->derCert->buffer,
864
0
                issuer->derCert->length);
865
0
        ret = AddCA(cm, &derCert, WOLFSSL_USER_CA, 1);
866
0
        if (ret != WOLFSSL_SUCCESS) {
867
0
            goto out;
868
0
        }
869
0
        derCert = NULL;
870
0
    }
871
872
0
    ret = -1;
873
874
0
    certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID),
875
0
                                           cm->heap, DYNAMIC_TYPE_OPENSSL);
876
0
    if (certId == NULL)
877
0
        goto out;
878
879
0
    certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), cm->heap,
880
0
                                           DYNAMIC_TYPE_OPENSSL);
881
0
    if (certStatus == NULL)
882
0
        goto out;
883
884
0
    XMEMSET(certId, 0, sizeof(WOLFSSL_OCSP_CERTID));
885
0
    XMEMSET(certStatus, 0, sizeof(CertStatus));
886
887
0
    certId->status = certStatus;
888
0
    certId->ownStatus = 1;
889
890
0
    InitDecodedCert(cert, subject->derCert->buffer,
891
0
                    subject->derCert->length, NULL);
892
0
    if (ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm, NULL) != 0) {
893
0
        FreeDecodedCert(cert);
894
0
        goto out;
895
0
    }
896
0
    else {
897
0
        certId->hashAlgoOID = wc_HashGetOID(OCSP_DIGEST);
898
0
        XMEMCPY(certId->issuerHash, cert->issuerHash, OCSP_DIGEST_SIZE);
899
0
        XMEMCPY(certId->issuerKeyHash, cert->issuerKeyHash, OCSP_DIGEST_SIZE);
900
0
        XMEMCPY(certId->status->serial, cert->serial, (size_t)cert->serialSz);
901
0
        certId->status->serialSz = cert->serialSz;
902
0
        FreeDecodedCert(cert);
903
0
    }
904
905
0
    ret = 0;
906
907
0
out:
908
909
0
    if (ret != 0) {
910
0
        if (derCert != NULL)
911
0
            FreeDer(&derCert);
912
0
        if (cm != NULL) {
913
0
            XFREE(certId, cm->heap, DYNAMIC_TYPE_OPENSSL);
914
0
            certId = NULL;
915
0
            XFREE(certStatus, cm->heap, DYNAMIC_TYPE_OPENSSL);
916
0
        }
917
0
    }
918
919
0
#ifdef WOLFSSL_SMALL_STACK
920
0
    if (cm != NULL)
921
0
        XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
922
0
#endif
923
924
0
    if (cm != NULL)
925
0
        wolfSSL_CertManagerFree(cm);
926
927
0
    return certId;
928
0
}
929
930
void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse)
931
0
{
932
0
    wolfSSL_OCSP_RESPONSE_free(basicResponse);
933
0
}
934
935
/* Calculate ancode CertID DER encoding following RFC 6960:
936
   CertID ::= SEQUENCE {
937
       hashAlgorithm       AlgorithmIdentifier,
938
       issuerNameHash      OCTET STRING,
939
       issuerKeyHash       OCTET STRING,
940
       serialNumber        CertificateSerialNumber }
941
*/
942
static int OcspEncodeCertID(WOLFSSL_OCSP_CERTID* id, byte* output,
943
    word32* totalSz, word32* intSize)
944
0
{
945
0
    word32 idx = 0;
946
0
    int ret;
947
948
0
    if (id == NULL || totalSz == NULL || intSize == NULL ||
949
0
        (output != NULL && (*totalSz == 0 || *totalSz <= *intSize)))
950
0
        return BAD_FUNC_ARG;
951
952
0
    if (output != NULL) {
953
0
        ret = SetSequence(*intSize, output);
954
0
        if (ret < 0)
955
0
            return ret;
956
0
        idx += ret;
957
0
    }
958
959
0
    ret = SetAlgoID(id->hashAlgoOID, ((output != NULL) ? output + idx : output),
960
0
        oidHashType, 0);
961
0
    if (ret <= 0)
962
0
        return -1;
963
0
    idx += ret;
964
965
    /* issuerNameHash */
966
0
    ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output));
967
0
    if (ret < 0)
968
0
        return ret;
969
0
    idx += ret;
970
0
    if (output != NULL)
971
0
        XMEMCPY(output + idx, id->issuerHash, OCSP_DIGEST_SIZE);
972
0
    idx += OCSP_DIGEST_SIZE;
973
974
    /* issuerKeyHash */
975
0
    ret = SetOctetString(OCSP_DIGEST_SIZE, ((output != NULL) ? output + idx : output));
976
0
    if (ret < 0)
977
0
        return ret;
978
0
    idx += ret;
979
0
    if (output != NULL)
980
0
        XMEMCPY(output + idx, id->issuerKeyHash, OCSP_DIGEST_SIZE);
981
0
    idx += OCSP_DIGEST_SIZE;
982
983
    /* serialNumber */
984
0
    ret = SetASNInt(id->status->serialSz, id->status->serial[0], ((output != NULL) ? output + idx : output));
985
0
    if (ret < 0)
986
0
        return ret;
987
0
    idx += ret;
988
0
    if (output != NULL)
989
0
        XMEMCPY(output + idx, id->status->serial, id->status->serialSz);
990
0
    idx += id->status->serialSz;
991
992
0
    if (output == NULL) {
993
0
        *intSize = idx;
994
0
        ret = SetSequence(idx, NULL);
995
0
        if (ret < 0)
996
0
            return ret;
997
0
        idx += ret;
998
0
        *totalSz = idx;
999
0
    }
1000
0
    else if (idx != *totalSz) {
1001
0
        return BUFFER_E;
1002
0
    }
1003
1004
0
    return 0;
1005
0
}
1006
1007
static int OcspRespIdMatches(OcspResponse* resp, const byte* NameHash,
1008
    const byte* keyHash)
1009
0
{
1010
0
    if (resp->responderIdType == OCSP_RESPONDER_ID_NAME) {
1011
0
        return XMEMCMP(NameHash, resp->responderId.nameHash,
1012
0
                   SIGNER_DIGEST_SIZE) == 0;
1013
0
    }
1014
0
    else if (resp->responderIdType == OCSP_RESPONDER_ID_KEY) {
1015
0
        return XMEMCMP(keyHash, resp->responderId.keyHash,
1016
0
                   OCSP_RESPONDER_ID_KEY_SZ) == 0;
1017
0
    }
1018
1019
0
    return 0;
1020
0
}
1021
1022
static int OcspFindSigner(WOLFSSL_OCSP_BASICRESP *resp,
1023
    WOLF_STACK_OF(WOLFSSL_X509) *certs, DecodedCert **signer, int *embedded,
1024
    unsigned long flags)
1025
0
{
1026
0
    WOLFSSL_X509 *signer_x509 = NULL;
1027
0
    DecodedCert *certDecoded;
1028
0
    int i;
1029
1030
0
    certDecoded = (DecodedCert *)XMALLOC(sizeof(*certDecoded), resp->heap,
1031
0
                                            DYNAMIC_TYPE_DCERT);
1032
0
    if (certDecoded == NULL)
1033
0
        return MEMORY_E;
1034
1035
0
    for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) {
1036
0
        signer_x509 = wolfSSL_sk_X509_value(certs, i);
1037
0
        if (signer_x509 == NULL)
1038
0
            continue;
1039
1040
0
        InitDecodedCert(certDecoded, signer_x509->derCert->buffer,
1041
0
                       signer_x509->derCert->length, resp->heap);
1042
0
        if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY,
1043
0
                NULL, NULL) == 0) {
1044
0
                if (OcspRespIdMatches(resp, certDecoded->subjectHash,
1045
0
                        certDecoded->subjectKeyHash)) {
1046
0
                    *signer = certDecoded;
1047
0
                    *embedded = 0;
1048
0
                    return 0;
1049
0
                }
1050
0
        }
1051
0
        FreeDecodedCert(certDecoded);
1052
0
    }
1053
1054
0
    if (flags & WOLFSSL_OCSP_NOINTERN) {
1055
0
        XFREE(certDecoded, resp->heap, DYNAMIC_TYPE_DCERT);
1056
0
        return ASN_NO_SIGNER_E;
1057
0
    }
1058
1059
    /* not found in certs, search the cert embedded in the response */
1060
0
    InitDecodedCert(certDecoded, resp->cert, resp->certSz, resp->heap);
1061
0
    if (ParseCertRelative(certDecoded, CERT_TYPE, NO_VERIFY, NULL, NULL) == 0) {
1062
0
        if (OcspRespIdMatches(resp, certDecoded->subjectHash,
1063
0
                certDecoded->subjectKeyHash)) {
1064
0
            *signer = certDecoded;
1065
0
            *embedded = 1;
1066
0
            return 0;
1067
0
        }
1068
0
    }
1069
0
    FreeDecodedCert(certDecoded);
1070
1071
0
    XFREE(certDecoded, resp->heap, DYNAMIC_TYPE_DCERT);
1072
0
    return ASN_NO_SIGNER_E;
1073
0
}
1074
1075
static int OcspVerifySigner(WOLFSSL_OCSP_BASICRESP *resp, DecodedCert *cert,
1076
     WOLFSSL_X509_STORE *st, unsigned long flags)
1077
0
{
1078
0
    WC_DECLARE_VAR(c, DecodedCert, 1, 0);
1079
1080
0
    int ret = -1;
1081
0
    if (st == NULL)
1082
0
        return ASN_OCSP_CONFIRM_E;
1083
1084
0
    WC_ALLOC_VAR_EX(c, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
1085
0
        return MEMORY_E);
1086
1087
0
    InitDecodedCert(c, cert->source, cert->maxIdx, NULL);
1088
0
    if (ParseCertRelative(c, CERT_TYPE, VERIFY, st->cm, NULL) != 0) {
1089
0
        ret = ASN_OCSP_CONFIRM_E;
1090
0
        goto err;
1091
0
    }
1092
0
#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK
1093
0
    if ((flags & WOLFSSL_OCSP_NOCHECKS) == 0) {
1094
0
        ret = CheckOcspResponder(resp, c->subjectHash, c->subjectKeyHash,
1095
0
                c->extExtKeyUsage, c->issuerHash,
1096
0
                (c->ca != NULL) ? c->ca->subjectKeyHash : NULL);
1097
0
    }
1098
0
    else {
1099
0
        ret = 0;
1100
0
    }
1101
#else
1102
    (void)resp;
1103
    (void)flags;
1104
    ret = 0;
1105
#endif
1106
1107
0
err:
1108
0
    FreeDecodedCert(c);
1109
0
    WC_FREE_VAR_EX(c, NULL, DYNAMIC_TYPE_DCERT);
1110
0
    return ret;
1111
0
}
1112
/* Signature verified in DecodeBasicOcspResponse.
1113
 * But no store available to verify certificate. */
1114
int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP* bs,
1115
    WOLF_STACK_OF(WOLFSSL_X509) * certs, WOLFSSL_X509_STORE* st,
1116
    unsigned long flags)
1117
0
{
1118
0
    int         ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
1119
0
    int embedded;
1120
0
    DecodedCert *cert = NULL;
1121
1122
0
    if (bs == NULL)
1123
0
        return WOLFSSL_FAILURE;
1124
1125
0
    ret = OcspFindSigner(bs, certs, &cert, &embedded, flags);
1126
0
    if (ret != 0) {
1127
0
        WOLFSSL_MSG("OCSP no signer found");
1128
0
        return WOLFSSL_FAILURE;
1129
0
    }
1130
1131
    /* skip certificate verification if cert in certs and TRUST_OTHER is true */
1132
0
    if (!embedded && (flags & WOLFSSL_OCSP_TRUSTOTHER) != 0)
1133
0
        flags |= WOLFSSL_OCSP_NOVERIFY;
1134
1135
    /* verify response signature */
1136
0
    ret = ConfirmSignature(
1137
0
        &cert->sigCtx,
1138
0
        bs->response, bs->responseSz,
1139
0
        cert->publicKey, cert->pubKeySize, cert->keyOID,
1140
0
        bs->sig, bs->sigSz, bs->sigOID, bs->sigParams, bs->sigParamsSz,
1141
0
        NULL);
1142
1143
0
    if (ret != 0) {
1144
0
        WOLFSSL_MSG("OCSP signature verification failed");
1145
0
        ret = -1;
1146
0
        goto err;
1147
0
    }
1148
1149
0
    if ((flags & WOLFSSL_OCSP_NOVERIFY) == 0) {
1150
0
        ret = OcspVerifySigner(bs, cert, st, flags);
1151
0
    }
1152
1153
0
err:
1154
0
    FreeDecodedCert(cert);
1155
0
    XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
1156
0
    return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
1157
0
}
1158
1159
void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
1160
0
{
1161
0
    OcspEntry *s, *sNext;
1162
0
    if (response == NULL)
1163
0
        return;
1164
1165
1166
0
    s = response->single;
1167
0
    while (s != NULL) {
1168
0
        sNext = s->next;
1169
0
        FreeOcspEntry(s, NULL);
1170
0
        XFREE(s, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
1171
0
        s = sNext;
1172
0
    }
1173
1174
0
    XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1175
1176
0
    XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
1177
0
}
1178
1179
#ifndef NO_BIO
1180
OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
1181
    OcspResponse** response)
1182
0
{
1183
0
    byte*         data;
1184
0
    byte*         p;
1185
0
    int           len;
1186
0
    int           dataAlloced = 0;
1187
0
    OcspResponse* ret = NULL;
1188
1189
0
    if (bio == NULL)
1190
0
        return NULL;
1191
1192
0
    if (bio->type == WOLFSSL_BIO_MEMORY) {
1193
0
        len = wolfSSL_BIO_get_mem_data(bio, &data);
1194
0
        if (len <= 0 || data == NULL) {
1195
0
            return NULL;
1196
0
        }
1197
0
    }
1198
0
#ifndef NO_FILESYSTEM
1199
0
    else if (bio->type == WOLFSSL_BIO_FILE) {
1200
0
        long fcur;
1201
0
        long flen;
1202
1203
0
        if (bio->ptr.fh == NULL)
1204
0
            return NULL;
1205
1206
0
        fcur = XFTELL(bio->ptr.fh);
1207
0
        if (fcur < 0)
1208
0
            return NULL;
1209
0
        if(XFSEEK(bio->ptr.fh, 0, SEEK_END) != 0)
1210
0
            return NULL;
1211
0
        flen = XFTELL(bio->ptr.fh);
1212
0
        if (flen < 0)
1213
0
            return NULL;
1214
0
        if (XFSEEK(bio->ptr.fh, fcur, SEEK_SET) != 0)
1215
0
            return NULL;
1216
1217
        /* check calculated length */
1218
0
        fcur = flen - fcur;
1219
0
        if (fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0)
1220
0
            return NULL;
1221
1222
0
        data = (byte*)XMALLOC((size_t)fcur, 0, DYNAMIC_TYPE_TMP_BUFFER);
1223
0
        if (data == NULL)
1224
0
            return NULL;
1225
0
        dataAlloced = 1;
1226
1227
0
        len = wolfSSL_BIO_read(bio, (char *)data, (int)fcur);
1228
0
    }
1229
0
#endif
1230
0
    else
1231
0
        return NULL;
1232
1233
0
    if (len > 0) {
1234
0
        p = data;
1235
0
        ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p,
1236
0
            len);
1237
0
    }
1238
1239
0
    if (dataAlloced)
1240
0
        XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER);
1241
1242
0
    return ret;
1243
0
}
1244
#endif /* !NO_BIO */
1245
1246
OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
1247
    const unsigned char** data, int len)
1248
0
{
1249
0
    OcspResponse *resp = NULL;
1250
0
    word32 idx = 0;
1251
0
    int length = 0;
1252
0
    int ret;
1253
1254
0
    if (data == NULL || *data == NULL || len <= 0)
1255
0
        return NULL;
1256
1257
0
    if (response != NULL)
1258
0
        resp = *response;
1259
0
    if (resp == NULL) {
1260
0
        resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
1261
0
                                      DYNAMIC_TYPE_OCSP_REQUEST);
1262
0
        if (resp == NULL)
1263
0
            return NULL;
1264
0
        XMEMSET(resp, 0, sizeof(OcspResponse));
1265
0
    }
1266
1267
0
    if (resp->source != NULL)
1268
0
        XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1269
0
    resp->source = (byte*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1270
0
    if (resp->source == NULL)
1271
0
        goto error;
1272
1273
0
    if (resp->single != NULL) {
1274
0
        OcspEntry* s = resp->single;
1275
1276
        /* Release the whole SingleResponse chain, as
1277
         * wolfSSL_OCSP_RESPONSE_free() does. Every entry after the first was
1278
         * allocated by the previous decode and FreeOcspEntry() on its own
1279
         * only reaches the head. */
1280
0
        while (s != NULL) {
1281
0
            OcspEntry* sNext = s->next;
1282
1283
0
            FreeOcspEntry(s, NULL);
1284
0
            XFREE(s, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
1285
0
            s = sNext;
1286
0
        }
1287
0
    }
1288
0
    resp->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
1289
0
                                      DYNAMIC_TYPE_OCSP_ENTRY);
1290
0
    if (resp->single == NULL)
1291
0
        goto error;
1292
    /* Zeroed before the next allocation can fail: the error path walks it. */
1293
0
    XMEMSET(resp->single, 0, sizeof(OcspEntry));
1294
0
    resp->single->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
1295
0
                                      DYNAMIC_TYPE_OCSP_STATUS);
1296
0
    if (resp->single->status == NULL)
1297
0
        goto error;
1298
    /* Leave the object in the state a fresh one is in. On reuse the response,
1299
     * cert, sig, sigParams and nonce references all pointed into the source
1300
     * buffer released above, and the new encoding need not set them again. */
1301
0
    InitOcspResponse(resp, resp->single, resp->single->status, resp->source,
1302
0
                     (word32)len, resp->heap);
1303
0
    resp->single->ownStatus = 1;
1304
0
    XMEMCPY(resp->source, *data, (size_t)len);
1305
1306
0
    ret = OcspResponseDecode(resp, NULL, NULL, 1, 1);
1307
0
    if (ret != 0 && ret != WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E)) {
1308
        /* for just converting from a DER to an internal structure the CA may
1309
         * not yet be known to this function for signature verification */
1310
0
        goto error;
1311
0
    }
1312
1313
0
    if (GetSequence(*data, &idx, &length, (word32)len) >= 0)
1314
0
        (*data) += idx + length;
1315
1316
0
    if (response != NULL && *response == NULL)
1317
0
        *response = resp;
1318
1319
0
    return resp;
1320
1321
0
error:
1322
0
    wolfSSL_OCSP_RESPONSE_free(resp);
1323
0
    if (response != NULL && *response == resp)
1324
0
        *response = NULL;
1325
0
    return NULL;
1326
0
}
1327
1328
int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response,
1329
    unsigned char** data)
1330
0
{
1331
0
    if (response == NULL)
1332
0
        return BAD_FUNC_ARG;
1333
1334
0
    if (response->source == NULL)
1335
0
        return BAD_FUNC_ARG;
1336
1337
0
    if (data == NULL)
1338
0
        return (int)response->maxIdx;
1339
1340
0
    if (*data == NULL) {
1341
0
        *data = (unsigned char*)XMALLOC(response->maxIdx, NULL,
1342
0
                                        DYNAMIC_TYPE_OPENSSL);
1343
0
        if (*data == NULL)
1344
0
            return -1;
1345
0
        XMEMCPY(*data, response->source, response->maxIdx);
1346
0
    }
1347
0
    else {
1348
0
        XMEMCPY(*data, response->source, response->maxIdx);
1349
0
        *data += response->maxIdx;
1350
0
    }
1351
1352
0
    return (int)response->maxIdx;
1353
0
}
1354
1355
int wolfSSL_OCSP_response_status(OcspResponse *response)
1356
0
{
1357
0
    if (response == NULL)
1358
0
        return -1;
1359
0
    return response->responseStatus;
1360
0
}
1361
1362
const char *wolfSSL_OCSP_response_status_str(long s)
1363
0
{
1364
0
    switch (s) {
1365
0
        case OCSP_SUCCESSFUL:
1366
0
            return "successful";
1367
0
        case OCSP_MALFORMED_REQUEST:
1368
0
            return "malformedrequest";
1369
0
        case OCSP_INTERNAL_ERROR:
1370
0
            return "internalerror";
1371
0
        case OCSP_TRY_LATER:
1372
0
            return "trylater";
1373
0
        case OCSP_SIG_REQUIRED:
1374
0
            return "sigrequired";
1375
0
        case OCSP_UNAUTHORIZED:
1376
0
            return "unauthorized";
1377
0
        default:
1378
0
            return "(UNKNOWN)";
1379
0
    }
1380
0
}
1381
1382
WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
1383
0
{
1384
0
    WOLFSSL_OCSP_BASICRESP* bs;
1385
0
    const unsigned char *ptr;
1386
1387
0
    if (response == NULL || response->source == NULL)
1388
0
        return NULL;
1389
1390
0
    ptr = response->source;
1391
0
    bs = wolfSSL_d2i_OCSP_RESPONSE(NULL, &ptr, response->maxIdx);
1392
0
    return bs;
1393
0
}
1394
1395
OcspRequest* wolfSSL_OCSP_REQUEST_new(void)
1396
0
{
1397
0
    OcspRequest* request;
1398
1399
0
    request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL,
1400
0
                                    DYNAMIC_TYPE_OPENSSL);
1401
0
    if (request != NULL)
1402
0
        XMEMSET(request, 0, sizeof(OcspRequest));
1403
1404
0
    return request;
1405
0
}
1406
1407
void wolfSSL_OCSP_REQUEST_free(OcspRequest* request)
1408
0
{
1409
0
    FreeOcspRequest(request);
1410
0
    XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL);
1411
0
}
1412
1413
int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data)
1414
0
{
1415
0
    int size;
1416
1417
0
    if (request == NULL)
1418
0
        return BAD_FUNC_ARG;
1419
1420
0
    size = EncodeOcspRequest(request, NULL, 0);
1421
0
    if (size <= 0 || data == NULL)
1422
0
        return size;
1423
1424
0
    size = EncodeOcspRequest(request, *data, (word32) size);
1425
0
    if (size > 0)
1426
0
        *data += size;
1427
1428
0
    return size;
1429
0
}
1430
1431
WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req,
1432
    WOLFSSL_OCSP_CERTID *cid)
1433
0
{
1434
0
    if (req == NULL || cid == NULL || cid->status == NULL)
1435
0
        return NULL;
1436
1437
0
    if (req->cid != NULL)
1438
0
        wolfSSL_OCSP_CERTID_free((WOLFSSL_OCSP_CERTID*)req->cid);
1439
    /* Keep to free */
1440
0
    req->cid = (void*)cid;
1441
1442
0
    XMEMCPY(req->issuerHash, cid->issuerHash, WC_MAX_DIGEST_SIZE);
1443
0
    XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, WC_MAX_DIGEST_SIZE);
1444
0
    req->hashAlg = (int)cid->hashAlgoOID;
1445
0
    if (cid->status->serialSz > req->serialSz) {
1446
0
        XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP);
1447
0
        req->serial = (byte*)XMALLOC((size_t)cid->status->serialSz,
1448
0
                req->heap, DYNAMIC_TYPE_OCSP_REQUEST);
1449
0
        if (req->serial == NULL)
1450
0
            return NULL;
1451
0
    }
1452
0
    XMEMCPY(req->serial, cid->status->serial, (size_t)cid->status->serialSz);
1453
0
    req->serialSz = cid->status->serialSz;
1454
1455
0
    return req;
1456
0
}
1457
1458
WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_CERTID_dup(WOLFSSL_OCSP_CERTID* id)
1459
0
{
1460
0
    WOLFSSL_OCSP_CERTID* certId;
1461
1462
0
    if (id == NULL)
1463
0
        return NULL;
1464
1465
0
    certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID),
1466
0
        NULL, DYNAMIC_TYPE_OPENSSL);
1467
0
    if (certId == NULL)
1468
0
        return NULL;
1469
1470
0
    XMEMCPY(certId, id, sizeof(WOLFSSL_OCSP_CERTID));
1471
0
    certId->next = NULL;
1472
0
    certId->rawCertId = NULL;
1473
0
    certId->rawCertIdSize = 0;
1474
1475
    /* Deep-copy the status to avoid double-free */
1476
0
    if (id->status != NULL) {
1477
0
        certId->status = (CertStatus*)XMALLOC(sizeof(CertStatus),
1478
0
            NULL, DYNAMIC_TYPE_OCSP_STATUS);
1479
0
        if (certId->status == NULL) {
1480
0
            XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
1481
0
            return NULL;
1482
0
        }
1483
0
        XMEMCPY(certId->status, id->status, sizeof(CertStatus));
1484
0
        certId->status->next = NULL;
1485
        /* Don't share dynamically allocated fields */
1486
0
        certId->status->rawOcspResponse = NULL;
1487
0
        certId->status->rawOcspResponseSz = 0;
1488
0
        certId->status->serialInt = NULL;
1489
0
#ifdef WOLFSSL_OCSP_PARSE_STATUS
1490
0
        certId->status->thisDateAsn = NULL;
1491
0
        certId->status->nextDateAsn = NULL;
1492
0
#endif
1493
0
    }
1494
0
    certId->ownStatus = 1;
1495
1496
0
    return certId;
1497
0
}
1498
1499
#ifndef NO_BIO
1500
int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out,
1501
        WOLFSSL_OCSP_REQUEST *req)
1502
0
{
1503
0
    int size = -1;
1504
0
    unsigned char* data = NULL;
1505
1506
0
    WOLFSSL_ENTER("wolfSSL_i2d_OCSP_REQUEST_bio");
1507
0
    if (out == NULL || req == NULL)
1508
0
        return WOLFSSL_FAILURE;
1509
1510
0
    size = wolfSSL_i2d_OCSP_REQUEST(req, NULL);
1511
0
    if (size > 0) {
1512
0
        data = (unsigned char*) XMALLOC((size_t)size, out->heap,
1513
0
                DYNAMIC_TYPE_TMP_BUFFER);
1514
0
    }
1515
1516
0
    if (data != NULL) {
1517
0
        unsigned char* dataOrig = data;
1518
0
        size = wolfSSL_i2d_OCSP_REQUEST(req, &data);
1519
0
        data = dataOrig;
1520
0
    }
1521
1522
0
    if (size <= 0) {
1523
0
        XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER);
1524
0
        return WOLFSSL_FAILURE;
1525
0
    }
1526
1527
0
    if (wolfSSL_BIO_write(out, data, size) == (int)size) {
1528
0
        XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER);
1529
0
        return WOLFSSL_SUCCESS;
1530
0
    }
1531
1532
0
    XFREE(data, out->heap, DYNAMIC_TYPE_TMP_BUFFER);
1533
0
    return WOLFSSL_FAILURE;
1534
0
}
1535
#endif /* !NO_BIO */
1536
1537
int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID* id, unsigned char** data)
1538
0
{
1539
0
    int allocated = 0;
1540
0
    word32 derSz = 0;
1541
0
    word32 intSz = 0;
1542
0
    int ret;
1543
0
    WOLFSSL_ENTER("wolfSSL_i2d_OCSP_CERTID");
1544
1545
0
    if (id == NULL)
1546
0
        return -1;
1547
1548
0
    if (id->rawCertId != NULL) {
1549
0
        derSz = id->rawCertIdSize;
1550
0
    }
1551
0
    else {
1552
0
        ret = OcspEncodeCertID(id, NULL, &derSz, &intSz);
1553
0
        if (ret != 0) {
1554
0
            WOLFSSL_MSG("Failed to calculate CertID size");
1555
0
            return -1;
1556
0
        }
1557
0
    }
1558
1559
0
    if (data == NULL) {
1560
0
        return derSz;
1561
0
    }
1562
1563
0
    if (*data == NULL) {
1564
        /* Allocate buffer for DER encoding */
1565
0
        *data = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL);
1566
0
        if (*data == NULL) {
1567
0
            WOLFSSL_MSG("Failed to allocate memory for CertID DER encoding");
1568
0
            return -1;
1569
0
        }
1570
0
        allocated = 1;
1571
0
    }
1572
1573
0
    if (id->rawCertId != NULL) {
1574
0
        XMEMCPY(*data, id->rawCertId, id->rawCertIdSize);
1575
0
    }
1576
0
    else {
1577
0
        ret = OcspEncodeCertID(id, *data, &derSz, &intSz);
1578
0
        if (ret < 0) {
1579
0
            WOLFSSL_MSG("Failed to encode CertID");
1580
0
            if (allocated) {
1581
0
                XFREE(*data, NULL, DYNAMIC_TYPE_OPENSSL);
1582
0
                *data = NULL;
1583
0
            }
1584
0
            return -1;
1585
0
        }
1586
0
    }
1587
1588
0
    if (!allocated)
1589
0
        *data += derSz;
1590
1591
0
    return derSz;
1592
0
}
1593
1594
WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut,
1595
                                             const unsigned char** derIn,
1596
                                             int length)
1597
0
{
1598
0
    WOLFSSL_OCSP_CERTID *cid = NULL;
1599
0
    int isAllocated = 0;
1600
0
    word32 idx = 0;
1601
0
    int ret;
1602
1603
0
    if (derIn == NULL || *derIn == NULL || length <= 0)
1604
0
        return NULL;
1605
1606
0
    if (cidOut != NULL && *cidOut != NULL) {
1607
0
        cid = *cidOut;
1608
0
        FreeOcspEntry(cid, NULL);
1609
0
    }
1610
0
    else {
1611
0
        cid = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL,
1612
0
            DYNAMIC_TYPE_OPENSSL);
1613
0
        if (cid == NULL)
1614
0
            return NULL;
1615
0
        isAllocated = 1;
1616
0
    }
1617
1618
0
    XMEMSET(cid, 0, sizeof(WOLFSSL_OCSP_CERTID));
1619
0
    cid->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
1620
0
        DYNAMIC_TYPE_OCSP_STATUS);
1621
0
    if (cid->status == NULL) {
1622
0
        if (isAllocated) {
1623
0
            XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL);
1624
0
        }
1625
0
        return NULL;
1626
0
    }
1627
0
    XMEMSET(cid->status, 0, sizeof(CertStatus));
1628
0
    cid->ownStatus = 1;
1629
1630
0
    ret = OcspDecodeCertID(*derIn, &idx, length, cid);
1631
0
    if (ret != 0) {
1632
0
        FreeOcspEntry(cid, NULL);
1633
0
        if (isAllocated) {
1634
0
            XFREE(cid, NULL, DYNAMIC_TYPE_OPENSSL);
1635
0
        }
1636
0
        return NULL;
1637
0
    }
1638
1639
0
    *derIn += idx;
1640
1641
0
    if (isAllocated && cidOut != NULL)
1642
0
        *cidOut = cid;
1643
1644
0
    return cid;
1645
0
}
1646
1647
const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id(
1648
    const WOLFSSL_OCSP_SINGLERESP *single)
1649
0
{
1650
0
    return single;
1651
0
}
1652
1653
/**
1654
 * Compare two WOLFSSL_OCSP_CERTID objects
1655
 * @param a
1656
 * @param b
1657
 * @return 0 on success and when objects have the same id otherwise either
1658
 *         the id's don't match or an error occurred
1659
 */
1660
int wolfSSL_OCSP_id_cmp(WOLFSSL_OCSP_CERTID *a, WOLFSSL_OCSP_CERTID *b)
1661
0
{
1662
0
    int ret = 0;
1663
0
    if (a == NULL || b == NULL)
1664
0
        return WOLFSSL_FATAL_ERROR;
1665
1666
0
    ret = a->hashAlgoOID != b->hashAlgoOID;
1667
0
    if (ret == 0)
1668
0
        ret = XMEMCMP(a->issuerHash, b->issuerHash, OCSP_DIGEST_SIZE);
1669
0
    if (ret == 0)
1670
0
        ret = XMEMCMP(a->issuerKeyHash, b->issuerKeyHash, OCSP_DIGEST_SIZE);
1671
0
    if (ret == 0) {
1672
0
        if (a->status != NULL && b->status != NULL) {
1673
0
            if (a->status->serialSz == b->status->serialSz)
1674
0
                ret = XMEMCMP(a->status->serial, b->status->serial,
1675
0
                        (size_t)a->status->serialSz);
1676
0
            else
1677
0
                ret = -1;
1678
0
        }
1679
0
        else if (a->status != b->status) {
1680
            /* If either is not null then return non-zero */
1681
0
            ret = -1;
1682
0
        }
1683
0
    }
1684
0
    return ret;
1685
0
}
1686
1687
int wolfSSL_OCSP_single_get0_status(WOLFSSL_OCSP_SINGLERESP *single,
1688
                                    int *reason,
1689
                                    WOLFSSL_ASN1_TIME **revtime,
1690
                                    WOLFSSL_ASN1_TIME **thisupd,
1691
                                    WOLFSSL_ASN1_TIME **nextupd)
1692
0
{
1693
0
    if (single == NULL || single->status == NULL)
1694
0
        return -1;
1695
1696
0
#ifdef WOLFSSL_OCSP_PARSE_STATUS
1697
    /* NULL when the response has no such field, as with OpenSSL. */
1698
0
    if (thisupd != NULL) {
1699
0
        *thisupd = (single->status->thisDateParsed.length > 0) ?
1700
0
            &single->status->thisDateParsed : NULL;
1701
0
    }
1702
0
    if (nextupd != NULL) {
1703
0
        *nextupd = (single->status->nextDateParsed.length > 0) ?
1704
0
            &single->status->nextDateParsed : NULL;
1705
0
    }
1706
#else
1707
    if (thisupd != NULL)
1708
        *thisupd = NULL;
1709
    if (nextupd != NULL)
1710
        *nextupd = NULL;
1711
#endif
1712
0
    if (reason != NULL)
1713
0
        *reason = 0;
1714
0
    if (revtime != NULL)
1715
0
        *revtime = NULL;
1716
1717
0
    return single->status->status;
1718
0
}
1719
1720
int wolfSSL_OCSP_resp_count(WOLFSSL_OCSP_BASICRESP *bs)
1721
0
{
1722
0
    WOLFSSL_OCSP_SINGLERESP* single;
1723
0
    int count = 0;
1724
1725
0
    if (bs == NULL)
1726
0
        return WOLFSSL_FAILURE;
1727
1728
0
    single = bs->single;
1729
0
    while(single != NULL)
1730
0
    {
1731
0
        ++count;
1732
0
        single = single->next;
1733
0
    }
1734
1735
0
    return count;
1736
0
}
1737
1738
WOLFSSL_OCSP_SINGLERESP* wolfSSL_OCSP_resp_get0(WOLFSSL_OCSP_BASICRESP *bs, int idx)
1739
0
{
1740
0
    WOLFSSL_OCSP_SINGLERESP* single;
1741
0
    int currIdx = 0;
1742
1743
0
    if (bs == NULL)
1744
0
        return NULL;
1745
1746
0
    single = bs->single;
1747
0
    while(single != NULL && currIdx != idx)
1748
0
    {
1749
0
        single = single->next;
1750
0
        ++currIdx;
1751
0
    }
1752
1753
0
    return single;
1754
0
}
1755
1756
#endif /* OPENSSL_EXTRA */
1757
1758
#ifdef OPENSSL_ALL
1759
1760
/*******************************************************************************
1761
 * START OF WOLFSSL_OCSP_REQ_CTX API
1762
 ******************************************************************************/
1763
1764
enum ocspReqStates {
1765
    ORS_INVALID = 0,
1766
    ORS_HEADER_ADDED,
1767
    ORS_REQ_DONE
1768
};
1769
1770
enum ocspReqIOStates {
1771
    ORIOS_INVALID = 0,
1772
    ORIOS_WRITE,
1773
    ORIOS_READ
1774
};
1775
1776
WOLFSSL_OCSP_REQ_CTX* wolfSSL_OCSP_REQ_CTX_new(WOLFSSL_BIO *bio, int maxline)
1777
0
{
1778
0
    WOLFSSL_OCSP_REQ_CTX* ret = NULL;
1779
1780
0
    WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_new");
1781
1782
0
    if (maxline <= 0)
1783
0
        maxline = OCSP_MAX_REQUEST_SZ;
1784
1785
0
    ret = (WOLFSSL_OCSP_REQ_CTX*)XMALLOC(sizeof(*ret), NULL,
1786
0
            DYNAMIC_TYPE_OPENSSL);
1787
0
    if (ret != NULL) {
1788
0
        XMEMSET(ret, 0, sizeof(*ret));
1789
0
        ret->buf = (byte*)XMALLOC((word32)maxline, NULL, DYNAMIC_TYPE_OPENSSL);
1790
0
        if (ret->buf == NULL)
1791
0
            goto error;
1792
0
        ret->reqResp = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
1793
0
        ret->bufLen = maxline;
1794
0
        ret->bio = bio;
1795
0
        ret->ioState = ORIOS_WRITE;
1796
0
    }
1797
1798
0
    return ret;
1799
0
error:
1800
0
    wolfSSL_OCSP_REQ_CTX_free(ret);
1801
0
    return NULL;
1802
0
}
1803
1804
void wolfSSL_OCSP_REQ_CTX_free(WOLFSSL_OCSP_REQ_CTX *ctx)
1805
0
{
1806
0
    WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_free");
1807
0
    if (ctx != NULL) {
1808
0
        if (ctx->buf != NULL)
1809
0
            XFREE(ctx->buf, NULL, DYNAMIC_TYPE_OPENSSL);
1810
0
        if (ctx->reqResp != NULL)
1811
0
            wolfSSL_BIO_free(ctx->reqResp);
1812
0
        XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL);
1813
0
    }
1814
0
}
1815
1816
WOLFSSL_OCSP_REQ_CTX* wolfSSL_OCSP_sendreq_new(WOLFSSL_BIO *bio,
1817
        const char *path, OcspRequest *req, int maxline)
1818
0
{
1819
0
    WOLFSSL_OCSP_REQ_CTX* ret = NULL;
1820
1821
0
    WOLFSSL_ENTER("wolfSSL_OCSP_sendreq_new");
1822
1823
0
    ret = wolfSSL_OCSP_REQ_CTX_new(bio, maxline);
1824
0
    if (ret == NULL)
1825
0
        return NULL;
1826
1827
0
    if (wolfSSL_OCSP_REQ_CTX_http(ret, "POST", path) != WOLFSSL_SUCCESS)
1828
0
        goto error;
1829
1830
0
    if (req != NULL &&
1831
0
            wolfSSL_OCSP_REQ_CTX_set1_req(ret, req) != WOLFSSL_SUCCESS)
1832
0
        goto error;
1833
1834
0
    return ret;
1835
0
error:
1836
0
    wolfSSL_OCSP_REQ_CTX_free(ret);
1837
0
    return NULL;
1838
0
}
1839
1840
/* Returns 0 if the string has no CR or LF, -1 if it does. */
1841
static int OCSP_REQ_CTX_no_crlf(const char* value)
1842
0
{
1843
0
    if (value != NULL) {
1844
0
        const char* c;
1845
0
        for (c = value; *c != '\0'; c++) {
1846
0
            if (*c == '\r' || *c == '\n')
1847
0
                return -1;
1848
0
        }
1849
0
    }
1850
1851
0
    return 0;
1852
0
}
1853
1854
int wolfSSL_OCSP_REQ_CTX_add1_header(WOLFSSL_OCSP_REQ_CTX *ctx,
1855
                             const char *name, const char *value)
1856
0
{
1857
0
    WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_add1_header");
1858
1859
0
    if (ctx == NULL || name == NULL) {
1860
0
        WOLFSSL_MSG("Bad parameter");
1861
0
        return WOLFSSL_FAILURE;
1862
0
    }
1863
0
    if (OCSP_REQ_CTX_no_crlf(name) != 0 || OCSP_REQ_CTX_no_crlf(value) != 0) {
1864
0
        WOLFSSL_MSG("CR/LF in header name or value");
1865
0
        return WOLFSSL_FAILURE;
1866
0
    }
1867
    /* A name starting with whitespace is an obs-fold continuation line
1868
     * (RFC 7230 Section 3.2.4) appending to the previous header's value. */
1869
0
    if (*name == ' ' || *name == '\t') {
1870
0
        WOLFSSL_MSG("Leading whitespace in header name");
1871
0
        return WOLFSSL_FAILURE;
1872
0
    }
1873
0
    if (wolfSSL_BIO_puts(ctx->reqResp, name) <= 0) {
1874
0
        WOLFSSL_MSG("wolfSSL_BIO_puts error");
1875
0
        return WOLFSSL_FAILURE;
1876
0
    }
1877
0
    if (value != NULL) {
1878
0
        if (wolfSSL_BIO_write(ctx->reqResp, ": ", 2) != 2) {
1879
0
            WOLFSSL_MSG("wolfSSL_BIO_write error");
1880
0
            return WOLFSSL_FAILURE;
1881
0
        }
1882
0
        if (wolfSSL_BIO_puts(ctx->reqResp, value) <= 0) {
1883
0
            WOLFSSL_MSG("wolfSSL_BIO_puts error");
1884
0
            return WOLFSSL_FAILURE;
1885
0
        }
1886
0
    }
1887
0
    if (wolfSSL_BIO_write(ctx->reqResp, "\r\n", 2) != 2) {
1888
0
        WOLFSSL_MSG("wolfSSL_BIO_write error");
1889
0
        return WOLFSSL_FAILURE;
1890
0
    }
1891
1892
0
    ctx->state = ORS_HEADER_ADDED;
1893
1894
0
    return WOLFSSL_SUCCESS;
1895
0
}
1896
1897
int wolfSSL_OCSP_REQ_CTX_http(WOLFSSL_OCSP_REQ_CTX *ctx, const char *op,
1898
        const char *path)
1899
0
{
1900
0
    static const char http_hdr[] = "%s %s HTTP/1.0\r\n";
1901
1902
0
    WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_http");
1903
1904
0
    if (ctx == NULL || op == NULL) {
1905
0
        WOLFSSL_MSG("Bad parameter");
1906
0
        return WOLFSSL_FAILURE;
1907
0
    }
1908
1909
0
    if (path == NULL)
1910
0
        path = "/";
1911
1912
0
    if (OCSP_REQ_CTX_no_crlf(op) != 0 || OCSP_REQ_CTX_no_crlf(path) != 0) {
1913
0
        WOLFSSL_MSG("CR/LF in HTTP op or path");
1914
0
        return WOLFSSL_FAILURE;
1915
0
    }
1916
1917
0
    if (wolfSSL_BIO_printf(ctx->reqResp, http_hdr, op, path) <= 0) {
1918
0
        WOLFSSL_MSG("WOLFSSL_OCSP_REQ_CTX: wolfSSL_BIO_printf error");
1919
0
        return WOLFSSL_FAILURE;
1920
0
    }
1921
1922
0
    ctx->state = ORS_HEADER_ADDED;
1923
1924
0
    return WOLFSSL_SUCCESS;
1925
0
}
1926
1927
int wolfSSL_OCSP_REQ_CTX_set1_req(WOLFSSL_OCSP_REQ_CTX *ctx, OcspRequest *req)
1928
0
{
1929
0
    static const char req_hdr[] =
1930
0
        "Content-Type: application/ocsp-request\r\n"
1931
0
        "Content-Length: %d\r\n\r\n";
1932
    /* Should be enough to hold Content-Length */
1933
0
    char req_hdr_buf[sizeof(req_hdr) + 10];
1934
0
    int req_hdr_buf_len;
1935
0
    int req_len = wolfSSL_i2d_OCSP_REQUEST(req, NULL);
1936
1937
0
    WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_set1_req");
1938
1939
0
    if (ctx == NULL || req == NULL) {
1940
0
        WOLFSSL_MSG("Bad parameters");
1941
0
        return WOLFSSL_FAILURE;
1942
0
    }
1943
1944
0
    if (req_len <= 0) {
1945
0
        WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: request len error");
1946
0
        return WOLFSSL_FAILURE;
1947
0
    }
1948
1949
0
    req_hdr_buf_len =
1950
0
            XSNPRINTF(req_hdr_buf, sizeof(req_hdr_buf), req_hdr, req_len);
1951
0
    if (req_hdr_buf_len >= (int)sizeof(req_hdr_buf)) {
1952
0
        WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: request too long");
1953
0
        return WOLFSSL_FAILURE;
1954
0
    }
1955
1956
0
    if (wolfSSL_BIO_write(ctx->reqResp, req_hdr_buf, req_hdr_buf_len) <= 0) {
1957
0
        WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: wolfSSL_BIO_write error");
1958
0
        return WOLFSSL_FAILURE;
1959
0
    }
1960
1961
0
    if (wolfSSL_i2d_OCSP_REQUEST_bio(ctx->reqResp, req) <= 0) {
1962
0
        WOLFSSL_MSG("wolfSSL_OCSP_REQ_CTX_set1_req: request i2d error");
1963
0
        return WOLFSSL_FAILURE;
1964
0
    }
1965
1966
0
    ctx->state = ORS_REQ_DONE;
1967
1968
0
    return WOLFSSL_SUCCESS;
1969
0
}
1970
1971
static int OCSP_REQ_CTX_bio_cb(char *buf, int sz, void *ctx)
1972
0
{
1973
0
    return BioReceiveInternal((WOLFSSL_BIO*)ctx, NULL, buf, sz);
1974
0
}
1975
1976
int wolfSSL_OCSP_REQ_CTX_nbio(WOLFSSL_OCSP_REQ_CTX *ctx)
1977
0
{
1978
0
    WOLFSSL_ENTER("wolfSSL_OCSP_REQ_CTX_nbio");
1979
1980
0
    if (ctx == NULL) {
1981
0
        WOLFSSL_MSG("Bad parameters");
1982
0
        return WOLFSSL_FAILURE;
1983
0
    }
1984
1985
0
    switch ((enum ocspReqIOStates)ctx->ioState) {
1986
0
        case ORIOS_WRITE:
1987
0
        case ORIOS_READ:
1988
0
            break;
1989
0
        case ORIOS_INVALID:
1990
0
        default:
1991
0
            WOLFSSL_MSG("Invalid ctx->ioState state");
1992
0
            return WOLFSSL_FAILURE;
1993
0
    }
1994
1995
0
    if (ctx->ioState == ORIOS_WRITE) {
1996
0
        switch ((enum ocspReqStates)ctx->state) {
1997
0
            case ORS_HEADER_ADDED:
1998
                /* Write final new line to complete http header */
1999
0
                if (wolfSSL_BIO_write(ctx->reqResp, "\r\n", 2) != 2) {
2000
0
                    WOLFSSL_MSG("wolfSSL_BIO_write error");
2001
0
                    return WOLFSSL_FAILURE;
2002
0
                }
2003
0
                break;
2004
0
            case ORS_REQ_DONE:
2005
0
                break;
2006
0
            case ORS_INVALID:
2007
0
            default:
2008
0
                WOLFSSL_MSG("Invalid WOLFSSL_OCSP_REQ_CTX state");
2009
0
                return WOLFSSL_FAILURE;
2010
0
        }
2011
0
    }
2012
2013
0
    switch ((enum ocspReqIOStates)ctx->ioState) {
2014
0
        case ORIOS_WRITE:
2015
0
        {
2016
0
            const unsigned char *req;
2017
0
            int reqLen = wolfSSL_BIO_get_mem_data(ctx->reqResp, (void*)&req);
2018
0
            if (reqLen <= 0) {
2019
0
                WOLFSSL_MSG("wolfSSL_BIO_get_mem_data error");
2020
0
                return WOLFSSL_FAILURE;
2021
0
            }
2022
0
            while (ctx->sent < reqLen) {
2023
0
                int sent = wolfSSL_BIO_write(ctx->bio, req + ctx->sent,
2024
0
                        reqLen - ctx->sent);
2025
0
                if (sent <= 0) {
2026
0
                    if (wolfSSL_BIO_should_retry(ctx->bio))
2027
0
                        return WOLFSSL_FATAL_ERROR;
2028
0
                    WOLFSSL_MSG("wolfSSL_BIO_write error");
2029
0
                    ctx->ioState = ORIOS_INVALID;
2030
0
                    return 0;
2031
0
                }
2032
0
                ctx->sent += sent;
2033
0
            }
2034
0
            ctx->sent = 0;
2035
0
            ctx->ioState = ORIOS_READ;
2036
0
            (void)wolfSSL_BIO_reset(ctx->reqResp);
2037
0
            FALL_THROUGH;
2038
0
        }
2039
0
        case ORIOS_READ:
2040
0
        {
2041
0
            byte* resp = NULL;
2042
0
            int respLen;
2043
0
            int ret;
2044
2045
0
            if (ctx->buf == NULL) /* Should be allocated in new call */
2046
0
                return WOLFSSL_FAILURE;
2047
2048
0
            ret = wolfIO_HttpProcessResponseOcspGenericIO(OCSP_REQ_CTX_bio_cb,
2049
0
                    ctx->bio, &resp, ctx->buf, ctx->bufLen, NULL);
2050
0
            if (ret <= 0) {
2051
0
                if (resp != NULL)
2052
0
                    XFREE(resp, NULL, DYNAMIC_TYPE_OCSP);
2053
0
                if (ret == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ) ||
2054
0
                    ret == WC_NO_ERR_TRACE(OCSP_WANT_READ))
2055
0
                {
2056
0
                    return WOLFSSL_FATAL_ERROR;
2057
0
                }
2058
0
                return WOLFSSL_FAILURE;
2059
0
            }
2060
0
            respLen = ret;
2061
0
            ret = wolfSSL_BIO_write(ctx->reqResp, resp, respLen);
2062
0
            XFREE(resp, NULL, DYNAMIC_TYPE_OCSP);
2063
0
            if (ret != respLen) {
2064
0
                WOLFSSL_MSG("wolfSSL_BIO_write error");
2065
0
                return WOLFSSL_FAILURE;
2066
0
            }
2067
0
            break;
2068
0
        }
2069
0
        case ORIOS_INVALID:
2070
0
        default:
2071
0
            WOLFSSL_MSG("Invalid ctx->ioState state");
2072
0
            return WOLFSSL_FAILURE;
2073
0
    }
2074
2075
0
    return WOLFSSL_SUCCESS;
2076
0
}
2077
2078
int wolfSSL_OCSP_sendreq_nbio(OcspResponse **presp, WOLFSSL_OCSP_REQ_CTX *ctx)
2079
0
{
2080
0
    int ret;
2081
0
    int len;
2082
0
    const unsigned char *resp = NULL;
2083
2084
0
    WOLFSSL_ENTER("wolfSSL_OCSP_sendreq_nbio");
2085
2086
0
    if (presp == NULL)
2087
0
        return WOLFSSL_FAILURE;
2088
2089
0
    ret = wolfSSL_OCSP_REQ_CTX_nbio(ctx);
2090
0
    if (ret != WOLFSSL_SUCCESS)
2091
0
        return ret;
2092
2093
0
    len = wolfSSL_BIO_get_mem_data(ctx->reqResp, (void*)&resp);
2094
0
    if (len <= 0)
2095
0
        return WOLFSSL_FAILURE;
2096
0
    return wolfSSL_d2i_OCSP_RESPONSE(presp, &resp, len) != NULL
2097
0
            ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
2098
0
}
2099
2100
/*******************************************************************************
2101
 * END OF WOLFSSL_OCSP_REQ_CTX API
2102
 ******************************************************************************/
2103
2104
#ifndef NO_WOLFSSL_STUB
2105
int wolfSSL_OCSP_REQUEST_add_ext(OcspRequest* req, WOLFSSL_X509_EXTENSION* ext,
2106
        int idx)
2107
0
{
2108
0
    WOLFSSL_STUB("wolfSSL_OCSP_REQUEST_add_ext");
2109
0
    (void)req;
2110
0
    (void)ext;
2111
0
    (void)idx;
2112
0
    return WOLFSSL_FATAL_ERROR;
2113
0
}
2114
#endif
2115
2116
#ifndef NO_WOLFSSL_STUB
2117
OcspResponse* wolfSSL_OCSP_response_create(int status,
2118
    WOLFSSL_OCSP_BASICRESP* bs)
2119
0
{
2120
0
    WOLFSSL_STUB("wolfSSL_OCSP_response_create");
2121
0
    (void)status;
2122
0
    (void)bs;
2123
0
    return NULL;
2124
0
}
2125
#endif
2126
2127
#ifndef NO_WOLFSSL_STUB
2128
const char* wolfSSL_OCSP_crl_reason_str(long s)
2129
0
{
2130
0
    WOLFSSL_STUB("wolfSSL_OCSP_crl_reason_str");
2131
0
    (void)s;
2132
0
    return NULL;
2133
0
}
2134
#endif
2135
2136
/* Returns elements of an OCSP_CERTID struct. Currently only supports
2137
 * returning the serial number, and returns an error if user requests
2138
 * any of name, pmd, and/or keyHash.
2139
 * Return 1 on success, 0 on failure */
2140
int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name,
2141
  WOLFSSL_ASN1_OBJECT **pmd, WOLFSSL_ASN1_STRING **keyHash,
2142
  WOLFSSL_ASN1_INTEGER **serial, WOLFSSL_OCSP_CERTID *cid)
2143
0
{
2144
0
    WOLFSSL_ENTER("wolfSSL_OCSP_id_get0_info");
2145
2146
0
    if (cid == NULL)
2147
0
        return 0;
2148
2149
    /* build up ASN1_INTEGER for serial */
2150
0
    if (serial != NULL) {
2151
0
        int i = 0;
2152
0
        WOLFSSL_ASN1_INTEGER* ser;
2153
2154
0
        ser = wolfSSL_ASN1_INTEGER_new();
2155
0
        if (ser == NULL)
2156
0
            return 0;
2157
2158
0
        if (cid->status->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
2159
            /* allocate data buffer, +2 for type and length */
2160
0
            ser->data = (unsigned char*)XMALLOC((size_t)cid->status->serialSz + 2, NULL,
2161
0
                DYNAMIC_TYPE_OPENSSL);
2162
0
            if (ser->data == NULL) {
2163
0
                wolfSSL_ASN1_INTEGER_free(ser);
2164
0
                return 0;
2165
0
            }
2166
0
            ser->dataMax = (unsigned int)cid->status->serialSz + 2;
2167
0
            ser->isDynamic = 1;
2168
0
        } else {
2169
            /* Use array instead of dynamic memory */
2170
0
            ser->data    = ser->intData;
2171
0
            ser->dataMax = WOLFSSL_ASN1_INTEGER_MAX;
2172
0
        }
2173
2174
        #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY)
2175
            /* Serial number starts at 0 index of ser->data */
2176
            XMEMCPY(&ser->data[i], cid->status->serial,
2177
                (size_t)cid->status->serialSz);
2178
            ser->length = cid->status->serialSz;
2179
        #else
2180
0
            ser->data[i++] = ASN_INTEGER;
2181
0
            i += SetLength(cid->status->serialSz, ser->data + i);
2182
0
            XMEMCPY(&ser->data[i], cid->status->serial,
2183
0
                (size_t)cid->status->serialSz);
2184
0
            ser->length = i + cid->status->serialSz;
2185
0
        #endif
2186
2187
0
        cid->status->serialInt = ser;
2188
0
        *serial = ser;
2189
0
    }
2190
2191
    /* Not needed for Apache, return error if user is requesting */
2192
0
    if (name != NULL || pmd != NULL || keyHash != NULL) {
2193
0
        if (name != NULL)
2194
0
            *name = NULL;
2195
2196
0
        if (pmd != NULL)
2197
0
            *pmd = NULL;
2198
2199
0
        if (keyHash != NULL)
2200
0
            *keyHash = NULL;
2201
0
        return 0;
2202
0
    }
2203
2204
0
    return 1;
2205
0
}
2206
2207
int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val,
2208
        int sz)
2209
0
{
2210
0
    WC_RNG rng;
2211
2212
0
    WOLFSSL_ENTER("wolfSSL_OCSP_request_add1_nonce");
2213
2214
0
    if (req == NULL || sz > MAX_OCSP_NONCE_SZ) {
2215
0
        WOLFSSL_MSG("Bad parameter");
2216
0
        return WOLFSSL_FAILURE;
2217
0
    }
2218
2219
0
    if (sz <= 0)
2220
0
        sz = MAX_OCSP_NONCE_SZ;
2221
2222
0
    if (val != NULL) {
2223
0
        XMEMCPY(req->nonce, val, (size_t)sz);
2224
0
    }
2225
0
    else {
2226
0
        if (
2227
0
#ifndef HAVE_FIPS
2228
0
            wc_InitRng_ex(&rng, req->heap, INVALID_DEVID)
2229
#else
2230
            wc_InitRng(&rng)
2231
#endif
2232
0
            != 0) {
2233
0
            WOLFSSL_MSG("RNG init failed");
2234
0
            return WOLFSSL_FAILURE;
2235
0
        }
2236
0
        if (wc_RNG_GenerateBlock(&rng, req->nonce, (word32)sz) != 0) {
2237
0
            WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
2238
0
            wc_FreeRng(&rng);
2239
0
            return WOLFSSL_FAILURE;
2240
0
        }
2241
0
        wc_FreeRng(&rng);
2242
0
    }
2243
0
    req->nonceSz = sz;
2244
2245
0
    return WOLFSSL_SUCCESS;
2246
0
}
2247
2248
/* Returns result of OCSP nonce comparison. Return values:
2249
 *  1 - nonces are both present and equal
2250
 *  2 - both nonces are absent
2251
 *  3 - nonce only present in response
2252
 * -1 - nonce only present in request
2253
 *  0 - both nonces present and equal
2254
 */
2255
int wolfSSL_OCSP_check_nonce(OcspRequest* req, WOLFSSL_OCSP_BASICRESP* bs)
2256
0
{
2257
0
    const byte* reqNonce = NULL;
2258
0
    const byte* rspNonce = NULL;
2259
0
    int reqNonceSz = 0;
2260
0
    int rspNonceSz = 0;
2261
2262
0
    WOLFSSL_ENTER("wolfSSL_OCSP_check_nonce");
2263
2264
0
    if (req != NULL) {
2265
0
        reqNonce = req->nonce;
2266
0
        reqNonceSz = req->nonceSz;
2267
0
    }
2268
2269
0
    if (bs != NULL) {
2270
0
        rspNonce = bs->nonce;
2271
0
        rspNonceSz = bs->nonceSz;
2272
0
    }
2273
2274
    /* nonce absent in both req and rsp */
2275
0
    if (reqNonce == NULL && rspNonce == NULL)
2276
0
        return 2;
2277
2278
    /* nonce present in rsp only */
2279
0
    if (reqNonce == NULL && rspNonce != NULL)
2280
0
        return 3;
2281
2282
    /* nonce present in req only */
2283
0
    if (reqNonce != NULL && rspNonce == NULL)
2284
0
        return WOLFSSL_FATAL_ERROR;
2285
2286
    /* nonces are present and equal, return 1. Extra NULL check for fixing
2287
        scan-build warning. */
2288
0
    if (reqNonceSz == rspNonceSz && reqNonce && rspNonce) {
2289
0
        if (XMEMCMP(reqNonce, rspNonce, (size_t)reqNonceSz) == 0)
2290
0
            return 1;
2291
0
    }
2292
2293
    /* nonces are present but not equal */
2294
0
    return 0;
2295
0
}
2296
2297
#endif /* OPENSSL_ALL */
2298
2299
#ifdef HAVE_OCSP_RESPONDER
2300
2301
/* Free a CA entry and all its resources */
2302
static void FreeOcspResponderCa(OcspResponderCa* ca, void* heap)
2303
{
2304
    OcspResponderCertStatus* status;
2305
    OcspResponderCertStatus* nextStatus;
2306
2307
    if (ca == NULL)
2308
        return;
2309
2310
    /* Free private key */
2311
#ifndef NO_RSA
2312
    if (ca->keyType == RSAk) {
2313
        wc_FreeRsaKey(&ca->key.rsa);
2314
    }
2315
#endif
2316
#ifdef HAVE_ECC
2317
    if (ca->keyType == ECDSAk) {
2318
        wc_ecc_free(&ca->key.ecc);
2319
    }
2320
#endif
2321
2322
    /* Free certificate DER if allocated */
2323
    if (ca->certDer != NULL) {
2324
        XFREE(ca->certDer, heap, DYNAMIC_TYPE_OCSP);
2325
    }
2326
2327
    /* Free certificate status list */
2328
    status = ca->statuses;
2329
    while (status != NULL) {
2330
        nextStatus = status->next;
2331
        XFREE(status, heap, DYNAMIC_TYPE_OCSP);
2332
        status = nextStatus;
2333
    }
2334
2335
    XFREE(ca, heap, DYNAMIC_TYPE_OCSP);
2336
}
2337
2338
/* Allocate and initialize an OCSP Responder */
2339
OcspResponder* wc_OcspResponder_new(void* heap, int sendCerts)
2340
{
2341
    OcspResponder* responder;
2342
2343
    WOLFSSL_ENTER("wc_OcspResponder_new");
2344
2345
    responder = (OcspResponder*)XMALLOC(sizeof(OcspResponder), heap,
2346
                                         DYNAMIC_TYPE_OCSP);
2347
    if (responder != NULL) {
2348
        XMEMSET(responder, 0, sizeof(OcspResponder));
2349
        responder->heap = heap;
2350
        responder->sendCerts = sendCerts ? 1 : 0;
2351
        if (wc_InitRng(&responder->rng) != 0) {
2352
            XFREE(responder, heap, DYNAMIC_TYPE_OCSP);
2353
            responder = NULL;
2354
        }
2355
    }
2356
    return responder;
2357
}
2358
2359
/* Free an OCSP Responder */
2360
void wc_OcspResponder_free(OcspResponder* responder)
2361
{
2362
    WOLFSSL_ENTER("wc_OcspResponder_free");
2363
    if (responder != NULL) {
2364
        OcspResponderCa* ca;
2365
        OcspResponderCa* nextCa;
2366
        /* Free all CAs */
2367
        ca = responder->caList;
2368
        while (ca != NULL) {
2369
            nextCa = ca->next;
2370
            FreeOcspResponderCa(ca, responder->heap);
2371
            ca = nextCa;
2372
        }
2373
        wc_FreeRng(&responder->rng);
2374
        XFREE(responder, responder->heap, DYNAMIC_TYPE_OCSP);
2375
    }
2376
}
2377
2378
int wc_OcspResponder_AddSigner(OcspResponder* responder,
2379
    const byte* signerDer, word32 signerDerSz,
2380
    const byte* keyDer, word32 keyDerSz,
2381
    /* Necessary when adding an authorized responder */
2382
    const byte* issuerCertDer, word32 issuerCertDerSz)
2383
{
2384
    int ret = -1;
2385
    OcspResponderCa* ca = NULL;
2386
    DecodedCert* decoded = NULL;
2387
    word32 keyOID = 0;
2388
2389
    WOLFSSL_ENTER("wc_OcspResponder_AddSigner");
2390
2391
    if (responder == NULL || signerDer == NULL || signerDerSz == 0 ||
2392
        keyDer == NULL || keyDerSz == 0 ||
2393
        (issuerCertDerSz != 0 && issuerCertDer == NULL))
2394
        return BAD_FUNC_ARG;
2395
2396
    /* Allocate CA structure */
2397
    ca = (OcspResponderCa*)XMALLOC(sizeof(OcspResponderCa), responder->heap,
2398
                                   DYNAMIC_TYPE_OCSP);
2399
    if (ca == NULL) {
2400
        ret = MEMORY_E;
2401
        goto out;
2402
    }
2403
    XMEMSET(ca, 0, sizeof(OcspResponderCa));
2404
2405
    /* Parse certificate */
2406
    decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), responder->heap,
2407
                                    DYNAMIC_TYPE_OCSP);
2408
    if (decoded == NULL) {
2409
        ret = MEMORY_E;
2410
        goto out;
2411
    }
2412
2413
    wc_InitDecodedCert(decoded, signerDer, signerDerSz, responder->heap);
2414
    ret = wc_ParseCert(decoded, CERT_TYPE, 0, NULL);
2415
    if (ret != 0)
2416
        goto out;
2417
2418
    ret = wc_CheckPrivateKeyCert(keyDer, keyDerSz, decoded, 1, responder->heap);
2419
    if (ret != 1) {
2420
        ret = (ret == 0) ? BAD_FUNC_ARG : ret;
2421
        goto out;
2422
    }
2423
    keyOID = decoded->keyOID;
2424
2425
    ret = wc_ShaHash(decoded->publicKeyForHash, decoded->pubKeyForHashSize,
2426
            ca->responderKeyHash);
2427
    if (ret != 0)
2428
        goto out;
2429
2430
    /* Now place the real issuer into decoded and perform cert can actually
2431
     * sign for issuer. */
2432
    if (issuerCertDer != NULL && issuerCertDerSz > 0) {
2433
        char issuer[WC_ASN_NAME_MAX];
2434
2435
        if (signerDerSz == issuerCertDerSz &&
2436
                XMEMCMP(signerDer, issuerCertDer, signerDerSz) == 0) {
2437
            /* API misuse */
2438
            ret = BAD_FUNC_ARG;
2439
            goto out;
2440
        }
2441
        if ((decoded->extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) {
2442
            /* Cert is not authorized for OCSP signing */
2443
            ret = BAD_FUNC_ARG;
2444
            goto out;
2445
        }
2446
        XMEMCPY(issuer, decoded->issuer, WC_ASN_NAME_MAX);
2447
2448
        /* Use allocated DecodedCert */
2449
        wc_FreeDecodedCert(decoded);
2450
        wc_InitDecodedCert(decoded, issuerCertDer, issuerCertDerSz,
2451
                          responder->heap);
2452
        ret = wc_ParseCert(decoded, CERT_TYPE, 0, NULL);
2453
        if (ret != 0)
2454
            goto out;
2455
2456
        if (XSTRNCMP(issuer, decoded->subject, WC_ASN_NAME_MAX) != 0) {
2457
            /* Issuer name in responder cert does not match subject of issuer cert */
2458
            ret = BAD_FUNC_ARG;
2459
            goto out;
2460
        }
2461
2462
        ca->authResp = 1;
2463
    }
2464
2465
    /* Use responder cert's subject and public key for hashes */
2466
    if (decoded->subjectRawForHash == NULL ||
2467
            decoded->subjectRawForHashLen <= 0) {
2468
        ret = BAD_FUNC_ARG;
2469
        goto out;
2470
    }
2471
    ret = AsnHashesHash(&ca->issuerHashes, decoded->subjectRawForHash,
2472
            (word32)decoded->subjectRawForHashLen);
2473
    if (ret != 0)
2474
        goto out;
2475
    if (decoded->publicKeyForHash == NULL || decoded->pubKeyForHashSize == 0) {
2476
        ret = BAD_FUNC_ARG;
2477
        goto out;
2478
    }
2479
    ret = AsnHashesHash(&ca->issuerKeyHashes, decoded->publicKeyForHash,
2480
            decoded->pubKeyForHashSize);
2481
    if (ret != 0)
2482
        goto out;
2483
2484
    /* Extract necessary info from decoded cert */
2485
    XMEMCPY(ca->subject, decoded->subject, WC_ASN_NAME_MAX);
2486
2487
    /* Store raw certificate DER if sendCerts is enabled */
2488
    if (responder->sendCerts) {
2489
        ca->certDer = (byte*)XMALLOC(signerDerSz, responder->heap, DYNAMIC_TYPE_OCSP);
2490
        if (ca->certDer == NULL) {
2491
            ret = MEMORY_E;
2492
            goto out;
2493
        }
2494
        XMEMCPY(ca->certDer, signerDer, signerDerSz);
2495
        ca->certDerSz = signerDerSz;
2496
    }
2497
2498
    /* Load the private key */
2499
#ifndef NO_RSA
2500
    if (keyOID == RSAk) {
2501
        ret = wc_InitRsaKey(&ca->key.rsa, responder->heap);
2502
        if (ret == 0) {
2503
            word32 idx = 0;
2504
            ca->keyType = RSAk;
2505
            ret = wc_RsaPrivateKeyDecode(keyDer, &idx, &ca->key.rsa, keyDerSz);
2506
        }
2507
        if (ret != 0)
2508
            goto out;
2509
    }
2510
    else
2511
#endif
2512
#ifdef HAVE_ECC
2513
    if (keyOID == ECDSAk) {
2514
        ret = wc_ecc_init_ex(&ca->key.ecc, responder->heap, INVALID_DEVID);
2515
        if (ret == 0) {
2516
            word32 idx = 0;
2517
            ca->keyType = ECDSAk;
2518
            ret = wc_EccPrivateKeyDecode(keyDer, &idx, &ca->key.ecc, keyDerSz);
2519
        }
2520
        if (ret != 0)
2521
            goto out;
2522
    }
2523
    else
2524
#endif
2525
    {
2526
        ret = NOT_COMPILED_IN;
2527
        goto out;
2528
    }
2529
2530
    /* Check for duplicates before adding */
2531
    {
2532
        OcspResponderCa* existing = responder->caList;
2533
        while (existing != NULL) {
2534
            if (XMEMCMP(&existing->issuerHashes, &ca->issuerHashes,
2535
                       sizeof(AsnHashes)) == 0 &&
2536
                XMEMCMP(&existing->issuerKeyHashes, &ca->issuerKeyHashes,
2537
                       sizeof(AsnHashes)) == 0) {
2538
                ret = DUPE_ENTRY_E;
2539
                goto out;
2540
            }
2541
            existing = existing->next;
2542
        }
2543
    }
2544
2545
    /* Add CA to list */
2546
    ca->next = responder->caList;
2547
    responder->caList = ca;
2548
    ca = NULL; /* Ownership transferred */
2549
    ret = 0;
2550
2551
out:
2552
    if (decoded != NULL) {
2553
        wc_FreeDecodedCert(decoded);
2554
        XFREE(decoded, responder->heap, DYNAMIC_TYPE_OCSP);
2555
    }
2556
    if (ca != NULL)
2557
        FreeOcspResponderCa(ca, responder->heap);
2558
    return ret;
2559
}
2560
2561
/* Find Auth CA by issuer hashes from request */
2562
static OcspResponderCa* FindCaByHashes(OcspResponder* responder,
2563
    const byte* issuerHash, const byte* issuerKeyHash, int hashAlg)
2564
{
2565
    OcspResponderCa* ca = responder->caList;
2566
2567
    while (ca != NULL) {
2568
        int hashSz = 0;
2569
        const byte* caIssuerHash = AsnHashesGetHash(&ca->issuerHashes,
2570
            hashAlg, &hashSz);
2571
        const byte* caKeyHash = AsnHashesGetHash(&ca->issuerKeyHashes,
2572
            hashAlg, &hashSz);
2573
2574
        if (caIssuerHash != NULL && caKeyHash != NULL && hashSz > 0 &&
2575
            XMEMCMP(caIssuerHash, issuerHash, (size_t)hashSz) == 0 &&
2576
            XMEMCMP(caKeyHash, issuerKeyHash, (size_t)hashSz) == 0) {
2577
            return ca;
2578
        }
2579
        ca = ca->next;
2580
    }
2581
2582
    return NULL;
2583
}
2584
2585
/* Find certificate status in a CA */
2586
static OcspResponderCertStatus* FindCertStatus(OcspResponderCa* ca,
2587
    const byte* serial, word32 serialSz)
2588
{
2589
    OcspResponderCertStatus* status = ca->statuses;
2590
2591
    while (status != NULL) {
2592
        if (status->serialSz == (int)serialSz &&
2593
            XMEMCMP(status->serial, serial, serialSz) == 0) {
2594
            return status;
2595
        }
2596
        status = status->next;
2597
    }
2598
2599
    return NULL;
2600
}
2601
2602
/* Find Auth CA by subject string */
2603
static OcspResponderCa* FindCaBySubject(OcspResponder* responder,
2604
    const char* caSubject, word32 caSubjectSz)
2605
{
2606
    OcspResponderCa* ca = responder->caList;
2607
2608
    while (ca != NULL) {
2609
        word32 subjectLen = (word32)XSTRLEN(ca->subject);
2610
        if (subjectLen == caSubjectSz &&
2611
            XMEMCMP(ca->subject, caSubject, caSubjectSz) == 0) {
2612
            return ca;
2613
        }
2614
        ca = ca->next;
2615
    }
2616
2617
    return NULL;
2618
}
2619
2620
/* Add a certificate status for a specific CA */
2621
int wc_OcspResponder_SetCertStatus(OcspResponder* responder,
2622
    const char* caSubject, word32 caSubjectSz,
2623
    const byte* serial, word32 serialSz, enum Ocsp_Cert_Status status,
2624
    time_t revocationTime, enum WC_CRL_Reason revocationReason,
2625
    word32 validityPeriod)
2626
{
2627
    OcspResponderCa* ca = NULL;
2628
    OcspResponderCertStatus* certStatus = NULL;
2629
    int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
2630
    int isNew = 0;
2631
2632
    WOLFSSL_ENTER("wc_OcspResponder_SetCertStatus");
2633
2634
    if (responder == NULL || caSubject == NULL || caSubjectSz == 0 ||
2635
        serial == NULL || serialSz == 0 || serialSz > EXTERNAL_SERIAL_SIZE)
2636
        goto out;
2637
2638
    if (status != CERT_GOOD && status != CERT_REVOKED &&
2639
        status != CERT_UNKNOWN)
2640
        goto out;
2641
2642
    /* Validate revocation parameters when status is REVOKED */
2643
    if (status == CERT_REVOKED) {
2644
        if (revocationTime <= 0)
2645
            goto out;
2646
        if (revocationReason < WC_CRL_REASON_UNSPECIFIED ||
2647
            revocationReason > WC_CRL_REASON_AA_COMPROMISE)
2648
            goto out;
2649
        /* Skip value 7 which is not used */
2650
        if (revocationReason == 7)
2651
            goto out;
2652
    }
2653
2654
    if (status == CERT_GOOD && validityPeriod == 0)
2655
        goto out;
2656
    if (status != CERT_GOOD && validityPeriod != 0)
2657
        goto out;
2658
2659
    /* Find the CA */
2660
    ca = FindCaBySubject(responder, caSubject, caSubjectSz);
2661
    if (ca == NULL) {
2662
        ret = ASN_NO_SIGNER_E;
2663
        goto out;
2664
    }
2665
2666
    /* Check if status already exists for this serial */
2667
    certStatus = FindCertStatus(ca, serial, serialSz);
2668
    if (certStatus == NULL) {
2669
        /* Allocate new status entry */
2670
        certStatus = (OcspResponderCertStatus*)XMALLOC(
2671
            sizeof(OcspResponderCertStatus), responder->heap, DYNAMIC_TYPE_OCSP);
2672
        if (certStatus == NULL) {
2673
            ret = MEMORY_E;
2674
            goto out;
2675
        }
2676
        XMEMSET(certStatus, 0, sizeof(OcspResponderCertStatus));
2677
        XMEMCPY(certStatus->serial, serial, serialSz);
2678
        certStatus->serialSz = serialSz;
2679
        isNew = 1;
2680
    }
2681
2682
    certStatus->status = status;
2683
    certStatus->validityPeriod = 0;
2684
    if (status == CERT_REVOKED) {
2685
        ret = GetFormattedTime_ex(&revocationTime, certStatus->revocationDate,
2686
            sizeof(certStatus->revocationDate), ASN_GENERALIZED_TIME);
2687
        if (ret <= 0) {
2688
            WOLFSSL_MSG("Failed to format revocation time");
2689
            goto out;
2690
        }
2691
        certStatus->revocationDateSz = (word32)ret;
2692
        certStatus->revocationReason = revocationReason;
2693
    }
2694
    else if (status == CERT_GOOD) {
2695
        certStatus->validityPeriod = validityPeriod;
2696
    }
2697
2698
    if (isNew) {
2699
        /* Add to CA's status list */
2700
        certStatus->next = ca->statuses;
2701
        ca->statuses = certStatus;
2702
        certStatus = NULL; /* Ownership transferred */
2703
    }
2704
    ret = 0;
2705
2706
out:
2707
    if (isNew && certStatus != NULL)
2708
        XFREE(certStatus, responder->heap, DYNAMIC_TYPE_OCSP);
2709
2710
    return ret;
2711
}
2712
2713
static int OcspResponse_WriteResponse(OcspResponder* responder, byte* response,
2714
        word32* responseSz, OcspResponderCa* ca,
2715
        OcspResponderCertStatus* certStatus, OcspRequest* req)
2716
{
2717
    OcspResponse resp;
2718
    CertStatus status;
2719
    OcspEntry entry;
2720
    int ret = 0;
2721
    time_t now;
2722
    RsaKey* rsaKey = NULL;
2723
    ecc_key* eccKey = NULL;
2724
    int respInited = 0;
2725
    int hashSz = 0;
2726
    const byte* caIssuerHash = NULL;
2727
    const byte* caKeyHash = NULL;
2728
    int hashAlg = -1;
2729
2730
    WOLFSSL_ASSERT_SIZEOF_EQ(resp.responderId.keyHash, ca->responderKeyHash);
2731
2732
    WOLFSSL_ENTER("OcspResponse_WriteResponse");
2733
2734
    if (responseSz == NULL || ca == NULL || certStatus == NULL ||
2735
            certStatus->serialSz > EXTERNAL_SERIAL_SIZE) {
2736
        ret = BAD_FUNC_ARG;
2737
        goto out;
2738
    }
2739
2740
    InitOcspResponse(&resp, &entry, &status, NULL, 0, responder->heap);
2741
    respInited = 1;
2742
2743
    resp.responseStatus = OCSP_SUCCESSFUL;
2744
2745
    status.status = certStatus->status;
2746
2747
    XMEMCPY(status.serial, certStatus->serial, certStatus->serialSz);
2748
    status.serialSz = (byte)certStatus->serialSz;
2749
2750
    /* Copy revocation information if status is REVOKED */
2751
    if (certStatus->status == CERT_REVOKED) {
2752
        XMEMCPY(status.revocationDate, certStatus->revocationDate,
2753
                certStatus->revocationDateSz);
2754
        status.revocationDateSz = certStatus->revocationDateSz;
2755
        status.revocationReason = (byte)certStatus->revocationReason;
2756
    }
2757
2758
    now = wc_Time(NULL);
2759
    ret = GetFormattedTime_ex(&now, status.thisDate, sizeof(status.thisDate),
2760
            ASN_GENERALIZED_TIME);
2761
    if (ret <= 0) {
2762
        WOLFSSL_MSG("Failed to format thisUpdate time");
2763
        goto out;
2764
    }
2765
    XMEMCPY(resp.producedDate, status.thisDate, ret);
2766
    resp.producedDateSz = status.thisDateSz = (byte)(ret);
2767
    resp.producedDateFormat = status.thisDateFormat = ASN_GENERALIZED_TIME;
2768
2769
    /* Set nextUpdate if validity period is specified (for CERT_GOOD) */
2770
    if (certStatus->status == CERT_GOOD && certStatus->validityPeriod > 0) {
2771
        time_t nextTime = now + (time_t)certStatus->validityPeriod;
2772
        ret = GetFormattedTime_ex(&nextTime, status.nextDate,
2773
                sizeof(status.nextDate), ASN_GENERALIZED_TIME);
2774
        if (ret <= 0) {
2775
            WOLFSSL_MSG("Failed to format nextUpdate time");
2776
            goto out;
2777
        }
2778
        status.nextDateSz = (byte)ret;
2779
        status.nextDateFormat = ASN_GENERALIZED_TIME;
2780
    }
2781
2782
    /* Set certificate if sendCerts is enabled */
2783
    if (responder->sendCerts && ca->certDer != NULL) {
2784
        resp.cert = ca->certDer;
2785
        resp.certSz = ca->certDerSz;
2786
    }
2787
2788
    /* Copy nonce from request to response if present */
2789
    if (req != NULL && req->nonceSz > 0) {
2790
        resp.nonce = req->nonce;
2791
        resp.nonceSz = req->nonceSz;
2792
    }
2793
2794
    /* Echo the hash algorithm from the request */
2795
    if (req == NULL) {
2796
        hashAlg = SHAh; /* Fall back to SHA-1 as its required for OCSP */
2797
    }
2798
    else {
2799
        hashAlg = req->hashAlg;
2800
    }
2801
    caIssuerHash = AsnHashesGetHash(&ca->issuerHashes, hashAlg, &hashSz);
2802
    caKeyHash = AsnHashesGetHash(&ca->issuerKeyHashes, hashAlg, &hashSz);
2803
    if (caIssuerHash == NULL || caKeyHash == NULL || hashSz <= 0) {
2804
        ret = ASN_SIG_HASH_E;
2805
        goto out;
2806
    }
2807
    entry.hashAlgoOID = (word32)hashAlg;
2808
    XMEMCPY(entry.issuerHash, caIssuerHash, (size_t)hashSz);
2809
    XMEMCPY(entry.issuerKeyHash, caKeyHash, (size_t)hashSz);
2810
2811
    resp.responderIdType = OCSP_RESPONDER_ID_KEY;
2812
    XMEMCPY(resp.responderId.keyHash, ca->responderKeyHash, WC_SHA_DIGEST_SIZE);
2813
2814
    /* TODO allow user to set algo */
2815
    if (ca->keyType == RSAk) {
2816
        rsaKey = &ca->key.rsa;
2817
        resp.sigOID = CTC_SHA256wRSA;
2818
    }
2819
    else if (ca->keyType == ECDSAk) {
2820
        eccKey = &ca->key.ecc;
2821
        resp.sigOID = CTC_SHA256wECDSA;
2822
    }
2823
    else {
2824
        ret = NOT_COMPILED_IN;
2825
        goto out;
2826
    }
2827
2828
    ret = OcspResponseEncode(&resp, response, responseSz, rsaKey, eccKey,
2829
            &responder->rng);
2830
    if (ret != 0) {
2831
        WOLFSSL_MSG("Failed to encode OCSP response");
2832
        goto out;
2833
    }
2834
2835
    ret = 0;
2836
out:
2837
    if (respInited)
2838
        FreeOcspResponse(&resp);
2839
    return ret;
2840
}
2841
2842
/* Generate OCSP response for a request */
2843
int wc_OcspResponder_WriteResponse(OcspResponder* responder,
2844
    const byte* request, word32 requestSz,
2845
    byte* response, word32* responseSz)
2846
{
2847
    int ret = 0;
2848
    OcspRequest req;
2849
    OcspResponderCa* ca = NULL;
2850
    OcspResponderCertStatus* certStatus = NULL;
2851
    int reqInited = 0;
2852
2853
    WOLFSSL_ENTER("wc_OcspResponder_WriteResponse");
2854
2855
    if (responder == NULL || request == NULL || requestSz == 0) {
2856
        ret = BAD_FUNC_ARG;
2857
        goto out;
2858
    }
2859
2860
    XMEMSET(&req, 0, sizeof(OcspRequest));
2861
2862
    /* Decode the OCSP request */
2863
    ret = DecodeOcspRequest(&req, request, requestSz);
2864
    if (ret != 0) {
2865
        WOLFSSL_MSG("Failed to decode OCSP request");
2866
        goto out;
2867
    }
2868
    reqInited = 1;
2869
2870
    /* Find the CA by issuer hashes */
2871
    ca = FindCaByHashes(responder, req.issuerHash, req.issuerKeyHash,
2872
                        req.hashAlg);
2873
    if (ca == NULL) {
2874
        WOLFSSL_MSG("No matching CA found for request");
2875
        ret = ASN_NO_SIGNER_E;
2876
        goto out;
2877
    }
2878
2879
    /* Find the certificate status */
2880
    certStatus = FindCertStatus(ca, req.serial, req.serialSz);
2881
    if (certStatus == NULL) {
2882
        /* RFC 6960: 'unknown' is a per-certificate status inside a successful
2883
         * OCSPResponse, not an error response. Generate a successful response
2884
         * with CERT_UNKNOWN so clients can distinguish it from UNAUTHORIZED. */
2885
        OcspResponderCertStatus unknownStatus;
2886
        WOLFSSL_MSG("No status for requested certificate, responding unknown");
2887
        if (req.serialSz > EXTERNAL_SERIAL_SIZE) {
2888
            ret = BUFFER_E;
2889
            goto out;
2890
        }
2891
        XMEMSET(&unknownStatus, 0, sizeof(unknownStatus));
2892
        XMEMCPY(unknownStatus.serial, req.serial, req.serialSz);
2893
        unknownStatus.serialSz = req.serialSz;
2894
        unknownStatus.status = CERT_UNKNOWN;
2895
        ret = OcspResponse_WriteResponse(responder, response, responseSz, ca,
2896
                &unknownStatus, &req);
2897
    }
2898
    else {
2899
        WOLFSSL_MSG("Found CA and certificate status");
2900
        ret = OcspResponse_WriteResponse(responder, response, responseSz, ca,
2901
                certStatus, &req);
2902
    }
2903
2904
out:
2905
    if (reqInited)
2906
        FreeOcspRequest(&req);
2907
    WOLFSSL_LEAVE("wc_OcspResponder_WriteResponse", ret);
2908
    return ret;
2909
}
2910
2911
int wc_OcspResponder_WriteErrorResponse(enum Ocsp_Response_Status status,
2912
    byte* response, word32* responseSz)
2913
{
2914
    int ret = 0;
2915
    OcspResponse resp;
2916
    int respInited = 0;
2917
2918
    WOLFSSL_ENTER("wc_OcspResponder_WriteErrorResponse");
2919
2920
    if (responseSz == NULL) {
2921
        ret = BAD_FUNC_ARG;
2922
        goto out;
2923
    }
2924
2925
    /* Validate status - OCSP_SUCCESSFUL is not allowed for error responses */
2926
    if (status == OCSP_SUCCESSFUL) {
2927
        WOLFSSL_MSG("OCSP_SUCCESSFUL is not a valid error status");
2928
        ret = BAD_FUNC_ARG;
2929
        goto out;
2930
    }
2931
2932
    /* Validate that status is a known enumeration value */
2933
    if (status != OCSP_MALFORMED_REQUEST &&
2934
        status != OCSP_INTERNAL_ERROR &&
2935
        status != OCSP_TRY_LATER &&
2936
        status != OCSP_SIG_REQUIRED &&
2937
        status != OCSP_UNAUTHORIZED) {
2938
        WOLFSSL_MSG("Invalid OCSP response status");
2939
        ret = BAD_FUNC_ARG;
2940
        goto out;
2941
    }
2942
2943
    /* Initialize a minimal OCSP response structure */
2944
    InitOcspResponse(&resp, NULL, NULL, NULL, 0, NULL);
2945
    respInited = 1;
2946
2947
    /* Set the error status */
2948
    resp.responseStatus = (byte)status;
2949
2950
    /* Encode the error response (no responseBytes, just status) */
2951
    ret = OcspResponseEncode(&resp, response, responseSz, NULL, NULL, NULL);
2952
    if (ret != 0) {
2953
        WOLFSSL_MSG("Failed to encode OCSP error response");
2954
        goto out;
2955
    }
2956
2957
    ret = 0;
2958
out:
2959
    if (respInited)
2960
        FreeOcspResponse(&resp);
2961
    return ret;
2962
}
2963
2964
#endif /* HAVE_OCSP_RESPONDER */
2965
2966
/* Helper functions for testing */
2967
int wc_InitOcspRequest(OcspRequest* req, DecodedCert* cert,
2968
                                    byte useNonce, void* heap)
2969
0
{
2970
0
    return InitOcspRequest(req, cert, useNonce, heap);
2971
0
}
2972
2973
int wc_EncodeOcspRequest(OcspRequest* req, byte* output,
2974
                                      word32 size)
2975
0
{
2976
0
    return EncodeOcspRequest(req, output, size);
2977
0
}
2978
2979
#else /* HAVE_OCSP */
2980
2981
2982
#ifdef _MSC_VER
2983
    /* 4206 warning for blank file */
2984
    #pragma warning(disable: 4206)
2985
#endif
2986
2987
2988
#endif /* HAVE_OCSP */
2989
#endif /* WOLFCRYPT_ONLY */