From bbfe113c2d7540c6883eb3d83d7052f49f7988fc Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 24 Nov 2012 09:41:50 +0100 Subject: [PATCH] Introduced ASN1_ETYPE_UTC_TIME and ASN1_ETYPE_GENERALIZED_TIME --- NEWS | 1 + lib/ASN1.c | 4 ++-- lib/ASN1.y | 4 ++-- lib/coding.c | 20 +++++++++----------- lib/decoding.c | 30 ++++++++++++------------------ lib/element.c | 30 ++++++++++++------------------ lib/int.h | 30 ++++++++++++++++++++++++------ lib/libtasn1.h | 3 ++- lib/structure.c | 6 ++---- 9 files changed, 66 insertions(+), 62 deletions(-) diff --git a/NEWS b/NEWS index 371e804..b2dddec 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ GNU Libtasn1 NEWS -*- outline -*- - Parser outputs more detailed syntax error message. - Added asn1_decode_simple_der() and asn1_encode_simple_der(). - Added asn1_read_value_type() to return value and type. +- Introduced ASN1_ETYPE_UTC_TIME and ASN1_ETYPE_GENERALIZED_TIME * Noteworthy changes in release 3.0 (2012-10-28) [stable] - Added tool in tests/ to benchmark X.509 structure decoding. diff --git a/lib/ASN1.c b/lib/ASN1.c index 928d28d..2a60527 100644 --- a/lib/ASN1.c +++ b/lib/ASN1.c @@ -1987,14 +1987,14 @@ yyreduce: /* Line 1806 of yacc.c */ #line 233 "ASN1.y" - {(yyval.node)=_asn1_add_static_node(ASN1_ETYPE_TIME|CONST_UTC);} + {(yyval.node)=_asn1_add_static_node(ASN1_ETYPE_UTC_TIME);} break; case 39: /* Line 1806 of yacc.c */ #line 234 "ASN1.y" - {(yyval.node)=_asn1_add_static_node(ASN1_ETYPE_TIME|CONST_GENERALIZED);} + {(yyval.node)=_asn1_add_static_node(ASN1_ETYPE_GENERALIZED_TIME);} break; case 40: diff --git a/lib/ASN1.y b/lib/ASN1.y index dafe15a..874eb13 100644 --- a/lib/ASN1.y +++ b/lib/ASN1.y @@ -230,8 +230,8 @@ integer_def: INTEGER {$$=_asn1_add_static_node(ASN1_ETYPE_INT boolean_def: BOOLEAN {$$=_asn1_add_static_node(ASN1_ETYPE_BOOLEAN);} ; -Time: UTCTime {$$=_asn1_add_static_node(ASN1_ETYPE_TIME|CONST_UTC);} - | GeneralizedTime {$$=_asn1_add_static_node(ASN1_ETYPE_TIME|CONST_GENERALIZED);} +Time: UTCTime {$$=_asn1_add_static_node(ASN1_ETYPE_UTC_TIME);} + | GeneralizedTime {$$=_asn1_add_static_node(ASN1_ETYPE_GENERALIZED_TIME);} ; size_def2: SIZE'('num_identifier')' {$$=_asn1_add_static_node(ASN1_ETYPE_SIZE|CONST_1_PARAM); diff --git a/lib/coding.c b/lib/coding.c index 5c1a58b..c39c595 100644 --- a/lib/coding.c +++ b/lib/coding.c @@ -216,6 +216,10 @@ asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned i if (ETYPE_OK(etype) == 0) return ASN1_VALUE_NOT_VALID; + /* doesn't handle constructed classes */ + if (ETYPE_CLASS(etype) != ASN1_CLASS_UNIVERSAL) + return ASN1_VALUE_NOT_VALID; + _asn1_tag_der (ETYPE_CLASS(etype), ETYPE_TAG(etype), der_tag, &tag_len); @@ -536,7 +540,10 @@ const tag_and_class_st _asn1_tags[] = [ASN1_ETYPE_SEQUENCE_OF] ={ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SEQ_OF"}, [ASN1_ETYPE_SET] = {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"}, [ASN1_ETYPE_SET_OF] = {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET_OF"}, + [ASN1_ETYPE_GENERALIZED_TIME] = {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"}, + [ASN1_ETYPE_UTC_TIME] = {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"}, }; + unsigned int _asn1_tags_size = sizeof(_asn1_tags)/sizeof(_asn1_tags[0]); /******************************************************/ @@ -630,16 +637,6 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter, unsigned type = type_field (node->type); switch (type) { - case ASN1_ETYPE_TIME: - if (node->type & CONST_UTC) - { - _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_UTCTime, tag_der, - &tag_len); - } - else - _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_GENERALIZEDTime, - tag_der, &tag_len); - break; CASE_HANDLED_ETYPES: _asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag, tag_der, &tag_len); @@ -1064,7 +1061,8 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len, } move = RIGHT; break; - case ASN1_ETYPE_TIME: + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: if (p->value == NULL) { _asn1_error_description_value_not_found (p, ErrorDescription); diff --git a/lib/decoding.c b/lib/decoding.c index 5df1f36..68f0634 100644 --- a/lib/decoding.c +++ b/lib/decoding.c @@ -511,25 +511,12 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, case ASN1_ETYPE_SEQUENCE_OF: case ASN1_ETYPE_SET: case ASN1_ETYPE_SET_OF: + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: if ((class != _asn1_tags[type].class) || (tag != _asn1_tags[type].tag)) return ASN1_DER_ERROR; break; - case ASN1_ETYPE_TIME: - if (node->type & CONST_UTC) - { - if ((class != ASN1_CLASS_UNIVERSAL) - || (tag != ASN1_TAG_UTCTime)) - return ASN1_DER_ERROR; - } - else - { - if ((class != ASN1_CLASS_UNIVERSAL) - || (tag != ASN1_TAG_GENERALIZEDTime)) - return ASN1_DER_ERROR; - } - break; - case ASN1_ETYPE_OCTET_STRING: /* OCTET STRING is handled differently to allow * BER encodings (structured class). */ @@ -1055,7 +1042,8 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, counter += len2; move = RIGHT; break; - case ASN1_ETYPE_TIME: + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: result = _asn1_get_time_der (der + counter, len - counter, &len2, temp, sizeof (temp) - 1); @@ -1707,7 +1695,8 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName, counter += len2; move = RIGHT; break; - case ASN1_ETYPE_TIME: + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: if (state == FOUND) { result = @@ -2347,7 +2336,8 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len, counter += len3; move = RIGHT; break; - case ASN1_ETYPE_TIME: + case ASN1_ETYPE_UTC_TIME: + case ASN1_ETYPE_GENERALIZED_TIME: case ASN1_ETYPE_OBJECT_ID: case ASN1_ETYPE_INTEGER: case ASN1_ETYPE_ENUMERATED: @@ -2896,6 +2886,10 @@ asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned i if (ETYPE_OK(etype) == 0) return ASN1_VALUE_NOT_VALID; + /* doesn't handle constructed classes */ + if (ETYPE_CLASS(etype) != ASN1_CLASS_UNIVERSAL) + return ASN1_VALUE_NOT_VALID; + p = der; ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); if (ret != ASN1_SUCCESS) diff --git a/lib/element.c b/lib/element.c index 2e3d48e..c1718e2 100644 --- a/lib/element.c +++ b/lib/element.c @@ -276,6 +276,7 @@ asn1_write_value (asn1_node node_root, const char *name, int len2, k, k2, negative; size_t i; const unsigned char *value = ivalue; + unsigned int type; node = asn1_find_node (node_root, name); if (node == NULL) @@ -286,8 +287,10 @@ asn1_write_value (asn1_node node_root, const char *name, asn1_delete_structure (&node); return ASN1_SUCCESS; } + + type = type_field(node->type); - if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) && (value == NULL) + if ((type == ASN1_ETYPE_SEQUENCE_OF) && (value == NULL) && (len == 0)) { p = node->down; @@ -301,7 +304,7 @@ asn1_write_value (asn1_node node_root, const char *name, return ASN1_SUCCESS; } - switch (type_field (node->type)) + switch (type) { case ASN1_ETYPE_BOOLEAN: if (!_asn1_strcmp (value, "TRUE")) @@ -496,8 +499,7 @@ asn1_write_value (asn1_node node_root, const char *name, } _asn1_set_value (node, value, _asn1_strlen (value) + 1); break; - case ASN1_ETYPE_TIME: - if (node->type & CONST_UTC) + case ASN1_ETYPE_UTC_TIME: { if (_asn1_strlen (value) < 11) return ASN1_VALUE_NOT_VALID; @@ -536,11 +538,10 @@ asn1_write_value (asn1_node node_root, const char *name, } _asn1_set_value (node, value, _asn1_strlen (value) + 1); } - else - { /* GENERALIZED TIME */ - if (value) - _asn1_set_value (node, value, _asn1_strlen (value) + 1); - } + break; + case ASN1_ETYPE_GENERALIZED_TIME: + if (value) + _asn1_set_value (node, value, _asn1_strlen (value) + 1); break; case ASN1_ETYPE_OCTET_STRING: case ASN1_ETYPE_GENERALSTRING: @@ -892,7 +893,8 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue, int *len, PUT_STR_VALUE (value, value_size, node->value); } break; - case ASN1_ETYPE_TIME: + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: PUT_STR_VALUE (value, value_size, node->value); break; case ASN1_ETYPE_OCTET_STRING: @@ -1003,14 +1005,6 @@ asn1_read_tag (asn1_node root, const char *name, int *tagValue, CASE_HANDLED_ETYPES: *tagValue = _asn1_tags[type].tag; break; - case ASN1_ETYPE_TIME: - if (node->type & CONST_UTC) - { - *tagValue = ASN1_TAG_UTCTime; - } - else - *tagValue = ASN1_TAG_GENERALIZEDTime; - break; case ASN1_ETYPE_TAG: case ASN1_ETYPE_CHOICE: case ASN1_ETYPE_ANY: diff --git a/lib/int.h b/lib/int.h index 072e0c6..1cd3e66 100644 --- a/lib/int.h +++ b/lib/int.h @@ -85,6 +85,8 @@ typedef struct tag_and_class_st { case ASN1_ETYPE_SEQUENCE: \ case ASN1_ETYPE_SEQUENCE_OF: \ case ASN1_ETYPE_SET: \ + case ASN1_ETYPE_UTC_TIME: \ + case ASN1_ETYPE_GENERALIZED_TIME: \ case ASN1_ETYPE_SET_OF #define ETYPE_TAG(etype) (_asn1_tags[etype].tag) @@ -110,12 +112,6 @@ extern const tag_and_class_st _asn1_tags[]; #define RIGHT 2 #define DOWN 3 -/****************************************/ -/* Returns the first 8 bits. */ -/* Used with the field type of asn1_node_st */ -/****************************************/ -#define type_field(x) (x&0xFF) - /***********************************************************************/ /* List of constants to better specify the type of typedef asn1_node_st. */ /***********************************************************************/ @@ -141,6 +137,7 @@ extern const tag_and_class_st _asn1_tags[]; #define CONST_DEFINED_BY (1<<22) +/* Those two are deprecated and used for backwards compatibility */ #define CONST_GENERALIZED (1<<23) #define CONST_UTC (1<<24) @@ -153,4 +150,25 @@ extern const tag_and_class_st _asn1_tags[]; #define CONST_DOWN (1<<29) #define CONST_RIGHT (1<<30) + +#define ASN1_ETYPE_TIME 17 +/****************************************/ +/* Returns the first 8 bits. */ +/* Used with the field type of asn1_node_st */ +/****************************************/ +inline static unsigned int type_field(unsigned int ntype) +{ +unsigned int type = ntype & 0xff; + if (type == ASN1_ETYPE_TIME) + { + if (type & CONST_UTC) + type = ASN1_ETYPE_UTC_TIME; + else + type = ASN1_ETYPE_GENERALIZED_TIME; + } + + return type; +} + + #endif /* INT_H */ diff --git a/lib/libtasn1.h b/lib/libtasn1.h index 403ee80..5b50c47 100644 --- a/lib/libtasn1.h +++ b/lib/libtasn1.h @@ -152,7 +152,6 @@ extern "C" #define ASN1_ETYPE_SET 14 #define ASN1_ETYPE_SET_OF 15 #define ASN1_ETYPE_DEFINITIONS 16 -#define ASN1_ETYPE_TIME 17 #define ASN1_ETYPE_CHOICE 18 #define ASN1_ETYPE_IMPORTS 19 #define ASN1_ETYPE_NULL 20 @@ -166,6 +165,8 @@ extern "C" #define ASN1_ETYPE_BMP_STRING 33 #define ASN1_ETYPE_UTF8_STRING 34 #define ASN1_ETYPE_VISIBLE_STRING 35 +#define ASN1_ETYPE_UTC_TIME 36 +#define ASN1_ETYPE_GENERALIZED_TIME 37 struct asn1_data_node_st { diff --git a/lib/structure.c b/lib/structure.c index a508030..4d69765 100644 --- a/lib/structure.c +++ b/lib/structure.c @@ -753,9 +753,6 @@ asn1_print_structure (FILE * out, asn1_node structure, const char *name, case ASN1_ETYPE_IDENTIFIER: fprintf (out, "type:IDENTIFIER"); break; - case ASN1_ETYPE_TIME: - fprintf (out, "type:TIME"); - break; case ASN1_ETYPE_ANY: fprintf (out, "type:ANY"); break; @@ -826,7 +823,8 @@ asn1_print_structure (FILE * out, asn1_node structure, const char *name, fprintf (out, "%02x", (p->value)[k + len2]); } break; - case ASN1_ETYPE_TIME: + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: if (p->value) fprintf (out, " value:%s", p->value); break; -- 2.7.4