ocsp_lib.c revision 296465
115645Sjoerg/* ocsp_lib.c */ 221673Sjkh/* 31592Srgrimes * Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL 41592Srgrimes * project. 522208Sdavidn */ 61592Srgrimes 71592Srgrimes/* 81875Swollman * History: This file was transfered to Richard Levitte from CertCo by Kathy 91875Swollman * Weinhold in mid-spring 2000 to be included in OpenSSL or released as a 1015645Sjoerg * patch kit. 1115645Sjoerg */ 121592Srgrimes 131592Srgrimes/* ==================================================================== 1422208Sdavidn * 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 76/* Convert a certificate and its issuer to an OCSP_CERTID */ 77 78OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer) 79{ 80 X509_NAME *iname; 81 ASN1_INTEGER *serial; 82 ASN1_BIT_STRING *ikey; 83#ifndef OPENSSL_NO_SHA1 84 if (!dgst) 85 dgst = EVP_sha1(); 86#endif 87 if (subject) { 88 iname = X509_get_issuer_name(subject); 89 serial = X509_get_serialNumber(subject); 90 } else { 91 iname = X509_get_subject_name(issuer); 92 serial = NULL; 93 } 94 ikey = X509_get0_pubkey_bitstr(issuer); 95 return OCSP_cert_id_new(dgst, iname, ikey, serial); 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())) 110 goto err; 111 112 alg = cid->hashAlgorithm; 113 if (alg->algorithm != NULL) 114 ASN1_OBJECT_free(alg->algorithm); 115 if ((nid = EVP_MD_type(dgst)) == NID_undef) { 116 OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_UNKNOWN_NID); 117 goto err; 118 } 119 if (!(alg->algorithm = OBJ_nid2obj(nid))) 120 goto err; 121 if ((alg->parameter = ASN1_TYPE_new()) == NULL) 122 goto err; 123 alg->parameter->type = V_ASN1_NULL; 124 125 if (!X509_NAME_digest(issuerName, dgst, md, &i)) 126 goto digerr; 127 if (!(ASN1_OCTET_STRING_set(cid->issuerNameHash, md, i))) 128 goto err; 129 130 /* Calculate the issuerKey hash, excluding tag and length */ 131 EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, NULL); 132 133 if (!(ASN1_OCTET_STRING_set(cid->issuerKeyHash, md, i))) 134 goto err; 135 136 if (serialNumber) { 137 ASN1_INTEGER_free(cid->serialNumber); 138 if (!(cid->serialNumber = ASN1_INTEGER_dup(serialNumber))) 139 goto err; 140 } 141 return cid; 142 digerr: 143 OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_DIGEST_ERR); 144 err: 145 if (cid) 146 OCSP_CERTID_free(cid); 147 return NULL; 148} 149 150int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b) 151{ 152 int ret; 153 ret = OBJ_cmp(a->hashAlgorithm->algorithm, b->hashAlgorithm->algorithm); 154 if (ret) 155 return ret; 156 ret = ASN1_OCTET_STRING_cmp(a->issuerNameHash, b->issuerNameHash); 157 if (ret) 158 return ret; 159 return ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash); 160} 161 162int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b) 163{ 164 int ret; 165 ret = OCSP_id_issuer_cmp(a, b); 166 if (ret) 167 return ret; 168 return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber); 169} 170 171/* 172 * Parse a URL and split it up into host, port and path components and 173 * whether it is SSL. 174 */ 175 176int OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, 177 int *pssl) 178{ 179 char *p, *buf; 180 181 char *host, *port; 182 183 *phost = NULL; 184 *pport = NULL; 185 *ppath = NULL; 186 187 /* dup the buffer since we are going to mess with it */ 188 buf = BUF_strdup(url); 189 if (!buf) 190 goto mem_err; 191 192 /* Check for initial colon */ 193 p = strchr(buf, ':'); 194 195 if (!p) 196 goto parse_err; 197 198 *(p++) = '\0'; 199 200 if (!strcmp(buf, "http")) { 201 *pssl = 0; 202 port = "80"; 203 } else if (!strcmp(buf, "https")) { 204 *pssl = 1; 205 port = "443"; 206 } else 207 goto parse_err; 208 209 /* Check for double slash */ 210 if ((p[0] != '/') || (p[1] != '/')) 211 goto parse_err; 212 213 p += 2; 214 215 host = p; 216 217 /* Check for trailing part of path */ 218 219 p = strchr(p, '/'); 220 221 if (!p) 222 *ppath = BUF_strdup("/"); 223 else { 224 *ppath = BUF_strdup(p); 225 /* Set start of path to 0 so hostname is valid */ 226 *p = '\0'; 227 } 228 229 if (!*ppath) 230 goto mem_err; 231 232 p = host; 233 if (host[0] == '[') { 234 /* ipv6 literal */ 235 host++; 236 p = strchr(host, ']'); 237 if (!p) 238 goto parse_err; 239 *p = '\0'; 240 p++; 241 } 242 243 /* Look for optional ':' for port number */ 244 if ((p = strchr(p, ':'))) { 245 *p = 0; 246 port = p + 1; 247 } else { 248 /* Not found: set default port */ 249 if (*pssl) 250 port = "443"; 251 else 252 port = "80"; 253 } 254 255 *pport = BUF_strdup(port); 256 if (!*pport) 257 goto mem_err; 258 259 *phost = BUF_strdup(host); 260 261 if (!*phost) 262 goto mem_err; 263 264 OPENSSL_free(buf); 265 266 return 1; 267 268 mem_err: 269 OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE); 270 goto err; 271 272 parse_err: 273 OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL); 274 275 err: 276 if (buf) 277 OPENSSL_free(buf); 278 if (*ppath) 279 OPENSSL_free(*ppath); 280 if (*pport) 281 OPENSSL_free(*pport); 282 if (*phost) 283 OPENSSL_free(*phost); 284 return 0; 285 286} 287