Beispiel #1
0
/*
 *  Time ::= CHOICE {
 *       utcTime        UTCTime,
 *       generalTime    GeneralizedTime }
 */
int x509_get_time( unsigned char **p, const unsigned char *end,
                   x509_time *time )
{
    int ret;
    size_t len;
    unsigned char tag;

    if( ( end - *p ) < 1 )
        return( POLARSSL_ERR_X509_INVALID_DATE +
                POLARSSL_ERR_ASN1_OUT_OF_DATA );

    tag = **p;

    if( tag == ASN1_UTC_TIME )
    {
        (*p)++;
        ret = asn1_get_len( p, end, &len );

        if( ret != 0 )
            return( POLARSSL_ERR_X509_INVALID_DATE + ret );

        CHECK( x509_parse_int( p, 2, &time->year ) );
        CHECK( x509_parse_int( p, 2, &time->mon ) );
        CHECK( x509_parse_int( p, 2, &time->day ) );
        CHECK( x509_parse_int( p, 2, &time->hour ) );
        CHECK( x509_parse_int( p, 2, &time->min ) );
        if( len > 10 )
            CHECK( x509_parse_int( p, 2, &time->sec ) );
        if( len > 12 && *(*p)++ != 'Z' )
            return( POLARSSL_ERR_X509_INVALID_DATE );

        time->year +=  100 * ( time->year < 50 );
        time->year += 1900;

        return( 0 );
    }
    else if( tag == ASN1_GENERALIZED_TIME )
    {
        (*p)++;
        ret = asn1_get_len( p, end, &len );

        if( ret != 0 )
            return( POLARSSL_ERR_X509_INVALID_DATE + ret );

        CHECK( x509_parse_int( p, 4, &time->year ) );
        CHECK( x509_parse_int( p, 2, &time->mon ) );
        CHECK( x509_parse_int( p, 2, &time->day ) );
        CHECK( x509_parse_int( p, 2, &time->hour ) );
        CHECK( x509_parse_int( p, 2, &time->min ) );
        if( len > 12 )
            CHECK( x509_parse_int( p, 2, &time->sec ) );
        if( len > 14 && *(*p)++ != 'Z' )
            return( POLARSSL_ERR_X509_INVALID_DATE );

        return( 0 );
    }
    else
        return( POLARSSL_ERR_X509_INVALID_DATE +
                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
}
Beispiel #2
0
static ssh_string asn1_get_int(ssh_buffer buffer) {
    ssh_string str;
    unsigned char type;
    uint32_t size;

    if (ssh_buffer_get_data(buffer, &type, 1) == 0 || type != ASN1_INTEGER) {
        return NULL;
    }
    size = asn1_get_len(buffer);
    if (size == 0) {
        return NULL;
    }

    str = ssh_string_new(size);
    if (str == NULL) {
        return NULL;
    }

    if (ssh_buffer_get_data(buffer, ssh_string_data(str), size) == 0) {
        ssh_string_free(str);
        return NULL;
    }

    return str;
}
Beispiel #3
0
/*
 *  CertificateSerialNumber  ::=  INTEGER
 */
static int x509_get_serial( unsigned char **p,
                            unsigned char *end,
                            x509_buf *serial )
{
    int ret;

    if( ( end - *p ) < 1 )
        return( ERR_X509_CERT_INVALID_SERIAL |
                ERR_ASN1_OUT_OF_DATA );

    if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
        **p !=   ASN1_INTEGER )
        return( ERR_X509_CERT_INVALID_SERIAL |
                ERR_ASN1_UNEXPECTED_TAG );

    serial->tag = *(*p)++;

    if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
        return( ERR_X509_CERT_INVALID_SERIAL | ret );

    serial->p = *p;
    *p += serial->len;

    return( 0 );
}
Beispiel #4
0
static int asn1_check_sequence(ssh_buffer buffer) {
    unsigned char *j = NULL;
    unsigned char tmp;
    int i;
    uint32_t size;
    uint32_t padding;

    if (ssh_buffer_get_data(buffer, &tmp, 1) == 0 || tmp != ASN1_SEQUENCE) {
        return 0;
    }

    size = asn1_get_len(buffer);
    if ((padding = ssh_buffer_get_len(buffer) - size) > 0) {
        for (i = ssh_buffer_get_len(buffer) - size,
                j = (unsigned char*)ssh_buffer_get(buffer) + size;
                i;
                i--, j++)
        {
            if (*j != padding) {                   /* padding is allowed */
                return 0;                            /* but nothing else */
            }
        }
    }

    return 1;
}
Beispiel #5
0
/*
 *  CertificateSerialNumber   ::=  INTEGER
 */
static svn_error_t *
x509_get_serial(const unsigned char **p,
                const unsigned char *end, x509_buf * serial)
{
  svn_error_t *err;

  if ((end - *p) < 1)
    {
      err = svn_error_create(SVN_ERR_ASN1_OUT_OF_DATA, NULL, NULL);
      return svn_error_create(SVN_ERR_X509_CERT_INVALID_SERIAL, err, NULL);
    }

  if (**p != (ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2) &&
      **p != ASN1_INTEGER)
    {
      err = svn_error_create(SVN_ERR_ASN1_UNEXPECTED_TAG, NULL, NULL);
      return svn_error_create(SVN_ERR_X509_CERT_INVALID_SERIAL, err, NULL);
    }

  serial->tag = *(*p)++;

  err = asn1_get_len(p, end, &serial->len);
  if (err)
    return svn_error_create(SVN_ERR_X509_CERT_INVALID_SERIAL, err, NULL);

  serial->p = *p;
  *p += serial->len;

  return SVN_NO_ERROR;
}
Beispiel #6
0
/*
 *  AttributeTypeAndValue ::= SEQUENCE {
 *    type     AttributeType,
 *    value     AttributeValue }
 *
 *  AttributeType ::= OBJECT IDENTIFIER
 *
 *  AttributeValue ::= ANY DEFINED BY AttributeType
 */
static svn_error_t *
x509_get_attribute(const unsigned char **p, const unsigned char *end,
                   x509_name *cur, apr_pool_t *result_pool)
{
  svn_error_t *err;
  ptrdiff_t len;
  x509_buf *oid;
  x509_buf *val;

  err = asn1_get_tag(p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
  if (err)
    return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL);

  end = *p + len;

  oid = &cur->oid;

  err = asn1_get_tag(p, end, &oid->len, ASN1_OID);
  if (err)
    return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL);

  oid->tag = ASN1_OID;
  oid->p = *p;
  *p += oid->len;

  if ((end - *p) < 1)
    {
      err = svn_error_create(SVN_ERR_ASN1_OUT_OF_DATA, NULL, NULL);
      return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL);
    }

  if (**p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
      **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
      **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING)
    {
      err = svn_error_create(SVN_ERR_ASN1_UNEXPECTED_TAG, NULL, NULL);
      return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL);
    }

  val = &cur->val;
  val->tag = *(*p)++;

  err = asn1_get_len(p, end, &val->len);
  if (err)
    return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL);

  val->p = *p;
  *p += val->len;

  cur->next = NULL;

  if (*p != end)
    {
      err = svn_error_create(SVN_ERR_ASN1_LENGTH_MISMATCH, NULL, NULL);
      return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL);
    }

  return SVN_NO_ERROR;
}
Beispiel #7
0
/*
 *  AttributeTypeAndValue ::= SEQUENCE {
 *    type     AttributeType,
 *    value    AttributeValue }
 *
 *  AttributeType ::= OBJECT IDENTIFIER
 *
 *  AttributeValue ::= ANY DEFINED BY AttributeType
 */
static int x509_get_attr_type_value( unsigned char **p,
                                     const unsigned char *end,
                                     x509_name *cur )
{
    int ret;
    size_t len;
    x509_buf *oid;
    x509_buf *val;

    if( ( ret = asn1_get_tag( p, end, &len,
                              ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
        return( POLARSSL_ERR_X509_INVALID_NAME + ret );

    if( ( end - *p ) < 1 )
        return( POLARSSL_ERR_X509_INVALID_NAME +
                POLARSSL_ERR_ASN1_OUT_OF_DATA );

    oid = &cur->oid;
    oid->tag = **p;

    if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
        return( POLARSSL_ERR_X509_INVALID_NAME + ret );

    oid->p = *p;
    *p += oid->len;

    if( ( end - *p ) < 1 )
        return( POLARSSL_ERR_X509_INVALID_NAME +
                POLARSSL_ERR_ASN1_OUT_OF_DATA );

    if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING      &&
            **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
            **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING &&
            **p != ASN1_BIT_STRING )
        return( POLARSSL_ERR_X509_INVALID_NAME +
                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );

    val = &cur->val;
    val->tag = *(*p)++;

    if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
        return( POLARSSL_ERR_X509_INVALID_NAME + ret );

    val->p = *p;
    *p += val->len;

    cur->next = NULL;

    return( 0 );
}
Beispiel #8
0
static svn_error_t *
asn1_get_tag(const unsigned char **p,
             const unsigned char *end, ptrdiff_t *len, int tag)
{
  if ((end - *p) < 1)
    return svn_error_create(SVN_ERR_ASN1_OUT_OF_DATA, NULL, NULL);

  if (**p != tag)
    return svn_error_create(SVN_ERR_ASN1_UNEXPECTED_TAG, NULL, NULL);

  (*p)++;

  return svn_error_trace(asn1_get_len(p, end, len));
}
Beispiel #9
0
static int asn1_get_tag( unsigned char **p,
                         unsigned char *end,
                         int *len, int tag )
{
    if( ( end - *p ) < 1 )
        return( ERR_ASN1_OUT_OF_DATA );

    if( **p != tag )
        return( ERR_ASN1_UNEXPECTED_TAG );

    (*p)++;

    return( asn1_get_len( p, end, len ) );
}
Beispiel #10
0
int asn1_get_tag( unsigned char **p,
                  const unsigned char *end,
                  size_t *len, int tag )
{
    if( ( end - *p ) < 1 )
        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );

    if( **p != tag )
        return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );

    (*p)++;

    return( asn1_get_len( p, end, len ) );
}
SSL_ROM_TEXT_SECTION
int asn1_get_alg( unsigned char **p,
                  const unsigned char *end,
                  asn1_buf *alg, asn1_buf *params )
{
    int ret;
    size_t len;

    if( ( ret = asn1_get_tag( p, end, &len,
            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
        return( ret );

    if( ( end - *p ) < 1 )
        return( POLARSSL_ERR_ASN1_OUT_OF_DATA );

    alg->tag = **p;
    end = *p + len;

    if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
        return( ret );

    alg->p = *p;
    *p += alg->len;

    if( *p == end )
    {
        memset( params, 0, sizeof(asn1_buf) );
        return( 0 );
    }

    params->tag = **p;
    (*p)++;

    if( ( ret = asn1_get_len( p, end, &params->len ) ) != 0 )
        return( ret );

    params->p = *p;
    *p += params->len;

    if( *p != end )
        return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH );

    return( 0 );
}
Beispiel #12
0
static gpg_error_t
asn1_get_public_exp (unsigned char *cert, int cert_len,
		     unsigned char **sub_start, int *sub_len)
{
  gpg_error_t err;
  int len;

  /* The path to the public exp entry in the DER file.  This is
     Sequence->Sequence->Version,Serial,AlgID,Issuer,Time,Subject,
     Sequence->Sequence,Bitstring->Sequence->Integer,Integer  */
  struct asn1_path path[] = { { '\x30', true }, { '\x30', true },
			      { '\xa0', false }, { '\x02', false },
			      { '\x30', false }, { '\x30', false },
			      { '\x30', false }, { '\x30', false },
			      { '\x30', true }, { '\x30', false },
			      { '\x03', true }, { '\x30', true },
			      { '\x02', false }, { '\x02', false } };

  err = asn1_get_element (cert, cert_len, sub_start, sub_len,
			  path, DIM (path));
  if (err)
    return err;

  if (*sub_len < 1)
    {
      DEBUG (DBG_INFO, "public exponent too short");
      return gpg_error (GPG_ERR_GENERAL);
    }

  (*sub_start)++;
  (*sub_len)--;
  err = asn1_get_len (sub_start, sub_len, &len);
  if (err)
    return err;

  /* PKCS #11 expects an unsigned big integer.  */
  while (**sub_start == '\x00' && *sub_len > 0)
    {
      (*sub_start)++;
      (*sub_len)--;
    }

  return 0;
}
Beispiel #13
0
/*
 * SubjectAltName ::= GeneralNames
 *
 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
 *
 * GeneralName ::= CHOICE {
 *      otherName                       [0]     OtherName,
 *      rfc822Name                      [1]     IA5String,
 *      dNSName                         [2]     IA5String,
 *      x400Address                     [3]     ORAddress,
 *      directoryName                   [4]     Name,
 *      ediPartyName                    [5]     EDIPartyName,
 *      uniformResourceIdentifier       [6]     IA5String,
 *      iPAddress                       [7]     OCTET STRING,
 *      registeredID                    [8]     OBJECT IDENTIFIER }
 *
 * OtherName ::= SEQUENCE {
 *      type-id    OBJECT IDENTIFIER,
 *      value      [0] EXPLICIT ANY DEFINED BY type-id }
 *
 * EDIPartyName ::= SEQUENCE {
 *      nameAssigner            [0]     DirectoryString OPTIONAL,
 *      partyName               [1]     DirectoryString }
 *
 * NOTE: PolarSSL only parses and uses dNSName at this point.
 */
static int x509_get_subject_alt_name( unsigned char **p,
                                      const unsigned char *end,
                                      x509_sequence *subject_alt_name )
{
    int ret;
    size_t len, tag_len;
    asn1_buf *buf;
    unsigned char tag;
    asn1_sequence *cur = subject_alt_name;

    /* Get main sequence tag */
    if( ( ret = asn1_get_tag( p, end, &len,
            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );

    if( *p + len != end )
        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );

    while( *p < end )
    {
        if( ( end - *p ) < 1 )
            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
                    POLARSSL_ERR_ASN1_OUT_OF_DATA );

        tag = **p;
        (*p)++;
        if( ( ret = asn1_get_len( p, end, &tag_len ) ) != 0 )
            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );

        if( ( tag & ASN1_CONTEXT_SPECIFIC ) != ASN1_CONTEXT_SPECIFIC )
            return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
                    POLARSSL_ERR_ASN1_UNEXPECTED_TAG );

        if( tag != ( ASN1_CONTEXT_SPECIFIC | 2 ) )
        {
            *p += tag_len;
            continue;
        }

        buf = &(cur->buf);
        buf->tag = tag;
        buf->p = *p;
        buf->len = tag_len;
        *p += buf->len;

        /* Allocate and assign next pointer */
        if (*p < end)
        {
            cur->next = (asn1_sequence *) polarssl_malloc(
                 sizeof( asn1_sequence ) );

            if( cur->next == NULL )
                return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
                        POLARSSL_ERR_ASN1_MALLOC_FAILED );

            memset( cur->next, 0, sizeof( asn1_sequence ) );
            cur = cur->next;
        }
    }

    /* Set final sequence entry's next pointer to NULL */
    cur->next = NULL;

    if( *p != end )
        return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );

    return( 0 );
}
Beispiel #14
0
static gpg_error_t
asn1_get_element (unsigned char *cert, int cert_len,
		  unsigned char **sub_start, int *sub_len,
		  struct asn1_path *path, int path_size)
{
  gpg_error_t err;
  unsigned char *prev_certp = NULL;
  unsigned char *certp = cert;
  int cert_left = cert_len;
  int len;
  int i;

  for (i = 0; i < path_size; i++)
    {
      prev_certp = certp;
      if (cert_left < 1)
	{
	  DEBUG (DBG_INFO, "unexpected end of certificate");
	  return gpg_error (GPG_ERR_GENERAL);
	}
      if (*certp != path[i].tag)
	{
	  DEBUG (DBG_INFO, "wrong element in lookup path");
	  return gpg_error (GPG_ERR_GENERAL);
	}
      certp++;
      cert_left--;
      err = asn1_get_len (&certp, &cert_left, &len);
      if (err)
	return err;
      if (!path[i].enter)
	{
	  if (cert_left < len)
	    {
	      DEBUG (DBG_INFO, "unexpected end of certificate");
	      return gpg_error (GPG_ERR_GENERAL);
	    }
	  certp += len;
	  cert_left -= len;
	}
      else
	{
	  /* Special code to deal with ASN.1 data encapsulated in a
	     bit string.  */
	  if (path[i].tag == '\x03')
	    {
	      if (cert_left < 1)
		{
		  DEBUG (DBG_INFO, "unexpected end of certificate");
		  return gpg_error (GPG_ERR_GENERAL);
		}
	      if (*certp != '\x00')
		{
		  DEBUG (DBG_INFO, "expected binary encapsulation missing");
		  return gpg_error (GPG_ERR_GENERAL);
		}
	      certp++;
	      cert_left--;
	    }
	}
    }

  /* We found the subject.  */
  *sub_start = prev_certp;
  *sub_len = certp - prev_certp;
  
  return 0;
}
Beispiel #15
0
/*
 * X.509 v3 extensions (not parsed)
 */
static svn_error_t *
x509_get_ext(apr_array_header_t *dnsnames,
             const unsigned char **p,
             const unsigned char *end)
{
  svn_error_t *err;
  ptrdiff_t len;

  if (*p == end)
    return SVN_NO_ERROR;

  err = asn1_get_tag(p, end, &len,
                     ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3);
  if (err)
    {
      /* If there aren't extensions that's ok they aren't required */
      if (err->apr_err == SVN_ERR_ASN1_UNEXPECTED_TAG)
        {
          svn_error_clear(err);
          return SVN_NO_ERROR;
        }

      return svn_error_trace(err);
    }

  end = *p + len;

  SVN_ERR(asn1_get_tag(p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE));

  if (end != *p + len)
    {
      err = svn_error_create(SVN_ERR_ASN1_LENGTH_MISMATCH, NULL, NULL);
      return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err, NULL);
    }

  while (*p < end)
    {
      ptrdiff_t ext_len;
      const unsigned char *ext_start, *sna_end;
      err = asn1_get_tag(p, end, &ext_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
      if (err)
        return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err,
                                NULL);
      ext_start = *p;

      err = asn1_get_tag(p, end, &len, ASN1_OID);
      if (err)
        return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err,
                                NULL);

      /* skip all extensions except SubjectAltName */
      if (!equal(*p, len,
                 OID_SUBJECT_ALT_NAME, sizeof(OID_SUBJECT_ALT_NAME) - 1))
        {
          *p += ext_len - (*p - ext_start);
          continue;
        }
      *p += len;

      err = asn1_get_tag(p, end, &len, ASN1_OCTET_STRING);
      if (err)
        return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err,
                                NULL);

      /*   SubjectAltName ::= GeneralNames

           GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName

           GeneralName ::= CHOICE {
                other Name                      [0]     OtherName,
                rfc822Name                      [1]     IA5String,
                dNSName                         [2]     IA5String,
                x400Address                     [3]     ORAddress,
                directoryName                   [4]     Name,
                ediPartyName                    [5]     EDIPartyName,
                uniformResourceIdentifier       [6]     IA5String,
                iPAddress                       [7]     OCTET STRING,
                registeredID                    [8]     OBJECT IDENTIFIER } */
      sna_end = *p + len;

      err = asn1_get_tag(p, sna_end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
      if (err)
        return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err,
                                NULL);

      if (sna_end != *p + len)
        {
          err = svn_error_create(SVN_ERR_ASN1_LENGTH_MISMATCH, NULL, NULL);
          return svn_error_create(SVN_ERR_X509_CERT_INVALID_EXTENSIONS, err, NULL);
        }

      while (*p < sna_end)
        {
          err = asn1_get_tag(p, sna_end, &len, ASN1_CONTEXT_SPECIFIC |
                             ASN1_PRIMITIVE | 2);
          if (err)
            {
              /* not not a dNSName */
              if (err->apr_err == SVN_ERR_ASN1_UNEXPECTED_TAG)
                {
                  svn_error_clear(err);
                  /* need to skip the tag and then find the length to
                   * skip to ignore this SNA entry. */
                  (*p)++;
                  SVN_ERR(asn1_get_len(p, sna_end, &len));
                  *p += len;
                  continue;
                }

              return svn_error_trace(err);
            }
          else
            {
              /* We found a dNSName entry */
              x509_buf *dnsname = apr_palloc(dnsnames->pool, sizeof(*dnsname));
              dnsname->tag = ASN1_IA5_STRING; /* implicit based on dNSName */
              dnsname->len = len;
              dnsname->p = *p;
              APR_ARRAY_PUSH(dnsnames, x509_buf *) = dnsname;
            }

          *p += len;
        }

    }

  return SVN_NO_ERROR;
}
Beispiel #16
0
/*
 *  RelativeDistinguishedName ::=
 *    SET OF AttributeTypeAndValue
 *
 *  AttributeTypeAndValue ::= SEQUENCE {
 *    type     AttributeType,
 *    value    AttributeValue }
 *
 *  AttributeType ::= OBJECT IDENTIFIER
 *
 *  AttributeValue ::= ANY DEFINED BY AttributeType
 */
static int x509_get_name( unsigned char **p,
                          unsigned char *end,
                          x509_name *cur )
{
    int ret, len;
    unsigned char *end2;
    x509_buf *oid;
    x509_buf *val;

    if( ( ret = asn1_get_tag( p, end, &len,
            ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
        return( ERR_X509_CERT_INVALID_NAME | ret );

    end2 = end;
    end  = *p + len;

    if( ( ret = asn1_get_tag( p, end, &len,
            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
        return( ERR_X509_CERT_INVALID_NAME | ret );

    if( *p + len != end )
        return( ERR_X509_CERT_INVALID_NAME |
                ERR_ASN1_LENGTH_MISMATCH );

    oid = &cur->oid;
    oid->tag = **p;

    if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
        return( ERR_X509_CERT_INVALID_NAME | ret );

    oid->p = *p;
    *p += oid->len;

    if( ( end - *p ) < 1 )
        return( ERR_X509_CERT_INVALID_NAME |
                ERR_ASN1_OUT_OF_DATA );

    if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING      &&
        **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
        **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
        return( ERR_X509_CERT_INVALID_NAME |
                ERR_ASN1_UNEXPECTED_TAG );

    val = &cur->val;
    val->tag = *(*p)++;

    if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
        return( ERR_X509_CERT_INVALID_NAME | ret );

    val->p = *p;
    *p += val->len;

    cur->next = NULL;

    if( *p != end )
        return( ERR_X509_CERT_INVALID_NAME |
                ERR_ASN1_LENGTH_MISMATCH );

    /*
     * recurse until end of SEQUENCE is reached
     */
    if( *p == end2 )
        return( 0 );

    cur->next = (x509_name *) malloc(
         sizeof( x509_name ) );

    if( cur->next == NULL )
        return( 1 );

    return( x509_get_name( p, end2, cur->next ) );
}
Beispiel #17
0
/*
 *  Time ::= CHOICE {
 *       utcTime        UTCTime,
 *       generalTime    GeneralizedTime }
 */
int x509_get_time( unsigned char **p, const unsigned char *end,
                   x509_time *time )
{
    int ret;
    size_t len;
    char date[64];
    unsigned char tag;

    if( ( end - *p ) < 1 )
        return( POLARSSL_ERR_X509_INVALID_DATE +
                POLARSSL_ERR_ASN1_OUT_OF_DATA );

    tag = **p;

    if( tag == ASN1_UTC_TIME )
    {
        (*p)++;
        ret = asn1_get_len( p, end, &len );

        if( ret != 0 )
            return( POLARSSL_ERR_X509_INVALID_DATE + ret );

        memset( date,  0, sizeof( date ) );
        memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
                len : sizeof( date ) - 1 );

        if( sscanf( date, "%2d%2d%2d%2d%2d%2dZ",
                    &time->year, &time->mon, &time->day,
                    &time->hour, &time->min, &time->sec ) < 5 )
            return( POLARSSL_ERR_X509_INVALID_DATE );

        time->year +=  100 * ( time->year < 50 );
        time->year += 1900;

        *p += len;

        return( 0 );
    }
    else if( tag == ASN1_GENERALIZED_TIME )
    {
        (*p)++;
        ret = asn1_get_len( p, end, &len );

        if( ret != 0 )
            return( POLARSSL_ERR_X509_INVALID_DATE + ret );

        memset( date,  0, sizeof( date ) );
        memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
                len : sizeof( date ) - 1 );

        if( sscanf( date, "%4d%2d%2d%2d%2d%2dZ",
                    &time->year, &time->mon, &time->day,
                    &time->hour, &time->min, &time->sec ) < 5 )
            return( POLARSSL_ERR_X509_INVALID_DATE );

        *p += len;

        return( 0 );
    }
    else
        return( POLARSSL_ERR_X509_INVALID_DATE +
                POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
}