simplified and renamed asn1_encode_string_der() and asn1_decode_string_der()
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 23 Nov 2012 20:00:50 +0000 (21:00 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 23 Nov 2012 20:00:50 +0000 (21:00 +0100)
NEWS
lib/coding.c
lib/decoding.c
lib/int.h
lib/libtasn1.h
lib/libtasn1.map
tests/Test_strings.c

diff --git a/NEWS b/NEWS
index a8bd32a..a29e187 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,7 +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().
+- Added asn1_decode_simple_der() and asn1_encode_simple_der().
 
 * Noteworthy changes in release 3.0 (2012-10-28) [stable]
 - Added tool in tests/ to benchmark X.509 structure decoding.
index 007703c..aa777f3 100644 (file)
@@ -184,32 +184,38 @@ asn1_octet_der (const unsigned char *str, int str_len,
 
 
 /**
- * asn1_encode_string_der:
+ * asn1_encode_simple_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
+ * @tl: the encoded tag and length
+ * @tl_len: the bytes of the @tl field
  *
- * 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.
+ * Creates the DER encoding for various simple ASN.1 types like strings etc.
+ * It stores the tag and length in @tl, which should have space for at least 
+ * %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl.
+ *
+ * The complete DER encoding should consist of the value in @tl appended
+ * with the provided @str.
  *
  * 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)
+asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned int str_len,
+                        unsigned char *tl, unsigned int *tl_len)
 {
-  int tag_len, len_len, tlen;
+  int tag_len, len_len;
+  unsigned tlen;
   unsigned char der_tag[ASN1_MAX_TAG_SIZE];
   unsigned char der_length[ASN1_MAX_LENGTH_SIZE];
   unsigned char* p;
 
-  if (der == NULL)
+  if (str == 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);
@@ -219,20 +225,17 @@ asn1_encode_string_der (unsigned int etype, const unsigned char *str, unsigned i
   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;
+  tlen = tag_len + len_len;
 
+  if (*tl_len < tlen)
+    return ASN1_MEM_ERROR;
+
+  p = tl;
   memcpy(p, der_tag, tag_len);
   p+=tag_len;
   memcpy(p, der_length, len_len);
-  p+=len_len;
-  memcpy(p, str, str_len);
+  
+  *tl_len = tlen;
 
   return ASN1_SUCCESS;
 }
index 82e5f4e..5df1f36 100644 (file)
@@ -2868,23 +2868,23 @@ asn1_expand_octet_string (asn1_node definitions, asn1_node * element,
 }
 
 /**
- * asn1_decode_string_der:
+ * asn1_decode_simple_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
+ * @str: a pointer to the data
+ * @str_len: the length of the data
  *
- * 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.
+ * Decodes a simple DER encoded type (e.g. a string, which is not constructed).
+ * The output is a pointer inside the @der.
  *
  * 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)
+asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned int der_len,
+                        const unsigned char **str, unsigned int *str_len)
 {
-  int tag_len, len_len, tlen;
+  int tag_len, len_len;
   const unsigned char* p;
   unsigned char class;
   unsigned long tag;
@@ -2900,6 +2900,9 @@ asn1_decode_string_der (unsigned int etype, const unsigned char *der, unsigned i
   ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag);
   if (ret != ASN1_SUCCESS)
     return ret;
+  
+  if (class != ETYPE_CLASS(etype) || tag != ETYPE_TAG(etype))
+    return ASN1_DER_ERROR;
 
   p += tag_len;
   der_len -= tag_len;
@@ -2910,14 +2913,9 @@ asn1_decode_string_der (unsigned int etype, const unsigned char *der, unsigned i
 
   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;
+  
+  *str_len = ret;
+  *str = p;
 
   return ASN1_SUCCESS;
 }
index daecada..9400cb8 100644 (file)
--- a/lib/int.h
+++ b/lib/int.h
@@ -39,7 +39,6 @@
 #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
index 8c68205..6a164b0 100644 (file)
@@ -272,7 +272,9 @@ extern "C"
 
   extern ASN1_API void asn1_perror (int error);
 
+#define ASN1_MAX_TAG_SIZE 4
 #define ASN1_MAX_LENGTH_SIZE 9
+#define ASN1_MAX_TL_SIZE (ASN1_MAX_TAG_SIZE+ASN1_MAX_LENGTH_SIZE)
   extern ASN1_API long
     asn1_get_length_der (const unsigned char *der, int der_len, int *len);
 
@@ -285,12 +287,12 @@ extern "C"
   /* 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);
+    int asn1_decode_simple_der (unsigned int etype, const unsigned char *der, unsigned int der_len,
+                        const 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 int
+    asn1_encode_simple_der (unsigned int etype, const unsigned char *str, unsigned int str_len,
+                        unsigned char *tl, unsigned int *tl_len);
 
   extern ASN1_API asn1_node
     asn1_find_node (asn1_node pointer, const char *name);
index 9ae741a..a2b9416 100644 (file)
@@ -50,8 +50,8 @@ LIBTASN1_0_3
     asn1_strerror;
     asn1_write_value;
     asn1_read_node_value;
-    asn1_encode_string_der;
-    asn1_decode_string_der;
+    asn1_encode_simple_der;
+    asn1_decode_simple_der;
 
     # Old symbols
     libtasn1_strerror;
index c2b9da1..b43620f 100644 (file)
@@ -37,7 +37,7 @@ struct tv
 
 static const struct tv tv[] = {
   {ASN1_ETYPE_IA5_STRING, 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"},
+                          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_PRINTABLE_STRING, 5, "\x4e\x69\x6b\x6f\x73", 
                                7, "\x13\x05\x4e\x69\x6b\x6f\x73"},
   {ASN1_ETYPE_UTF8_STRING, 12, "Αττική",
@@ -52,8 +52,9 @@ int
 main (int argc, char *argv[])
 {
   int ret;
-  unsigned char* der;
-  unsigned int der_len;
+  unsigned char tl[ASN1_MAX_TL_SIZE];
+  unsigned int tl_len, der_len, str_len;
+  const unsigned char* str;
   unsigned int i;
 
   /* Dummy test */
@@ -61,35 +62,35 @@ main (int argc, char *argv[])
   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);
+      tl_len = sizeof(tl);
+      ret = asn1_encode_simple_der(tv[i].etype, tv[i].str, tv[i].str_len,
+                                   tl, &tl_len);
       if (ret != ASN1_SUCCESS)
         {
           fprintf(stderr, "Encoding error in %u: %s\n", i, asn1_strerror(ret));
           return 1;
         }
+      der_len = tl_len+tv[i].str_len;
         
-      if (der_len != tv[i].der_len || memcmp(der, tv[i].der, der_len) != 0)
+      if (der_len != tv[i].der_len || memcmp(tl, tv[i].der, tl_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);
+      ret = asn1_decode_simple_der(tv[i].etype, tv[i].der, tv[i].der_len, &str, &str_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)
+      if (str_len != tv[i].str_len || memcmp(str, tv[i].str, str_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);
     }