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