Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for custom constructed ASN.1 types #624

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/headers/tomcrypt_pk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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); \
Expand Down
9 changes: 5 additions & 4 deletions src/pk/asn1/der/custom_type/der_encode_custom_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions src/pk/asn1/der/utf8/der_decode_utf8_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,

https://tools.ietf.org/html/rfc3629#section-3
*/
for (y = 0; x < inlen; ) {
len += x;
for (y = 0; x < len; ) {
/* read first byte */
tmp = in[x++];

Expand Down Expand Up @@ -87,7 +88,7 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
/* now update z so it equals the number of additional bytes to read */
if (z > 0) { --z; }

if (x + z > inlen) {
if (x + z > len) {
return CRYPT_INVALID_PACKET;
}

Expand Down
92 changes: 68 additions & 24 deletions tests/der_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ int der_test(void)

#else

#include <wchar.h>

#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 2
#define LTC_DER_TESTS_PRINT_FLEXI
#endif
Expand Down Expand Up @@ -252,7 +254,7 @@ static void s_free(void *p)
XFREE(p);
}

static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
static void s_der_tests_print_flexi_i(ltc_asn1_list* l, unsigned int level)
{
char *buf = NULL;
const char* name = NULL;
Expand Down Expand Up @@ -435,15 +437,28 @@ static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
}

if (ostring) {
s_der_tests_print_flexi(ostring, level + 1);
s_der_tests_print_flexi_i(ostring, level + 1);
der_free_sequence_flexi(ostring);
}

if (l->child)
s_der_tests_print_flexi(l->child, level + 1);
s_der_tests_print_flexi_i(l->child, level + 1);

if (l->next)
s_der_tests_print_flexi(l->next, level);
s_der_tests_print_flexi_i(l->next, level);
}

static void s_der_tests_print_flexi(ltc_asn1_list* l)
{
fprintf(stderr, "\n\n");
s_der_tests_print_flexi_i(l, 0);
fprintf(stderr, "\n\n");
}

#else
static void s_der_tests_print_flexi(ltc_asn1_list* l)
{
LTC_UNUSED_PARAM(l);
}
#endif

Expand Down Expand Up @@ -471,11 +486,7 @@ static void der_cacert_test(void)
CHECK_ASN1_TYPE(decoded_list, LTC_ASN1_SEQUENCE);
CHECK_ASN1_HAS_NO_DATA(decoded_list);

#ifdef LTC_DER_TESTS_PRINT_FLEXI
printf("\n\n--- test print start ---\n\n");
s_der_tests_print_flexi(decoded_list, 0);
printf("\n\n--- test print end ---\n\n");
#endif
s_der_tests_print_flexi(decoded_list);

l = decoded_list;

Expand Down Expand Up @@ -1169,11 +1180,7 @@ static void s_der_decode_print(const void* p, unsigned long* plen)
{
ltc_asn1_list *list;
DO(der_decode_sequence_flexi(p, plen, &list));
#ifdef LTC_DER_TESTS_PRINT_FLEXI
fprintf(stderr, "\n\n");
s_der_tests_print_flexi(list, 0);
fprintf(stderr, "\n\n");
#endif
s_der_tests_print_flexi(list);
der_sequence_free(list);
}

Expand Down Expand Up @@ -1342,11 +1349,7 @@ static void der_Xcode_test(void)

i = sizeof(teletex_neg_int);
DO(der_decode_sequence_flexi(teletex_neg_int, &i, &list));
#ifdef LTC_DER_TESTS_PRINT_FLEXI
fprintf(stderr, "\n\n");
s_der_tests_print_flexi(list, 0);
fprintf(stderr, "\n\n");
#endif
s_der_tests_print_flexi(list);
if (list->child == NULL || list->child->next == NULL)
exit(EXIT_FAILURE);
ttex_neg_int[0] = *list->child->next;
Expand All @@ -1368,11 +1371,7 @@ static int s_der_decode_sequence_flexi(const void *in, unsigned long inlen, void
{
ltc_asn1_list** list = ctx;
if (der_decode_sequence_flexi(in, &inlen, list) == CRYPT_OK) {
#ifdef LTC_DER_TESTS_PRINT_FLEXI
fprintf(stderr, "\n\n");
s_der_tests_print_flexi(*list, 0);
fprintf(stderr, "\n\n");
#endif
s_der_tests_print_flexi(*list);
der_sequence_free(*list);
}
return CRYPT_OK;
Expand Down Expand Up @@ -1423,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;
Expand Down Expand Up @@ -1653,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();
Expand Down