diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-11-23 20:24:35 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2012-11-23 20:24:35 +0100 |
commit | f4e6030e0ee82a3d10ad9c0f55fad972d1c3a2c5 (patch) | |
tree | f28d55cc155e673e03fbaad171a29fd1ca32e57a | |
parent | 1153d7fa1ba99b6320cfc152395508692480440d (diff) | |
download | libtasn1-f4e6030e0ee82a3d10ad9c0f55fad972d1c3a2c5.tar.gz libtasn1-f4e6030e0ee82a3d10ad9c0f55fad972d1c3a2c5.tar.bz2 libtasn1-f4e6030e0ee82a3d10ad9c0f55fad972d1c3a2c5.zip |
Added asn1_decode_string_der() and asn1_encode_string_der().
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | lib/ASN1.c | 4 | ||||
-rw-r--r-- | lib/ASN1.y | 4 | ||||
-rw-r--r-- | lib/coding.c | 138 | ||||
-rw-r--r-- | lib/decoding.c | 63 | ||||
-rw-r--r-- | lib/element.c | 6 | ||||
-rw-r--r-- | lib/int.h | 6 | ||||
-rw-r--r-- | lib/libtasn1.h | 47 | ||||
-rw-r--r-- | lib/libtasn1.map | 2 | ||||
-rw-r--r-- | lib/parser_aux.c | 6 | ||||
-rw-r--r-- | lib/parser_aux.h | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 7 | ||||
-rw-r--r-- | tests/Test_strings.c | 97 |
15 files changed, 324 insertions, 64 deletions
@@ -1,3 +1,5 @@ +tags +*~ *.gcda *.gcno *.gcov @@ -188,6 +190,8 @@ tests/Makefile tests/Makefile.in tests/Test_encoding tests/Test_encoding.o +tests/Test_strings.o +tests/Test_strings tests/Test_errors tests/Test_errors.o tests/Test_indefinite @@ -7,6 +7,7 @@ GNU Libtasn1 NEWS -*- outline -*- PrintableString, UniversalString, BMPString, UTF8String. When re-defined a warning is being print instead of failing. - Parser outputs more detailed syntax error message. +- Added asn1_decode_string_der() and asn1_encode_string_der(). * Noteworthy changes in release 3.0 (2012-10-28) [stable] - Added tool in tests/ to benchmark X.509 structure decoding. diff --git a/configure.ac b/configure.ac index 0acd74a..839fc6b 100644 --- a/configure.ac +++ b/configure.ac @@ -78,6 +78,7 @@ if test "$gl_gcc_warnings" = yes; then nw="$nw -Wundef" # nw="$nw -Wunreachable-code" # Too many false positives nw="$nw -Wunused-macros" # Breaks on bison generated ASN1.c + nw="$nw -Wswitch-default" # Breaks on bison generated ASN1.c nw="$nw -Wunsafe-loop-optimizations" nw="$nw -Wstrict-overflow" nw="$nw -Wsuggest-attribute=pure" # Is it worth using pure attributes? @@ -3286,7 +3286,7 @@ _asn1_yyerror (const char *s) snprintf (last_error_token, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s", last_token); fprintf(stderr, - "%s:%ld: Warning: %s is a built-in ASN.1 type.\n", + "%s:%u: Warning: %s is a built-in ASN.1 type.\n", file_name, line_number, last_token); return; } @@ -3295,7 +3295,7 @@ _asn1_yyerror (const char *s) if (result_parse != ASN1_NAME_TOO_LONG) { snprintf (last_error, ASN1_MAX_ERROR_DESCRIPTION_SIZE, - "%s:%ld: Error: %s near '%s'", file_name, + "%s:%u: Error: %s near '%s'", file_name, line_number, s, last_token); result_parse = ASN1_SYNTAX_ERROR; } @@ -872,7 +872,7 @@ _asn1_yyerror (const char *s) snprintf (last_error_token, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s", last_token); fprintf(stderr, - "%s:%ld: Warning: %s is a built-in ASN.1 type.\n", + "%s:%u: Warning: %s is a built-in ASN.1 type.\n", file_name, line_number, last_token); return; } @@ -881,7 +881,7 @@ _asn1_yyerror (const char *s) if (result_parse != ASN1_NAME_TOO_LONG) { snprintf (last_error, ASN1_MAX_ERROR_DESCRIPTION_SIZE, - "%s:%ld: Error: %s near '%s'", file_name, + "%s:%u: Error: %s near '%s'", file_name, line_number, s, last_token); result_parse = ASN1_SYNTAX_ERROR; } diff --git a/lib/coding.c b/lib/coding.c index 0802f73..1d67f5f 100644 --- a/lib/coding.c +++ b/lib/coding.c @@ -61,24 +61,30 @@ _asn1_error_description_value_not_found (asn1_node node, /** * asn1_length_der: * @len: value to convert. - * @ans: string returned. - * @ans_len: number of meaningful bytes of ANS (ans[0]..ans[ans_len-1]). + * @der: the encoding (may be %NULL). + * @der_len: number of meaningful bytes of ANS (der[0]..der[der_len-1]). * - * Creates the DER coding for the LEN parameter (only the length). - * The @ans buffer is pre-allocated and must have room for the output. + * Creates the DER encoding of the provided length value. + * The @der buffer must have enough room for the output. The maximum + * length this function will encode is %ASN1_MAX_LENGTH_SIZE. + * + * To know the size of the DER encoding use a %NULL value for @der. **/ void -asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len) +asn1_length_der (unsigned long int len, unsigned char *der, int *der_len) { int k; - unsigned char temp[SIZEOF_UNSIGNED_LONG_INT]; + unsigned char temp[ASN1_MAX_LENGTH_SIZE]; +#if SIZEOF_UNSIGNED_LONG_INT > 8 + len &= 0xFFFFFFFFFFFFFFFF; +#endif if (len < 128) { /* short form */ - if (ans != NULL) - ans[0] = (unsigned char) len; - *ans_len = 1; + if (der != NULL) + der[0] = (unsigned char) len; + *der_len = 1; } else { @@ -89,12 +95,12 @@ asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len) temp[k++] = len & 0xFF; len = len >> 8; } - *ans_len = k + 1; - if (ans != NULL) + *der_len = k + 1; + if (der != NULL) { - ans[0] = ((unsigned char) k & 0x7F) + 128; + der[0] = ((unsigned char) k & 0x7F) + 128; while (k--) - ans[*ans_len - 1 - k] = temp[k]; + der[*der_len - 1 - k] = temp[k]; } } } @@ -103,6 +109,7 @@ asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len) /* Function : _asn1_tag_der */ /* Description: creates the DER coding for the CLASS */ /* and TAG parameters. */ +/* It is limited by the ASN1_MAX_TAG_SIZE variable */ /* Parameters: */ /* class: value to convert. */ /* tag_value: value to convert. */ @@ -116,7 +123,7 @@ _asn1_tag_der (unsigned char class, unsigned int tag_value, unsigned char *ans, int *ans_len) { int k; - unsigned char temp[SIZEOF_UNSIGNED_INT]; + unsigned char temp[ASN1_MAX_TAG_SIZE]; if (tag_value < 31) { @@ -129,10 +136,13 @@ _asn1_tag_der (unsigned char class, unsigned int tag_value, /* Long form */ ans[0] = (class & 0xE0) + 31; k = 0; - while (tag_value) + while (tag_value != 0) { temp[k++] = tag_value & 0x7F; - tag_value = tag_value >> 7; + tag_value >>= 7; + + if (k > ASN1_MAX_TAG_SIZE-1) + break; /* will not encode larger tags */ } *ans_len = k + 1; while (k--) @@ -143,12 +153,20 @@ _asn1_tag_der (unsigned char class, unsigned int tag_value, /** * asn1_octet_der: - * @str: OCTET string. - * @str_len: STR length (str[0]..str[str_len-1]). - * @der: string returned. - * @der_len: number of meaningful bytes of DER (der[0]..der[ans_len-1]). + * @str: the input data. + * @str_len: STR length (str[0]..str[*str_len-1]). + * @der: encoded string returned. + * @der_len: number of meaningful bytes of DER (der[0]..der[der_len-1]). * - * Creates the DER coding for an OCTET type (length included). + * Creates a length-value DER encoding for the input data. + * The DER encoding of the input data will be placed in the @der variable. + * + * Note that the OCTET STRING tag is not included in the output. + * + * This function does not return any value because it is expected + * that @der_len will contain enough bytes to store the string + * plus the DER encoding. The DER encoding size can be obtained using + * asn1_length_der(). **/ void asn1_octet_der (const unsigned char *str, int str_len, @@ -158,11 +176,67 @@ asn1_octet_der (const unsigned char *str, int str_len, if (der == NULL || str_len < 0) return; + asn1_length_der (str_len, der, &len_len); memcpy (der + len_len, str, str_len); *der_len = str_len + len_len; } + +/** + * asn1_encode_string_der: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @str: the string data. + * @str_len: the string length + * @der: the encoded string + * @der_len: the bytes of the encoded string + * + * Creates the DER encoding for the various ASN.1 STRING types. + * The DER encoding of the input data will be placed in the @der variable. + * + * Returns: %ASN1_SUCCESS if successful or an error value. + **/ +int +asn1_encode_string_der (unsigned int etype, const unsigned char *str, unsigned int str_len, + unsigned char **der, unsigned int *der_len) +{ + int tag_len, len_len, tlen; + unsigned char der_tag[ASN1_MAX_TAG_SIZE]; + unsigned char der_length[ASN1_MAX_LENGTH_SIZE]; + unsigned char* p; + + if (der == NULL) + return ASN1_VALUE_NOT_VALID; + + if (ETYPE_OK(etype) == 0) + return ASN1_VALUE_NOT_VALID; + + _asn1_tag_der (ETYPE_CLASS(etype), ETYPE_TAG(etype), + der_tag, &tag_len); + + asn1_length_der(str_len, der_length, &len_len); + + if (tag_len <= 0 || len_len <= 0) + return ASN1_VALUE_NOT_VALID; + + tlen = tag_len + len_len + str_len; + + p = malloc(tlen); + if (p == NULL) + return ASN1_MEM_ALLOC_ERROR; + + *der = p; + *der_len = tag_len + len_len + str_len; + + memcpy(p, der_tag, tag_len); + p+=tag_len; + memcpy(p, der_length, len_len); + p+=len_len; + memcpy(p, str, str_len); + + return ASN1_SUCCESS; +} + /******************************************************/ /* Function : _asn1_time_der */ /* Description: creates the DER coding for a TIME */ @@ -333,8 +407,16 @@ static const unsigned char bit_mask[] = * @der_len: number of meaningful bytes of DER * (der[0]..der[ans_len-1]). * - * Creates the DER coding for a BIT STRING type (length and pad - * included). + * Creates a length-value DER encoding for the input data + * as it would have been for a BIT STRING. + * The DER encoded data will be copied in @der. + * + * Note that the BIT STRING tag is not included in the output. + * + * This function does not return any value because it is expected + * that @der_len will contain enough bytes to store the string + * plus the DER encoding. The DER encoding size can be obtained using + * asn1_length_der(). **/ void asn1_bit_der (const unsigned char *str, int bit_len, @@ -344,6 +426,7 @@ asn1_bit_der (const unsigned char *str, int bit_len, if (der == NULL) return; + len_byte = bit_len >> 3; len_pad = 8 - (bit_len & 7); if (len_pad == 8) @@ -437,10 +520,10 @@ const tag_and_class_st _asn1_tags[] = [ASN1_ETYPE_TELETEXSTRING] = {ASN1_TAG_TELETEXSTRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"}, [ASN1_ETYPE_PRINTABLESTRING] = {ASN1_TAG_PRINTABLESTRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"}, [ASN1_ETYPE_UNIVERSALSTRING] = {ASN1_TAG_UNIVERSALSTRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"}, - [ASN1_ETYPE_BMPSTRING] = {ASN1_TAG_BMPSTRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"}, - [ASN1_ETYPE_UTF8STRING] = {ASN1_TAG_UTF8STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"}, - [ASN1_ETYPE_VISIBLESTRING] = {ASN1_TAG_VISIBLESTRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"}, - [ASN1_ETYPE_OCTET_STRING] = {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"}, + [ASN1_ETYPE_BMPSTRING] = {ASN1_TAG_BMPSTRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"}, + [ASN1_ETYPE_UTF8STRING] = {ASN1_TAG_UTF8STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"}, + [ASN1_ETYPE_VISIBLESTRING] = {ASN1_TAG_VISIBLESTRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"}, + [ASN1_ETYPE_OCTET_STRING] = {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"}, [ASN1_ETYPE_BIT_STRING] = {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"}, [ASN1_ETYPE_OBJECT_ID] = {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_STR"}, [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"}, @@ -452,6 +535,7 @@ const tag_and_class_st _asn1_tags[] = [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"}, }; +unsigned int _asn1_tags_size = sizeof(_asn1_tags)/sizeof(_asn1_tags[0]); /******************************************************/ /* Function : _asn1_insert_tag_der */ diff --git a/lib/decoding.c b/lib/decoding.c index eb4ca0e..d11a5a7 100644 --- a/lib/decoding.c +++ b/lib/decoding.c @@ -1277,7 +1277,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, if (len4 != -1) { len2 += len4; - _asn1_set_value_octet (p, der + counter, len2 + len3); + _asn1_set_value_lv (p, der + counter, len2 + len3); counter += len2 + len3; } else @@ -1294,7 +1294,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len, if (result != ASN1_SUCCESS) goto cleanup; - _asn1_set_value_octet (p, der + counter, len2); + _asn1_set_value_lv (p, der + counter, len2); counter += len2; /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with @@ -1973,7 +1973,7 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName, len2 += len4; if (state == FOUND) { - _asn1_set_value_octet (p, der + counter, len2 + len3); + _asn1_set_value_lv (p, der + counter, len2 + len3); if (p == nodeFound) state = EXIT; @@ -1996,7 +1996,7 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName, if (state == FOUND) { - _asn1_set_value_octet (p, der + counter, len2); + _asn1_set_value_lv (p, der + counter, len2); if (p == nodeFound) state = EXIT; @@ -2866,3 +2866,58 @@ asn1_expand_octet_string (asn1_node definitions, asn1_node * element, return retCode; } + +/** + * asn1_decode_string_der: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @der: the encoded string + * @der_len: the bytes of the encoded string + * @str: the decoded string data. + * @str_len: the string length + * + * Creates the DER encoding for the various ASN.1 STRING types. + * The DER encoding of the input data will be placed in the @der variable. + * + * Returns: %ASN1_SUCCESS if successful or an error value. + **/ +int +asn1_decode_string_der (unsigned int etype, const unsigned char *der, unsigned int der_len, + unsigned char **str, unsigned int *str_len) +{ + int tag_len, len_len, tlen; + const unsigned char* p; + unsigned char class; + unsigned long tag; + long ret; + + if (der == NULL || der_len == 0) + return ASN1_VALUE_NOT_VALID; + + if (ETYPE_OK(etype) == 0) + return ASN1_VALUE_NOT_VALID; + + p = der; + ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); + if (ret != ASN1_SUCCESS) + return ret; + + p += tag_len; + der_len -= tag_len; + + ret = asn1_get_length_der (p, der_len, &len_len); + if (ret < 0) + return ASN1_DER_ERROR; + + p += len_len; + der_len -= len_len; + tlen = ret; + + *str = malloc(tlen); + if (*str == NULL) + return ASN1_MEM_ALLOC_ERROR; + + memcpy(*str, p, tlen); + *str_len = tlen; + + return ASN1_SUCCESS; +} diff --git a/lib/element.c b/lib/element.c index f85fb2f..32d2894 100644 --- a/lib/element.c +++ b/lib/element.c @@ -408,7 +408,7 @@ asn1_write_value (asn1_node node_root, const char *name, (!negative && (value_temp[k] & 0x80))) k--; - _asn1_set_value_octet (node, value_temp + k, len - k); + _asn1_set_value_lv (node, value_temp + k, len - k); if (node->type & CONST_DEFAULT) { @@ -554,7 +554,7 @@ asn1_write_value (asn1_node node_root, const char *name, case ASN1_ETYPE_VISIBLESTRING: if (len == 0) len = _asn1_strlen (value); - _asn1_set_value_octet (node, value, len); + _asn1_set_value_lv (node, value, len); break; case ASN1_ETYPE_BIT_STRING: if (len == 0) @@ -593,7 +593,7 @@ asn1_write_value (asn1_node node_root, const char *name, return ASN1_ELEMENT_NOT_FOUND; break; case ASN1_ETYPE_ANY: - _asn1_set_value_octet (node, value, len); + _asn1_set_value_lv (node, value, len); break; case ASN1_ETYPE_SEQUENCE_OF: case ASN1_ETYPE_SET_OF: @@ -39,6 +39,7 @@ #include <libtasn1.h> #define ASN1_SMALL_VALUE_SIZE 16 +#define ASN1_MAX_TAG_SIZE 4 /* This structure is also in libtasn1.h, but then contains less fields. You cannot make any modifications to these first fields @@ -87,6 +88,11 @@ typedef struct tag_and_class_st { case ASN1_ETYPE_SET: \ case ASN1_ETYPE_SET_OF +#define ETYPE_TAG(etype) (_asn1_tags[etype].tag) +#define ETYPE_CLASS(etype) (_asn1_tags[etype].class) +#define ETYPE_OK(etype) ((etype <= _asn1_tags_size)?1:0) + +extern unsigned int _asn1_tags_size; extern const tag_and_class_st _asn1_tags[]; #define _asn1_strlen(s) strlen((const char *) s) diff --git a/lib/libtasn1.h b/lib/libtasn1.h index ad3b554..9f3eae4 100644 --- a/lib/libtasn1.h +++ b/lib/libtasn1.h @@ -272,7 +272,34 @@ extern "C" extern ASN1_API void asn1_perror (int error); - /* DER utility functions. */ +#define ASN1_MAX_LENGTH_SIZE 9 + extern ASN1_API long + asn1_get_length_der (const unsigned char *der, int der_len, int *len); + + extern ASN1_API long + asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len); + + extern ASN1_API void + asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len); + + /* Other utility functions. */ + + extern ASN1_API + int asn1_decode_string_der (unsigned int etype, const unsigned char *der, unsigned int der_len, + unsigned char **str, unsigned int *str_len); + + extern ASN1_API + int asn1_encode_string_der (unsigned int etype, const unsigned char *str, unsigned int str_len, + unsigned char **der, unsigned int *der_len); + + extern ASN1_API asn1_node + asn1_find_node (asn1_node pointer, const char *name); + + extern ASN1_API int + asn1_copy_node (asn1_node dst, const char *dst_name, + asn1_node src, const char *src_name); + + /* Internal and low-level DER utility functions. */ extern ASN1_API int asn1_get_tag_der (const unsigned char *der, int der_len, @@ -295,24 +322,6 @@ extern "C" int *ret_len, unsigned char *str, int str_size, int *bit_len); - extern ASN1_API long - asn1_get_length_der (const unsigned char *der, int der_len, int *len); - - extern ASN1_API long - asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len); - - extern ASN1_API void - asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len); - - /* Other utility functions. */ - - extern ASN1_API asn1_node - asn1_find_node (asn1_node pointer, const char *name); - - extern ASN1_API int - asn1_copy_node (asn1_node dst, const char *dst_name, - asn1_node src, const char *src_name); - /* Compatibility types */ typedef int asn1_retCode; /* type returned by libtasn1 functions */ diff --git a/lib/libtasn1.map b/lib/libtasn1.map index 83235ed..9ae741a 100644 --- a/lib/libtasn1.map +++ b/lib/libtasn1.map @@ -50,6 +50,8 @@ LIBTASN1_0_3 asn1_strerror; asn1_write_value; asn1_read_node_value; + asn1_encode_string_der; + asn1_decode_string_der; # Old symbols libtasn1_strerror; diff --git a/lib/parser_aux.c b/lib/parser_aux.c index cced582..7d16fa3 100644 --- a/lib/parser_aux.c +++ b/lib/parser_aux.c @@ -241,10 +241,10 @@ _asn1_set_value (asn1_node node, const void *value, unsigned int len) } /******************************************************************/ -/* Function : _asn1_set_value_octet */ +/* Function : _asn1_set_value_lv */ /* Description: sets the field VALUE in a NODE_ASN element. The */ /* previous value (if exist) will be lost. The value */ -/* given is stored as an octet string. */ +/* given is stored as an length-value format (LV */ /* Parameters: */ /* node: element pointer. */ /* value: pointer to the value that you want to set. */ @@ -252,7 +252,7 @@ _asn1_set_value (asn1_node node, const void *value, unsigned int len) /* Return: pointer to the NODE_ASN element. */ /******************************************************************/ asn1_node -_asn1_set_value_octet (asn1_node node, const void *value, unsigned int len) +_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len) { int len2; void *temp; diff --git a/lib/parser_aux.h b/lib/parser_aux.h index df369c7..f270b73 100644 --- a/lib/parser_aux.h +++ b/lib/parser_aux.h @@ -35,7 +35,7 @@ _asn1_set_value (asn1_node node, const void *value, unsigned int len); asn1_node _asn1_set_value_m (asn1_node node, void *value, unsigned int len); asn1_node -_asn1_set_value_octet (asn1_node node, const void *value, unsigned int len); +_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len); asn1_node _asn1_append_value (asn1_node node, const void *value, unsigned int len); diff --git a/tests/Makefile.am b/tests/Makefile.am index a7f8336..8f01d35 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -33,11 +33,12 @@ dist_check_SCRIPTS += threadsafety MOSTLYCLEANFILES = Test_parser_ERROR.asn -check_PROGRAMS = Test_parser Test_tree Test_encoding Test_indefinite \ - Test_errors Test_simple Test_overflow +check_PROGRAMS = Test_parser Test_tree Test_encoding Test_indefinite \ + Test_errors Test_simple Test_overflow Test_strings TESTS = Test_parser Test_tree Test_encoding Test_indefinite \ - Test_errors Test_simple Test_overflow crlf threadsafety + Test_errors Test_simple Test_overflow crlf threadsafety \ + Test_strings TESTS_ENVIRONMENT = \ ASN1PARSER=$(srcdir)/Test_parser.asn \ diff --git a/tests/Test_strings.c b/tests/Test_strings.c new file mode 100644 index 0000000..8a6a9f7 --- /dev/null +++ b/tests/Test_strings.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Written by Simon Josefsson + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "libtasn1.h" + +struct tv +{ + unsigned int etype; + unsigned int str_len; + const void *str; + unsigned int der_len; + const void *der; +}; + +static const struct tv tv[] = { + {ASN1_ETYPE_IA5STRING, 20, "\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72", + 22, "\x16\x14\x63\x73\x63\x61\x40\x70\x61\x73\x73\x70\x6f\x72\x74\x2e\x67\x6f\x76\x2e\x67\x72"}, + {ASN1_ETYPE_PRINTABLESTRING, 5, "\x4e\x69\x6b\x6f\x73", + 7, "\x13\x05\x4e\x69\x6b\x6f\x73"}, + {ASN1_ETYPE_UTF8STRING, 12, "Αττική", + 14, "\x0c\x0c\xce\x91\xcf\x84\xcf\x84\xce\xb9\xce\xba\xce\xae"}, + {ASN1_ETYPE_TELETEXSTRING, 15, "\x53\x69\x6d\x6f\x6e\x20\x4a\x6f\x73\x65\x66\x73\x73\x6f\x6e", + 17, "\x14\x0f\x53\x69\x6d\x6f\x6e\x20\x4a\x6f\x73\x65\x66\x73\x73\x6f\x6e"}, + {ASN1_ETYPE_OCTET_STRING, 36, "\x30\x22\x80\x0F\x32\x30\x31\x31\x30\x38\x32\x31\x30\x38\x30\x30\x30\x36\x5A\x81\x0F\x32\x30\x31\x31\x30\x38\x32\x33\x32\x30\x35\x39\x35\x39\x5A", + 38, "\x04\x24\x30\x22\x80\x0F\x32\x30\x31\x31\x30\x38\x32\x31\x30\x38\x30\x30\x30\x36\x5A\x81\x0F\x32\x30\x31\x31\x30\x38\x32\x33\x32\x30\x35\x39\x35\x39\x5A"} +}; + +int +main (int argc, char *argv[]) +{ + int ret; + unsigned char* der; + unsigned int der_len; + unsigned int i; + + /* Dummy test */ + + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { + /* Encode */ + ret = asn1_encode_string_der(tv[i].etype, tv[i].str, tv[i].str_len, + &der, &der_len); + if (ret != ASN1_SUCCESS) + { + fprintf(stderr, "Encoding error in %u: %s\n", i, asn1_strerror(ret)); + return 1; + } + + if (der_len != tv[i].der_len || memcmp(der, tv[i].der, der_len) != 0) + { + fprintf(stderr, "DER encoding differs in %u! (size: %u, expected: %u)\n", i, der_len, tv[i].der_len); + return 1; + } + free(der); + + /* decoding */ + ret = asn1_decode_string_der(tv[i].etype, tv[i].der, tv[i].der_len, &der, &der_len); + if (ret != ASN1_SUCCESS) + { + fprintf(stderr, "Decoding error in %u: %s\n", i, asn1_strerror(ret)); + return 1; + } + + if (der_len != tv[i].str_len || memcmp(der, tv[i].str, der_len) != 0) + { + fprintf(stderr, "DER decoded data differ in %u! (size: %u, expected: %u)\n", i, der_len, tv[i].str_len); + return 1; + } + free(der); + } + + + return 0; +} |