Skip to content

Commit 05a51bd

Browse files
committed
Add support for custom constructed ASN.1 types
This fixes #622 Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent aacafad commit 05a51bd

File tree

3 files changed

+58
-4
lines changed

3 files changed

+58
-4
lines changed

src/headers/tomcrypt_pk.h

+8
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,14 @@ typedef struct ltc_asn1_list_ {
572572
LTC_MACRO_list[LTC_TMPVAR(LTC_SAI)].tag = (Tag); \
573573
} while (0)
574574

575+
#define LTC_SET_ASN1_CUSTOM(list, index, Class, Structure, Tag, Type, Data, Size) \
576+
do { \
577+
int LTC_TMPVAR(LTC_SAC) = (index); \
578+
LTC_SET_ASN1(list, LTC_TMPVAR(LTC_SAC), LTC_ASN1_CUSTOM_TYPE, Data, Size); \
579+
LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(LTC_SAC), Class, Structure, Tag); \
580+
list[LTC_TMPVAR(LTC_SAC)].used = (int)(Type); \
581+
} while (0)
582+
575583
#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \
576584
do { \
577585
int LTC_TMPVAR(LTC_SACC) = (index); \

src/pk/asn1/der/custom_type/der_encode_custom_type.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
int der_encode_custom_type(const ltc_asn1_list *root,
2525
unsigned char *out, unsigned long *outlen)
2626
{
27-
int err;
27+
int err, use_root;
2828
ltc_asn1_type type;
2929
const ltc_asn1_list *list;
3030
unsigned long size, x, y, z, i, inlen, id_len;
@@ -49,8 +49,9 @@ int der_encode_custom_type(const ltc_asn1_list *root,
4949
if (der_length_asn1_identifier(root, &id_len) != CRYPT_OK) return CRYPT_INVALID_ARG;
5050
x = id_len;
5151

52-
53-
if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
52+
use_root = root->pc == LTC_ASN1_PC_PRIMITIVE ||
53+
(root->used >= LTC_ASN1_SEQUENCE && root->used <= LTC_ASN1_SETOF);
54+
if (use_root) {
5455
list = root;
5556
inlen = 1;
5657
/* 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,
7273
/* store data */
7374
*outlen -= x;
7475
for (i = 0; i < inlen; i++) {
75-
if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
76+
if (use_root) {
7677
type = (ltc_asn1_type)list[i].used;
7778
} else {
7879
type = list[i].type;

tests/der_test.c

+45
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,49 @@ static void s_der_regression_test(void)
14221422
SHOULD_FAIL(der_decode_sequence_flexi(issue_507, &len, &l));
14231423
}
14241424

1425+
static void s_der_custom_setof(void)
1426+
{
1427+
/*
1428+
* C.f. https://github.com/libtom/libtomcrypt/issues/622
1429+
*
1430+
Toy ::= SEQUENCE {
1431+
hello UTF8String,
1432+
numbers [0] IMPLICIT SET OF Number }
1433+
1434+
Number ::= INTEGER { zero(0), one(1) }
1435+
1436+
30 0F
1437+
0C 02 68 69
1438+
A0 09
1439+
02 01 00
1440+
02 01 00
1441+
02 01 01
1442+
1443+
*
1444+
*/
1445+
1446+
ltc_asn1_list setof[3];
1447+
ltc_asn1_list seq[2];
1448+
const unsigned long zero = 0;
1449+
const unsigned long one = 1;
1450+
const wchar_t *hello = L"hi";
1451+
unsigned char buf[32];
1452+
unsigned long buflen = sizeof(buf);
1453+
ltc_asn1_list *flexi;
1454+
1455+
LTC_SET_ASN1(setof, 0, LTC_ASN1_SHORT_INTEGER, &one, 1);
1456+
LTC_SET_ASN1(setof, 1, LTC_ASN1_SHORT_INTEGER, &zero, 1);
1457+
LTC_SET_ASN1(setof, 2, LTC_ASN1_SHORT_INTEGER, &zero, 1);
1458+
1459+
LTC_SET_ASN1(seq, 0, LTC_ASN1_UTF8_STRING, hello, wcslen(hello));
1460+
LTC_SET_ASN1_CUSTOM(seq, 1, LTC_ASN1_CL_CONTEXT_SPECIFIC, LTC_ASN1_PC_CONSTRUCTED, 0, LTC_ASN1_SETOF, setof, 3);
1461+
DO(der_encode_sequence(seq, 2, buf, &buflen));
1462+
1463+
DO(der_decode_sequence_flexi(buf, &buflen, &flexi));
1464+
s_der_tests_print_flexi(flexi);
1465+
der_free_sequence_flexi(flexi);
1466+
}
1467+
14251468
static void der_toolong_test(void)
14261469
{
14271470
int n, err, failed = 0;
@@ -1652,6 +1695,8 @@ int der_test(void)
16521695

16531696
if (ltc_mp.name == NULL) return CRYPT_NOP;
16541697

1698+
s_der_custom_setof();
1699+
16551700
s_der_recursion_limit();
16561701

16571702
der_Xcode_test();

0 commit comments

Comments
 (0)