3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
6 /* ====================================================================
7 * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * openssl-core@openssl.org.
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
35 * 6. Redistributions of any form whatsoever must retain the following
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
62 #include <openssl/objects.h>
63 #include <openssl/rand.h>
64 #include <openssl/x509.h>
65 #include <openssl/pem.h>
66 #include <openssl/x509v3.h>
67 #include <openssl/ocsp.h>
70 * Utility functions related to sending OCSP responses and extracting
71 * relevant information from the request.
74 int OCSP_request_onereq_count(OCSP_REQUEST
*req
)
76 return sk_OCSP_ONEREQ_num(req
->tbsRequest
->requestList
);
79 OCSP_ONEREQ
*OCSP_request_onereq_get0(OCSP_REQUEST
*req
, int i
)
81 return sk_OCSP_ONEREQ_value(req
->tbsRequest
->requestList
, i
);
84 OCSP_CERTID
*OCSP_onereq_get0_id(OCSP_ONEREQ
*one
)
89 int OCSP_id_get0_info(ASN1_OCTET_STRING
**piNameHash
, ASN1_OBJECT
**pmd
,
90 ASN1_OCTET_STRING
**pikeyHash
,
91 ASN1_INTEGER
**pserial
, OCSP_CERTID
*cid
)
96 *pmd
= cid
->hashAlgorithm
->algorithm
;
98 *piNameHash
= cid
->issuerNameHash
;
100 *pikeyHash
= cid
->issuerKeyHash
;
102 *pserial
= cid
->serialNumber
;
106 int OCSP_request_is_signed(OCSP_REQUEST
*req
)
108 if (req
->optionalSignature
)
113 /* Create an OCSP response and encode an optional basic response */
114 OCSP_RESPONSE
*OCSP_response_create(int status
, OCSP_BASICRESP
*bs
)
116 OCSP_RESPONSE
*rsp
= NULL
;
118 if (!(rsp
= OCSP_RESPONSE_new()))
120 if (!(ASN1_ENUMERATED_set(rsp
->responseStatus
, status
)))
124 if (!(rsp
->responseBytes
= OCSP_RESPBYTES_new()))
126 rsp
->responseBytes
->responseType
= OBJ_nid2obj(NID_id_pkix_OCSP_basic
);
128 (bs
, ASN1_ITEM_rptr(OCSP_BASICRESP
), &rsp
->responseBytes
->response
))
133 OCSP_RESPONSE_free(rsp
);
137 OCSP_SINGLERESP
*OCSP_basic_add1_status(OCSP_BASICRESP
*rsp
,
139 int status
, int reason
,
144 OCSP_SINGLERESP
*single
= NULL
;
146 OCSP_REVOKEDINFO
*ri
;
148 if (!rsp
->tbsResponseData
->responses
&&
149 !(rsp
->tbsResponseData
->responses
= sk_OCSP_SINGLERESP_new_null()))
152 if (!(single
= OCSP_SINGLERESP_new()))
155 if (!ASN1_TIME_to_generalizedtime(thisupd
, &single
->thisUpdate
))
158 !ASN1_TIME_to_generalizedtime(nextupd
, &single
->nextUpdate
))
161 OCSP_CERTID_free(single
->certId
);
163 if (!(single
->certId
= OCSP_CERTID_dup(cid
)))
166 cs
= single
->certStatus
;
167 switch (cs
->type
= status
) {
168 case V_OCSP_CERTSTATUS_REVOKED
:
170 OCSPerr(OCSP_F_OCSP_BASIC_ADD1_STATUS
, OCSP_R_NO_REVOKED_TIME
);
173 if (!(cs
->value
.revoked
= ri
= OCSP_REVOKEDINFO_new()))
175 if (!ASN1_TIME_to_generalizedtime(revtime
, &ri
->revocationTime
))
177 if (reason
!= OCSP_REVOKED_STATUS_NOSTATUS
) {
178 if (!(ri
->revocationReason
= ASN1_ENUMERATED_new()))
180 if (!(ASN1_ENUMERATED_set(ri
->revocationReason
, reason
)))
185 case V_OCSP_CERTSTATUS_GOOD
:
186 cs
->value
.good
= ASN1_NULL_new();
189 case V_OCSP_CERTSTATUS_UNKNOWN
:
190 cs
->value
.unknown
= ASN1_NULL_new();
197 if (!(sk_OCSP_SINGLERESP_push(rsp
->tbsResponseData
->responses
, single
)))
201 OCSP_SINGLERESP_free(single
);
205 /* Add a certificate to an OCSP request */
207 int OCSP_basic_add1_cert(OCSP_BASICRESP
*resp
, X509
*cert
)
209 if (!resp
->certs
&& !(resp
->certs
= sk_X509_new_null()))
212 if (!sk_X509_push(resp
->certs
, cert
))
214 CRYPTO_add(&cert
->references
, 1, CRYPTO_LOCK_X509
);
218 int OCSP_basic_sign(OCSP_BASICRESP
*brsp
,
219 X509
*signer
, EVP_PKEY
*key
, const EVP_MD
*dgst
,
220 STACK_OF(X509
) *certs
, unsigned long flags
)
225 if (!X509_check_private_key(signer
, key
)) {
226 OCSPerr(OCSP_F_OCSP_BASIC_SIGN
,
227 OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE
);
231 if (!(flags
& OCSP_NOCERTS
)) {
232 if (!OCSP_basic_add1_cert(brsp
, signer
))
234 for (i
= 0; i
< sk_X509_num(certs
); i
++) {
235 X509
*tmpcert
= sk_X509_value(certs
, i
);
236 if (!OCSP_basic_add1_cert(brsp
, tmpcert
))
241 rid
= brsp
->tbsResponseData
->responderId
;
242 if (flags
& OCSP_RESPID_KEY
) {
243 unsigned char md
[SHA_DIGEST_LENGTH
];
244 X509_pubkey_digest(signer
, EVP_sha1(), md
, NULL
);
245 if (!(rid
->value
.byKey
= ASN1_OCTET_STRING_new()))
247 if (!(ASN1_OCTET_STRING_set(rid
->value
.byKey
, md
, SHA_DIGEST_LENGTH
)))
249 rid
->type
= V_OCSP_RESPID_KEY
;
251 if (!X509_NAME_set(&rid
->value
.byName
, X509_get_subject_name(signer
)))
253 rid
->type
= V_OCSP_RESPID_NAME
;
256 if (!(flags
& OCSP_NOTIME
) &&
257 !X509_gmtime_adj(brsp
->tbsResponseData
->producedAt
, 0))
261 * Right now, I think that not doing double hashing is the right thing.
265 if (!OCSP_BASICRESP_sign(brsp
, key
, dgst
, 0))