Coverage Report

Created: 2025-11-24 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/ocsp/ocsp_cl.c
Line
Count
Source
1
/*
2
 * Copyright 2001-2021 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 <time.h>
12
#include "internal/cryptlib.h"
13
#include <openssl/asn1.h>
14
#include <openssl/objects.h>
15
#include <openssl/x509.h>
16
#include <openssl/pem.h>
17
#include <openssl/x509v3.h>
18
#include <openssl/ocsp.h>
19
#include "ocsp_local.h"
20
21
/*
22
 * Utility functions related to sending OCSP requests and extracting relevant
23
 * information from the response.
24
 */
25
26
/*
27
 * Add an OCSP_CERTID to an OCSP request. Return new OCSP_ONEREQ pointer:
28
 * useful if we want to add extensions.
29
 */
30
OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid)
31
0
{
32
0
    OCSP_ONEREQ *one = NULL;
33
34
0
    if ((one = OCSP_ONEREQ_new()) == NULL)
35
0
        return NULL;
36
0
    OCSP_CERTID_free(one->reqCert);
37
0
    one->reqCert = cid;
38
0
    if (req && !sk_OCSP_ONEREQ_push(req->tbsRequest.requestList, one)) {
39
0
        one->reqCert = NULL; /* do not free on error */
40
0
        OCSP_ONEREQ_free(one);
41
0
        return NULL;
42
0
    }
43
0
    return one;
44
0
}
45
46
/* Set requestorName from an X509_NAME structure */
47
int OCSP_request_set1_name(OCSP_REQUEST *req, const X509_NAME *nm)
48
0
{
49
0
    return GENERAL_NAME_set1_X509_NAME(&req->tbsRequest.requestorName, nm);
50
0
}
51
52
/* Add a certificate to an OCSP request */
53
int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert)
54
0
{
55
0
    if (req->optionalSignature == NULL
56
0
            && (req->optionalSignature = OCSP_SIGNATURE_new()) == NULL)
57
0
        return 0;
58
0
    if (cert == NULL)
59
0
        return 1;
60
0
    return ossl_x509_add_cert_new(&req->optionalSignature->certs, cert,
61
0
                                  X509_ADD_FLAG_UP_REF);
62
0
}
63
64
/*
65
 * Sign an OCSP request set the requestorName to the subject name of an
66
 * optional signers certificate and include one or more optional certificates
67
 * in the request. Behaves like PKCS7_sign().
68
 */
69
int OCSP_request_sign(OCSP_REQUEST *req,
70
                      X509 *signer,
71
                      EVP_PKEY *key,
72
                      const EVP_MD *dgst,
73
                      STACK_OF(X509) *certs, unsigned long flags)
74
0
{
75
0
    if (!OCSP_request_set1_name(req, X509_get_subject_name(signer)))
76
0
        goto err;
77
78
0
    if ((req->optionalSignature = OCSP_SIGNATURE_new()) == NULL)
79
0
        goto err;
80
0
    if (key != NULL) {
81
0
        if (!X509_check_private_key(signer, key)) {
82
0
            ERR_raise(ERR_LIB_OCSP,
83
0
                      OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
84
0
            goto err;
85
0
        }
86
0
        if (!OCSP_REQUEST_sign(req, key, dgst, signer->libctx, signer->propq))
87
0
            goto err;
88
0
    }
89
90
0
    if ((flags & OCSP_NOCERTS) == 0) {
91
0
        if (!OCSP_request_add1_cert(req, signer)
92
0
            || !X509_add_certs(req->optionalSignature->certs, certs,
93
0
                               X509_ADD_FLAG_UP_REF))
94
0
            goto err;
95
0
    }
96
97
0
    return 1;
98
0
 err:
99
0
    OCSP_SIGNATURE_free(req->optionalSignature);
100
0
    req->optionalSignature = NULL;
101
0
    return 0;
102
0
}
103
104
/* Get response status */
105
int OCSP_response_status(OCSP_RESPONSE *resp)
106
0
{
107
0
    return ASN1_ENUMERATED_get(resp->responseStatus);
108
0
}
109
110
/*
111
 * Extract basic response from OCSP_RESPONSE or NULL if no basic response
112
 * present.
113
 */
114
OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp)
115
0
{
116
0
    OCSP_RESPBYTES *rb = resp->responseBytes;
117
118
0
    if (rb == NULL) {
119
0
        ERR_raise(ERR_LIB_OCSP, OCSP_R_NO_RESPONSE_DATA);
120
0
        return NULL;
121
0
    }
122
0
    if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) {
123
0
        ERR_raise(ERR_LIB_OCSP, OCSP_R_NOT_BASIC_RESPONSE);
124
0
        return NULL;
125
0
    }
126
127
0
    return ASN1_item_unpack(rb->response, ASN1_ITEM_rptr(OCSP_BASICRESP));
128
0
}
129
130
const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs)
131
0
{
132
0
    return bs->signature;
133
0
}
134
135
const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs)
136
0
{
137
0
    return &bs->signatureAlgorithm;
138
0
}
139
140
const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs)
141
0
{
142
0
    return &bs->tbsResponseData;
143
0
}
144
145
/* Return number of OCSP_SINGLERESP responses present in a basic response */
146
147
int OCSP_resp_count(OCSP_BASICRESP *bs)
148
0
{
149
0
    if (bs == NULL)
150
0
        return -1;
151
0
    return sk_OCSP_SINGLERESP_num(bs->tbsResponseData.responses);
152
0
}
153
154
/* Extract an OCSP_SINGLERESP response with a given index */
155
OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx)
156
0
{
157
0
    if (bs == NULL)
158
0
        return NULL;
159
0
    return sk_OCSP_SINGLERESP_value(bs->tbsResponseData.responses, idx);
160
0
}
161
162
const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP *bs)
163
0
{
164
0
    return bs->tbsResponseData.producedAt;
165
0
}
166
167
const STACK_OF(X509) *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs)
168
0
{
169
0
    return bs->certs;
170
0
}
171
172
int OCSP_resp_get0_id(const OCSP_BASICRESP *bs,
173
                      const ASN1_OCTET_STRING **pid,
174
                      const X509_NAME **pname)
175
0
{
176
0
    const OCSP_RESPID *rid = &bs->tbsResponseData.responderId;
177
178
0
    if (rid->type == V_OCSP_RESPID_NAME) {
179
0
        *pname = rid->value.byName;
180
0
        *pid = NULL;
181
0
    } else if (rid->type == V_OCSP_RESPID_KEY) {
182
0
        *pid = rid->value.byKey;
183
0
        *pname = NULL;
184
0
    } else {
185
0
        return 0;
186
0
    }
187
0
    return 1;
188
0
}
189
190
int OCSP_resp_get1_id(const OCSP_BASICRESP *bs,
191
                      ASN1_OCTET_STRING **pid,
192
                      X509_NAME **pname)
193
0
{
194
0
    const OCSP_RESPID *rid = &bs->tbsResponseData.responderId;
195
196
0
    if (rid->type == V_OCSP_RESPID_NAME) {
197
0
        *pname = X509_NAME_dup(rid->value.byName);
198
0
        *pid = NULL;
199
0
    } else if (rid->type == V_OCSP_RESPID_KEY) {
200
0
        *pid = ASN1_OCTET_STRING_dup(rid->value.byKey);
201
0
        *pname = NULL;
202
0
    } else {
203
0
        return 0;
204
0
    }
205
0
    if (*pname == NULL && *pid == NULL)
206
0
        return 0;
207
0
    return 1;
208
0
}
209
210
/* Look single response matching a given certificate ID */
211
int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last)
212
0
{
213
0
    int i;
214
0
    STACK_OF(OCSP_SINGLERESP) *sresp;
215
0
    OCSP_SINGLERESP *single;
216
217
0
    if (bs == NULL)
218
0
        return -1;
219
0
    if (last < 0)
220
0
        last = 0;
221
0
    else
222
0
        last++;
223
0
    sresp = bs->tbsResponseData.responses;
224
0
    for (i = last; i < sk_OCSP_SINGLERESP_num(sresp); i++) {
225
0
        single = sk_OCSP_SINGLERESP_value(sresp, i);
226
0
        if (!OCSP_id_cmp(id, single->certId))
227
0
            return i;
228
0
    }
229
0
    return -1;
230
0
}
231
232
/*
233
 * Extract status information from an OCSP_SINGLERESP structure. Note: the
234
 * revtime and reason values are only set if the certificate status is
235
 * revoked. Returns numerical value of status.
236
 */
237
int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
238
                            ASN1_GENERALIZEDTIME **revtime,
239
                            ASN1_GENERALIZEDTIME **thisupd,
240
                            ASN1_GENERALIZEDTIME **nextupd)
241
0
{
242
0
    int ret;
243
0
    OCSP_CERTSTATUS *cst;
244
245
0
    if (single == NULL)
246
0
        return -1;
247
0
    cst = single->certStatus;
248
0
    ret = cst->type;
249
0
    if (ret == V_OCSP_CERTSTATUS_REVOKED) {
250
0
        OCSP_REVOKEDINFO *rev = cst->value.revoked;
251
252
0
        if (revtime)
253
0
            *revtime = rev->revocationTime;
254
0
        if (reason) {
255
0
            if (rev->revocationReason)
256
0
                *reason = ASN1_ENUMERATED_get(rev->revocationReason);
257
0
            else
258
0
                *reason = -1;
259
0
        }
260
0
    }
261
0
    if (thisupd != NULL)
262
0
        *thisupd = single->thisUpdate;
263
0
    if (nextupd != NULL)
264
0
        *nextupd = single->nextUpdate;
265
0
    return ret;
266
0
}
267
268
/*
269
 * This function combines the previous ones: look up a certificate ID and if
270
 * found extract status information. Return 0 is successful.
271
 */
272
int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
273
                          int *reason,
274
                          ASN1_GENERALIZEDTIME **revtime,
275
                          ASN1_GENERALIZEDTIME **thisupd,
276
                          ASN1_GENERALIZEDTIME **nextupd)
277
0
{
278
0
    int i = OCSP_resp_find(bs, id, -1);
279
0
    OCSP_SINGLERESP *single;
280
281
    /* Maybe check for multiple responses and give an error? */
282
0
    if (i < 0)
283
0
        return 0;
284
0
    single = OCSP_resp_get0(bs, i);
285
0
    i = OCSP_single_get0_status(single, reason, revtime, thisupd, nextupd);
286
0
    if (status != NULL)
287
0
        *status = i;
288
0
    return 1;
289
0
}
290
291
/*
292
 * Check validity of thisUpdate and nextUpdate fields. It is possible that
293
 * the request will take a few seconds to process and/or the time won't be
294
 * totally accurate. Therefore to avoid rejecting otherwise valid time we
295
 * allow the times to be within 'nsec' of the current time. Also to avoid
296
 * accepting very old responses without a nextUpdate field an optional maxage
297
 * parameter specifies the maximum age the thisUpdate field can be.
298
 */
299
int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
300
                        ASN1_GENERALIZEDTIME *nextupd, long nsec, long maxsec)
301
0
{
302
0
    int ret = 1;
303
0
    time_t t_now, t_tmp;
304
305
0
    time(&t_now);
306
    /* Check thisUpdate is valid and not more than nsec in the future */
307
0
    if (!ASN1_GENERALIZEDTIME_check(thisupd)) {
308
0
        ERR_raise(ERR_LIB_OCSP, OCSP_R_ERROR_IN_THISUPDATE_FIELD);
309
0
        ret = 0;
310
0
    } else {
311
0
        t_tmp = t_now + nsec;
312
0
        if (X509_cmp_time(thisupd, &t_tmp) > 0) {
313
0
            ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_NOT_YET_VALID);
314
0
            ret = 0;
315
0
        }
316
317
        /*
318
         * If maxsec specified check thisUpdate is not more than maxsec in
319
         * the past
320
         */
321
0
        if (maxsec >= 0) {
322
0
            t_tmp = t_now - maxsec;
323
0
            if (X509_cmp_time(thisupd, &t_tmp) < 0) {
324
0
                ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_TOO_OLD);
325
0
                ret = 0;
326
0
            }
327
0
        }
328
0
    }
329
330
0
    if (nextupd == NULL)
331
0
        return ret;
332
333
    /* Check nextUpdate is valid and not more than nsec in the past */
334
0
    if (!ASN1_GENERALIZEDTIME_check(nextupd)) {
335
0
        ERR_raise(ERR_LIB_OCSP, OCSP_R_ERROR_IN_NEXTUPDATE_FIELD);
336
0
        ret = 0;
337
0
    } else {
338
0
        t_tmp = t_now - nsec;
339
0
        if (X509_cmp_time(nextupd, &t_tmp) < 0) {
340
0
            ERR_raise(ERR_LIB_OCSP, OCSP_R_STATUS_EXPIRED);
341
0
            ret = 0;
342
0
        }
343
0
    }
344
345
    /* Also don't allow nextUpdate to precede thisUpdate */
346
0
    if (ASN1_STRING_cmp(nextupd, thisupd) < 0) {
347
0
        ERR_raise(ERR_LIB_OCSP, OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE);
348
0
        ret = 0;
349
0
    }
350
351
0
    return ret;
352
0
}
353
354
const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single)
355
0
{
356
0
    return single->certId;
357
0
}