1109998Smarkm/* ocsp_lib.c */ 2296465Sdelphij/* 3296465Sdelphij * Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL 4296465Sdelphij * project. 5296465Sdelphij */ 6109998Smarkm 7296465Sdelphij/* 8296465Sdelphij * History: This file was transfered to Richard Levitte from CertCo by Kathy 9296465Sdelphij * Weinhold in mid-spring 2000 to be included in OpenSSL or released as a 10296465Sdelphij * patch kit. 11296465Sdelphij */ 12109998Smarkm 13109998Smarkm/* ==================================================================== 14109998Smarkm * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. 15109998Smarkm * 16109998Smarkm * Redistribution and use in source and binary forms, with or without 17109998Smarkm * modification, are permitted provided that the following conditions 18109998Smarkm * are met: 19109998Smarkm * 20109998Smarkm * 1. Redistributions of source code must retain the above copyright 21296465Sdelphij * notice, this list of conditions and the following disclaimer. 22109998Smarkm * 23109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 24109998Smarkm * notice, this list of conditions and the following disclaimer in 25109998Smarkm * the documentation and/or other materials provided with the 26109998Smarkm * distribution. 27109998Smarkm * 28109998Smarkm * 3. All advertising materials mentioning features or use of this 29109998Smarkm * software must display the following acknowledgment: 30109998Smarkm * "This product includes software developed by the OpenSSL Project 31109998Smarkm * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 32109998Smarkm * 33109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 34109998Smarkm * endorse or promote products derived from this software without 35109998Smarkm * prior written permission. For written permission, please contact 36109998Smarkm * openssl-core@openssl.org. 37109998Smarkm * 38109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 39109998Smarkm * nor may "OpenSSL" appear in their names without prior written 40109998Smarkm * permission of the OpenSSL Project. 41109998Smarkm * 42109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 43109998Smarkm * acknowledgment: 44109998Smarkm * "This product includes software developed by the OpenSSL Project 45109998Smarkm * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 46109998Smarkm * 47109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 48109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 50109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 51109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 52109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 53109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 54109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 56109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 57109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 58109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 59109998Smarkm * ==================================================================== 60109998Smarkm * 61109998Smarkm * This product includes cryptographic software written by Eric Young 62109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 63109998Smarkm * Hudson (tjh@cryptsoft.com). 64109998Smarkm * 65109998Smarkm */ 66109998Smarkm 67109998Smarkm#include <stdio.h> 68109998Smarkm#include <cryptlib.h> 69109998Smarkm#include <openssl/objects.h> 70109998Smarkm#include <openssl/rand.h> 71109998Smarkm#include <openssl/x509.h> 72109998Smarkm#include <openssl/pem.h> 73109998Smarkm#include <openssl/x509v3.h> 74109998Smarkm#include <openssl/ocsp.h> 75109998Smarkm 76109998Smarkm/* Convert a certificate and its issuer to an OCSP_CERTID */ 77109998Smarkm 78109998SmarkmOCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer) 79109998Smarkm{ 80296465Sdelphij X509_NAME *iname; 81296465Sdelphij ASN1_INTEGER *serial; 82296465Sdelphij ASN1_BIT_STRING *ikey; 83109998Smarkm#ifndef OPENSSL_NO_SHA1 84296465Sdelphij if (!dgst) 85296465Sdelphij dgst = EVP_sha1(); 86109998Smarkm#endif 87296465Sdelphij if (subject) { 88296465Sdelphij iname = X509_get_issuer_name(subject); 89296465Sdelphij serial = X509_get_serialNumber(subject); 90296465Sdelphij } else { 91296465Sdelphij iname = X509_get_subject_name(issuer); 92296465Sdelphij serial = NULL; 93296465Sdelphij } 94296465Sdelphij ikey = X509_get0_pubkey_bitstr(issuer); 95296465Sdelphij return OCSP_cert_id_new(dgst, iname, ikey, serial); 96109998Smarkm} 97109998Smarkm 98296465SdelphijOCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, 99296465Sdelphij X509_NAME *issuerName, 100296465Sdelphij ASN1_BIT_STRING *issuerKey, 101296465Sdelphij ASN1_INTEGER *serialNumber) 102296465Sdelphij{ 103296465Sdelphij int nid; 104296465Sdelphij unsigned int i; 105296465Sdelphij X509_ALGOR *alg; 106296465Sdelphij OCSP_CERTID *cid = NULL; 107296465Sdelphij unsigned char md[EVP_MAX_MD_SIZE]; 108109998Smarkm 109296465Sdelphij if (!(cid = OCSP_CERTID_new())) 110296465Sdelphij goto err; 111109998Smarkm 112296465Sdelphij alg = cid->hashAlgorithm; 113296465Sdelphij if (alg->algorithm != NULL) 114296465Sdelphij ASN1_OBJECT_free(alg->algorithm); 115296465Sdelphij if ((nid = EVP_MD_type(dgst)) == NID_undef) { 116296465Sdelphij OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_UNKNOWN_NID); 117296465Sdelphij goto err; 118296465Sdelphij } 119296465Sdelphij if (!(alg->algorithm = OBJ_nid2obj(nid))) 120296465Sdelphij goto err; 121296465Sdelphij if ((alg->parameter = ASN1_TYPE_new()) == NULL) 122296465Sdelphij goto err; 123296465Sdelphij alg->parameter->type = V_ASN1_NULL; 124109998Smarkm 125296465Sdelphij if (!X509_NAME_digest(issuerName, dgst, md, &i)) 126296465Sdelphij goto digerr; 127296465Sdelphij if (!(ASN1_OCTET_STRING_set(cid->issuerNameHash, md, i))) 128296465Sdelphij goto err; 129109998Smarkm 130296465Sdelphij /* Calculate the issuerKey hash, excluding tag and length */ 131296465Sdelphij EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, NULL); 132109998Smarkm 133296465Sdelphij if (!(ASN1_OCTET_STRING_set(cid->issuerKeyHash, md, i))) 134296465Sdelphij goto err; 135109998Smarkm 136296465Sdelphij if (serialNumber) { 137296465Sdelphij ASN1_INTEGER_free(cid->serialNumber); 138296465Sdelphij if (!(cid->serialNumber = ASN1_INTEGER_dup(serialNumber))) 139296465Sdelphij goto err; 140296465Sdelphij } 141296465Sdelphij return cid; 142296465Sdelphij digerr: 143296465Sdelphij OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_DIGEST_ERR); 144296465Sdelphij err: 145296465Sdelphij if (cid) 146296465Sdelphij OCSP_CERTID_free(cid); 147296465Sdelphij return NULL; 148296465Sdelphij} 149109998Smarkm 150109998Smarkmint OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b) 151296465Sdelphij{ 152296465Sdelphij int ret; 153296465Sdelphij ret = OBJ_cmp(a->hashAlgorithm->algorithm, b->hashAlgorithm->algorithm); 154296465Sdelphij if (ret) 155296465Sdelphij return ret; 156296465Sdelphij ret = ASN1_OCTET_STRING_cmp(a->issuerNameHash, b->issuerNameHash); 157296465Sdelphij if (ret) 158296465Sdelphij return ret; 159296465Sdelphij return ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash); 160296465Sdelphij} 161109998Smarkm 162109998Smarkmint OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b) 163296465Sdelphij{ 164296465Sdelphij int ret; 165296465Sdelphij ret = OCSP_id_issuer_cmp(a, b); 166296465Sdelphij if (ret) 167296465Sdelphij return ret; 168296465Sdelphij return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber); 169296465Sdelphij} 170109998Smarkm 171296465Sdelphij/* 172296465Sdelphij * Parse a URL and split it up into host, port and path components and 173296465Sdelphij * whether it is SSL. 174109998Smarkm */ 175109998Smarkm 176296465Sdelphijint OCSP_parse_url(char *url, char **phost, char **pport, char **ppath, 177296465Sdelphij int *pssl) 178296465Sdelphij{ 179296465Sdelphij char *p, *buf; 180109998Smarkm 181296465Sdelphij char *host, *port; 182109998Smarkm 183296465Sdelphij *phost = NULL; 184296465Sdelphij *pport = NULL; 185296465Sdelphij *ppath = NULL; 186237998Sjkim 187296465Sdelphij /* dup the buffer since we are going to mess with it */ 188296465Sdelphij buf = BUF_strdup(url); 189296465Sdelphij if (!buf) 190296465Sdelphij goto mem_err; 191109998Smarkm 192296465Sdelphij /* Check for initial colon */ 193296465Sdelphij p = strchr(buf, ':'); 194109998Smarkm 195296465Sdelphij if (!p) 196296465Sdelphij goto parse_err; 197109998Smarkm 198296465Sdelphij *(p++) = '\0'; 199109998Smarkm 200296465Sdelphij if (!strcmp(buf, "http")) { 201296465Sdelphij *pssl = 0; 202296465Sdelphij port = "80"; 203296465Sdelphij } else if (!strcmp(buf, "https")) { 204296465Sdelphij *pssl = 1; 205296465Sdelphij port = "443"; 206296465Sdelphij } else 207296465Sdelphij goto parse_err; 208109998Smarkm 209296465Sdelphij /* Check for double slash */ 210296465Sdelphij if ((p[0] != '/') || (p[1] != '/')) 211296465Sdelphij goto parse_err; 212109998Smarkm 213296465Sdelphij p += 2; 214109998Smarkm 215296465Sdelphij host = p; 216109998Smarkm 217296465Sdelphij /* Check for trailing part of path */ 218109998Smarkm 219296465Sdelphij p = strchr(p, '/'); 220109998Smarkm 221296465Sdelphij if (!p) 222296465Sdelphij *ppath = BUF_strdup("/"); 223296465Sdelphij else { 224296465Sdelphij *ppath = BUF_strdup(p); 225296465Sdelphij /* Set start of path to 0 so hostname is valid */ 226296465Sdelphij *p = '\0'; 227296465Sdelphij } 228109998Smarkm 229296465Sdelphij if (!*ppath) 230296465Sdelphij goto mem_err; 231109998Smarkm 232296465Sdelphij p = host; 233296465Sdelphij if (host[0] == '[') { 234296465Sdelphij /* ipv6 literal */ 235296465Sdelphij host++; 236296465Sdelphij p = strchr(host, ']'); 237296465Sdelphij if (!p) 238296465Sdelphij goto parse_err; 239296465Sdelphij *p = '\0'; 240296465Sdelphij p++; 241296465Sdelphij } 242279265Sdelphij 243296465Sdelphij /* Look for optional ':' for port number */ 244296465Sdelphij if ((p = strchr(p, ':'))) { 245296465Sdelphij *p = 0; 246296465Sdelphij port = p + 1; 247296465Sdelphij } else { 248296465Sdelphij /* Not found: set default port */ 249296465Sdelphij if (*pssl) 250296465Sdelphij port = "443"; 251296465Sdelphij else 252296465Sdelphij port = "80"; 253296465Sdelphij } 254109998Smarkm 255296465Sdelphij *pport = BUF_strdup(port); 256296465Sdelphij if (!*pport) 257296465Sdelphij goto mem_err; 258109998Smarkm 259296465Sdelphij *phost = BUF_strdup(host); 260109998Smarkm 261296465Sdelphij if (!*phost) 262296465Sdelphij goto mem_err; 263109998Smarkm 264296465Sdelphij OPENSSL_free(buf); 265109998Smarkm 266296465Sdelphij return 1; 267109998Smarkm 268296465Sdelphij mem_err: 269296465Sdelphij OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE); 270296465Sdelphij goto err; 271109998Smarkm 272296465Sdelphij parse_err: 273296465Sdelphij OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL); 274109998Smarkm 275296465Sdelphij err: 276296465Sdelphij if (buf) 277296465Sdelphij OPENSSL_free(buf); 278296465Sdelphij if (*ppath) 279296465Sdelphij OPENSSL_free(*ppath); 280296465Sdelphij if (*pport) 281296465Sdelphij OPENSSL_free(*pport); 282296465Sdelphij if (*phost) 283296465Sdelphij OPENSSL_free(*phost); 284296465Sdelphij return 0; 285109998Smarkm 286296465Sdelphij} 287