Page MenuHome GnuPG

README.asn1
No OneTemporary

README.asn1

------------------------------------------------ -*- text -*-
-- Readme file for ASN1 parser --
-- --
-- Originator: Fabio Fiorina --
-- e-mail: Fabio.Fiorina@alcatel.it --
-- fiorinaf@bgonline.it --
-- Changed: wk@gnupg.org
------------------------------------------------
INTRODUCTION
------------
This file describes the forth version of ASN.1 parser I developed.
The main difference from the first version is the use of pointers and
the possibility to save/get ASN1 definitions in/from a C vector.
Other differences are:
- write_value function for type ANY
- the introduction of ENUMERATED type,
- negative integer are allowed in ASN.1 syntax files,
- PKIX1Implicit88.txt instead of Certificate.txt for the
Certificate description
- functions naming
- an easier way to set INTEGER and get OBJECT IDENTFIER
FILE LIST
---------
README.asn1 (ASN.readme.txt) this file
asn1-parse.y (cert_ASN.y) bison input file
asn1-func.c (cert_asn1.c) functions for ASN1 parser and for
reading and setting elements value
asn1-func.h (cert_asn1.h) contains constants for the
gnutls_asn1.c. Must be included in files
that use ASN1 parser.
CertificateExample.c example based on Appendix D.1 of rfc2459
These files are not used:
CrlExample.c example based on Appendix D.4 of rfc2459
PkixTabExample.c the program used to create pkix_asn1_tab.c
pkix.asn certificate and CRL structures
pkix_asn1_tab.c C vector to use with 'asn1_create_tree' function.
It was created from pkix.asn file.
ASN.1 SYNTAX
------------
The parser is case sensitive. The comments begin with "-- " and end at
the end of line. An example is in "Certificate.txt" file.
The ASN.1 declarations must have this form:
object_name {<object definition>}
DEFINITIONS <EXPLICIT or IMPLICIT> TAGS ::=
BEGIN
<type and constants definitions>
END
The token "::=" must be separate from others elements, so this is a
wrong declaration:
Version ::=INTEGER
the correct one is :
Version ::= INTEGER
Here is the list of types that the parser can manage:
INTEGER
ENUMERATED
BOOLEAN
OBJECT IDENTIFIER
NULL
BIT STRING
OCTET STRING
UTCTime
GeneralizedTime
SEQUENCE
SEQUENCE OF
SET
SET OF
CHOICE
ANY
ANY DEFINED BY
This version doesn't manage REAL type. It also not allow the use of
"EXPORT" and "IMPORT" sections.
The SIZE constraints are allowed but no check is done on them.
NAMING
--------
If you have this definitions:
Example { 1 2 3 4 }
DEFINITIONS EXPLICIT TAGS ::=
BEGIN
Group ::= SEQUENCE {
id OBJECT IDENTIFIER,
value Value
}
Value ::= SEQUENCE {
value1 INTEGER,
value2 BOOLEAN
}
END
to identify the type 'Group' you have to use the null terminated
string "Example.Group". Others examples:
Field 'id' in 'Group' type: "Example.Group.id"
Field 'value1' in filed 'value' in type 'Group': "Example.Group.value.value1"
These strings are used in functions that are described below.
Elements of structured types that don't have a name, receve the name
"?1","?2", and so on. The name "?LAST" indicates the last element of
a SET_OF or SEQUENCE_OF.
FUNCTIONS
---------
int asn1_parser_asn1(char *file_name,node_asn **pointer);
--------------------------------------------------------
Creates the structures needed to manage the definitions included in
*FILE_NAME file.
Input Parameter:
char *file_name: specify the path and the name of file that
contains ASN.1 declarations.
Output Parameter:
node_asn **pointer : return the pointer to the structure created from
"file_name" ASN.1 declarations.
Return Value:
ASN_OK: the file has a correct syntax and
every identifier is known.
ASN_FILE_NOT_FOUND: an error occured while opening FILE_NAME.
ASN_SYNTAX_ERROR: the syntax is not correct.
ASN_IDENTIFIER_NOT_FOUND: in the file there is an identifier that
is not defined.
int asn1_parser_asn1_file_c(char *file_name);
--------------------------------------------
Creates a file containing a C vector to use to manage the definitions
included in *FILE_NAME file. If *FILE_NAME is "/aa/bb/xx.yy" the file
created is "/aa/bb/xx_asn1_tab.c", and the vector is "xx_asn1_tab".
Input Parameter:
char *file_name: specify the path and the name of file that contains
ASN.1 declarations.
Return Value:
ASN_OK: the file has a correct syntax and every identifier is known.
ASN_FILE_NOT_FOUND: an error occured while opening FILE_NAME.
ASN_SYNTAX_ERROR: the syntax is not correct.
ASN_IDENTIFIER_NOT_FOUND: in the file there is an identifier that is
not defined.
int asn1_create_tree(static_asn *root,node_asn **pointer);
---------------------------------------------------------
Creates the structures needed to manage the ASN1 definitions. ROOT is
a vector created by 'asn1_parser_asn1_file_c' function.
Input Parameter:
static_asn *root: specify vector that contains ASN.1 declarations.
Output Parameter:
node_asn **pointer : return the pointer to the structure created by
*ROOT ASN.1 declarations.
Return Value:
ASN_OK: structure created correctly.
ASN_GENERIC_ERROR: an error occured while structure creation.
int asn1_create_structure(node_asn *p_structure, char *source_name,
node_asn **pointer, char *dest_name);
----------------------------------------------------------------
Creates a structure called DEST_NAME of type SOURCE_NAME.
Input Parameters:
node_asn *p_structure: pointer to the structure returned by
"parser_asn1" function
char *source_name: the name of the type of the new structure (must
be inside p_structure).
char *dest_name: the name of the new structure.
Output Parameter:
node_asn **pointer : pointer to the structure created.
Return Value:
ASN_OK: creation OK
ASN_ELEMENT_NOT_FOUND: SOURCE_NAME isn't known
Example: using "pkix.asn"
result=asn1_create_structure(cert_def,"PKIX1Implicit88.Certificate",
&cert,"certificate1");
int asn1_write_value(node_asn *pointer,char *name,
unsigned char *value,int len);
--------------------------------------------------
Set the value of one element inside a structure.
Input Parameters:
node_asn *pointer: pointer to a structure
char *name: the name of the element inside the structure that you
want to set.
unsigned char *value: vector used to specify the value to set. If len is >0,
*VALUE must be a two's complement form integer.
if len=0 *VALUE must be a null terminated
string with an integer value.
int len: number of bytes of *value to use to set the value:
value[0]..value[len-1] or 0 if value is a null terminated
string
Return Value:
ASN_OK: set value OK
ASN_ELEMENT_NOT_FOUND: NAME is not a valid element.
ASN_VALUE_NOT_VALID: VALUE has a wrong format.
Examples: description for each type
INTEGER: VALUE must contain a two's complement form integer.
value[0]=0xFF , len=1 -> integer=-1
value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1
value[0]=0x01 , len=1 -> integer= 1
value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1
value="123" , len=0 -> integer= 123
ENUMERATED: as INTEGER (but only with not negative numbers)
BOOLEAN: VALUE must be the null terminated string "TRUE" or "FALSE" and LEN != 0
value="TRUE" , len=1 -> boolean=TRUE
value="FALSE" , len=1 -> boolean=FALSE
OBJECT IDENTIFIER: VALUE must be a null terminated string with each number separated by
a blank (e.g. "1 2 3 543 1").
LEN != 0
value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha
UTCTime: VALUE must be a null terminated string in one of these formats:
"YYMMDDhhmmssZ" "YYMMDDhhmmssZ" "YYMMDDhhmmss+hh'mm'" "YYMMDDhhmmss-hh'mm'"
"YYMMDDhhmm+hh'mm'" "YYMMDDhhmm-hh'mm'".
LEN != 0
value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998 at 12h 00m Greenwich Mean Time
GeneralizedTime: VALUE must be in one of this format:
"YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.s+hh'mm'"
"YYYYMMDDhhmmss.s-hh'mm'" "YYYYMMDDhhmm+hh'mm'" "YYYYMMDDhhmm-hh'mm'"
where ss.s indicates the seconds with any precision like "10.1" or "01.02".
LEN != 0
value="2001010112001.12-0700" , len=1 -> time=Jannuary 1st, 2001 at 12h 00m 01.12s
Pacific Daylight Time
OCTET STRING: VALUE contains the octet string and LEN is the number of octet.
value="\x01\x02\x03" , len=3 -> three bytes octet string
BIT STRING: VALUE contains the bit string organized by bytes and LEN is the number of bits.
value="\xCF" , len=6 -> bit string="110011" (six bits)
CHOICE: if NAME indicates a choice type, VALUE must specify one of the alternatives with a
null terminated string. LEN != 0
Using "pkix.asn":
result=asn1_write_value(cert,"certificate1.tbsCertificate.subject","rdnSequence",1);
ANY: VALUE indicates the der encoding of a structure.
LEN != 0
SEQUENCE OF: VALUE must be the null terminated string "NEW" and LEN != 0. With this
instruction another element is appended in the sequence. The name of this
element will be "?1" if it's the first one, "?2" for the second and so on.
Using "pkix.asn":
result=asn1_write_value(cert,"certificate1.tbsCertificate.subject.rdnSequence","NEW",1);
SET OF: the same as SEQUENCE OF.
Using "pkix.asn":
result=asn1_write_value(cert,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
If an element is OPTIONAL and you want to delete it, you must use the value=NULL and len=0.
Using "pkix.asn":
result=asn1_write_value(cert,"certificate1.tbsCertificate.issuerUniqueID",NULL,0);
int asn1_read_value(node_asn *pointer,char *name,unsigned char *value,int *len);
--------------------------------------------------------
Returns the value of one element inside a structure.
Input Parameters:
node_asn *pointer: pointer to a structure
char *name: the name of the element inside a structure that you want to read.
Output Parameters:
unsigned char *value: vector that will contain the element's content.
VALUE must be a pointer to memory cells already allocated.
int *len: number of bytes of *value: value[0]..value[len-1]
Return Value:
ASN_OK: set value OK
ASN_ELEMENT_NOT_FOUND: NAME is not a valid element.
ASN_VALUE_NOT_FOUND: there isn't any value for the element selected.
Examples: a description for each type
INTEGER: VALUE will contain a two's complement form integer.
integer=-1 -> value[0]=0xFF , len=1
integer=1 -> value[0]=0x01 , len=1
ENUMERATED: as INTEGER (but only with not negative numbers)
BOOLEAN: VALUE will be the null terminated string "TRUE" or "FALSE" and LEN=5 or LEN=6
OBJECT IDENTIFIER: VALUE will be a null terminated string with each number separated by
a blank (i.e. "1 2 3 543 1").
LEN = strlen(VALUE)+1
UTCTime: VALUE will be a null terminated string in one of these formats:
"YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'"
LEN=strlen(VALUE)+1
GeneralizedTime: VALUE will be a null terminated string in the same format used to set
the value
OCTET STRING: VALUE will contain the octet string and LEN will be the number of octet.
BIT STRING: VALUE will contain the bit string organized by bytes and LEN will be the
number of bits.
CHOICE: if NAME indicates a choice type, VALUE will specify the alternative selected
ANY: if NAME indicates an any type, VALUE will indicate the DER encoding of the structure
actually used.
If an element is OPTIONAL and the function "read_value" returns ASN_ELEMENT_NOT_FOUND, it
means that this element wasn't present in the der encoding that created the structure.
The first element of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and so on.
int asn1_create_der(node_asn *pointer,char *name,unsigned char *der,int *len);
------------------------------------------------------
Creates the DER encoding for the NAME structure (inside *POINTER structure).
Input Parameters:
node_asn *pointer: pointer to a structure
char *name: the name of the structure you want to encode (it must be inside *POINTER).
Output Parameters:
unsigned char *der: vector that will contain the DER encoding.
DER must be a pointer to memory cells already allocated.
int *len: number of bytes of *der: der[0]..der[len-1]
Return Value:
ASN_OK: DER encoding OK
ASN_ELEMENT_NOT_FOUND: NAME is not a valid element.
ASN_VALUE_NOT_FOUND: there is an element without a value.
int asn1_get_der(node_asn *pointer,char *name,unsigned char *der,int len);
--------------------------------------------------------------------------
Fill the structure *POINTER with values of a DER encoding string. The
sructure must just be created with function 'create_stucture'.
Input Parameters:
node_asn *pointer: Pointer to the structure that you want to fill.
unsigned char *der: Vector that contains the DER encoding.
int len: Number of bytes of *der: der[0]..der[len-1]
Return Value:
ASN_OK: DER encoding OK
ASN_ELEMENT_NOT_FOUND: NAME is not a valid element.
ASN_TAG_ERROR, ASN_DER_ERROR: The der encoding doesn't match the
structure NAME.
int asn1_get_start_end_der(node_asn *pointer,
unsigned char *der, int len,
char *name_element, int *start, int *end)
--------------------------------------------------------------------
Find the start and end point of an element in a DER encoding string. I
mean that if you have a der encoding and you have already used the
function "get_der" to fill a structure, it may happen that you want to
find the piece of string concerning an element of the structure.
Example: the sequence "tbsCertificate" inside an X509 certificate.
Input Parameters:
node_asn *pointer: The pointer to the structure that is already
setted with DER string.
unsigned char *der: Vector that contains the DER encoding.
int len: Number of bytes of *der: der[0]..der[len-1]
char *name_element: An element of NAME structure.
Output Parameters:
int *start: The position of the first byte of NAME_ELEMENT
decoding (der[*start])
int *end: The position of the last byte of NAME_ELEMENT
decoding (der[*end])
Return Value:
ASN_OK: DER encoding OK
ASN_ELEMENT_NOT_FOUND: NAME or NAME_ELEMENT is not a valid element.
ASN_TAG_ERROR, ASN_DER_ERROR: the der encoding doesn't match the
structure NAME.
int asn1_delete_structure(node_asn *pointer);
---------------------------------
Deletes the structure *POINTER.
Input Parameters:
node_asn *pointer: pointer to the structure that you want to delete.
Return Value:
ASN_OK: everything OK
ASN_ELEMENT_NOT_FOUND: pointer==NULL.
void asn1_visit_tree(node_asn *pointer,char *name);
---------------------------------------------------
Prints on the standard output the structure's tree starting from the
NAME element inside the structure *POINTER.
FUTURE DEVELOPMENTS
-------------------
1. type REAL
2. improve the error signaling with strings that give you more details.
Examples: in case of ASN1 syntax error you will have the line
number where the error is, if creating a der encoding the result
is ASN_VALUE_NOT_FOUND you will have the name of the element
without the value.
3. improve the 'visit_tree' function and change the output from stdout
to a null terminated string.

File Metadata

Mime Type
text/plain
Expires
Mon, Dec 23, 1:18 PM (21 m, 44 s)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
b4/36/ee92ce3cd38cbf26d2e1eeabaf8a

Event Timeline