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