diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index 903e118d..3eb25f90 100644 --- a/src/headers/tomcrypt_pk.h +++ b/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); \ diff --git a/src/pk/asn1/der/custom_type/der_encode_custom_type.c b/src/pk/asn1/der/custom_type/der_encode_custom_type.c index 586fb316..9b8aca07 100644 --- a/src/pk/asn1/der/custom_type/der_encode_custom_type.c +++ b/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; diff --git a/tests/der_test.c b/tests/der_test.c index 32494fb0..7d5901d8 100644 --- a/tests/der_test.c +++ b/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();