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 79OCSP_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 99OCSP_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 152int 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 164int 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 178int OCSP_parse_url(const 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 284IMPLEMENT_ASN1_DUP_FUNCTION(OCSP_CERTID) 285