summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2012-11-23 20:24:35 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2012-11-23 20:24:35 +0100
commitf4e6030e0ee82a3d10ad9c0f55fad972d1c3a2c5 (patch)
treef28d55cc155e673e03fbaad171a29fd1ca32e57a
parent1153d7fa1ba99b6320cfc152395508692480440d (diff)
downloadlibtasn1-f4e6030e0ee82a3d10ad9c0f55fad972d1c3a2c5.tar.gz
libtasn1-f4e6030e0ee82a3d10ad9c0f55fad972d1c3a2c5.tar.bz2
libtasn1-f4e6030e0ee82a3d10ad9c0f55fad972d1c3a2c5.zip
Added asn1_decode_string_der() and asn1_encode_string_der().
-rw-r--r--.gitignore4
-rw-r--r--NEWS1
-rw-r--r--configure.ac1
-rw-r--r--lib/ASN1.c4
-rw-r--r--lib/ASN1.y4
-rw-r--r--lib/coding.c138
-rw-r--r--lib/decoding.c63
-rw-r--r--lib/element.c6
-rw-r--r--lib/int.h6
-rw-r--r--lib/libtasn1.h47
-rw-r--r--lib/libtasn1.map2
-rw-r--r--lib/parser_aux.c6
-rw-r--r--lib/parser_aux.h2
-rw-r--r--tests/Makefile.am7
-rw-r--r--tests/Test_strings.c97
15 files changed, 324 insertions, 64 deletions
diff --git a/.gitignore b/.gitignore
index e6f9fc5..2b5f79c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/NEWS b/NEWS
index be519ba..a8bd32a 100644
--- a/NEWS
+++ b/NEWS
@@ -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?
diff --git a/lib/ASN1.c b/lib/ASN1.c
index 120b6d8..477addd 100644
--- a/lib/ASN1.c
+++ b/lib/ASN1.c
@@ -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;
}
diff --git a/lib/ASN1.y b/lib/ASN1.y
index ce0a8af..aa0baa7 100644
--- a/lib/ASN1.y
+++ b/lib/ASN1.y
@@ -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:
diff --git a/lib/int.h b/lib/int.h
index 70fa896..6bbf084 100644
--- a/lib/int.h
+++ b/lib/int.h
@@ -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;
+}