|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* Copyright (C) 2000-2014 Free Software Foundation, Inc.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This file is part of LIBTASN1.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The LIBTASN1 library is free software; you can redistribute it
|
|
Packit |
549fdc |
* and/or modify it under the terms of the GNU Lesser General Public
|
|
Packit |
549fdc |
* License as published by the Free Software Foundation; either
|
|
Packit |
549fdc |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
549fdc |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
549fdc |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
549fdc |
* Lesser General Public License for more details.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
549fdc |
* License along with this library; if not, write to the Free Software
|
|
Packit |
549fdc |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit |
549fdc |
* 02110-1301, USA
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*****************************************************/
|
|
Packit |
549fdc |
/* File: element.c */
|
|
Packit |
549fdc |
/* Description: Functions with the read and write */
|
|
Packit |
549fdc |
/* functions. */
|
|
Packit |
549fdc |
/*****************************************************/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include <int.h>
|
|
Packit |
549fdc |
#include "parser_aux.h"
|
|
Packit |
549fdc |
#include <gstr.h>
|
|
Packit |
549fdc |
#include "structure.h"
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include "element.h"
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_asn1_hierarchical_name (asn1_node node, char *name, int name_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
asn1_node p;
|
|
Packit |
549fdc |
char tmp_name[64];
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
p = node;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
name[0] = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
while (p != NULL)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (p->name[0] != 0)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
_asn1_str_cpy (tmp_name, sizeof (tmp_name), name),
|
|
Packit |
549fdc |
_asn1_str_cpy (name, name_size, p->name);
|
|
Packit |
549fdc |
_asn1_str_cat (name, name_size, ".");
|
|
Packit |
549fdc |
_asn1_str_cat (name, name_size, tmp_name);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
p = _asn1_find_up (p);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (name[0] == 0)
|
|
Packit |
549fdc |
_asn1_str_cpy (name, name_size, "ROOT");
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/******************************************************************/
|
|
Packit |
549fdc |
/* Function : _asn1_convert_integer */
|
|
Packit |
549fdc |
/* Description: converts an integer from a null terminated string */
|
|
Packit |
549fdc |
/* to der decoding. The convertion from a null */
|
|
Packit |
549fdc |
/* terminated string to an integer is made with */
|
|
Packit |
549fdc |
/* the 'strtol' function. */
|
|
Packit |
549fdc |
/* Parameters: */
|
|
Packit |
549fdc |
/* value: null terminated string to convert. */
|
|
Packit |
549fdc |
/* value_out: convertion result (memory must be already */
|
|
Packit |
549fdc |
/* allocated). */
|
|
Packit |
549fdc |
/* value_out_size: number of bytes of value_out. */
|
|
Packit |
549fdc |
/* len: number of significant byte of value_out. */
|
|
Packit |
549fdc |
/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS */
|
|
Packit |
549fdc |
/******************************************************************/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
|
|
Packit |
549fdc |
int value_out_size, int *len)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
char negative;
|
|
Packit |
549fdc |
unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
|
|
Packit |
549fdc |
long valtmp;
|
|
Packit |
549fdc |
int k, k2;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
valtmp = _asn1_strtol (value, NULL, 10);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
val[SIZEOF_UNSIGNED_LONG_INT - k - 1] = (valtmp >> (8 * k)) & 0xFF;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (val[0] & 0x80)
|
|
Packit |
549fdc |
negative = 1;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
negative = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT - 1; k++)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (negative && (val[k] != 0xFF))
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
else if (!negative && val[k])
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((negative && !(val[k] & 0x80)) || (!negative && (val[k] & 0x80)))
|
|
Packit |
549fdc |
k--;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*len = SIZEOF_UNSIGNED_LONG_INT - k;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (SIZEOF_UNSIGNED_LONG_INT - k > value_out_size)
|
|
Packit |
549fdc |
/* VALUE_OUT is too short to contain the value conversion */
|
|
Packit |
549fdc |
return ASN1_MEM_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (value_out != NULL)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
|
|
Packit |
549fdc |
value_out[k2 - k] = val[k2];
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#if 0
|
|
Packit |
549fdc |
printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len);
|
|
Packit |
549fdc |
for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++)
|
|
Packit |
549fdc |
printf (", vOut[%d]=%d", k, value_out[k]);
|
|
Packit |
549fdc |
printf ("\n");
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ASN1_SUCCESS;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Appends a new element into the sequence (or set) defined by this
|
|
Packit |
549fdc |
* node. The new element will have a name of '?number', where number
|
|
Packit |
549fdc |
* is a monotonically increased serial number.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The last element in the list may be provided in @pcache, to avoid
|
|
Packit |
549fdc |
* traversing the list, an expensive operation in long lists.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* On success it returns in @pcache the added element (which is the
|
|
Packit |
549fdc |
* tail in the list of added elements).
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
asn1_node p, p2;
|
|
Packit |
549fdc |
char temp[LTOSTR_MAX_SIZE];
|
|
Packit |
549fdc |
long n;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (!node || !(node->down))
|
|
Packit |
549fdc |
return ASN1_GENERIC_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while ((type_field (p->type) == ASN1_ETYPE_TAG)
|
|
Packit |
549fdc |
|| (type_field (p->type) == ASN1_ETYPE_SIZE))
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
p2 = _asn1_copy_structure3 (p);
|
|
Packit |
549fdc |
if (p2 == NULL)
|
|
Packit |
549fdc |
return ASN1_GENERIC_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (pcache == NULL || pcache->tail == NULL || pcache->head != node)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
while (p->right)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = pcache->tail;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_asn1_set_right (p, p2);
|
|
Packit |
549fdc |
if (pcache)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
pcache->head = node;
|
|
Packit |
549fdc |
pcache->tail = p2;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (p->name[0] == 0)
|
|
Packit |
549fdc |
_asn1_str_cpy (temp, sizeof (temp), "?1");
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
n = strtol (p->name + 1, NULL, 0);
|
|
Packit |
549fdc |
n++;
|
|
Packit |
549fdc |
temp[0] = '?';
|
|
Packit |
549fdc |
_asn1_ltostr (n, temp + 1);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
_asn1_set_name (p2, temp);
|
|
Packit |
549fdc |
/* p2->type |= CONST_OPTION; */
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ASN1_SUCCESS;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* asn1_write_value:
|
|
Packit |
549fdc |
* @node_root: pointer to a structure
|
|
Packit |
549fdc |
* @name: the name of the element inside the structure that you want to set.
|
|
Packit |
549fdc |
* @ivalue: vector used to specify the value to set. If len is >0,
|
|
Packit |
549fdc |
* VALUE must be a two's complement form integer. if len=0 *VALUE
|
|
Packit |
549fdc |
* must be a null terminated string with an integer value.
|
|
Packit |
549fdc |
* @len: number of bytes of *value to use to set the value:
|
|
Packit |
549fdc |
* value[0]..value[len-1] or 0 if value is a null terminated string
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Set the value of one element inside a structure.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If an element is OPTIONAL and you want to delete it, you must use
|
|
Packit |
549fdc |
* the value=NULL and len=0. Using "pkix.asn":
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* result=asn1_write_value(cert, "tbsCertificate.issuerUniqueID",
|
|
Packit |
549fdc |
* NULL, 0);
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Description for each type:
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* INTEGER: VALUE must contain a two's complement form integer.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* value[0]=0xFF , len=1 -> integer=-1.
|
|
Packit |
549fdc |
* value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1.
|
|
Packit |
549fdc |
* value[0]=0x01 , len=1 -> integer= 1.
|
|
Packit |
549fdc |
* value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1.
|
|
Packit |
549fdc |
* value="123" , len=0 -> integer= 123.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* ENUMERATED: As INTEGER (but only with not negative numbers).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* BOOLEAN: VALUE must be the null terminated string "TRUE" or
|
|
Packit |
549fdc |
* "FALSE" and LEN != 0.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* value="TRUE" , len=1 -> boolean=TRUE.
|
|
Packit |
549fdc |
* value="FALSE" , len=1 -> boolean=FALSE.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* OBJECT IDENTIFIER: VALUE must be a null terminated string with
|
|
Packit |
549fdc |
* each number separated by a dot (e.g. "1.2.3.543.1"). LEN != 0.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* UTCTime: VALUE must be a null terminated string in one of these
|
|
Packit |
549fdc |
* formats: "YYMMDDhhmmssZ", "YYMMDDhhmmssZ",
|
|
Packit |
549fdc |
* "YYMMDDhhmmss+hh'mm'", "YYMMDDhhmmss-hh'mm'",
|
|
Packit |
549fdc |
* "YYMMDDhhmm+hh'mm'", or "YYMMDDhhmm-hh'mm'". LEN != 0.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998
|
|
Packit |
549fdc |
* at 12h 00m Greenwich Mean Time
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* GeneralizedTime: VALUE must be in one of this format:
|
|
Packit |
549fdc |
* "YYYYMMDDhhmmss.sZ", "YYYYMMDDhhmmss.sZ",
|
|
Packit |
549fdc |
* "YYYYMMDDhhmmss.s+hh'mm'", "YYYYMMDDhhmmss.s-hh'mm'",
|
|
Packit |
549fdc |
* "YYYYMMDDhhmm+hh'mm'", or "YYYYMMDDhhmm-hh'mm'" where ss.s
|
|
Packit |
549fdc |
* indicates the seconds with any precision like "10.1" or "01.02".
|
|
Packit |
549fdc |
* LEN != 0
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* value="2001010112001.12-0700" , len=1 -> time=Jannuary
|
|
Packit |
549fdc |
* 1st, 2001 at 12h 00m 01.12s Pacific Daylight Time
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* OCTET STRING: VALUE contains the octet string and LEN is the
|
|
Packit |
549fdc |
* number of octets.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* value="$\backslash$x01$\backslash$x02$\backslash$x03" ,
|
|
Packit |
549fdc |
* len=3 -> three bytes octet string
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* GeneralString: VALUE contains the generalstring and LEN is the
|
|
Packit |
549fdc |
* number of octets.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* value="$\backslash$x01$\backslash$x02$\backslash$x03" ,
|
|
Packit |
549fdc |
* len=3 -> three bytes generalstring
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* BIT STRING: VALUE contains the bit string organized by bytes and
|
|
Packit |
549fdc |
* LEN is the number of bits.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* value="$\backslash$xCF" , len=6 -> bit string="110011" (six
|
|
Packit |
549fdc |
* bits)
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* CHOICE: if NAME indicates a choice type, VALUE must specify one of
|
|
Packit |
549fdc |
* the alternatives with a null terminated string. LEN != 0. Using
|
|
Packit |
549fdc |
* "pkix.asn"\:
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* result=asn1_write_value(cert,
|
|
Packit |
549fdc |
* "certificate1.tbsCertificate.subject", "rdnSequence",
|
|
Packit |
549fdc |
* 1);
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* ANY: VALUE indicates the der encoding of a structure. LEN != 0.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* SEQUENCE OF: VALUE must be the null terminated string "NEW" and
|
|
Packit |
549fdc |
* LEN != 0. With this instruction another element is appended in
|
|
Packit |
549fdc |
* the sequence. The name of this element will be "?1" if it's the
|
|
Packit |
549fdc |
* first one, "?2" for the second and so on.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Using "pkix.asn"\:
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* result=asn1_write_value(cert,
|
|
Packit |
549fdc |
* "certificate1.tbsCertificate.subject.rdnSequence", "NEW", 1);
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* SET OF: the same as SEQUENCE OF. Using "pkix.asn":
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* result=asn1_write_value(cert,
|
|
Packit |
549fdc |
* "tbsCertificate.subject.rdnSequence.?LAST", "NEW", 1);
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %ASN1_SUCCESS if the value was set,
|
|
Packit |
549fdc |
* %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, and
|
|
Packit |
549fdc |
* %ASN1_VALUE_NOT_VALID if @ivalue has a wrong format.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
asn1_write_value (asn1_node node_root, const char *name,
|
|
Packit |
549fdc |
const void *ivalue, int len)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
asn1_node node, p, p2;
|
|
Packit |
549fdc |
unsigned char *temp, *value_temp = NULL, *default_temp = NULL;
|
|
Packit |
549fdc |
int len2, k, k2, negative;
|
|
Packit |
549fdc |
size_t i;
|
|
Packit |
549fdc |
const unsigned char *value = ivalue;
|
|
Packit |
549fdc |
unsigned int type;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
node = asn1_find_node (node_root, name);
|
|
Packit |
549fdc |
if (node == NULL)
|
|
Packit |
549fdc |
return ASN1_ELEMENT_NOT_FOUND;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((node->type & CONST_OPTION) && (value == NULL) && (len == 0))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
asn1_delete_structure (&node);
|
|
Packit |
549fdc |
return ASN1_SUCCESS;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
type = type_field (node->type);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((type == ASN1_ETYPE_SEQUENCE_OF || type == ASN1_ETYPE_SET_OF) && (value == NULL) && (len == 0))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while ((type_field (p->type) == ASN1_ETYPE_TAG)
|
|
Packit |
549fdc |
|| (type_field (p->type) == ASN1_ETYPE_SIZE))
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
while (p->right)
|
|
Packit |
549fdc |
asn1_delete_structure (&p->right);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ASN1_SUCCESS;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Don't allow element deletion for other types */
|
|
Packit |
549fdc |
if (value == NULL)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
switch (type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
case ASN1_ETYPE_BOOLEAN:
|
|
Packit |
549fdc |
if (!_asn1_strcmp (value, "TRUE"))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (node->type & CONST_DEFAULT)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
if (p->type & CONST_TRUE)
|
|
Packit |
549fdc |
_asn1_set_value (node, NULL, 0);
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
_asn1_set_value (node, "T", 1);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
_asn1_set_value (node, "T", 1);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else if (!_asn1_strcmp (value, "FALSE"))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (node->type & CONST_DEFAULT)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
if (p->type & CONST_FALSE)
|
|
Packit |
549fdc |
_asn1_set_value (node, NULL, 0);
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
_asn1_set_value (node, "F", 1);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
_asn1_set_value (node, "F", 1);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_INTEGER:
|
|
Packit |
549fdc |
case ASN1_ETYPE_ENUMERATED:
|
|
Packit |
549fdc |
if (len == 0)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if ((isdigit (value[0])) || (value[0] == '-'))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
|
|
Packit |
549fdc |
if (value_temp == NULL)
|
|
Packit |
549fdc |
return ASN1_MEM_ALLOC_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_asn1_convert_integer (value, value_temp,
|
|
Packit |
549fdc |
SIZEOF_UNSIGNED_LONG_INT, &len;;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{ /* is an identifier like v1 */
|
|
Packit |
549fdc |
if (!(node->type & CONST_LIST))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (p)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (type_field (p->type) == ASN1_ETYPE_CONSTANT)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (!_asn1_strcmp (p->name, value))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
|
|
Packit |
549fdc |
if (value_temp == NULL)
|
|
Packit |
549fdc |
return ASN1_MEM_ALLOC_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_asn1_convert_integer (p->value,
|
|
Packit |
549fdc |
value_temp,
|
|
Packit |
549fdc |
SIZEOF_UNSIGNED_LONG_INT,
|
|
Packit |
549fdc |
&len;;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
if (p == NULL)
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{ /* len != 0 */
|
|
Packit |
549fdc |
value_temp = malloc (len);
|
|
Packit |
549fdc |
if (value_temp == NULL)
|
|
Packit |
549fdc |
return ASN1_MEM_ALLOC_ERROR;
|
|
Packit |
549fdc |
memcpy (value_temp, value, len);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (value_temp[0] & 0x80)
|
|
Packit |
549fdc |
negative = 1;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
negative = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (negative && (type_field (node->type) == ASN1_ETYPE_ENUMERATED))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
free (value_temp);
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (k = 0; k < len - 1; k++)
|
|
Packit |
549fdc |
if (negative && (value_temp[k] != 0xFF))
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
else if (!negative && value_temp[k])
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((negative && !(value_temp[k] & 0x80)) ||
|
|
Packit |
549fdc |
(!negative && (value_temp[k] & 0x80)))
|
|
Packit |
549fdc |
k--;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_asn1_set_value_lv (node, value_temp + k, len - k);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (node->type & CONST_DEFAULT)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
if ((isdigit (p->value[0])) || (p->value[0] == '-'))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
|
|
Packit |
549fdc |
if (default_temp == NULL)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
free (value_temp);
|
|
Packit |
549fdc |
return ASN1_MEM_ALLOC_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_asn1_convert_integer (p->value, default_temp,
|
|
Packit |
549fdc |
SIZEOF_UNSIGNED_LONG_INT, &len2);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{ /* is an identifier like v1 */
|
|
Packit |
549fdc |
if (!(node->type & CONST_LIST))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
free (value_temp);
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
p2 = node->down;
|
|
Packit |
549fdc |
while (p2)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (type_field (p2->type) == ASN1_ETYPE_CONSTANT)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (!_asn1_strcmp (p2->name, p->value))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
|
|
Packit |
549fdc |
if (default_temp == NULL)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
free (value_temp);
|
|
Packit |
549fdc |
return ASN1_MEM_ALLOC_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_asn1_convert_integer (p2->value,
|
|
Packit |
549fdc |
default_temp,
|
|
Packit |
549fdc |
SIZEOF_UNSIGNED_LONG_INT,
|
|
Packit |
549fdc |
&len2);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
p2 = p2->right;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
if (p2 == NULL)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
free (value_temp);
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((len - k) == len2)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
for (k2 = 0; k2 < len2; k2++)
|
|
Packit |
549fdc |
if (value_temp[k + k2] != default_temp[k2])
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
if (k2 == len2)
|
|
Packit |
549fdc |
_asn1_set_value (node, NULL, 0);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
free (default_temp);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
free (value_temp);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_OBJECT_ID:
|
|
Packit |
549fdc |
for (i = 0; i < _asn1_strlen (value); i++)
|
|
Packit |
549fdc |
if ((!isdigit (value[i])) && (value[i] != '.') && (value[i] != '+'))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
if (node->type & CONST_DEFAULT)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
if (!_asn1_strcmp (value, p->value))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
_asn1_set_value (node, NULL, 0);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
_asn1_set_value (node, value, _asn1_strlen (value) + 1);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_UTC_TIME:
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
len = _asn1_strlen (value);
|
|
Packit |
549fdc |
if (len < 11)
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
for (k = 0; k < 10; k++)
|
|
Packit |
549fdc |
if (!isdigit (value[k]))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
switch (len)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
case 11:
|
|
Packit |
549fdc |
if (value[10] != 'Z')
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case 13:
|
|
Packit |
549fdc |
if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
|
|
Packit |
549fdc |
(value[12] != 'Z'))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case 15:
|
|
Packit |
549fdc |
if ((value[10] != '+') && (value[10] != '-'))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
for (k = 11; k < 15; k++)
|
|
Packit |
549fdc |
if (!isdigit (value[k]))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case 17:
|
|
Packit |
549fdc |
if ((!isdigit (value[10])) || (!isdigit (value[11])))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
if ((value[12] != '+') && (value[12] != '-'))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
for (k = 13; k < 17; k++)
|
|
Packit |
549fdc |
if (!isdigit (value[k]))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
default:
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_FOUND;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
_asn1_set_value (node, value, len);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_GENERALIZED_TIME:
|
|
Packit |
549fdc |
len = _asn1_strlen (value);
|
|
Packit |
549fdc |
_asn1_set_value (node, value, len);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_OCTET_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_GENERALSTRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_NUMERIC_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_IA5_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_TELETEX_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_PRINTABLE_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_UNIVERSAL_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_BMP_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_UTF8_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_VISIBLE_STRING:
|
|
Packit |
549fdc |
if (len == 0)
|
|
Packit |
549fdc |
len = _asn1_strlen (value);
|
|
Packit |
549fdc |
_asn1_set_value_lv (node, value, len);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_BIT_STRING:
|
|
Packit |
549fdc |
if (len == 0)
|
|
Packit |
549fdc |
len = _asn1_strlen (value);
|
|
Packit |
549fdc |
asn1_length_der ((len >> 3) + 2, NULL, &len2);
|
|
Packit |
549fdc |
temp = malloc ((len >> 3) + 2 + len2);
|
|
Packit |
549fdc |
if (temp == NULL)
|
|
Packit |
549fdc |
return ASN1_MEM_ALLOC_ERROR;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
asn1_bit_der (value, len, temp, &len2);
|
|
Packit |
549fdc |
_asn1_set_value_m (node, temp, len2);
|
|
Packit |
549fdc |
temp = NULL;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_CHOICE:
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (p)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (!_asn1_strcmp (p->name, value))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p2 = node->down;
|
|
Packit |
549fdc |
while (p2)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (p2 != p)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
asn1_delete_structure (&p2;;
|
|
Packit |
549fdc |
p2 = node->down;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
p2 = p2->right;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
if (!p)
|
|
Packit |
549fdc |
return ASN1_ELEMENT_NOT_FOUND;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_ANY:
|
|
Packit |
549fdc |
_asn1_set_value_lv (node, value, len);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_SEQUENCE_OF:
|
|
Packit |
549fdc |
case ASN1_ETYPE_SET_OF:
|
|
Packit |
549fdc |
if (_asn1_strcmp (value, "NEW"))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_VALID;
|
|
Packit |
549fdc |
_asn1_append_sequence_set (node, NULL);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
default:
|
|
Packit |
549fdc |
return ASN1_ELEMENT_NOT_FOUND;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ASN1_SUCCESS;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#define PUT_VALUE( ptr, ptr_size, data, data_size) \
|
|
Packit |
549fdc |
*len = data_size; \
|
|
Packit |
549fdc |
if (ptr_size < data_size) { \
|
|
Packit |
549fdc |
return ASN1_MEM_ERROR; \
|
|
Packit |
549fdc |
} else { \
|
|
Packit |
549fdc |
if (ptr && data_size > 0) \
|
|
Packit |
549fdc |
memcpy (ptr, data, data_size); \
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#define PUT_STR_VALUE( ptr, ptr_size, data) \
|
|
Packit |
549fdc |
*len = _asn1_strlen (data) + 1; \
|
|
Packit |
549fdc |
if (ptr_size < *len) { \
|
|
Packit |
549fdc |
return ASN1_MEM_ERROR; \
|
|
Packit |
549fdc |
} else { \
|
|
Packit |
549fdc |
/* this strcpy is checked */ \
|
|
Packit |
549fdc |
if (ptr) { \
|
|
Packit |
549fdc |
_asn1_strcpy (ptr, data); \
|
|
Packit |
549fdc |
} \
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
|
|
Packit |
549fdc |
*len = data_size + 1; \
|
|
Packit |
549fdc |
if (ptr_size < *len) { \
|
|
Packit |
549fdc |
return ASN1_MEM_ERROR; \
|
|
Packit |
549fdc |
} else { \
|
|
Packit |
549fdc |
/* this strcpy is checked */ \
|
|
Packit |
549fdc |
if (ptr) { \
|
|
Packit |
549fdc |
if (data_size > 0) \
|
|
Packit |
549fdc |
memcpy (ptr, data, data_size); \
|
|
Packit |
549fdc |
ptr[data_size] = 0; \
|
|
Packit |
549fdc |
} \
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#define ADD_STR_VALUE( ptr, ptr_size, data) \
|
|
Packit |
549fdc |
*len += _asn1_strlen(data); \
|
|
Packit |
549fdc |
if (ptr_size < (int) *len) { \
|
|
Packit |
549fdc |
(*len)++; \
|
|
Packit |
549fdc |
return ASN1_MEM_ERROR; \
|
|
Packit |
549fdc |
} else { \
|
|
Packit |
549fdc |
/* this strcat is checked */ \
|
|
Packit |
549fdc |
if (ptr) _asn1_strcat (ptr, data); \
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* asn1_read_value:
|
|
Packit |
549fdc |
* @root: pointer to a structure.
|
|
Packit |
549fdc |
* @name: the name of the element inside a structure that you want to read.
|
|
Packit |
549fdc |
* @ivalue: vector that will contain the element's content, must be a
|
|
Packit |
549fdc |
* pointer to memory cells already allocated (may be %NULL).
|
|
Packit |
549fdc |
* @len: number of bytes of *value: value[0]..value[len-1]. Initialy
|
|
Packit |
549fdc |
* holds the sizeof value.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns the value of one element inside a structure.
|
|
Packit |
549fdc |
* If an element is OPTIONAL and this returns
|
|
Packit |
549fdc |
* %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
|
|
Packit |
549fdc |
* in the der encoding that created the structure. The first element
|
|
Packit |
549fdc |
* of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
|
|
Packit |
549fdc |
* so on. If the @root provided is a node to specific sequence element,
|
|
Packit |
549fdc |
* then the keyword "?CURRENT" is also acceptable and indicates the
|
|
Packit |
549fdc |
* current sequence element of this node.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that there can be valid values with length zero. In these case
|
|
Packit |
549fdc |
* this function will succeed and @len will be zero.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* INTEGER: VALUE will contain a two's complement form integer.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* integer=-1 -> value[0]=0xFF , len=1.
|
|
Packit |
549fdc |
* integer=1 -> value[0]=0x01 , len=1.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* ENUMERATED: As INTEGER (but only with not negative numbers).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* BOOLEAN: VALUE will be the null terminated string "TRUE" or
|
|
Packit |
549fdc |
* "FALSE" and LEN=5 or LEN=6.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* OBJECT IDENTIFIER: VALUE will be a null terminated string with
|
|
Packit |
549fdc |
* each number separated by a dot (i.e. "1.2.3.543.1").
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* LEN = strlen(VALUE)+1
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* UTCTime: VALUE will be a null terminated string in one of these
|
|
Packit |
549fdc |
* formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'".
|
|
Packit |
549fdc |
* LEN=strlen(VALUE)+1.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* GeneralizedTime: VALUE will be a null terminated string in the
|
|
Packit |
549fdc |
* same format used to set the value.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* OCTET STRING: VALUE will contain the octet string and LEN will be
|
|
Packit |
549fdc |
* the number of octets.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* GeneralString: VALUE will contain the generalstring and LEN will
|
|
Packit |
549fdc |
* be the number of octets.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* BIT STRING: VALUE will contain the bit string organized by bytes
|
|
Packit |
549fdc |
* and LEN will be the number of bits.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* CHOICE: If NAME indicates a choice type, VALUE will specify the
|
|
Packit |
549fdc |
* alternative selected.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* ANY: If NAME indicates an any type, VALUE will indicate the DER
|
|
Packit |
549fdc |
* encoding of the structure actually used.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %ASN1_SUCCESS if value is returned,
|
|
Packit |
549fdc |
* %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element,
|
|
Packit |
549fdc |
* %ASN1_VALUE_NOT_FOUND if there isn't any value for the element
|
|
Packit |
549fdc |
* selected, and %ASN1_MEM_ERROR if The value vector isn't big enough
|
|
Packit |
549fdc |
* to store the result, and in this case @len will contain the number of
|
|
Packit |
549fdc |
* bytes needed. On the occasion that the stored data are of zero-length
|
|
Packit |
549fdc |
* this function may return %ASN1_SUCCESS even if the provided @len is zero.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return asn1_read_value_type (root, name, ivalue, len, NULL);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* asn1_read_value_type:
|
|
Packit |
549fdc |
* @root: pointer to a structure.
|
|
Packit |
549fdc |
* @name: the name of the element inside a structure that you want to read.
|
|
Packit |
549fdc |
* @ivalue: vector that will contain the element's content, must be a
|
|
Packit |
549fdc |
* pointer to memory cells already allocated (may be %NULL).
|
|
Packit |
549fdc |
* @len: number of bytes of *value: value[0]..value[len-1]. Initialy
|
|
Packit |
549fdc |
* holds the sizeof value.
|
|
Packit |
549fdc |
* @etype: The type of the value read (ASN1_ETYPE)
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns the type and value of one element inside a structure.
|
|
Packit |
549fdc |
* If an element is OPTIONAL and this returns
|
|
Packit |
549fdc |
* %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
|
|
Packit |
549fdc |
* in the der encoding that created the structure. The first element
|
|
Packit |
549fdc |
* of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
|
|
Packit |
549fdc |
* so on. If the @root provided is a node to specific sequence element,
|
|
Packit |
549fdc |
* then the keyword "?CURRENT" is also acceptable and indicates the
|
|
Packit |
549fdc |
* current sequence element of this node.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that there can be valid values with length zero. In these case
|
|
Packit |
549fdc |
* this function will succeed and @len will be zero.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* INTEGER: VALUE will contain a two's complement form integer.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* integer=-1 -> value[0]=0xFF , len=1.
|
|
Packit |
549fdc |
* integer=1 -> value[0]=0x01 , len=1.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* ENUMERATED: As INTEGER (but only with not negative numbers).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* BOOLEAN: VALUE will be the null terminated string "TRUE" or
|
|
Packit |
549fdc |
* "FALSE" and LEN=5 or LEN=6.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* OBJECT IDENTIFIER: VALUE will be a null terminated string with
|
|
Packit |
549fdc |
* each number separated by a dot (i.e. "1.2.3.543.1").
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* LEN = strlen(VALUE)+1
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* UTCTime: VALUE will be a null terminated string in one of these
|
|
Packit |
549fdc |
* formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'".
|
|
Packit |
549fdc |
* LEN=strlen(VALUE)+1.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* GeneralizedTime: VALUE will be a null terminated string in the
|
|
Packit |
549fdc |
* same format used to set the value.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* OCTET STRING: VALUE will contain the octet string and LEN will be
|
|
Packit |
549fdc |
* the number of octets.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* GeneralString: VALUE will contain the generalstring and LEN will
|
|
Packit |
549fdc |
* be the number of octets.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* BIT STRING: VALUE will contain the bit string organized by bytes
|
|
Packit |
549fdc |
* and LEN will be the number of bits.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* CHOICE: If NAME indicates a choice type, VALUE will specify the
|
|
Packit |
549fdc |
* alternative selected.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* ANY: If NAME indicates an any type, VALUE will indicate the DER
|
|
Packit |
549fdc |
* encoding of the structure actually used.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %ASN1_SUCCESS if value is returned,
|
|
Packit |
549fdc |
* %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element,
|
|
Packit |
549fdc |
* %ASN1_VALUE_NOT_FOUND if there isn't any value for the element
|
|
Packit |
549fdc |
* selected, and %ASN1_MEM_ERROR if The value vector isn't big enough
|
|
Packit |
549fdc |
* to store the result, and in this case @len will contain the number of
|
|
Packit |
549fdc |
* bytes needed. On the occasion that the stored data are of zero-length
|
|
Packit |
549fdc |
* this function may return %ASN1_SUCCESS even if the provided @len is zero.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
|
|
Packit |
549fdc |
int *len, unsigned int *etype)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
asn1_node node, p, p2;
|
|
Packit |
549fdc |
int len2, len3, result;
|
|
Packit |
549fdc |
int value_size = *len;
|
|
Packit |
549fdc |
unsigned char *value = ivalue;
|
|
Packit |
549fdc |
unsigned type;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
node = asn1_find_node (root, name);
|
|
Packit |
549fdc |
if (node == NULL)
|
|
Packit |
549fdc |
return ASN1_ELEMENT_NOT_FOUND;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
type = type_field (node->type);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if ((type != ASN1_ETYPE_NULL) &&
|
|
Packit |
549fdc |
(type != ASN1_ETYPE_CHOICE) &&
|
|
Packit |
549fdc |
!(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) &&
|
|
Packit |
549fdc |
(node->value == NULL))
|
|
Packit |
549fdc |
return ASN1_VALUE_NOT_FOUND;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (etype)
|
|
Packit |
549fdc |
*etype = type;
|
|
Packit |
549fdc |
switch (type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
case ASN1_ETYPE_NULL:
|
|
Packit |
549fdc |
PUT_STR_VALUE (value, value_size, "NULL");
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_BOOLEAN:
|
|
Packit |
549fdc |
if ((node->type & CONST_DEFAULT) && (node->value == NULL))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
if (p->type & CONST_TRUE)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
PUT_STR_VALUE (value, value_size, "TRUE");
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
PUT_STR_VALUE (value, value_size, "FALSE");
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else if (node->value[0] == 'T')
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
PUT_STR_VALUE (value, value_size, "TRUE");
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
PUT_STR_VALUE (value, value_size, "FALSE");
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_INTEGER:
|
|
Packit |
549fdc |
case ASN1_ETYPE_ENUMERATED:
|
|
Packit |
549fdc |
if ((node->type & CONST_DEFAULT) && (node->value == NULL))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
if ((isdigit (p->value[0])) || (p->value[0] == '-')
|
|
Packit |
549fdc |
|| (p->value[0] == '+'))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
result = _asn1_convert_integer
|
|
Packit |
549fdc |
(p->value, value, value_size, len);
|
|
Packit |
549fdc |
if (result != ASN1_SUCCESS)
|
|
Packit |
549fdc |
return result;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{ /* is an identifier like v1 */
|
|
Packit |
549fdc |
p2 = node->down;
|
|
Packit |
549fdc |
while (p2)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (type_field (p2->type) == ASN1_ETYPE_CONSTANT)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (!_asn1_strcmp (p2->name, p->value))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
result = _asn1_convert_integer
|
|
Packit |
549fdc |
(p2->value, value, value_size,
|
|
Packit |
549fdc |
len);
|
|
Packit |
549fdc |
if (result != ASN1_SUCCESS)
|
|
Packit |
549fdc |
return result;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
p2 = p2->right;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
len2 = -1;
|
|
Packit |
549fdc |
result = asn1_get_octet_der
|
|
Packit |
549fdc |
(node->value, node->value_len, &len2, value, value_size,
|
|
Packit |
549fdc |
len);
|
|
Packit |
549fdc |
if (result != ASN1_SUCCESS)
|
|
Packit |
549fdc |
return result;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_OBJECT_ID:
|
|
Packit |
549fdc |
if (node->type & CONST_ASSIGN)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
*len = 0;
|
|
Packit |
549fdc |
if (value)
|
|
Packit |
549fdc |
value[0] = 0;
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (p)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (type_field (p->type) == ASN1_ETYPE_CONSTANT)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
ADD_STR_VALUE (value, value_size, p->value);
|
|
Packit |
549fdc |
if (p->right)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
ADD_STR_VALUE (value, value_size, ".");
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
(*len)++;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
PUT_STR_VALUE (value, value_size, p->value);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
PUT_STR_VALUE (value, value_size, node->value);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_GENERALIZED_TIME:
|
|
Packit |
549fdc |
case ASN1_ETYPE_UTC_TIME:
|
|
Packit |
549fdc |
PUT_AS_STR_VALUE (value, value_size, node->value, node->value_len);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_OCTET_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_GENERALSTRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_NUMERIC_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_IA5_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_TELETEX_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_PRINTABLE_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_UNIVERSAL_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_BMP_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_UTF8_STRING:
|
|
Packit |
549fdc |
case ASN1_ETYPE_VISIBLE_STRING:
|
|
Packit |
549fdc |
len2 = -1;
|
|
Packit |
549fdc |
result = asn1_get_octet_der
|
|
Packit |
549fdc |
(node->value, node->value_len, &len2, value, value_size,
|
|
Packit |
549fdc |
len);
|
|
Packit |
549fdc |
if (result != ASN1_SUCCESS)
|
|
Packit |
549fdc |
return result;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_BIT_STRING:
|
|
Packit |
549fdc |
len2 = -1;
|
|
Packit |
549fdc |
result = asn1_get_bit_der
|
|
Packit |
549fdc |
(node->value, node->value_len, &len2, value, value_size,
|
|
Packit |
549fdc |
len);
|
|
Packit |
549fdc |
if (result != ASN1_SUCCESS)
|
|
Packit |
549fdc |
return result;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_CHOICE:
|
|
Packit |
549fdc |
PUT_STR_VALUE (value, value_size, node->down->name);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_ANY:
|
|
Packit |
549fdc |
len3 = -1;
|
|
Packit |
549fdc |
len2 = asn1_get_length_der (node->value, node->value_len, &len3);
|
|
Packit |
549fdc |
if (len2 < 0)
|
|
Packit |
549fdc |
return ASN1_DER_ERROR;
|
|
Packit |
549fdc |
PUT_VALUE (value, value_size, node->value + len3, len2);
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
default:
|
|
Packit |
549fdc |
return ASN1_ELEMENT_NOT_FOUND;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
return ASN1_SUCCESS;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* asn1_read_tag:
|
|
Packit |
549fdc |
* @root: pointer to a structure
|
|
Packit |
549fdc |
* @name: the name of the element inside a structure.
|
|
Packit |
549fdc |
* @tagValue: variable that will contain the TAG value.
|
|
Packit |
549fdc |
* @classValue: variable that will specify the TAG type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns the TAG and the CLASS of one element inside a structure.
|
|
Packit |
549fdc |
* CLASS can have one of these constants: %ASN1_CLASS_APPLICATION,
|
|
Packit |
549fdc |
* %ASN1_CLASS_UNIVERSAL, %ASN1_CLASS_PRIVATE or
|
|
Packit |
549fdc |
* %ASN1_CLASS_CONTEXT_SPECIFIC.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
|
|
Packit |
549fdc |
* @name is not a valid element.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
asn1_read_tag (asn1_node root, const char *name, int *tagValue,
|
|
Packit |
549fdc |
int *classValue)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
asn1_node node, p, pTag;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
node = asn1_find_node (root, name);
|
|
Packit |
549fdc |
if (node == NULL)
|
|
Packit |
549fdc |
return ASN1_ELEMENT_NOT_FOUND;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
p = node->down;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* pTag will points to the IMPLICIT TAG */
|
|
Packit |
549fdc |
pTag = NULL;
|
|
Packit |
549fdc |
if (node->type & CONST_TAG)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
while (p)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (type_field (p->type) == ASN1_ETYPE_TAG)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if ((p->type & CONST_IMPLICIT) && (pTag == NULL))
|
|
Packit |
549fdc |
pTag = p;
|
|
Packit |
549fdc |
else if (p->type & CONST_EXPLICIT)
|
|
Packit |
549fdc |
pTag = NULL;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
p = p->right;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (pTag)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
*tagValue = _asn1_strtoul (pTag->value, NULL, 10);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (pTag->type & CONST_APPLICATION)
|
|
Packit |
549fdc |
*classValue = ASN1_CLASS_APPLICATION;
|
|
Packit |
549fdc |
else if (pTag->type & CONST_UNIVERSAL)
|
|
Packit |
549fdc |
*classValue = ASN1_CLASS_UNIVERSAL;
|
|
Packit |
549fdc |
else if (pTag->type & CONST_PRIVATE)
|
|
Packit |
549fdc |
*classValue = ASN1_CLASS_PRIVATE;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
*classValue = ASN1_CLASS_CONTEXT_SPECIFIC;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
unsigned type = type_field (node->type);
|
|
Packit |
549fdc |
*classValue = ASN1_CLASS_UNIVERSAL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
switch (type)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
CASE_HANDLED_ETYPES:
|
|
Packit |
549fdc |
*tagValue = _asn1_tags[type].tag;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
case ASN1_ETYPE_TAG:
|
|
Packit |
549fdc |
case ASN1_ETYPE_CHOICE:
|
|
Packit |
549fdc |
case ASN1_ETYPE_ANY:
|
|
Packit |
549fdc |
*tagValue = -1;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
default:
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ASN1_SUCCESS;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* asn1_read_node_value:
|
|
Packit |
549fdc |
* @node: pointer to a node.
|
|
Packit |
549fdc |
* @data: a point to a asn1_data_node_st
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns the value a data node inside a asn1_node structure.
|
|
Packit |
549fdc |
* The data returned should be handled as constant values.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %ASN1_SUCCESS if the node exists.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
asn1_read_node_value (asn1_node node, asn1_data_node_st * data)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
data->name = node->name;
|
|
Packit |
549fdc |
data->value = node->value;
|
|
Packit |
549fdc |
data->value_len = node->value_len;
|
|
Packit |
549fdc |
data->type = type_field (node->type);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ASN1_SUCCESS;
|
|
Packit |
549fdc |
}
|