ocsp_lib.c revision 1.20
1178173Simp/* $OpenBSD: ocsp_lib.c,v 1.20 2017/01/29 17:49:23 beck Exp $ */
2178173Simp/* Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL
3178173Simp * project. */
4178173Simp
5178173Simp/* History:
6178173Simp   This file was transfered to Richard Levitte from CertCo by Kathy
7178173Simp   Weinhold in mid-spring 2000 to be included in OpenSSL or released
8178173Simp   as a patch kit. */
9178173Simp
10178173Simp/* ====================================================================
11178173Simp * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
12178173Simp *
13178173Simp * Redistribution and use in source and binary forms, with or without
14178173Simp * modification, are permitted provided that the following conditions
15178173Simp * are met:
16178173Simp *
17178173Simp * 1. Redistributions of source code must retain the above copyright
18178173Simp *    notice, this list of conditions and the following disclaimer.
19178173Simp *
20178173Simp * 2. Redistributions in binary form must reproduce the above copyright
21178173Simp *    notice, this list of conditions and the following disclaimer in
22178173Simp *    the documentation and/or other materials provided with the
23178173Simp *    distribution.
24178173Simp *
25178173Simp * 3. All advertising materials mentioning features or use of this
26178173Simp *    software must display the following acknowledgment:
27178173Simp *    "This product includes software developed by the OpenSSL Project
28178173Simp *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
29178173Simp *
30178173Simp * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
31178173Simp *    endorse or promote products derived from this software without
32178173Simp *    prior written permission. For written permission, please contact
33178173Simp *    openssl-core@openssl.org.
34178173Simp *
35178173Simp * 5. Products derived from this software may not be called "OpenSSL"
36178173Simp *    nor may "OpenSSL" appear in their names without prior written
37178173Simp *    permission of the OpenSSL Project.
38178173Simp *
39178173Simp * 6. Redistributions of any form whatsoever must retain the following
40178173Simp *    acknowledgment:
41178173Simp *    "This product includes software developed by the OpenSSL Project
42178173Simp *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
43178173Simp *
44178173Simp * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
45178173Simp * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46178173Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47178173Simp * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
48178173Simp * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49178173Simp * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50178173Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51178173Simp * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52178173Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53178173Simp * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54178173Simp * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55178173Simp * OF THE POSSIBILITY OF SUCH DAMAGE.
56178173Simp * ====================================================================
57178173Simp *
58178173Simp * This product includes cryptographic software written by Eric Young
59178173Simp * (eay@cryptsoft.com).  This product includes software written by Tim
60178173Simp * Hudson (tjh@cryptsoft.com).
61178173Simp *
62178173Simp */
63178173Simp
64178173Simp#include <stdio.h>
65178173Simp#include <string.h>
66178173Simp
67178173Simp#include <openssl/opensslconf.h>
68178173Simp
69178173Simp#include <openssl/asn1t.h>
70178173Simp#include <openssl/err.h>
71178173Simp#include <openssl/objects.h>
72178173Simp#include <openssl/ocsp.h>
73178173Simp#include <openssl/pem.h>
74178173Simp#include <openssl/x509.h>
75202037Simp#include <openssl/x509v3.h>
76202037Simp
77202037Simp/* Convert a certificate and its issuer to an OCSP_CERTID */
78202037Simp
79202037SimpOCSP_CERTID *
80202037SimpOCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer)
81178173Simp{
82178173Simp	X509_NAME *iname;
83178173Simp	ASN1_INTEGER *serial;
84178173Simp	ASN1_BIT_STRING *ikey;
85178173Simp
86178173Simp#ifndef OPENSSL_NO_SHA1
87178173Simp	if (!dgst)
88178173Simp		dgst = EVP_sha1();
89178173Simp#endif
90178173Simp	if (subject) {
91178173Simp		iname = X509_get_issuer_name(subject);
92178173Simp		serial = X509_get_serialNumber(subject);
93178173Simp	} else {
94178173Simp		iname = X509_get_subject_name(issuer);
95178173Simp		serial = NULL;
96202954Sgonzo	}
97178173Simp	ikey = X509_get0_pubkey_bitstr(issuer);
98178173Simp	return OCSP_cert_id_new(dgst, iname, ikey, serial);
99216318Sgonzo}
100216320Sgonzo
101216318SgonzoOCSP_CERTID *
102178173SimpOCSP_cert_id_new(const EVP_MD *dgst, X509_NAME *issuerName,
103178173Simp    ASN1_BIT_STRING* issuerKey, ASN1_INTEGER *serialNumber)
104178173Simp{
105178173Simp	int nid;
106178173Simp	unsigned int i;
107178173Simp	X509_ALGOR *alg;
108178173Simp	OCSP_CERTID *cid = NULL;
109178173Simp	unsigned char md[EVP_MAX_MD_SIZE];
110178173Simp
111202849Simp	if (!(cid = OCSP_CERTID_new()))
112202849Simp		goto err;
113202849Simp
114178173Simp	alg = cid->hashAlgorithm;
115178173Simp	if (alg->algorithm != NULL)
116178173Simp		ASN1_OBJECT_free(alg->algorithm);
117178173Simp	if ((nid = EVP_MD_type(dgst)) == NID_undef) {
118178173Simp		OCSPerror(OCSP_R_UNKNOWN_NID);
119178173Simp		goto err;
120178173Simp	}
121178173Simp	if (!(alg->algorithm = OBJ_nid2obj(nid)))
122178173Simp		goto err;
123178173Simp	if ((alg->parameter = ASN1_TYPE_new()) == NULL)
124178173Simp		goto err;
125178173Simp	alg->parameter->type = V_ASN1_NULL;
126178173Simp
127178173Simp	if (!X509_NAME_digest(issuerName, dgst, md, &i))
128178173Simp		goto digerr;
129178173Simp	if (!(ASN1_OCTET_STRING_set(cid->issuerNameHash, md, i)))
130178173Simp		goto err;
131178173Simp
132178173Simp	/* Calculate the issuerKey hash, excluding tag and length */
133202954Sgonzo	if (!EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, NULL))
134178173Simp		goto err;
135178173Simp
136202954Sgonzo	if (!(ASN1_OCTET_STRING_set(cid->issuerKeyHash, md, i)))
137202954Sgonzo		goto err;
138202037Simp
139202037Simp	if (serialNumber) {
140202037Simp		ASN1_INTEGER_free(cid->serialNumber);
141178173Simp		if (!(cid->serialNumber = ASN1_INTEGER_dup(serialNumber)))
142178173Simp			goto err;
143178173Simp	}
144178173Simp	return cid;
145
146digerr:
147	OCSPerror(OCSP_R_DIGEST_ERR);
148err:
149	if (cid)
150		OCSP_CERTID_free(cid);
151	return NULL;
152}
153
154int
155OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
156{
157	int ret;
158
159	ret = OBJ_cmp(a->hashAlgorithm->algorithm, b->hashAlgorithm->algorithm);
160	if (ret)
161		return ret;
162	ret = ASN1_OCTET_STRING_cmp(a->issuerNameHash, b->issuerNameHash);
163	if (ret)
164		return ret;
165	return ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash);
166}
167
168int
169OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
170{
171	int ret;
172
173	ret = OCSP_id_issuer_cmp(a, b);
174	if (ret)
175		return ret;
176	return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber);
177}
178
179/* Parse a URL and split it up into host, port and path components and whether
180 * it is SSL.
181 */
182int
183OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pssl)
184{
185	char *host, *path, *port, *tmp;
186
187	*phost = *pport = *ppath = NULL;
188	*pssl = 0;
189
190	if (strncmp(url, "https://", 8) == 0) {
191		*pssl = 1;
192		host = strdup(url + 8);
193	} else if (strncmp(url, "http://", 7) == 0)
194		host = strdup(url + 7);
195	else {
196		OCSPerror(OCSP_R_ERROR_PARSING_URL);
197		return 0;
198	}
199	if (host == NULL) {
200		OCSPerror(ERR_R_MALLOC_FAILURE);
201		return 0;
202	}
203
204	if ((tmp = strchr(host, '/')) != NULL) {
205		path = strdup(tmp);
206		*tmp = '\0';
207	} else
208		path = strdup("/");
209
210	if ((tmp = strchr(host, ':')) != NULL ) {
211		port = strdup(tmp + 1);
212		*tmp = '\0';
213	} else {
214		if (*pssl)
215			port = strdup("443");
216		else
217			port = strdup("80");
218	}
219
220	if (path == NULL || port == NULL) {
221		free(host);
222		free(path);
223		free(port);
224		OCSPerror(ERR_R_MALLOC_FAILURE);
225		return 0;
226	}
227
228	*phost = host;
229	*ppath = path;
230	*pport = port;
231	return 1;
232}
233
234OCSP_CERTID *
235OCSP_CERTID_dup(OCSP_CERTID *x)
236{
237	return ASN1_item_dup(&OCSP_CERTID_it, x);
238}
239