Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl33/crypto/ocsp/ocsp_ext.c
Line
Count
Source
1
/*
2
 * Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include "internal/cryptlib.h"
12
#include <openssl/objects.h>
13
#include <openssl/x509.h>
14
#include <openssl/ocsp.h>
15
#include "ocsp_local.h"
16
#include <openssl/rand.h>
17
#include <openssl/x509v3.h>
18
19
/* Standard wrapper functions for extensions */
20
21
/* OCSP request extensions */
22
23
int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x)
24
0
{
25
0
    return X509v3_get_ext_count(x->tbsRequest.requestExtensions);
26
0
}
27
28
int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos)
29
0
{
30
0
    return (X509v3_get_ext_by_NID(x->tbsRequest.requestExtensions, nid, lastpos));
31
0
}
32
33
int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj,
34
    int lastpos)
35
0
{
36
0
    return (X509v3_get_ext_by_OBJ(x->tbsRequest.requestExtensions, obj, lastpos));
37
0
}
38
39
int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos)
40
0
{
41
0
    return (X509v3_get_ext_by_critical(x->tbsRequest.requestExtensions, crit, lastpos));
42
0
}
43
44
X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc)
45
0
{
46
0
    return X509v3_get_ext(x->tbsRequest.requestExtensions, loc);
47
0
}
48
49
X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc)
50
0
{
51
0
    return X509v3_delete_ext(x->tbsRequest.requestExtensions, loc);
52
0
}
53
54
void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx)
55
0
{
56
0
    return X509V3_get_d2i(x->tbsRequest.requestExtensions, nid, crit, idx);
57
0
}
58
59
int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
60
    unsigned long flags)
61
0
{
62
0
    return X509V3_add1_i2d(&x->tbsRequest.requestExtensions, nid, value,
63
0
        crit, flags);
64
0
}
65
66
int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc)
67
0
{
68
0
    return (X509v3_add_ext(&(x->tbsRequest.requestExtensions), ex, loc) != NULL);
69
0
}
70
71
/* Single extensions */
72
73
int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x)
74
0
{
75
0
    return X509v3_get_ext_count(x->singleRequestExtensions);
76
0
}
77
78
int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos)
79
0
{
80
0
    return X509v3_get_ext_by_NID(x->singleRequestExtensions, nid, lastpos);
81
0
}
82
83
int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj,
84
    int lastpos)
85
0
{
86
0
    return X509v3_get_ext_by_OBJ(x->singleRequestExtensions, obj, lastpos);
87
0
}
88
89
int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos)
90
0
{
91
0
    return (X509v3_get_ext_by_critical(x->singleRequestExtensions, crit, lastpos));
92
0
}
93
94
X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc)
95
0
{
96
0
    return X509v3_get_ext(x->singleRequestExtensions, loc);
97
0
}
98
99
X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc)
100
0
{
101
0
    return X509v3_delete_ext(x->singleRequestExtensions, loc);
102
0
}
103
104
void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx)
105
0
{
106
0
    return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx);
107
0
}
108
109
int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
110
    unsigned long flags)
111
0
{
112
0
    return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit,
113
0
        flags);
114
0
}
115
116
int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc)
117
0
{
118
0
    return (X509v3_add_ext(&(x->singleRequestExtensions), ex, loc) != NULL);
119
0
}
120
121
/* OCSP Basic response */
122
123
int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x)
124
0
{
125
0
    return X509v3_get_ext_count(x->tbsResponseData.responseExtensions);
126
0
}
127
128
int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos)
129
0
{
130
0
    return (X509v3_get_ext_by_NID(x->tbsResponseData.responseExtensions, nid, lastpos));
131
0
}
132
133
int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj,
134
    int lastpos)
135
0
{
136
0
    return (X509v3_get_ext_by_OBJ(x->tbsResponseData.responseExtensions, obj, lastpos));
137
0
}
138
139
int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit,
140
    int lastpos)
141
0
{
142
0
    return (X509v3_get_ext_by_critical(x->tbsResponseData.responseExtensions, crit, lastpos));
143
0
}
144
145
X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc)
146
0
{
147
0
    return X509v3_get_ext(x->tbsResponseData.responseExtensions, loc);
148
0
}
149
150
X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc)
151
0
{
152
0
    return X509v3_delete_ext(x->tbsResponseData.responseExtensions, loc);
153
0
}
154
155
void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit,
156
    int *idx)
157
0
{
158
0
    return X509V3_get_d2i(x->tbsResponseData.responseExtensions, nid, crit,
159
0
        idx);
160
0
}
161
162
int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value,
163
    int crit, unsigned long flags)
164
0
{
165
0
    return X509V3_add1_i2d(&x->tbsResponseData.responseExtensions, nid,
166
0
        value, crit, flags);
167
0
}
168
169
int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc)
170
0
{
171
0
    return (X509v3_add_ext(&(x->tbsResponseData.responseExtensions), ex, loc)
172
0
        != NULL);
173
0
}
174
175
/* OCSP single response extensions */
176
177
int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x)
178
0
{
179
0
    return X509v3_get_ext_count(x->singleExtensions);
180
0
}
181
182
int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos)
183
0
{
184
0
    return X509v3_get_ext_by_NID(x->singleExtensions, nid, lastpos);
185
0
}
186
187
int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj,
188
    int lastpos)
189
0
{
190
0
    return X509v3_get_ext_by_OBJ(x->singleExtensions, obj, lastpos);
191
0
}
192
193
int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit,
194
    int lastpos)
195
0
{
196
0
    return X509v3_get_ext_by_critical(x->singleExtensions, crit, lastpos);
197
0
}
198
199
X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc)
200
0
{
201
0
    return X509v3_get_ext(x->singleExtensions, loc);
202
0
}
203
204
X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc)
205
0
{
206
0
    return X509v3_delete_ext(x->singleExtensions, loc);
207
0
}
208
209
void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit,
210
    int *idx)
211
0
{
212
0
    return X509V3_get_d2i(x->singleExtensions, nid, crit, idx);
213
0
}
214
215
int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value,
216
    int crit, unsigned long flags)
217
0
{
218
0
    return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags);
219
0
}
220
221
int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc)
222
0
{
223
0
    return (X509v3_add_ext(&(x->singleExtensions), ex, loc) != NULL);
224
0
}
225
226
/* also CRL Entry Extensions */
227
228
/* Nonce handling functions */
229
230
/*
231
 * Add a nonce to an extension stack. A nonce can be specified or if NULL a
232
 * random nonce will be generated. Note: OpenSSL 0.9.7d and later create an
233
 * OCTET STRING containing the nonce, previous versions used the raw nonce.
234
 */
235
236
static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts,
237
    unsigned char *val, int len)
238
0
{
239
0
    unsigned char *tmpval;
240
0
    ASN1_OCTET_STRING os;
241
0
    int ret = 0;
242
0
    if (len <= 0)
243
0
        len = OCSP_DEFAULT_NONCE_LENGTH;
244
    /*
245
     * Create the OCTET STRING manually by writing out the header and
246
     * appending the content octets. This avoids an extra memory allocation
247
     * operation in some cases. Applications should *NOT* do this because it
248
     * relies on library internals.
249
     */
250
0
    os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING);
251
0
    if (os.length < 0)
252
0
        return 0;
253
254
0
    os.data = OPENSSL_malloc(os.length);
255
0
    if (os.data == NULL)
256
0
        goto err;
257
0
    tmpval = os.data;
258
0
    ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL);
259
0
    if (val)
260
0
        memcpy(tmpval, val, len);
261
0
    else if (RAND_bytes(tmpval, len) <= 0)
262
0
        goto err;
263
0
    if (X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce,
264
0
            &os, 0, X509V3_ADD_REPLACE)
265
0
        <= 0)
266
0
        goto err;
267
0
    ret = 1;
268
0
err:
269
0
    OPENSSL_free(os.data);
270
0
    return ret;
271
0
}
272
273
/* Add nonce to an OCSP request */
274
275
int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
276
0
{
277
0
    return ocsp_add1_nonce(&req->tbsRequest.requestExtensions, val, len);
278
0
}
279
280
/* Same as above but for a response */
281
282
int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len)
283
0
{
284
0
    return ocsp_add1_nonce(&resp->tbsResponseData.responseExtensions, val,
285
0
        len);
286
0
}
287
288
/*-
289
 * Check nonce validity in a request and response.
290
 * Return value reflects result:
291
 *  1: nonces present and equal.
292
 *  2: nonces both absent.
293
 *  3: nonce present in response only.
294
 *  0: nonces both present and not equal.
295
 * -1: nonce in request only.
296
 *
297
 *  For most responders clients can check return > 0.
298
 *  If responder doesn't handle nonces return != 0 may be
299
 *  necessary. return == 0 is always an error.
300
 */
301
302
int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
303
0
{
304
    /*
305
     * Since we are only interested in the presence or absence of
306
     * the nonce and comparing its value there is no need to use
307
     * the X509V3 routines: this way we can avoid them allocating an
308
     * ASN1_OCTET_STRING structure for the value which would be
309
     * freed immediately anyway.
310
     */
311
312
0
    int req_idx, resp_idx;
313
0
    X509_EXTENSION *req_ext, *resp_ext;
314
0
    req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
315
0
    resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, NID_id_pkix_OCSP_Nonce, -1);
316
    /* Check both absent */
317
0
    if ((req_idx < 0) && (resp_idx < 0))
318
0
        return 2;
319
    /* Check in request only */
320
0
    if ((req_idx >= 0) && (resp_idx < 0))
321
0
        return -1;
322
    /* Check in response but not request */
323
0
    if ((req_idx < 0) && (resp_idx >= 0))
324
0
        return 3;
325
    /*
326
     * Otherwise nonce in request and response so retrieve the extensions
327
     */
328
0
    req_ext = OCSP_REQUEST_get_ext(req, req_idx);
329
0
    resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx);
330
0
    if (ASN1_OCTET_STRING_cmp(X509_EXTENSION_get_data(req_ext),
331
0
            X509_EXTENSION_get_data(resp_ext)))
332
0
        return 0;
333
0
    return 1;
334
0
}
335
336
/*
337
 * Copy the nonce value (if any) from an OCSP request to a response.
338
 */
339
340
int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req)
341
0
{
342
0
    X509_EXTENSION *req_ext;
343
0
    int req_idx;
344
    /* Check for nonce in request */
345
0
    req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
346
    /* If no nonce that's OK */
347
0
    if (req_idx < 0)
348
0
        return 2;
349
0
    req_ext = OCSP_REQUEST_get_ext(req, req_idx);
350
0
    return OCSP_BASICRESP_add_ext(resp, req_ext, -1);
351
0
}
352
353
X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim)
354
0
{
355
0
    X509_EXTENSION *x = NULL;
356
0
    OCSP_CRLID *cid = NULL;
357
358
0
    if ((cid = OCSP_CRLID_new()) == NULL)
359
0
        goto err;
360
0
    if (url) {
361
0
        if ((cid->crlUrl = ASN1_IA5STRING_new()) == NULL)
362
0
            goto err;
363
0
        if (!(ASN1_STRING_set(cid->crlUrl, url, -1)))
364
0
            goto err;
365
0
    }
366
0
    if (n) {
367
0
        if ((cid->crlNum = ASN1_INTEGER_new()) == NULL)
368
0
            goto err;
369
0
        if (!(ASN1_INTEGER_set(cid->crlNum, *n)))
370
0
            goto err;
371
0
    }
372
0
    if (tim) {
373
0
        if ((cid->crlTime = ASN1_GENERALIZEDTIME_new()) == NULL)
374
0
            goto err;
375
0
        if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim)))
376
0
            goto err;
377
0
    }
378
0
    x = X509V3_EXT_i2d(NID_id_pkix_OCSP_CrlID, 0, cid);
379
0
err:
380
0
    OCSP_CRLID_free(cid);
381
0
    return x;
382
0
}
383
384
/*   AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */
385
X509_EXTENSION *OCSP_accept_responses_new(char **oids)
386
0
{
387
0
    int nid;
388
0
    STACK_OF(ASN1_OBJECT) *sk = NULL;
389
0
    ASN1_OBJECT *o = NULL;
390
0
    X509_EXTENSION *x = NULL;
391
392
0
    if ((sk = sk_ASN1_OBJECT_new_null()) == NULL)
393
0
        goto err;
394
0
    while (oids && *oids) {
395
0
        if ((nid = OBJ_txt2nid(*oids)) != NID_undef && (o = OBJ_nid2obj(nid)))
396
0
            sk_ASN1_OBJECT_push(sk, o);
397
0
        oids++;
398
0
    }
399
0
    x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk);
400
0
err:
401
0
    sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free);
402
0
    return x;
403
0
}
404
405
/*  ArchiveCutoff ::= GeneralizedTime */
406
X509_EXTENSION *OCSP_archive_cutoff_new(char *tim)
407
0
{
408
0
    X509_EXTENSION *x = NULL;
409
0
    ASN1_GENERALIZEDTIME *gt = NULL;
410
411
0
    if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
412
0
        goto err;
413
0
    if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim)))
414
0
        goto err;
415
0
    x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt);
416
0
err:
417
0
    ASN1_GENERALIZEDTIME_free(gt);
418
0
    return x;
419
0
}
420
421
/*
422
 * per ACCESS_DESCRIPTION parameter are oids, of which there are currently
423
 * two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value.  This method
424
 * forces NID_ad_ocsp and uniformResourceLocator [6] IA5String.
425
 */
426
X509_EXTENSION *OCSP_url_svcloc_new(const X509_NAME *issuer, const char **urls)
427
0
{
428
0
    X509_EXTENSION *x = NULL;
429
0
    ASN1_IA5STRING *ia5 = NULL;
430
0
    OCSP_SERVICELOC *sloc = NULL;
431
0
    ACCESS_DESCRIPTION *ad = NULL;
432
433
0
    if ((sloc = OCSP_SERVICELOC_new()) == NULL)
434
0
        goto err;
435
0
    X509_NAME_free(sloc->issuer);
436
0
    if ((sloc->issuer = X509_NAME_dup(issuer)) == NULL)
437
0
        goto err;
438
0
    if (urls && *urls
439
0
        && (sloc->locator = sk_ACCESS_DESCRIPTION_new_null()) == NULL)
440
0
        goto err;
441
0
    while (urls && *urls) {
442
0
        if ((ad = ACCESS_DESCRIPTION_new()) == NULL)
443
0
            goto err;
444
0
        if ((ad->method = OBJ_nid2obj(NID_ad_OCSP)) == NULL)
445
0
            goto err;
446
0
        if ((ia5 = ASN1_IA5STRING_new()) == NULL)
447
0
            goto err;
448
0
        if (!ASN1_STRING_set((ASN1_STRING *)ia5, *urls, -1))
449
0
            goto err;
450
        /* ad->location is allocated inside ACCESS_DESCRIPTION_new */
451
0
        ad->location->type = GEN_URI;
452
0
        ad->location->d.ia5 = ia5;
453
0
        ia5 = NULL;
454
0
        if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad))
455
0
            goto err;
456
0
        ad = NULL;
457
0
        urls++;
458
0
    }
459
0
    x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc);
460
0
err:
461
0
    ASN1_IA5STRING_free(ia5);
462
0
    ACCESS_DESCRIPTION_free(ad);
463
0
    OCSP_SERVICELOC_free(sloc);
464
0
    return x;
465
0
}