Home | History | Annotate | Line # | Download | only in ocsp
      1 /*
      2  * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the OpenSSL license (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <stdio.h>
     11 #include "internal/cryptlib.h"
     12 #include <openssl/objects.h>
     13 #include <openssl/x509.h>
     14 #include <openssl/pem.h>
     15 #include <openssl/x509v3.h>
     16 #include <openssl/ocsp.h>
     17 #include "ocsp_local.h"
     18 #include <openssl/asn1t.h>
     19 
     20 /* Convert a certificate and its issuer to an OCSP_CERTID */
     21 
     22 OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject,
     23                              const X509 *issuer)
     24 {
     25     X509_NAME *iname;
     26     const ASN1_INTEGER *serial;
     27     ASN1_BIT_STRING *ikey;
     28     if (!dgst)
     29         dgst = EVP_sha1();
     30     if (subject) {
     31         iname = X509_get_issuer_name(subject);
     32         serial = X509_get0_serialNumber(subject);
     33     } else {
     34         iname = X509_get_subject_name(issuer);
     35         serial = NULL;
     36     }
     37     ikey = X509_get0_pubkey_bitstr(issuer);
     38     return OCSP_cert_id_new(dgst, iname, ikey, serial);
     39 }
     40 
     41 OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
     42                               const X509_NAME *issuerName,
     43                               const ASN1_BIT_STRING *issuerKey,
     44                               const ASN1_INTEGER *serialNumber)
     45 {
     46     int nid;
     47     unsigned int i;
     48     X509_ALGOR *alg;
     49     OCSP_CERTID *cid = NULL;
     50     unsigned char md[EVP_MAX_MD_SIZE];
     51 
     52     if ((cid = OCSP_CERTID_new()) == NULL)
     53         goto err;
     54 
     55     alg = &cid->hashAlgorithm;
     56     ASN1_OBJECT_free(alg->algorithm);
     57     if ((nid = EVP_MD_type(dgst)) == NID_undef) {
     58         OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_UNKNOWN_NID);
     59         goto err;
     60     }
     61     if ((alg->algorithm = OBJ_nid2obj(nid)) == NULL)
     62         goto err;
     63     if ((alg->parameter = ASN1_TYPE_new()) == NULL)
     64         goto err;
     65     alg->parameter->type = V_ASN1_NULL;
     66 
     67     if (!X509_NAME_digest(issuerName, dgst, md, &i))
     68         goto digerr;
     69     if (!(ASN1_OCTET_STRING_set(&cid->issuerNameHash, md, i)))
     70         goto err;
     71 
     72     /* Calculate the issuerKey hash, excluding tag and length */
     73     if (!EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, NULL))
     74         goto err;
     75 
     76     if (!(ASN1_OCTET_STRING_set(&cid->issuerKeyHash, md, i)))
     77         goto err;
     78 
     79     if (serialNumber) {
     80         if (ASN1_STRING_copy(&cid->serialNumber, serialNumber) == 0)
     81             goto err;
     82     }
     83     return cid;
     84  digerr:
     85     OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_DIGEST_ERR);
     86  err:
     87     OCSP_CERTID_free(cid);
     88     return NULL;
     89 }
     90 
     91 int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
     92 {
     93     int ret;
     94     ret = OBJ_cmp(a->hashAlgorithm.algorithm, b->hashAlgorithm.algorithm);
     95     if (ret)
     96         return ret;
     97     ret = ASN1_OCTET_STRING_cmp(&a->issuerNameHash, &b->issuerNameHash);
     98     if (ret)
     99         return ret;
    100     return ASN1_OCTET_STRING_cmp(&a->issuerKeyHash, &b->issuerKeyHash);
    101 }
    102 
    103 int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
    104 {
    105     int ret;
    106     ret = OCSP_id_issuer_cmp(a, b);
    107     if (ret)
    108         return ret;
    109     return ASN1_INTEGER_cmp(&a->serialNumber, &b->serialNumber);
    110 }
    111 
    112 /*
    113  * Parse a URL and split it up into host, port and path components and
    114  * whether it is SSL.
    115  */
    116 
    117 int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
    118                    int *pssl)
    119 {
    120     char *p, *buf;
    121 
    122     char *host, *port;
    123 
    124     *phost = NULL;
    125     *pport = NULL;
    126     *ppath = NULL;
    127 
    128     /* dup the buffer since we are going to mess with it */
    129     buf = OPENSSL_strdup(url);
    130     if (!buf)
    131         goto mem_err;
    132 
    133     /* Check for initial colon */
    134     p = strchr(buf, ':');
    135 
    136     if (!p)
    137         goto parse_err;
    138 
    139     *(p++) = '\0';
    140 
    141     if (strcmp(buf, "http") == 0) {
    142         *pssl = 0;
    143         port = "80";
    144     } else if (strcmp(buf, "https") == 0) {
    145         *pssl = 1;
    146         port = "443";
    147     } else
    148         goto parse_err;
    149 
    150     /* Check for double slash */
    151     if ((p[0] != '/') || (p[1] != '/'))
    152         goto parse_err;
    153 
    154     p += 2;
    155 
    156     host = p;
    157 
    158     /* Check for trailing part of path */
    159 
    160     p = strchr(p, '/');
    161 
    162     if (!p)
    163         *ppath = OPENSSL_strdup("/");
    164     else {
    165         *ppath = OPENSSL_strdup(p);
    166         /* Set start of path to 0 so hostname is valid */
    167         *p = '\0';
    168     }
    169 
    170     if (!*ppath)
    171         goto mem_err;
    172 
    173     p = host;
    174     if (host[0] == '[') {
    175         /* ipv6 literal */
    176         host++;
    177         p = strchr(host, ']');
    178         if (!p)
    179             goto parse_err;
    180         *p = '\0';
    181         p++;
    182     }
    183 
    184     /* Look for optional ':' for port number */
    185     if ((p = strchr(p, ':'))) {
    186         *p = 0;
    187         port = p + 1;
    188     }
    189 
    190     *pport = OPENSSL_strdup(port);
    191     if (!*pport)
    192         goto mem_err;
    193 
    194     *phost = OPENSSL_strdup(host);
    195 
    196     if (!*phost)
    197         goto mem_err;
    198 
    199     OPENSSL_free(buf);
    200 
    201     return 1;
    202 
    203  mem_err:
    204     OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE);
    205     goto err;
    206 
    207  parse_err:
    208     OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL);
    209 
    210  err:
    211     OPENSSL_free(buf);
    212     OPENSSL_free(*ppath);
    213     *ppath = NULL;
    214     OPENSSL_free(*pport);
    215     *pport = NULL;
    216     OPENSSL_free(*phost);
    217     *phost = NULL;
    218     return 0;
    219 
    220 }
    221 
    222 IMPLEMENT_ASN1_DUP_FUNCTION(OCSP_CERTID)
    223