Przeglądaj źródła

Add support for custom constructed ASN.1 types

This fixes #622

Signed-off-by: Steffen Jaeckel <[email protected]>
Steffen Jaeckel 2 lat temu
rodzic
commit
c253c0e527

+ 8 - 0
src/headers/tomcrypt_pk.h

@@ -572,6 +572,14 @@ typedef struct ltc_asn1_list_ {
       LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].tag = (Tag);                   \
    } while (0)
 
+#define LTC_SET_ASN1_CUSTOM(list, index, Class, Structure, Tag, Type, Data, Size)   \
+   do {                                                                             \
+      int LTC_TMPVAR(SAC) = (index);                                                \
+      LTC_SET_ASN1(list, LTC_TMPVAR(SAC), LTC_ASN1_CUSTOM_TYPE, Data, Size);        \
+      LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SAC), Class, Structure, Tag);        \
+      list[LTC_TMPVAR(SAC)].used = (int)(Type);                                     \
+   } while (0)
+
 #define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data)                       \
    do {                                                                                      \
       int LTC_TMPVAR(SACC) = (index);                                                        \

+ 5 - 4
src/pk/asn1/der/custom_type/der_encode_custom_type.c

@@ -24,7 +24,7 @@
 int der_encode_custom_type(const ltc_asn1_list *root,
                                  unsigned char *out,  unsigned long *outlen)
 {
-   int           err;
+   int           err, use_root;
    ltc_asn1_type type;
    const ltc_asn1_list *list;
    unsigned long size, x, y, z, i, inlen, id_len;
@@ -49,8 +49,9 @@ int der_encode_custom_type(const ltc_asn1_list *root,
    if (der_length_asn1_identifier(root, &id_len) != CRYPT_OK) return CRYPT_INVALID_ARG;
    x = id_len;
 
-
-   if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+   use_root = root->pc == LTC_ASN1_PC_PRIMITIVE ||
+         (root->used >= LTC_ASN1_SEQUENCE && root->used <= LTC_ASN1_SETOF);
+   if (use_root) {
       list = root;
       inlen = 1;
       /* In case it's a PRIMITIVE type we encode directly to the output
@@ -72,7 +73,7 @@ int der_encode_custom_type(const ltc_asn1_list *root,
    /* store data */
    *outlen -= x;
    for (i = 0; i < inlen; i++) {
-       if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+       if (use_root) {
           type = (ltc_asn1_type)list[i].used;
        } else {
           type = list[i].type;

+ 45 - 0
tests/der_test.c

@@ -1422,6 +1422,49 @@ static void s_der_regression_test(void)
    SHOULD_FAIL(der_decode_sequence_flexi(issue_507, &len, &l));
 }
 
+static void s_der_custom_setof(void)
+{
+   /*
+    * C.f. https://github.com/libtom/libtomcrypt/issues/622
+    *
+Toy ::= SEQUENCE {
+  hello        UTF8String,
+  numbers [0]  IMPLICIT SET OF Number  }
+
+Number ::= INTEGER { zero(0), one(1) }
+
+30 0F
+  0C 02 68 69
+  A0 09
+    02 01 00
+    02 01 00
+    02 01 01
+
+    *
+    */
+
+   ltc_asn1_list setof[3];
+   ltc_asn1_list seq[2];
+   const unsigned long zero = 0;
+   const unsigned long one = 1;
+   const wchar_t *hello = L"hi";
+   unsigned char buf[32];
+   unsigned long buflen = sizeof(buf);
+   ltc_asn1_list *flexi;
+
+   LTC_SET_ASN1(setof, 0, LTC_ASN1_SHORT_INTEGER, &one, 1);
+   LTC_SET_ASN1(setof, 1, LTC_ASN1_SHORT_INTEGER, &zero, 1);
+   LTC_SET_ASN1(setof, 2, LTC_ASN1_SHORT_INTEGER, &zero, 1);
+
+   LTC_SET_ASN1(seq, 0, LTC_ASN1_UTF8_STRING, hello, wcslen(hello));
+   LTC_SET_ASN1_CUSTOM(seq, 1, LTC_ASN1_CL_CONTEXT_SPECIFIC, LTC_ASN1_PC_CONSTRUCTED, 0, LTC_ASN1_SETOF, setof, 3);
+   DO(der_encode_sequence(seq, 2, buf, &buflen));
+
+   DO(der_decode_sequence_flexi(buf, &buflen, &flexi));
+   s_der_tests_print_flexi(flexi);
+   der_free_sequence_flexi(flexi);
+}
+
 static void der_toolong_test(void)
 {
    int n, err, failed = 0;
@@ -1652,6 +1695,8 @@ int der_test(void)
 
    if (ltc_mp.name == NULL) return CRYPT_NOP;
 
+   s_der_custom_setof();
+
    s_der_recursion_limit();
 
    der_Xcode_test();