ocsp_lib.c revision 279265
1/* ocsp_lib.c */
2/* Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL
3 * project. */
4
5/* History:
6   This file was transfered to Richard Levitte from CertCo by Kathy
7   Weinhold in mid-spring 2000 to be included in OpenSSL or released
8   as a patch kit. */
9
10/* ====================================================================
11 * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in
22 *    the documentation and/or other materials provided with the
23 *    distribution.
24 *
25 * 3. All advertising materials mentioning features or use of this
26 *    software must display the following acknowledgment:
27 *    "This product includes software developed by the OpenSSL Project
28 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
29 *
30 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
31 *    endorse or promote products derived from this software without
32 *    prior written permission. For written permission, please contact
33 *    openssl-core@openssl.org.
34 *
35 * 5. Products derived from this software may not be called "OpenSSL"
36 *    nor may "OpenSSL" appear in their names without prior written
37 *    permission of the OpenSSL Project.
38 *
39 * 6. Redistributions of any form whatsoever must retain the following
40 *    acknowledgment:
41 *    "This product includes software developed by the OpenSSL Project
42 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
45 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
48 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55 * OF THE POSSIBILITY OF SUCH DAMAGE.
56 * ====================================================================
57 *
58 * This product includes cryptographic software written by Eric Young
59 * (eay@cryptsoft.com).  This product includes software written by Tim
60 * Hudson (tjh@cryptsoft.com).
61 *
62 */
63
64#include <stdio.h>
65#include <cryptlib.h>
66#include <openssl/objects.h>
67#include <openssl/rand.h>
68#include <openssl/x509.h>
69#include <openssl/pem.h>
70#include <openssl/x509v3.h>
71#include <openssl/ocsp.h>
72
73/* Convert a certificate and its issuer to an OCSP_CERTID */
74
75OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer)
76{
77	X509_NAME *iname;
78	ASN1_INTEGER *serial;
79	ASN1_BIT_STRING *ikey;
80#ifndef OPENSSL_NO_SHA1
81	if(!dgst) dgst = EVP_sha1();
82#endif
83	if (subject)
84		{
85		iname = X509_get_issuer_name(subject);
86		serial = X509_get_serialNumber(subject);
87		}
88	else
89		{
90		iname = X509_get_subject_name(issuer);
91		serial = NULL;
92		}
93	ikey = X509_get0_pubkey_bitstr(issuer);
94	return OCSP_cert_id_new(dgst, iname, ikey, serial);
95}
96
97
98OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
99			      X509_NAME *issuerName,
100			      ASN1_BIT_STRING* issuerKey,
101			      ASN1_INTEGER *serialNumber)
102        {
103	int nid;
104        unsigned int i;
105	X509_ALGOR *alg;
106	OCSP_CERTID *cid = NULL;
107	unsigned char md[EVP_MAX_MD_SIZE];
108
109	if (!(cid = OCSP_CERTID_new())) goto err;
110
111	alg = cid->hashAlgorithm;
112	if (alg->algorithm != NULL) ASN1_OBJECT_free(alg->algorithm);
113	if ((nid = EVP_MD_type(dgst)) == NID_undef)
114	        {
115		OCSPerr(OCSP_F_OCSP_CERT_ID_NEW,OCSP_R_UNKNOWN_NID);
116		goto err;
117		}
118	if (!(alg->algorithm=OBJ_nid2obj(nid))) goto err;
119	if ((alg->parameter=ASN1_TYPE_new()) == NULL) goto err;
120	alg->parameter->type=V_ASN1_NULL;
121
122	if (!X509_NAME_digest(issuerName, dgst, md, &i)) goto digerr;
123	if (!(ASN1_OCTET_STRING_set(cid->issuerNameHash, md, i))) goto err;
124
125	/* Calculate the issuerKey hash, excluding tag and length */
126	EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, NULL);
127
128	if (!(ASN1_OCTET_STRING_set(cid->issuerKeyHash, md, i))) goto err;
129
130	if (serialNumber)
131		{
132		ASN1_INTEGER_free(cid->serialNumber);
133		if (!(cid->serialNumber = ASN1_INTEGER_dup(serialNumber))) goto err;
134		}
135	return cid;
136digerr:
137	OCSPerr(OCSP_F_OCSP_CERT_ID_NEW,OCSP_R_DIGEST_ERR);
138err:
139	if (cid) OCSP_CERTID_free(cid);
140	return NULL;
141	}
142
143int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
144	{
145	int ret;
146	ret = OBJ_cmp(a->hashAlgorithm->algorithm, b->hashAlgorithm->algorithm);
147	if (ret) return ret;
148	ret = ASN1_OCTET_STRING_cmp(a->issuerNameHash, b->issuerNameHash);
149	if (ret) return ret;
150	return ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash);
151	}
152
153int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
154	{
155	int ret;
156	ret = OCSP_id_issuer_cmp(a, b);
157	if (ret) return ret;
158	return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber);
159	}
160
161
162/* Parse a URL and split it up into host, port and path components and whether
163 * it is SSL.
164 */
165
166int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, int *pssl)
167	{
168	char *p, *buf;
169
170	char *host, *port;
171
172	*phost = NULL;
173	*pport = NULL;
174	*ppath = NULL;
175
176	/* dup the buffer since we are going to mess with it */
177	buf = BUF_strdup(url);
178	if (!buf) goto mem_err;
179
180	/* Check for initial colon */
181	p = strchr(buf, ':');
182
183	if (!p) goto parse_err;
184
185	*(p++) = '\0';
186
187	if (!strcmp(buf, "http"))
188		{
189		*pssl = 0;
190		port = "80";
191		}
192	else if (!strcmp(buf, "https"))
193		{
194		*pssl = 1;
195		port = "443";
196		}
197	else
198		goto parse_err;
199
200	/* Check for double slash */
201	if ((p[0] != '/') || (p[1] != '/'))
202		goto parse_err;
203
204	p += 2;
205
206	host = p;
207
208	/* Check for trailing part of path */
209
210	p = strchr(p, '/');
211
212	if (!p)
213		*ppath = BUF_strdup("/");
214	else
215		{
216		*ppath = BUF_strdup(p);
217		/* Set start of path to 0 so hostname is valid */
218		*p = '\0';
219		}
220
221	if (!*ppath) goto mem_err;
222
223	p = host;
224	if(host[0] == '[')
225		{
226		/* ipv6 literal */
227		host++;
228		p = strchr(host, ']');
229		if(!p) goto parse_err;
230		*p = '\0';
231		p++;
232		}
233
234	/* Look for optional ':' for port number */
235	if ((p = strchr(p, ':')))
236		{
237		*p = 0;
238		port = p + 1;
239		}
240	else
241		{
242		/* Not found: set default port */
243		if (*pssl) port = "443";
244		else port = "80";
245		}
246
247	*pport = BUF_strdup(port);
248	if (!*pport) goto mem_err;
249
250	*phost = BUF_strdup(host);
251
252	if (!*phost) goto mem_err;
253
254	OPENSSL_free(buf);
255
256	return 1;
257
258	mem_err:
259	OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE);
260	goto err;
261
262	parse_err:
263	OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL);
264
265
266	err:
267	if (buf) OPENSSL_free(buf);
268	if (*ppath) OPENSSL_free(*ppath);
269	if (*pport) OPENSSL_free(*pport);
270	if (*phost) OPENSSL_free(*phost);
271	return 0;
272
273	}
274