Browse Source

fix some DER bugs

1. the "ask for required memory size" pattern wasn't implemented for
`der_decode_object_identifier()`
2. fix wrong "required memory size" returned by UTF-8 de- & encoder
Steffen Jaeckel 8 years ago
parent
commit
aa8441409e

+ 1 - 1
src/headers/tomcrypt_pk.h

@@ -31,7 +31,7 @@ enum public_key_algorithms {
 
 typedef struct Oid {
     unsigned long OID[16];
-    /** Length of DER encoding */
+    /** Number of OID digits in use */
     unsigned long OIDlen;
 } oid_st;
 

+ 18 - 9
src/pk/asn1/der/object_identifier/der_decode_object_identifier.c

@@ -26,6 +26,7 @@ int der_decode_object_identifier(const unsigned char *in,    unsigned long  inle
                                        unsigned long *words, unsigned long *outlen)
 {
    unsigned long x, y, t, len;
+   int err;
 
    LTC_ARGCHK(in     != NULL);
    LTC_ARGCHK(words  != NULL);
@@ -38,6 +39,7 @@ int der_decode_object_identifier(const unsigned char *in,    unsigned long  inle
 
    /* must be room for at least two words */
    if (*outlen < 2) {
+      *outlen = 2;
       return CRYPT_BUFFER_OVERFLOW;
    }
 
@@ -73,21 +75,28 @@ int der_decode_object_identifier(const unsigned char *in,    unsigned long  inle
       if (!(in[x++] & 0x80)) {
          /* store t */
          if (y >= *outlen) {
-            return CRYPT_BUFFER_OVERFLOW;
-         }
-         if (y == 0) {
-            words[0] = t / 40;
-            words[1] = t % 40;
-            y = 2;
+            y++;
          } else {
-            words[y++] = t;
+            if (y == 0) {
+               words[0] = t / 40;
+               words[1] = t % 40;
+               y = 2;
+            } else {
+               words[y++] = t;
+            }
          }
-            t          = 0;
+         t = 0;
       }
    }
 
+   if (y > *outlen) {
+      err =  CRYPT_BUFFER_OVERFLOW;
+   } else {
+      err =  CRYPT_OK;
+   }
+
    *outlen = y;
-   return CRYPT_OK;
+   return err;
 }
 
 #endif

+ 10 - 5
src/pk/asn1/der/utf8/der_decode_utf8_string.c

@@ -29,6 +29,7 @@ int der_decode_utf8_string(const unsigned char *in,  unsigned long inlen,
 {
    wchar_t       tmp;
    unsigned long x, y, z, len;
+   int err;
 
    LTC_ARGCHK(in     != NULL);
    LTC_ARGCHK(out    != NULL);
@@ -91,15 +92,19 @@ int der_decode_utf8_string(const unsigned char *in,  unsigned long inlen,
          tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F);
       }
 
-      if (y > *outlen) {
-         *outlen = y;
-         return CRYPT_BUFFER_OVERFLOW;
+      if (y < *outlen) {
+         out[y] = tmp;
       }
-      out[y++] = tmp;
+      y++;
+   }
+   if (y > *outlen) {
+      err = CRYPT_BUFFER_OVERFLOW;
+   } else {
+      err = CRYPT_OK;
    }
    *outlen = y;
 
-   return CRYPT_OK;
+   return err;
 }
 
 #endif

+ 1 - 1
src/pk/asn1/der/utf8/der_encode_utf8_string.c

@@ -53,7 +53,7 @@ int der_encode_utf8_string(const wchar_t *in,  unsigned long inlen,
 
    /* too big? */
    if (y > *outlen) {
-      *outlen = len;
+      *outlen = y;
       return CRYPT_BUFFER_OVERFLOW;
    }