Skip to content

Commit 6b85be4

Browse files
authored
Merge pull request #533 from libtom/fix-373
really implement DER decoding resursion limit
2 parents 14ed10c + 561d4ab commit 6b85be4

File tree

2 files changed

+39
-25
lines changed

2 files changed

+39
-25
lines changed

src/pk/asn1/der/sequence/der_decode_sequence_flexi.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ static int _new_element(ltc_asn1_list **l)
3939
@param in The input buffer
4040
@param inlen [in/out] The length of the input buffer and on output the amount of decoded data
4141
@param out [out] A pointer to the linked list
42+
@param depth The depth/level of decoding recursion we've already reached
4243
@return CRYPT_OK on success.
4344
*/
44-
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
45+
static int _der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out, unsigned long depth)
4546
{
46-
ltc_asn1_list *l, *t;
47+
ltc_asn1_list *l;
4748
unsigned long err, identifier, len, totlen, data_offset, id_len, len_len;
4849
void *realloc_tmp;
4950

@@ -428,6 +429,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
428429
}
429430
}
430431

432+
/* check that we don't go over the recursion limit */
433+
if (depth > LTC_DER_MAX_RECURSION) {
434+
err = CRYPT_PK_ASN1_ERROR;
435+
goto error;
436+
}
437+
431438
if ((l->data = XMALLOC(len)) == NULL) {
432439
err = CRYPT_MEM;
433440
goto error;
@@ -446,7 +453,7 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
446453
len_len = len;
447454

448455
/* Sequence elements go as child */
449-
if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
456+
if ((err = _der_decode_sequence_flexi(in, &len, &(l->child), depth+1)) != CRYPT_OK) {
450457
goto error;
451458
}
452459
if (len_len != len) {
@@ -463,17 +470,6 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
463470
l->child->parent = l;
464471
}
465472

466-
t = l;
467-
len_len = 0;
468-
while((t != NULL) && (t->child != NULL)) {
469-
len_len++;
470-
t = t->child;
471-
}
472-
if (len_len > LTC_DER_MAX_RECURSION) {
473-
err = CRYPT_PK_ASN1_ERROR;
474-
goto error;
475-
}
476-
477473
break;
478474

479475
case 0x80: /* Context-specific */
@@ -535,6 +531,18 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
535531
return err;
536532
}
537533

534+
/**
535+
ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
536+
@param in The input buffer
537+
@param inlen [in/out] The length of the input buffer and on output the amount of decoded data
538+
@param out [out] A pointer to the linked list
539+
@return CRYPT_OK on success.
540+
*/
541+
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
542+
{
543+
return _der_decode_sequence_flexi(in, inlen, out, 0);
544+
}
545+
538546
#endif
539547

540548

tests/der_test.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,21 +1560,27 @@ static void der_toolong_test(void)
15601560

15611561
static void _der_recursion_limit(void)
15621562
{
1563-
int failed = 0;
1564-
unsigned int n;
1563+
unsigned int n, m;
15651564
unsigned long integer = 123, s;
15661565
ltc_asn1_list seqs[LTC_DER_MAX_RECURSION + 2], dummy[1], *flexi;
15671566
unsigned char buf[2048];
1568-
LTC_SET_ASN1(dummy, 0, LTC_ASN1_SHORT_INTEGER, &integer, 1);
1569-
LTC_SET_ASN1(seqs, LTC_DER_MAX_RECURSION + 1, LTC_ASN1_SEQUENCE, dummy, 1);
1570-
for (n = 0; n < LTC_DER_MAX_RECURSION + 1; ++n) {
1571-
LTC_SET_ASN1(seqs, LTC_DER_MAX_RECURSION - n, LTC_ASN1_SEQUENCE, &seqs[LTC_DER_MAX_RECURSION - n + 1], 1);
1567+
for (m = 0; m < 3; ++m) {
1568+
LTC_SET_ASN1(dummy, 0, LTC_ASN1_SHORT_INTEGER, &integer, 1);
1569+
LTC_SET_ASN1(seqs, LTC_DER_MAX_RECURSION + 1, LTC_ASN1_SEQUENCE, dummy, 1);
1570+
for (n = m; n < LTC_DER_MAX_RECURSION + 1; ++n) {
1571+
LTC_SET_ASN1(seqs, LTC_DER_MAX_RECURSION - n, LTC_ASN1_SEQUENCE, &seqs[LTC_DER_MAX_RECURSION - n + 1], 1);
1572+
}
1573+
s = sizeof(buf);
1574+
DO(der_encode_sequence(&seqs[m], 1, buf, &s));
1575+
DO(der_decode_sequence(buf, s, &seqs[m], 1));
1576+
if (m < 2) {
1577+
SHOULD_FAIL(der_decode_sequence_flexi(buf, &s, &flexi));
1578+
}
1579+
else {
1580+
DO(der_decode_sequence_flexi(buf, &s, &flexi));
1581+
der_free_sequence_flexi(flexi);
1582+
}
15721583
}
1573-
s = sizeof(buf);
1574-
DO(der_encode_sequence(seqs, 1, buf, &s));
1575-
DO(der_decode_sequence(buf, s, seqs, 1));
1576-
SHOULD_FAIL(der_decode_sequence_flexi(buf, &s, &flexi));
1577-
if (failed) exit(EXIT_FAILURE);
15781584
}
15791585

15801586
int der_test(void)

0 commit comments

Comments
 (0)