1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: ocsp_srv.c,v 1.12 2022/01/07 09:45:52 tb Exp $ */
2f5b1c8a1SJohn Marino /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3f5b1c8a1SJohn Marino  * project 2001.
4f5b1c8a1SJohn Marino  */
5f5b1c8a1SJohn Marino /* ====================================================================
6f5b1c8a1SJohn Marino  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
7f5b1c8a1SJohn Marino  *
8f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
9f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
10f5b1c8a1SJohn Marino  * are met:
11f5b1c8a1SJohn Marino  *
12f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the above copyright
13f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
14f5b1c8a1SJohn Marino  *
15f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
16f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in
17f5b1c8a1SJohn Marino  *    the documentation and/or other materials provided with the
18f5b1c8a1SJohn Marino  *    distribution.
19f5b1c8a1SJohn Marino  *
20f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this
21f5b1c8a1SJohn Marino  *    software must display the following acknowledgment:
22f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
23f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24f5b1c8a1SJohn Marino  *
25f5b1c8a1SJohn Marino  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26f5b1c8a1SJohn Marino  *    endorse or promote products derived from this software without
27f5b1c8a1SJohn Marino  *    prior written permission. For written permission, please contact
28f5b1c8a1SJohn Marino  *    openssl-core@openssl.org.
29f5b1c8a1SJohn Marino  *
30f5b1c8a1SJohn Marino  * 5. Products derived from this software may not be called "OpenSSL"
31f5b1c8a1SJohn Marino  *    nor may "OpenSSL" appear in their names without prior written
32f5b1c8a1SJohn Marino  *    permission of the OpenSSL Project.
33f5b1c8a1SJohn Marino  *
34f5b1c8a1SJohn Marino  * 6. Redistributions of any form whatsoever must retain the following
35f5b1c8a1SJohn Marino  *    acknowledgment:
36f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
37f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38f5b1c8a1SJohn Marino  *
39f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40f5b1c8a1SJohn Marino  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42f5b1c8a1SJohn Marino  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43f5b1c8a1SJohn Marino  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44f5b1c8a1SJohn Marino  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45f5b1c8a1SJohn Marino  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46f5b1c8a1SJohn Marino  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48f5b1c8a1SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49f5b1c8a1SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50f5b1c8a1SJohn Marino  * OF THE POSSIBILITY OF SUCH DAMAGE.
51f5b1c8a1SJohn Marino  * ====================================================================
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * This product includes cryptographic software written by Eric Young
54f5b1c8a1SJohn Marino  * (eay@cryptsoft.com).  This product includes software written by Tim
55f5b1c8a1SJohn Marino  * Hudson (tjh@cryptsoft.com).
56f5b1c8a1SJohn Marino  *
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino #include <stdio.h>
60f5b1c8a1SJohn Marino 
61f5b1c8a1SJohn Marino #include <openssl/err.h>
62f5b1c8a1SJohn Marino #include <openssl/objects.h>
63f5b1c8a1SJohn Marino #include <openssl/ocsp.h>
64f5b1c8a1SJohn Marino #include <openssl/pem.h>
65f5b1c8a1SJohn Marino #include <openssl/x509.h>
66f5b1c8a1SJohn Marino #include <openssl/x509v3.h>
67f5b1c8a1SJohn Marino 
68*de0e0e4dSAntonio Huete Jimenez #include "ocsp_local.h"
69*de0e0e4dSAntonio Huete Jimenez 
70f5b1c8a1SJohn Marino /* Utility functions related to sending OCSP responses and extracting
71f5b1c8a1SJohn Marino  * relevant information from the request.
72f5b1c8a1SJohn Marino  */
73f5b1c8a1SJohn Marino 
74f5b1c8a1SJohn Marino int
OCSP_request_onereq_count(OCSP_REQUEST * req)75f5b1c8a1SJohn Marino OCSP_request_onereq_count(OCSP_REQUEST *req)
76f5b1c8a1SJohn Marino {
77f5b1c8a1SJohn Marino 	return sk_OCSP_ONEREQ_num(req->tbsRequest->requestList);
78f5b1c8a1SJohn Marino }
79f5b1c8a1SJohn Marino 
80f5b1c8a1SJohn Marino OCSP_ONEREQ *
OCSP_request_onereq_get0(OCSP_REQUEST * req,int i)81f5b1c8a1SJohn Marino OCSP_request_onereq_get0(OCSP_REQUEST *req, int i)
82f5b1c8a1SJohn Marino {
83f5b1c8a1SJohn Marino 	return sk_OCSP_ONEREQ_value(req->tbsRequest->requestList, i);
84f5b1c8a1SJohn Marino }
85f5b1c8a1SJohn Marino 
86f5b1c8a1SJohn Marino OCSP_CERTID *
OCSP_onereq_get0_id(OCSP_ONEREQ * one)87f5b1c8a1SJohn Marino OCSP_onereq_get0_id(OCSP_ONEREQ *one)
88f5b1c8a1SJohn Marino {
89f5b1c8a1SJohn Marino 	return one->reqCert;
90f5b1c8a1SJohn Marino }
91f5b1c8a1SJohn Marino 
92f5b1c8a1SJohn Marino int
OCSP_id_get0_info(ASN1_OCTET_STRING ** piNameHash,ASN1_OBJECT ** pmd,ASN1_OCTET_STRING ** pikeyHash,ASN1_INTEGER ** pserial,OCSP_CERTID * cid)93f5b1c8a1SJohn Marino OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
94f5b1c8a1SJohn Marino     ASN1_OCTET_STRING **pikeyHash, ASN1_INTEGER **pserial, OCSP_CERTID *cid)
95f5b1c8a1SJohn Marino {
96f5b1c8a1SJohn Marino 	if (!cid)
97f5b1c8a1SJohn Marino 		return 0;
98f5b1c8a1SJohn Marino 	if (pmd)
99f5b1c8a1SJohn Marino 		*pmd = cid->hashAlgorithm->algorithm;
100f5b1c8a1SJohn Marino 	if (piNameHash)
101f5b1c8a1SJohn Marino 		*piNameHash = cid->issuerNameHash;
102f5b1c8a1SJohn Marino 	if (pikeyHash)
103f5b1c8a1SJohn Marino 		*pikeyHash = cid->issuerKeyHash;
104f5b1c8a1SJohn Marino 	if (pserial)
105f5b1c8a1SJohn Marino 		*pserial = cid->serialNumber;
106f5b1c8a1SJohn Marino 	return 1;
107f5b1c8a1SJohn Marino }
108f5b1c8a1SJohn Marino 
109f5b1c8a1SJohn Marino int
OCSP_request_is_signed(OCSP_REQUEST * req)110f5b1c8a1SJohn Marino OCSP_request_is_signed(OCSP_REQUEST *req)
111f5b1c8a1SJohn Marino {
112f5b1c8a1SJohn Marino 	if (req->optionalSignature)
113f5b1c8a1SJohn Marino 		return 1;
114f5b1c8a1SJohn Marino 	return 0;
115f5b1c8a1SJohn Marino }
116f5b1c8a1SJohn Marino 
117f5b1c8a1SJohn Marino /* Create an OCSP response and encode an optional basic response */
118f5b1c8a1SJohn Marino OCSP_RESPONSE *
OCSP_response_create(int status,OCSP_BASICRESP * bs)119f5b1c8a1SJohn Marino OCSP_response_create(int status, OCSP_BASICRESP *bs)
120f5b1c8a1SJohn Marino {
121f5b1c8a1SJohn Marino 	OCSP_RESPONSE *rsp = NULL;
122f5b1c8a1SJohn Marino 
123f5b1c8a1SJohn Marino 	if (!(rsp = OCSP_RESPONSE_new()))
124f5b1c8a1SJohn Marino 		goto err;
125f5b1c8a1SJohn Marino 	if (!(ASN1_ENUMERATED_set(rsp->responseStatus, status)))
126f5b1c8a1SJohn Marino 		goto err;
127f5b1c8a1SJohn Marino 	if (!bs)
128f5b1c8a1SJohn Marino 		return rsp;
129f5b1c8a1SJohn Marino 	if (!(rsp->responseBytes = OCSP_RESPBYTES_new()))
130f5b1c8a1SJohn Marino 		goto err;
131f5b1c8a1SJohn Marino 	rsp->responseBytes->responseType = OBJ_nid2obj(NID_id_pkix_OCSP_basic);
13272c33676SMaxim Ag 	if (!ASN1_item_pack(bs, &OCSP_BASICRESP_it,
133f5b1c8a1SJohn Marino 	    &rsp->responseBytes->response))
134f5b1c8a1SJohn Marino 		goto err;
135f5b1c8a1SJohn Marino 	return rsp;
136f5b1c8a1SJohn Marino 
137f5b1c8a1SJohn Marino err:
138f5b1c8a1SJohn Marino 	if (rsp)
139f5b1c8a1SJohn Marino 		OCSP_RESPONSE_free(rsp);
140f5b1c8a1SJohn Marino 	return NULL;
141f5b1c8a1SJohn Marino }
142f5b1c8a1SJohn Marino 
143f5b1c8a1SJohn Marino OCSP_SINGLERESP *
OCSP_basic_add1_status(OCSP_BASICRESP * rsp,OCSP_CERTID * cid,int status,int reason,ASN1_TIME * revtime,ASN1_TIME * thisupd,ASN1_TIME * nextupd)144f5b1c8a1SJohn Marino OCSP_basic_add1_status(OCSP_BASICRESP *rsp, OCSP_CERTID *cid, int status,
145f5b1c8a1SJohn Marino     int reason, ASN1_TIME *revtime, ASN1_TIME *thisupd, ASN1_TIME *nextupd)
146f5b1c8a1SJohn Marino {
147f5b1c8a1SJohn Marino 	OCSP_SINGLERESP *single = NULL;
148f5b1c8a1SJohn Marino 	OCSP_CERTSTATUS *cs;
149f5b1c8a1SJohn Marino 	OCSP_REVOKEDINFO *ri;
150f5b1c8a1SJohn Marino 
151f5b1c8a1SJohn Marino 	if (!rsp->tbsResponseData->responses &&
152f5b1c8a1SJohn Marino 	    !(rsp->tbsResponseData->responses = sk_OCSP_SINGLERESP_new_null()))
153f5b1c8a1SJohn Marino 		goto err;
154f5b1c8a1SJohn Marino 
155f5b1c8a1SJohn Marino 	if (!(single = OCSP_SINGLERESP_new()))
156f5b1c8a1SJohn Marino 		goto err;
157f5b1c8a1SJohn Marino 
158f5b1c8a1SJohn Marino 	if (!ASN1_TIME_to_generalizedtime(thisupd, &single->thisUpdate))
159f5b1c8a1SJohn Marino 		goto err;
160f5b1c8a1SJohn Marino 	if (nextupd &&
161f5b1c8a1SJohn Marino 	    !ASN1_TIME_to_generalizedtime(nextupd, &single->nextUpdate))
162f5b1c8a1SJohn Marino 		goto err;
163f5b1c8a1SJohn Marino 
164f5b1c8a1SJohn Marino 	OCSP_CERTID_free(single->certId);
165f5b1c8a1SJohn Marino 
166f5b1c8a1SJohn Marino 	if (!(single->certId = OCSP_CERTID_dup(cid)))
167f5b1c8a1SJohn Marino 		goto err;
168f5b1c8a1SJohn Marino 
169f5b1c8a1SJohn Marino 	cs = single->certStatus;
170f5b1c8a1SJohn Marino 	switch (cs->type = status) {
171f5b1c8a1SJohn Marino 	case V_OCSP_CERTSTATUS_REVOKED:
172f5b1c8a1SJohn Marino 		if (!revtime) {
17372c33676SMaxim Ag 			OCSPerror(OCSP_R_NO_REVOKED_TIME);
174f5b1c8a1SJohn Marino 			goto err;
175f5b1c8a1SJohn Marino 		}
176f5b1c8a1SJohn Marino 		if (!(cs->value.revoked = ri = OCSP_REVOKEDINFO_new()))
177f5b1c8a1SJohn Marino 			goto err;
178f5b1c8a1SJohn Marino 		if (!ASN1_TIME_to_generalizedtime(revtime, &ri->revocationTime))
179f5b1c8a1SJohn Marino 			goto err;
180f5b1c8a1SJohn Marino 		if (reason != OCSP_REVOKED_STATUS_NOSTATUS) {
181f5b1c8a1SJohn Marino 			if (!(ri->revocationReason = ASN1_ENUMERATED_new()))
182f5b1c8a1SJohn Marino 				goto err;
183f5b1c8a1SJohn Marino 			if (!(ASN1_ENUMERATED_set(ri->revocationReason,
184f5b1c8a1SJohn Marino 			    reason)))
185f5b1c8a1SJohn Marino 				goto err;
186f5b1c8a1SJohn Marino 		}
187f5b1c8a1SJohn Marino 		break;
188f5b1c8a1SJohn Marino 
189f5b1c8a1SJohn Marino 	case V_OCSP_CERTSTATUS_GOOD:
190f5b1c8a1SJohn Marino 		cs->value.good = ASN1_NULL_new();
191f5b1c8a1SJohn Marino 		break;
192f5b1c8a1SJohn Marino 
193f5b1c8a1SJohn Marino 	case V_OCSP_CERTSTATUS_UNKNOWN:
194f5b1c8a1SJohn Marino 		cs->value.unknown = ASN1_NULL_new();
195f5b1c8a1SJohn Marino 		break;
196f5b1c8a1SJohn Marino 
197f5b1c8a1SJohn Marino 	default:
198f5b1c8a1SJohn Marino 		goto err;
199f5b1c8a1SJohn Marino 	}
200f5b1c8a1SJohn Marino 	if (!(sk_OCSP_SINGLERESP_push(rsp->tbsResponseData->responses, single)))
201f5b1c8a1SJohn Marino 		goto err;
202f5b1c8a1SJohn Marino 	return single;
203f5b1c8a1SJohn Marino 
204f5b1c8a1SJohn Marino err:
205f5b1c8a1SJohn Marino 	OCSP_SINGLERESP_free(single);
206f5b1c8a1SJohn Marino 	return NULL;
207f5b1c8a1SJohn Marino }
208f5b1c8a1SJohn Marino 
209f5b1c8a1SJohn Marino /* Add a certificate to an OCSP request */
210f5b1c8a1SJohn Marino int
OCSP_basic_add1_cert(OCSP_BASICRESP * resp,X509 * cert)211f5b1c8a1SJohn Marino OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert)
212f5b1c8a1SJohn Marino {
213f5b1c8a1SJohn Marino 	if (!resp->certs && !(resp->certs = sk_X509_new_null()))
214f5b1c8a1SJohn Marino 		return 0;
215f5b1c8a1SJohn Marino 
216f5b1c8a1SJohn Marino 	if (!sk_X509_push(resp->certs, cert))
217f5b1c8a1SJohn Marino 		return 0;
218*de0e0e4dSAntonio Huete Jimenez 	X509_up_ref(cert);
219f5b1c8a1SJohn Marino 	return 1;
220f5b1c8a1SJohn Marino }
221f5b1c8a1SJohn Marino 
222f5b1c8a1SJohn Marino int
OCSP_basic_sign(OCSP_BASICRESP * brsp,X509 * signer,EVP_PKEY * key,const EVP_MD * dgst,STACK_OF (X509)* certs,unsigned long flags)223f5b1c8a1SJohn Marino OCSP_basic_sign(OCSP_BASICRESP *brsp, X509 *signer, EVP_PKEY *key,
224f5b1c8a1SJohn Marino     const EVP_MD *dgst, STACK_OF(X509) *certs, unsigned long flags)
225f5b1c8a1SJohn Marino {
226f5b1c8a1SJohn Marino 	int i;
227f5b1c8a1SJohn Marino 	OCSP_RESPID *rid;
228f5b1c8a1SJohn Marino 
229f5b1c8a1SJohn Marino 	if (!X509_check_private_key(signer, key)) {
23072c33676SMaxim Ag 		OCSPerror(OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
231f5b1c8a1SJohn Marino 		goto err;
232f5b1c8a1SJohn Marino 	}
233f5b1c8a1SJohn Marino 
234f5b1c8a1SJohn Marino 	if (!(flags & OCSP_NOCERTS)) {
235f5b1c8a1SJohn Marino 		if (!OCSP_basic_add1_cert(brsp, signer))
236f5b1c8a1SJohn Marino 			goto err;
237f5b1c8a1SJohn Marino 		for (i = 0; i < sk_X509_num(certs); i++) {
238f5b1c8a1SJohn Marino 			X509 *tmpcert = sk_X509_value(certs, i);
239f5b1c8a1SJohn Marino 			if (!OCSP_basic_add1_cert(brsp, tmpcert))
240f5b1c8a1SJohn Marino 				goto err;
241f5b1c8a1SJohn Marino 		}
242f5b1c8a1SJohn Marino 	}
243f5b1c8a1SJohn Marino 
244f5b1c8a1SJohn Marino 	rid = brsp->tbsResponseData->responderId;
245f5b1c8a1SJohn Marino 	if (flags & OCSP_RESPID_KEY) {
246f5b1c8a1SJohn Marino 		unsigned char md[SHA_DIGEST_LENGTH];
247f5b1c8a1SJohn Marino 
248f5b1c8a1SJohn Marino 		X509_pubkey_digest(signer, EVP_sha1(), md, NULL);
249f5b1c8a1SJohn Marino 		if (!(rid->value.byKey = ASN1_OCTET_STRING_new()))
250f5b1c8a1SJohn Marino 			goto err;
251f5b1c8a1SJohn Marino 		if (!(ASN1_OCTET_STRING_set(rid->value.byKey, md,
252f5b1c8a1SJohn Marino 		    SHA_DIGEST_LENGTH)))
253f5b1c8a1SJohn Marino 			goto err;
254f5b1c8a1SJohn Marino 		rid->type = V_OCSP_RESPID_KEY;
255f5b1c8a1SJohn Marino 	} else {
256f5b1c8a1SJohn Marino 		if (!X509_NAME_set(&rid->value.byName,
257f5b1c8a1SJohn Marino 		    X509_get_subject_name(signer)))
258f5b1c8a1SJohn Marino 			goto err;
259f5b1c8a1SJohn Marino 		rid->type = V_OCSP_RESPID_NAME;
260f5b1c8a1SJohn Marino 	}
261f5b1c8a1SJohn Marino 
262f5b1c8a1SJohn Marino 	if (!(flags & OCSP_NOTIME) &&
263f5b1c8a1SJohn Marino 	    !ASN1_GENERALIZEDTIME_set(brsp->tbsResponseData->producedAt, time(NULL)))
264f5b1c8a1SJohn Marino 		goto err;
265f5b1c8a1SJohn Marino 
266f5b1c8a1SJohn Marino 	/* Right now, I think that not doing double hashing is the right
267f5b1c8a1SJohn Marino 	   thing.	-- Richard Levitte */
268f5b1c8a1SJohn Marino 
269f5b1c8a1SJohn Marino 	if (!OCSP_BASICRESP_sign(brsp, key, dgst, 0))
270f5b1c8a1SJohn Marino 		goto err;
271f5b1c8a1SJohn Marino 
272f5b1c8a1SJohn Marino 	return 1;
273f5b1c8a1SJohn Marino 
274f5b1c8a1SJohn Marino err:
275f5b1c8a1SJohn Marino 	return 0;
276f5b1c8a1SJohn Marino }
277