2 * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
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
11 #include "internal/cryptlib.h"
12 #include <openssl/objects.h>
13 #include <openssl/x509.h>
14 #include <openssl/pem.h>
15 #include <openssl/x509v3.h>
16 #include <openssl/ocsp.h>
17 #include "ocsp_local.h"
20 * Utility functions related to sending OCSP responses and extracting
21 * relevant information from the request.
23 int OCSP_request_onereq_count(OCSP_REQUEST
*req
)
25 return sk_OCSP_ONEREQ_num(req
->tbsRequest
.requestList
);
28 OCSP_ONEREQ
*OCSP_request_onereq_get0(OCSP_REQUEST
*req
, int i
)
30 return sk_OCSP_ONEREQ_value(req
->tbsRequest
.requestList
, i
);
33 OCSP_CERTID
*OCSP_onereq_get0_id(OCSP_ONEREQ
*one
)
38 int OCSP_id_get0_info(ASN1_OCTET_STRING
**piNameHash
, ASN1_OBJECT
**pmd
,
39 ASN1_OCTET_STRING
**pikeyHash
,
40 ASN1_INTEGER
**pserial
, OCSP_CERTID
*cid
)
45 *pmd
= cid
->hashAlgorithm
.algorithm
;
47 *piNameHash
= &cid
->issuerNameHash
;
49 *pikeyHash
= &cid
->issuerKeyHash
;
51 *pserial
= &cid
->serialNumber
;
55 int OCSP_request_is_signed(OCSP_REQUEST
*req
)
57 if (req
->optionalSignature
)
62 /* Create an OCSP response and encode an optional basic response */
63 OCSP_RESPONSE
*OCSP_response_create(int status
, OCSP_BASICRESP
*bs
)
65 OCSP_RESPONSE
*rsp
= NULL
;
67 if ((rsp
= OCSP_RESPONSE_new()) == NULL
)
69 if (!(ASN1_ENUMERATED_set(rsp
->responseStatus
, status
)))
73 if ((rsp
->responseBytes
= OCSP_RESPBYTES_new()) == NULL
)
75 rsp
->responseBytes
->responseType
= OBJ_nid2obj(NID_id_pkix_OCSP_basic
);
77 (bs
, ASN1_ITEM_rptr(OCSP_BASICRESP
), &rsp
->responseBytes
->response
))
81 OCSP_RESPONSE_free(rsp
);
85 OCSP_SINGLERESP
*OCSP_basic_add1_status(OCSP_BASICRESP
*rsp
,
87 int status
, int reason
,
92 OCSP_SINGLERESP
*single
= NULL
;
96 if (rsp
->tbsResponseData
.responses
== NULL
97 && (rsp
->tbsResponseData
.responses
98 = sk_OCSP_SINGLERESP_new_null()) == NULL
)
101 if ((single
= OCSP_SINGLERESP_new()) == NULL
)
104 if (!ASN1_TIME_to_generalizedtime(thisupd
, &single
->thisUpdate
))
107 !ASN1_TIME_to_generalizedtime(nextupd
, &single
->nextUpdate
))
110 OCSP_CERTID_free(single
->certId
);
112 if ((single
->certId
= OCSP_CERTID_dup(cid
)) == NULL
)
115 cs
= single
->certStatus
;
116 switch (cs
->type
= status
) {
117 case V_OCSP_CERTSTATUS_REVOKED
:
119 ERR_raise(ERR_LIB_OCSP
, OCSP_R_NO_REVOKED_TIME
);
122 if ((cs
->value
.revoked
= ri
= OCSP_REVOKEDINFO_new()) == NULL
)
124 if (!ASN1_TIME_to_generalizedtime(revtime
, &ri
->revocationTime
))
126 if (reason
!= OCSP_REVOKED_STATUS_NOSTATUS
) {
127 if ((ri
->revocationReason
= ASN1_ENUMERATED_new()) == NULL
)
129 if (!(ASN1_ENUMERATED_set(ri
->revocationReason
, reason
)))
134 case V_OCSP_CERTSTATUS_GOOD
:
135 if ((cs
->value
.good
= ASN1_NULL_new()) == NULL
)
139 case V_OCSP_CERTSTATUS_UNKNOWN
:
140 if ((cs
->value
.unknown
= ASN1_NULL_new()) == NULL
)
148 if (!(sk_OCSP_SINGLERESP_push(rsp
->tbsResponseData
.responses
, single
)))
152 OCSP_SINGLERESP_free(single
);
156 /* Add a certificate to an OCSP request */
157 int OCSP_basic_add1_cert(OCSP_BASICRESP
*resp
, X509
*cert
)
159 return ossl_x509_add_cert_new(&resp
->certs
, cert
, X509_ADD_FLAG_UP_REF
);
163 * Sign an OCSP response using the parameters contained in the digest context,
164 * set the responderID to the subject name in the signer's certificate, and
165 * include one or more optional certificates in the response.
167 int OCSP_basic_sign_ctx(OCSP_BASICRESP
*brsp
,
168 X509
*signer
, EVP_MD_CTX
*ctx
,
169 STACK_OF(X509
) *certs
, unsigned long flags
)
174 if (ctx
== NULL
|| EVP_MD_CTX_pkey_ctx(ctx
) == NULL
) {
175 ERR_raise(ERR_LIB_OCSP
, OCSP_R_NO_SIGNER_KEY
);
179 pkey
= EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx
));
180 if (pkey
== NULL
|| !X509_check_private_key(signer
, pkey
)) {
181 ERR_raise(ERR_LIB_OCSP
, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE
);
185 if (!(flags
& OCSP_NOCERTS
)) {
186 if (!OCSP_basic_add1_cert(brsp
, signer
)
187 || !X509_add_certs(brsp
->certs
, certs
, X509_ADD_FLAG_UP_REF
))
191 rid
= &brsp
->tbsResponseData
.responderId
;
192 if (flags
& OCSP_RESPID_KEY
) {
193 if (!OCSP_RESPID_set_by_key(rid
, signer
))
195 } else if (!OCSP_RESPID_set_by_name(rid
, signer
)) {
199 if (!(flags
& OCSP_NOTIME
) &&
200 !X509_gmtime_adj(brsp
->tbsResponseData
.producedAt
, 0))
204 * Right now, I think that not doing double hashing is the right thing.
207 if (!OCSP_BASICRESP_sign_ctx(brsp
, ctx
, 0))
215 int OCSP_basic_sign(OCSP_BASICRESP
*brsp
,
216 X509
*signer
, EVP_PKEY
*key
, const EVP_MD
*dgst
,
217 STACK_OF(X509
) *certs
, unsigned long flags
)
219 EVP_MD_CTX
*ctx
= EVP_MD_CTX_new();
220 EVP_PKEY_CTX
*pkctx
= NULL
;
226 if (!EVP_DigestSignInit_ex(ctx
, &pkctx
, EVP_MD_name(dgst
),
227 signer
->libctx
, signer
->propq
, key
, NULL
)) {
228 EVP_MD_CTX_free(ctx
);
231 i
= OCSP_basic_sign_ctx(brsp
, signer
, ctx
, certs
, flags
);
232 EVP_MD_CTX_free(ctx
);
236 int OCSP_RESPID_set_by_name(OCSP_RESPID
*respid
, X509
*cert
)
238 if (!X509_NAME_set(&respid
->value
.byName
, X509_get_subject_name(cert
)))
241 respid
->type
= V_OCSP_RESPID_NAME
;
246 int OCSP_RESPID_set_by_key_ex(OCSP_RESPID
*respid
, X509
*cert
,
247 OSSL_LIB_CTX
*libctx
, const char *propq
)
249 ASN1_OCTET_STRING
*byKey
= NULL
;
250 unsigned char md
[SHA_DIGEST_LENGTH
];
251 EVP_MD
*sha1
= EVP_MD_fetch(libctx
, "SHA1", propq
);
257 /* RFC2560 requires SHA1 */
258 if (!X509_pubkey_digest(cert
, sha1
, md
, NULL
))
261 byKey
= ASN1_OCTET_STRING_new();
265 if (!(ASN1_OCTET_STRING_set(byKey
, md
, SHA_DIGEST_LENGTH
))) {
266 ASN1_OCTET_STRING_free(byKey
);
270 respid
->type
= V_OCSP_RESPID_KEY
;
271 respid
->value
.byKey
= byKey
;
279 int OCSP_RESPID_set_by_key(OCSP_RESPID
*respid
, X509
*cert
)
283 return OCSP_RESPID_set_by_key_ex(respid
, cert
, cert
->libctx
, cert
->propq
);
286 int OCSP_RESPID_match_ex(OCSP_RESPID
*respid
, X509
*cert
, OSSL_LIB_CTX
*libctx
,
292 if (respid
->type
== V_OCSP_RESPID_KEY
) {
293 unsigned char md
[SHA_DIGEST_LENGTH
];
295 sha1
= EVP_MD_fetch(libctx
, "SHA1", propq
);
299 if (respid
->value
.byKey
== NULL
)
302 /* RFC2560 requires SHA1 */
303 if (!X509_pubkey_digest(cert
, sha1
, md
, NULL
))
306 ret
= (ASN1_STRING_length(respid
->value
.byKey
) == SHA_DIGEST_LENGTH
)
307 && (memcmp(ASN1_STRING_get0_data(respid
->value
.byKey
), md
,
308 SHA_DIGEST_LENGTH
) == 0);
309 } else if (respid
->type
== V_OCSP_RESPID_NAME
) {
310 if (respid
->value
.byName
== NULL
)
313 return X509_NAME_cmp(respid
->value
.byName
,
314 X509_get_subject_name(cert
)) == 0;
322 int OCSP_RESPID_match(OCSP_RESPID
*respid
, X509
*cert
)
326 return OCSP_RESPID_match_ex(respid
, cert
, cert
->libctx
, cert
->propq
);