Coverage Report

Created: 2026-01-09 07:00

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