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).
61 #include "internal/cryptlib.h"
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>
71 * Utility functions related to sending OCSP responses and extracting
72 * relevant information from the request.
75 int OCSP_request_onereq_count(OCSP_REQUEST
*req
)
77 return sk_OCSP_ONEREQ_num(req
->tbsRequest
->requestList
);
80 OCSP_ONEREQ
*OCSP_request_onereq_get0(OCSP_REQUEST
*req
, int i
)
82 return sk_OCSP_ONEREQ_value(req
->tbsRequest
->requestList
, i
);
85 OCSP_CERTID
*OCSP_onereq_get0_id(OCSP_ONEREQ
*one
)
90 int OCSP_id_get0_info(ASN1_OCTET_STRING
**piNameHash
, ASN1_OBJECT
**pmd
,
91 ASN1_OCTET_STRING
**pikeyHash
,
92 ASN1_INTEGER
**pserial
, OCSP_CERTID
*cid
)
97 *pmd
= cid
->hashAlgorithm
->algorithm
;
99 *piNameHash
= cid
->issuerNameHash
;
101 *pikeyHash
= cid
->issuerKeyHash
;
103 *pserial
= cid
->serialNumber
;
107 int OCSP_request_is_signed(OCSP_REQUEST
*req
)
109 if (req
->optionalSignature
)
114 /* Create an OCSP response and encode an optional basic response */
115 OCSP_RESPONSE
*OCSP_response_create(int status
, OCSP_BASICRESP
*bs
)
117 OCSP_RESPONSE
*rsp
= NULL
;
119 if ((rsp
= OCSP_RESPONSE_new()) == NULL
)
121 if (!(ASN1_ENUMERATED_set(rsp
->responseStatus
, status
)))
125 if ((rsp
->responseBytes
= OCSP_RESPBYTES_new()) == NULL
)
127 rsp
->responseBytes
->responseType
= OBJ_nid2obj(NID_id_pkix_OCSP_basic
);
129 (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
== NULL
149 && (rsp
->tbsResponseData
->responses
150 = sk_OCSP_SINGLERESP_new_null()) == NULL
)
153 if ((single
= OCSP_SINGLERESP_new()) == NULL
)
156 if (!ASN1_TIME_to_generalizedtime(thisupd
, &single
->thisUpdate
))
159 !ASN1_TIME_to_generalizedtime(nextupd
, &single
->nextUpdate
))
162 OCSP_CERTID_free(single
->certId
);
164 if ((single
->certId
= OCSP_CERTID_dup(cid
)) == NULL
)
167 cs
= single
->certStatus
;
168 switch (cs
->type
= status
) {
169 case V_OCSP_CERTSTATUS_REVOKED
:
171 OCSPerr(OCSP_F_OCSP_BASIC_ADD1_STATUS
, OCSP_R_NO_REVOKED_TIME
);
174 if ((cs
->value
.revoked
= ri
= OCSP_REVOKEDINFO_new()) == NULL
)
176 if (!ASN1_TIME_to_generalizedtime(revtime
, &ri
->revocationTime
))
178 if (reason
!= OCSP_REVOKED_STATUS_NOSTATUS
) {
179 if ((ri
->revocationReason
= ASN1_ENUMERATED_new()) == NULL
)
181 if (!(ASN1_ENUMERATED_set(ri
->revocationReason
, reason
)))
186 case V_OCSP_CERTSTATUS_GOOD
:
187 cs
->value
.good
= ASN1_NULL_new();
190 case V_OCSP_CERTSTATUS_UNKNOWN
:
191 cs
->value
.unknown
= ASN1_NULL_new();
198 if (!(sk_OCSP_SINGLERESP_push(rsp
->tbsResponseData
->responses
, single
)))
202 OCSP_SINGLERESP_free(single
);
206 /* Add a certificate to an OCSP request */
208 int OCSP_basic_add1_cert(OCSP_BASICRESP
*resp
, X509
*cert
)
210 if (resp
->certs
== NULL
211 && (resp
->certs
= sk_X509_new_null()) == NULL
)
214 if (!sk_X509_push(resp
->certs
, cert
))
220 int OCSP_basic_sign(OCSP_BASICRESP
*brsp
,
221 X509
*signer
, EVP_PKEY
*key
, const EVP_MD
*dgst
,
222 STACK_OF(X509
) *certs
, unsigned long flags
)
227 if (!X509_check_private_key(signer
, key
)) {
228 OCSPerr(OCSP_F_OCSP_BASIC_SIGN
,
229 OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE
);
233 if (!(flags
& OCSP_NOCERTS
)) {
234 if (!OCSP_basic_add1_cert(brsp
, signer
))
236 for (i
= 0; i
< sk_X509_num(certs
); i
++) {
237 X509
*tmpcert
= sk_X509_value(certs
, i
);
238 if (!OCSP_basic_add1_cert(brsp
, tmpcert
))
243 rid
= brsp
->tbsResponseData
->responderId
;
244 if (flags
& OCSP_RESPID_KEY
) {
245 unsigned char md
[SHA_DIGEST_LENGTH
];
246 X509_pubkey_digest(signer
, EVP_sha1(), md
, NULL
);
247 if ((rid
->value
.byKey
= ASN1_OCTET_STRING_new()) == NULL
)
249 if (!(ASN1_OCTET_STRING_set(rid
->value
.byKey
, md
, SHA_DIGEST_LENGTH
)))
251 rid
->type
= V_OCSP_RESPID_KEY
;
253 if (!X509_NAME_set(&rid
->value
.byName
, X509_get_subject_name(signer
)))
255 rid
->type
= V_OCSP_RESPID_NAME
;
258 if (!(flags
& OCSP_NOTIME
) &&
259 !X509_gmtime_adj(brsp
->tbsResponseData
->producedAt
, 0))
263 * Right now, I think that not doing double hashing is the right thing.
267 if (!OCSP_BASICRESP_sign(brsp
, key
, dgst
, 0))