2 * Copyright 2001-2020 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.
24 int OCSP_request_onereq_count(OCSP_REQUEST
*req
)
26 return sk_OCSP_ONEREQ_num(req
->tbsRequest
.requestList
);
29 OCSP_ONEREQ
*OCSP_request_onereq_get0(OCSP_REQUEST
*req
, int i
)
31 return sk_OCSP_ONEREQ_value(req
->tbsRequest
.requestList
, i
);
34 OCSP_CERTID
*OCSP_onereq_get0_id(OCSP_ONEREQ
*one
)
39 int OCSP_id_get0_info(ASN1_OCTET_STRING
**piNameHash
, ASN1_OBJECT
**pmd
,
40 ASN1_OCTET_STRING
**pikeyHash
,
41 ASN1_INTEGER
**pserial
, OCSP_CERTID
*cid
)
46 *pmd
= cid
->hashAlgorithm
.algorithm
;
48 *piNameHash
= &cid
->issuerNameHash
;
50 *pikeyHash
= &cid
->issuerKeyHash
;
52 *pserial
= &cid
->serialNumber
;
56 int OCSP_request_is_signed(OCSP_REQUEST
*req
)
58 if (req
->optionalSignature
)
63 /* Create an OCSP response and encode an optional basic response */
64 OCSP_RESPONSE
*OCSP_response_create(int status
, OCSP_BASICRESP
*bs
)
66 OCSP_RESPONSE
*rsp
= NULL
;
68 if ((rsp
= OCSP_RESPONSE_new()) == NULL
)
70 if (!(ASN1_ENUMERATED_set(rsp
->responseStatus
, status
)))
74 if ((rsp
->responseBytes
= OCSP_RESPBYTES_new()) == NULL
)
76 rsp
->responseBytes
->responseType
= OBJ_nid2obj(NID_id_pkix_OCSP_basic
);
78 (bs
, ASN1_ITEM_rptr(OCSP_BASICRESP
), &rsp
->responseBytes
->response
))
82 OCSP_RESPONSE_free(rsp
);
86 OCSP_SINGLERESP
*OCSP_basic_add1_status(OCSP_BASICRESP
*rsp
,
88 int status
, int reason
,
93 OCSP_SINGLERESP
*single
= NULL
;
97 if (rsp
->tbsResponseData
.responses
== NULL
98 && (rsp
->tbsResponseData
.responses
99 = sk_OCSP_SINGLERESP_new_null()) == NULL
)
102 if ((single
= OCSP_SINGLERESP_new()) == NULL
)
105 if (!ASN1_TIME_to_generalizedtime(thisupd
, &single
->thisUpdate
))
108 !ASN1_TIME_to_generalizedtime(nextupd
, &single
->nextUpdate
))
111 OCSP_CERTID_free(single
->certId
);
113 if ((single
->certId
= OCSP_CERTID_dup(cid
)) == NULL
)
116 cs
= single
->certStatus
;
117 switch (cs
->type
= status
) {
118 case V_OCSP_CERTSTATUS_REVOKED
:
120 OCSPerr(OCSP_F_OCSP_BASIC_ADD1_STATUS
, OCSP_R_NO_REVOKED_TIME
);
123 if ((cs
->value
.revoked
= ri
= OCSP_REVOKEDINFO_new()) == NULL
)
125 if (!ASN1_TIME_to_generalizedtime(revtime
, &ri
->revocationTime
))
127 if (reason
!= OCSP_REVOKED_STATUS_NOSTATUS
) {
128 if ((ri
->revocationReason
= ASN1_ENUMERATED_new()) == NULL
)
130 if (!(ASN1_ENUMERATED_set(ri
->revocationReason
, reason
)))
135 case V_OCSP_CERTSTATUS_GOOD
:
136 if ((cs
->value
.good
= ASN1_NULL_new()) == NULL
)
140 case V_OCSP_CERTSTATUS_UNKNOWN
:
141 if ((cs
->value
.unknown
= ASN1_NULL_new()) == NULL
)
149 if (!(sk_OCSP_SINGLERESP_push(rsp
->tbsResponseData
.responses
, single
)))
153 OCSP_SINGLERESP_free(single
);
157 /* Add a certificate to an OCSP request */
159 int OCSP_basic_add1_cert(OCSP_BASICRESP
*resp
, X509
*cert
)
161 return X509_add_cert_new(&resp
->certs
, cert
, X509_ADD_FLAG_UP_REF
);
165 * Sign an OCSP response using the parameters contained in the digest context,
166 * set the responderID to the subject name in the signer's certificate, and
167 * include one or more optional certificates in the response.
170 int OCSP_basic_sign_ctx(OCSP_BASICRESP
*brsp
,
171 X509
*signer
, EVP_MD_CTX
*ctx
,
172 STACK_OF(X509
) *certs
, unsigned long flags
)
178 if (ctx
== NULL
|| EVP_MD_CTX_pkey_ctx(ctx
) == NULL
) {
179 OCSPerr(OCSP_F_OCSP_BASIC_SIGN_CTX
, OCSP_R_NO_SIGNER_KEY
);
183 pkey
= EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx
));
184 if (pkey
== NULL
|| !X509_check_private_key(signer
, pkey
)) {
185 OCSPerr(OCSP_F_OCSP_BASIC_SIGN_CTX
,
186 OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE
);
190 if (!(flags
& OCSP_NOCERTS
)) {
191 if (!OCSP_basic_add1_cert(brsp
, signer
))
193 for (i
= 0; i
< sk_X509_num(certs
); i
++) {
194 X509
*tmpcert
= sk_X509_value(certs
, i
);
195 if (!OCSP_basic_add1_cert(brsp
, tmpcert
))
200 rid
= &brsp
->tbsResponseData
.responderId
;
201 if (flags
& OCSP_RESPID_KEY
) {
202 if (!OCSP_RESPID_set_by_key(rid
, signer
))
204 } else if (!OCSP_RESPID_set_by_name(rid
, signer
)) {
208 if (!(flags
& OCSP_NOTIME
) &&
209 !X509_gmtime_adj(brsp
->tbsResponseData
.producedAt
, 0))
213 * Right now, I think that not doing double hashing is the right thing.
217 if (!OCSP_BASICRESP_sign_ctx(brsp
, ctx
, 0))
225 int OCSP_basic_sign(OCSP_BASICRESP
*brsp
,
226 X509
*signer
, EVP_PKEY
*key
, const EVP_MD
*dgst
,
227 STACK_OF(X509
) *certs
, unsigned long flags
)
229 EVP_MD_CTX
*ctx
= EVP_MD_CTX_new();
230 EVP_PKEY_CTX
*pkctx
= NULL
;
236 if (!EVP_DigestSignInit(ctx
, &pkctx
, dgst
, NULL
, key
)) {
237 EVP_MD_CTX_free(ctx
);
240 i
= OCSP_basic_sign_ctx(brsp
, signer
, ctx
, certs
, flags
);
241 EVP_MD_CTX_free(ctx
);
245 int OCSP_RESPID_set_by_name(OCSP_RESPID
*respid
, X509
*cert
)
247 if (!X509_NAME_set(&respid
->value
.byName
, X509_get_subject_name(cert
)))
250 respid
->type
= V_OCSP_RESPID_NAME
;
255 int OCSP_RESPID_set_by_key_ex(OCSP_RESPID
*respid
, X509
*cert
,
256 OPENSSL_CTX
*libctx
, const char *propq
)
258 ASN1_OCTET_STRING
*byKey
= NULL
;
259 unsigned char md
[SHA_DIGEST_LENGTH
];
260 EVP_MD
*sha1
= EVP_MD_fetch(libctx
, "SHA1", propq
);
266 /* RFC2560 requires SHA1 */
267 if (!X509_pubkey_digest(cert
, sha1
, md
, NULL
))
270 byKey
= ASN1_OCTET_STRING_new();
274 if (!(ASN1_OCTET_STRING_set(byKey
, md
, SHA_DIGEST_LENGTH
))) {
275 ASN1_OCTET_STRING_free(byKey
);
279 respid
->type
= V_OCSP_RESPID_KEY
;
280 respid
->value
.byKey
= byKey
;
288 int OCSP_RESPID_set_by_key(OCSP_RESPID
*respid
, X509
*cert
)
290 return OCSP_RESPID_set_by_key_ex(respid
, cert
, NULL
, NULL
);
293 int OCSP_RESPID_match_ex(OCSP_RESPID
*respid
, X509
*cert
, OPENSSL_CTX
*libctx
,
299 if (respid
->type
== V_OCSP_RESPID_KEY
) {
300 unsigned char md
[SHA_DIGEST_LENGTH
];
302 sha1
= EVP_MD_fetch(libctx
, "SHA1", propq
);
306 if (respid
->value
.byKey
== NULL
)
309 /* RFC2560 requires SHA1 */
310 if (!X509_pubkey_digest(cert
, sha1
, md
, NULL
))
313 ret
= (ASN1_STRING_length(respid
->value
.byKey
) == SHA_DIGEST_LENGTH
)
314 && (memcmp(ASN1_STRING_get0_data(respid
->value
.byKey
), md
,
315 SHA_DIGEST_LENGTH
) == 0);
316 } else if (respid
->type
== V_OCSP_RESPID_NAME
) {
317 if (respid
->value
.byName
== NULL
)
320 return X509_NAME_cmp(respid
->value
.byName
,
321 X509_get_subject_name(cert
)) == 0;
329 int OCSP_RESPID_match(OCSP_RESPID
*respid
, X509
*cert
)
331 return OCSP_RESPID_match_ex(respid
, cert
, NULL
, NULL
);