Browse Source

implement DER resursion limit

Steffen Jaeckel 7 years ago
parent
commit
62c2124b82

+ 7 - 0
src/headers/tomcrypt_custom.h

@@ -505,6 +505,13 @@
 #endif
 #endif
 
+#if defined(LTC_DER)
+   #ifndef LTC_DER_MAX_RECURSION
+      /* Maximum recursion limit when processing nested ASN.1 types. */
+      #define LTC_DER_MAX_RECURSION 30
+   #endif
+#endif
+
 #if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_MKAT)
    /* Include the MPI functionality?  (required by the PK algorithms) */
    #define LTC_MPI

+ 1 - 0
src/misc/crypt/crypt.c

@@ -428,6 +428,7 @@ const char *crypt_build_settings =
 #endif
 #if defined(LTC_DER)
     " DER "
+    " " NAME_VALUE(LTC_DER_MAX_RECURSION) " "
 #endif
 #if defined(LTC_PKCS_1)
     " PKCS#1 "

+ 4 - 0
src/misc/crypt/crypt_constants.c

@@ -126,6 +126,7 @@ static const crypt_constant _crypt_constants[] = {
 
 #ifdef LTC_DER
 /* DER handling */
+    {"LTC_DER", 1},
     _C_STRINGIFY(LTC_ASN1_EOL),
     _C_STRINGIFY(LTC_ASN1_BOOLEAN),
     _C_STRINGIFY(LTC_ASN1_INTEGER),
@@ -146,6 +147,9 @@ static const crypt_constant _crypt_constants[] = {
     _C_STRINGIFY(LTC_ASN1_TELETEX_STRING),
     _C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME),
     _C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE),
+    _C_STRINGIFY(LTC_DER_MAX_RECURSION),
+#else
+    {"LTC_DER", 0},
 #endif
 
 #ifdef LTC_CTR_MODE

+ 12 - 1
src/pk/asn1/der/sequence/der_decode_sequence_flexi.c

@@ -43,7 +43,7 @@ static int _new_element(ltc_asn1_list **l)
 */
 int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
 {
-   ltc_asn1_list *l;
+   ltc_asn1_list *l, *t;
    unsigned long err, identifier, len, totlen, data_offset, id_len, len_len;
    void          *realloc_tmp;
 
@@ -463,6 +463,17 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
                 l->child->parent = l;
              }
 
+             t = l;
+             len_len = 0;
+             while((t != NULL) && (t->child != NULL)) {
+                len_len++;
+                t = t->child;
+             }
+             if (len_len > LTC_DER_MAX_RECURSION) {
+                err = CRYPT_PK_ASN1_ERROR;
+                goto error;
+             }
+
              break;
 
          case 0x80: /* Context-specific */

+ 2 - 0
tests/common.h

@@ -16,9 +16,11 @@ extern prng_state yarrow_prng;
 #ifdef LTC_VERBOSE
 #define DO(x) do { fprintf(stderr, "%s:\n", #x); run_cmd((x), __LINE__, __FILE__, #x, NULL); } while (0)
 #define DOX(x, str) do { fprintf(stderr, "%s - %s:\n", #x, (str)); run_cmd((x), __LINE__, __FILE__, #x, (str)); } while (0)
+#define SHOULD_FAIL(x) do { fprintf(stderr, "%s:\n", #x); run_cmd((x) != CRYPT_OK ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0)
 #else
 #define DO(x) do { run_cmd((x), __LINE__, __FILE__, #x, NULL); } while (0)
 #define DOX(x, str) do { run_cmd((x), __LINE__, __FILE__, #x, (str)); } while (0)
+#define SHOULD_FAIL(x) do { run_cmd((x) != CRYPT_OK ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0)
 #endif
 
 void run_cmd(int res, int line, const char *file, const char *cmd, const char *algorithm);

+ 21 - 0
tests/der_test.c

@@ -1580,6 +1580,25 @@ static void der_toolong_test(void)
    if (failed) exit(EXIT_FAILURE);
 }
 
+static void _der_recursion_limit(void)
+{
+   int failed = 0;
+   unsigned int n;
+   unsigned long integer = 123, s;
+   ltc_asn1_list seqs[LTC_DER_MAX_RECURSION + 2], dummy[1], *flexi;
+   unsigned char buf[2048];
+   LTC_SET_ASN1(dummy, 0, LTC_ASN1_SHORT_INTEGER, &integer, 1);
+   LTC_SET_ASN1(seqs, LTC_DER_MAX_RECURSION + 1, LTC_ASN1_SEQUENCE, dummy, 1);
+   for (n = 0; n < LTC_DER_MAX_RECURSION + 1; ++n) {
+      LTC_SET_ASN1(seqs, LTC_DER_MAX_RECURSION - n, LTC_ASN1_SEQUENCE, &seqs[LTC_DER_MAX_RECURSION - n + 1], 1);
+   }
+   s = sizeof(buf);
+   DO(der_encode_sequence(seqs, 1, buf, &s));
+   DO(der_decode_sequence(buf, s, seqs, 1));
+   SHOULD_FAIL(der_decode_sequence_flexi(buf, &s, &flexi));
+   if (failed) exit(EXIT_FAILURE);
+}
+
 int der_test(void)
 {
    unsigned long x, y, z, zz, oid[2][32];
@@ -1614,6 +1633,8 @@ int der_test(void)
 
    if (ltc_mp.name == NULL) return CRYPT_NOP;
 
+   _der_recursion_limit();
+
    der_Xcode_test();
 
 #if !((defined(_WIN32) || defined(_WIN32_WCE)) && !defined(__GNUC__))