Added asn1_decode_string_der() and asn1_encode_string_der().
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 23 Nov 2012 19:24:35 +0000 (20:24 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 23 Nov 2012 19:24:35 +0000 (20:24 +0100)
15 files changed:
.gitignore
NEWS
configure.ac
lib/ASN1.c
lib/ASN1.y
lib/coding.c
lib/decoding.c
lib/element.c
lib/int.h
lib/libtasn1.h
lib/libtasn1.map
lib/parser_aux.c
lib/parser_aux.h
tests/Makefile.am
tests/Test_strings.c [new file with mode: 0644]

index e6f9fc5..2b5f79c 100644 (file)
@@ -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 (file)
--- 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.
index 0acd74a..839fc6b 100644 (file)
@@ -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?
index 120b6d8..477addd 100644 (file)
@@ -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;
     }
index ce0a8af..aa0baa7 100644 (file)
@@ -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;
     }
index 0802f73..1d67f5f 100644 (file)
@@ -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                    */
index eb4ca0e..d11a5a7 100644 (file)
@@ -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;
+}
index f85fb2f..32d2894 100644 (file)
@@ -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:
index 70fa896..6bbf084 100644 (file)
--- 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)
index ad3b554..9f3eae4 100644 (file)
@@ -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 */
index 83235ed..9ae741a 100644 (file)
@@ -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;
index cced582..7d16fa3 100644 (file)
@@ -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;
index df369c7..f270b73 100644 (file)
@@ -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);
index a7f8336..8f01d35 100644 (file)
@@ -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 (file)
index 0000000..8a6a9f7
--- /dev/null
@@ -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;
+}