Unverified Commit d2671758 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

x509asn1: make several functions static

and remove the private SIZE_T_MAX define and use the generic one.

Closes #2902
parent 362e9cc8
Loading
Loading
Loading
Loading
+59 −63
Original line number Diff line number Diff line
@@ -40,10 +40,6 @@
#include "curl_memory.h"
#include "memdebug.h"

/* For overflow checks. */
#define CURL_SIZE_T_MAX         ((size_t)-1)


/* ASN.1 OIDs. */
static const char       cnOID[] = "2.5.4.3";    /* Common name. */
static const char       sanOID[] = "2.5.29.17"; /* Subject alternative name. */
@@ -108,7 +104,7 @@ static const curl_OID OIDtable[] = {
 */


const char *Curl_getASN1Element(curl_asn1Element *elem,
static const char *getASN1Element(curl_asn1Element *elem,
                                  const char *beg, const char *end)
{
  unsigned char b;
@@ -146,7 +142,7 @@ const char *Curl_getASN1Element(curl_asn1Element *elem,
      return (const char *) NULL;
    elem->beg = beg;
    while(beg < end && *beg) {
      beg = Curl_getASN1Element(&lelem, beg, end);
      beg = getASN1Element(&lelem, beg, end);
      if(!beg)
        return (const char *) NULL;
    }
@@ -206,7 +202,7 @@ static const char *octet2str(const char *beg, const char *end)
  /* Convert an ASN.1 octet string to a printable string.
     Return the dynamically allocated string, or NULL if an error occurs. */

  if(n <= (CURL_SIZE_T_MAX - 1) / 3) {
  if(n <= (SIZE_T_MAX - 1) / 3) {
    buf = malloc(3 * n + 1);
    if(buf)
      for(n = 0; beg < end; n += 3)
@@ -287,7 +283,7 @@ utf8asn1str(char **to, int type, const char *from, const char *end)

  if(inlength % size)
    return -1;  /* Length inconsistent with character size. */
  if(inlength / size > (CURL_SIZE_T_MAX - 1) / 4)
  if(inlength / size > (SIZE_T_MAX - 1) / 4)
    return -1;  /* Too big. */
  buf = malloc(4 * (inlength / size) + 1);
  if(!buf)
@@ -546,7 +542,7 @@ static const char *UTime2str(const char *beg, const char *end)
                       tzl, tzp);
}

const char *Curl_ASN1tostr(curl_asn1Element *elem, int type)
static const char *ASN1tostr(curl_asn1Element *elem, int type)
{
  /* Convert an ASN.1 element to a printable string.
     Return the dynamically allocated string, or NULL if an error occurs. */
@@ -605,12 +601,12 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
     Return the total string length, even if larger than `n'. */

  for(p1 = dn->beg; p1 < dn->end;) {
    p1 = Curl_getASN1Element(&rdn, p1, dn->end);
    p1 = getASN1Element(&rdn, p1, dn->end);
    for(p2 = rdn.beg; p2 < rdn.end;) {
      p2 = Curl_getASN1Element(&atv, p2, rdn.end);
      p3 = Curl_getASN1Element(&oid, atv.beg, atv.end);
      Curl_getASN1Element(&value, p3, atv.end);
      str = Curl_ASN1tostr(&oid, 0);
      p2 = getASN1Element(&atv, p2, rdn.end);
      p3 = getASN1Element(&oid, atv.beg, atv.end);
      getASN1Element(&value, p3, atv.end);
      str = ASN1tostr(&oid, 0);
      if(!str)
        return -1;

@@ -640,7 +636,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
      l++;

      /* Generate value. */
      str = Curl_ASN1tostr(&value, 0);
      str = ASN1tostr(&value, 0);
      if(!str)
        return -1;
      for(p3 = str; *p3; p3++) {
@@ -655,7 +651,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
  return l;
}

const char *Curl_DNtostr(curl_asn1Element *dn)
static const char *DNtostr(curl_asn1Element *dn)
{
  char *buf = (char *) NULL;
  ssize_t n = encodeDN(buf, 0, dn);
@@ -694,17 +690,17 @@ int Curl_parseX509(curl_X509certificate *cert,
  cert->certificate.end = end;

  /* Get the sequence content. */
  if(!Curl_getASN1Element(&elem, beg, end))
  if(!getASN1Element(&elem, beg, end))
    return -1;  /* Invalid bounds/size. */
  beg = elem.beg;
  end = elem.end;

  /* Get tbsCertificate. */
  beg = Curl_getASN1Element(&tbsCertificate, beg, end);
  beg = getASN1Element(&tbsCertificate, beg, end);
  /* Skip the signatureAlgorithm. */
  beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
  beg = getASN1Element(&cert->signatureAlgorithm, beg, end);
  /* Get the signatureValue. */
  Curl_getASN1Element(&cert->signature, beg, end);
  getASN1Element(&cert->signature, beg, end);

  /* Parse TBSCertificate. */
  beg = tbsCertificate.beg;
@@ -713,28 +709,28 @@ int Curl_parseX509(curl_X509certificate *cert,
  cert->version.header = NULL;
  cert->version.beg = &defaultVersion;
  cert->version.end = &defaultVersion + sizeof(defaultVersion);
  beg = Curl_getASN1Element(&elem, beg, end);
  beg = getASN1Element(&elem, beg, end);
  if(elem.tag == 0) {
    Curl_getASN1Element(&cert->version, elem.beg, elem.end);
    beg = Curl_getASN1Element(&elem, beg, end);
    getASN1Element(&cert->version, elem.beg, elem.end);
    beg = getASN1Element(&elem, beg, end);
  }
  cert->serialNumber = elem;
  /* Get signature algorithm. */
  beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
  beg = getASN1Element(&cert->signatureAlgorithm, beg, end);
  /* Get issuer. */
  beg = Curl_getASN1Element(&cert->issuer, beg, end);
  beg = getASN1Element(&cert->issuer, beg, end);
  /* Get notBefore and notAfter. */
  beg = Curl_getASN1Element(&elem, beg, end);
  ccp = Curl_getASN1Element(&cert->notBefore, elem.beg, elem.end);
  Curl_getASN1Element(&cert->notAfter, ccp, elem.end);
  beg = getASN1Element(&elem, beg, end);
  ccp = getASN1Element(&cert->notBefore, elem.beg, elem.end);
  getASN1Element(&cert->notAfter, ccp, elem.end);
  /* Get subject. */
  beg = Curl_getASN1Element(&cert->subject, beg, end);
  beg = getASN1Element(&cert->subject, beg, end);
  /* Get subjectPublicKeyAlgorithm and subjectPublicKey. */
  beg = Curl_getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
  ccp = Curl_getASN1Element(&cert->subjectPublicKeyAlgorithm,
  beg = getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
  ccp = getASN1Element(&cert->subjectPublicKeyAlgorithm,
                            cert->subjectPublicKeyInfo.beg,
                            cert->subjectPublicKeyInfo.end);
  Curl_getASN1Element(&cert->subjectPublicKey, ccp,
  getASN1Element(&cert->subjectPublicKey, ccp,
                      cert->subjectPublicKeyInfo.end);
  /* Get optional issuerUiqueID, subjectUniqueID and extensions. */
  cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0;
@@ -745,19 +741,19 @@ int Curl_parseX509(curl_X509certificate *cert,
  cert->extensions.header = NULL;
  cert->extensions.beg = cert->extensions.end = "";
  if(beg < end)
    beg = Curl_getASN1Element(&elem, beg, end);
    beg = getASN1Element(&elem, beg, end);
  if(elem.tag == 1) {
    cert->issuerUniqueID = elem;
    if(beg < end)
      beg = Curl_getASN1Element(&elem, beg, end);
      beg = getASN1Element(&elem, beg, end);
  }
  if(elem.tag == 2) {
    cert->subjectUniqueID = elem;
    if(beg < end)
      beg = Curl_getASN1Element(&elem, beg, end);
      beg = getASN1Element(&elem, beg, end);
  }
  if(elem.tag == 3)
    Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
    getASN1Element(&cert->extensions, elem.beg, elem.end);
  return 0;
}

@@ -785,12 +781,12 @@ static const char *dumpAlgo(curl_asn1Element *param,

  /* Get algorithm parameters and return algorithm name. */

  beg = Curl_getASN1Element(&oid, beg, end);
  beg = getASN1Element(&oid, beg, end);
  param->header = NULL;
  param->tag = 0;
  param->beg = param->end = end;
  if(beg < end)
    Curl_getASN1Element(param, beg, end);
    getASN1Element(param, beg, end);
  return OID2str(oid.beg, oid.end, TRUE);
}

@@ -801,7 +797,7 @@ static void do_pubkey_field(struct Curl_easy *data, int certnum,

  /* Generate a certificate information record for the public key. */

  output = Curl_ASN1tostr(elem, 0);
  output = ASN1tostr(elem, 0);
  if(output) {
    if(data->set.ssl.certinfo)
      Curl_ssl_push_certinfo(data, certnum, label, output);
@@ -825,10 +821,10 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
  /* Generate all information records for the public key. */

  /* Get the public key (single element). */
  Curl_getASN1Element(&pk, pubkey->beg + 1, pubkey->end);
  getASN1Element(&pk, pubkey->beg + 1, pubkey->end);

  if(strcasecompare(algo, "rsaEncryption")) {
    p = Curl_getASN1Element(&elem, pk.beg, pk.end);
    p = getASN1Element(&elem, pk.beg, pk.end);
    /* Compute key length. */
    for(q = elem.beg; !*q && q < elem.end; q++)
      ;
@@ -849,22 +845,22 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
    }
    /* Generate coefficients. */
    do_pubkey_field(data, certnum, "rsa(n)", &elem);
    Curl_getASN1Element(&elem, p, pk.end);
    getASN1Element(&elem, p, pk.end);
    do_pubkey_field(data, certnum, "rsa(e)", &elem);
  }
  else if(strcasecompare(algo, "dsa")) {
    p = Curl_getASN1Element(&elem, param->beg, param->end);
    p = getASN1Element(&elem, param->beg, param->end);
    do_pubkey_field(data, certnum, "dsa(p)", &elem);
    p = Curl_getASN1Element(&elem, p, param->end);
    p = getASN1Element(&elem, p, param->end);
    do_pubkey_field(data, certnum, "dsa(q)", &elem);
    Curl_getASN1Element(&elem, p, param->end);
    getASN1Element(&elem, p, param->end);
    do_pubkey_field(data, certnum, "dsa(g)", &elem);
    do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
  }
  else if(strcasecompare(algo, "dhpublicnumber")) {
    p = Curl_getASN1Element(&elem, param->beg, param->end);
    p = getASN1Element(&elem, param->beg, param->end);
    do_pubkey_field(data, certnum, "dh(p)", &elem);
    Curl_getASN1Element(&elem, param->beg, param->end);
    getASN1Element(&elem, param->beg, param->end);
    do_pubkey_field(data, certnum, "dh(g)", &elem);
    do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
  }
@@ -903,7 +899,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
    return CURLE_OUT_OF_MEMORY;

  /* Subject. */
  ccp = Curl_DNtostr(&cert.subject);
  ccp = DNtostr(&cert.subject);
  if(!ccp)
    return CURLE_OUT_OF_MEMORY;
  if(data->set.ssl.certinfo)
@@ -913,7 +909,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
  free((char *) ccp);

  /* Issuer. */
  ccp = Curl_DNtostr(&cert.issuer);
  ccp = DNtostr(&cert.issuer);
  if(!ccp)
    return CURLE_OUT_OF_MEMORY;
  if(data->set.ssl.certinfo)
@@ -937,7 +933,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
    infof(data, "   Version: %lu (0x%lx)\n", version + 1, version);

  /* Serial number. */
  ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
  ccp = ASN1tostr(&cert.serialNumber, 0);
  if(!ccp)
    return CURLE_OUT_OF_MEMORY;
  if(data->set.ssl.certinfo)
@@ -958,7 +954,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
  free((char *) ccp);

  /* Start Date. */
  ccp = Curl_ASN1tostr(&cert.notBefore, 0);
  ccp = ASN1tostr(&cert.notBefore, 0);
  if(!ccp)
    return CURLE_OUT_OF_MEMORY;
  if(data->set.ssl.certinfo)
@@ -968,7 +964,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
  free((char *) ccp);

  /* Expire Date. */
  ccp = Curl_ASN1tostr(&cert.notAfter, 0);
  ccp = ASN1tostr(&cert.notAfter, 0);
  if(!ccp)
    return CURLE_OUT_OF_MEMORY;
  if(data->set.ssl.certinfo)
@@ -992,7 +988,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
/* TODO: extensions. */

  /* Signature. */
  ccp = Curl_ASN1tostr(&cert.signature, 0);
  ccp = ASN1tostr(&cert.signature, 0);
  if(!ccp)
    return CURLE_OUT_OF_MEMORY;
  if(data->set.ssl.certinfo)
@@ -1051,7 +1047,7 @@ static const char *checkOID(const char *beg, const char *end,
  /* Check if first ASN.1 element at `beg' is the given OID.
     Return a pointer in the source after the OID if found, else NULL. */

  ccp = Curl_getASN1Element(&e, beg, end);
  ccp = getASN1Element(&e, beg, end);
  if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
    return (const char *) NULL;

@@ -1110,19 +1106,19 @@ CURLcode Curl_verifyhost(struct connectdata *conn,

  /* Process extensions. */
  for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) {
    p = Curl_getASN1Element(&ext, p, cert.extensions.end);
    p = getASN1Element(&ext, p, cert.extensions.end);
    /* Check if extension is a subjectAlternativeName. */
    ext.beg = checkOID(ext.beg, ext.end, sanOID);
    if(ext.beg) {
      ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
      ext.beg = getASN1Element(&elem, ext.beg, ext.end);
      /* Skip critical if present. */
      if(elem.tag == CURL_ASN1_BOOLEAN)
        ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
        ext.beg = getASN1Element(&elem, ext.beg, ext.end);
      /* Parse the octet string contents: is a single sequence. */
      Curl_getASN1Element(&elem, elem.beg, elem.end);
      getASN1Element(&elem, elem.beg, elem.end);
      /* Check all GeneralNames. */
      for(q = elem.beg; matched != 1 && q < elem.end;) {
        q = Curl_getASN1Element(&name, q, elem.end);
        q = getASN1Element(&name, q, elem.end);
        switch(name.tag) {
        case 2: /* DNS name. */
          len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
@@ -1162,9 +1158,9 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
  /* we have to look to the last occurrence of a commonName in the
     distinguished one to get the most significant one. */
  while(q < cert.subject.end) {
    q = Curl_getASN1Element(&dn, q, cert.subject.end);
    q = getASN1Element(&dn, q, cert.subject.end);
    for(p = dn.beg; p < dn.end;) {
      p = Curl_getASN1Element(&elem, p, dn.end);
      p = getASN1Element(&elem, p, dn.end);
      /* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */
      elem.beg = checkOID(elem.beg, elem.end, cnOID);
      if(elem.beg)
@@ -1173,7 +1169,7 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
  }

  /* Check the CN if found. */
  if(!Curl_getASN1Element(&elem, name.beg, name.end))
  if(!getASN1Element(&elem, name.beg, name.end))
    failf(data, "SSL: unable to obtain common name from peer certificate");
  else {
    len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);