Skip to content

Commit 9d03c38

Browse files
committed
add flags to der_decode_sequence()
1 parent 3044b22 commit 9d03c38

File tree

9 files changed

+210
-46
lines changed

9 files changed

+210
-46
lines changed

src/headers/tomcrypt_pk.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -606,10 +606,32 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
606606

607607
#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE)
608608

609+
/** The supported bitmap for all the
610+
* decoders with a `flags` argument.
611+
*/
612+
enum ltc_der_seq {
613+
LTC_DER_SEQ_ZERO = 0x0u,
614+
615+
/** Bit0 - [0]=Unordered (SET or SETOF)
616+
* [1]=Ordered (SEQUENCE) */
617+
LTC_DER_SEQ_UNORDERED = LTC_DER_SEQ_ZERO,
618+
LTC_DER_SEQ_ORDERED = 0x1u,
619+
620+
/** Bit1 - [0]=Relaxed
621+
* [1]=Strict */
622+
LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO,
623+
LTC_DER_SEQ_STRICT = 0x2u,
624+
625+
/** Alternative naming */
626+
LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED,
627+
LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED,
628+
};
629+
609630
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
610-
ltc_asn1_list *list, unsigned long outlen, int ordered);
631+
ltc_asn1_list *list, unsigned long outlen, unsigned int flags);
611632

612-
#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1)
633+
#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED)
634+
#define der_decode_sequence_strict(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT)
613635

614636
int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
615637
unsigned long *outlen);
@@ -647,7 +669,7 @@ extern const unsigned long der_asn1_type_to_identifier_map_sz;
647669
#endif /* LTC_SOURCE */
648670

649671
/* SET */
650-
#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0)
672+
#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SET)
651673
#define der_length_set der_length_sequence
652674
int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
653675
unsigned char *out, unsigned long *outlen);
@@ -658,6 +680,10 @@ int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
658680
/* VA list handy helpers with triplets of <type, size, data> */
659681
int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
660682
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...);
683+
#ifdef LTC_SOURCE
684+
/* internal helper functions */
685+
int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...);
686+
#endif /* LTC_SOURCE */
661687

662688
/* FLEXI DECODER handle unknown list decoder */
663689
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out);

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

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
@param inlen The size of the input
2323
@param list The list of items to decode
2424
@param outlen The number of items in the list
25-
@param ordered Search an unordeded or ordered list
25+
@param flags c.f. enum ltc_der_seq
2626
@return CRYPT_OK on success
2727
*/
2828
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
29-
ltc_asn1_list *list, unsigned long outlen, int ordered)
29+
ltc_asn1_list *list, unsigned long outlen, unsigned int flags)
3030
{
31-
int err, i;
31+
int err, seq_err, i, ordered;
3232
ltc_asn1_type type;
3333
unsigned long size, x, y, z, blksize;
3434
void *data;
@@ -66,10 +66,12 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
6666
for (i = 0; i < (int)outlen; i++) {
6767
list[i].used = 0;
6868
}
69+
ordered = flags & LTC_DER_SEQ_ORDERED;
6970

7071
/* ok read data */
71-
blksize = inlen;
72-
inlen -= x;
72+
seq_err = CRYPT_OK;
73+
blksize += x;
74+
inlen -= x;
7375
for (i = 0; i < (int)outlen; i++) {
7476
z = 0;
7577
type = list[i].type;
@@ -258,7 +260,12 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
258260
}
259261

260262
z = inlen;
261-
if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
263+
err = der_decode_sequence_ex(in + x, z, data, size, flags);
264+
if (err == CRYPT_INPUT_TOO_LONG) {
265+
seq_err = CRYPT_INPUT_TOO_LONG;
266+
err = CRYPT_OK;
267+
}
268+
if (err != CRYPT_OK) {
262269
if (!ordered || list[i].optional) { continue; }
263270
goto LBL_ERR;
264271
}
@@ -306,8 +313,14 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
306313
}
307314
}
308315

309-
if (blksize == x) {
316+
if (blksize == x && seq_err == CRYPT_OK && inlen == 0) {
317+
/* everything decoded and no errors in nested sequences */
318+
err = CRYPT_OK;
319+
} else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) {
320+
/* a sequence reported too-long input, but now we've decoded everything */
310321
err = CRYPT_OK;
322+
} else if (blksize != x && ((flags & LTC_DER_SEQ_RELAXED) != LTC_DER_SEQ_RELAXED)) {
323+
err = CRYPT_INVALID_PACKET;
311324
} else {
312325
err = CRYPT_INPUT_TOO_LONG;
313326
}

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

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,27 @@
2121
Decode a SEQUENCE type using a VA list
2222
@param in Input buffer
2323
@param inlen Length of input in octets
24-
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
24+
@param a1 Initialized argument list #1
25+
@param a2 Initialized argument list #2 (copy of #1)
26+
@param flags c.f. enum ltc_der_seq
2527
@return CRYPT_OK on success
2628
*/
27-
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
29+
static int _der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags)
2830
{
2931
int err;
3032
ltc_asn1_type type;
3133
unsigned long size, x;
3234
void *data;
33-
va_list args;
3435
ltc_asn1_list *list;
3536

3637
LTC_ARGCHK(in != NULL);
3738

3839
/* get size of output that will be required */
39-
va_start(args, inlen);
4040
x = 0;
4141
for (;;) {
42-
type = (ltc_asn1_type)va_arg(args, int);
43-
size = va_arg(args, unsigned long);
44-
data = va_arg(args, void*);
42+
type = (ltc_asn1_type)va_arg(a1, int);
43+
size = va_arg(a1, unsigned long);
44+
data = va_arg(a1, void*);
4545
LTC_UNUSED_PARAM(size);
4646
LTC_UNUSED_PARAM(data);
4747

@@ -73,11 +73,9 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
7373

7474
case LTC_ASN1_EOL:
7575
case LTC_ASN1_CUSTOM_TYPE:
76-
va_end(args);
7776
return CRYPT_INVALID_ARG;
7877
}
7978
}
80-
va_end(args);
8179

8280
/* allocate structure for x elements */
8381
if (x == 0) {
@@ -90,12 +88,11 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
9088
}
9189

9290
/* fill in the structure */
93-
va_start(args, inlen);
9491
x = 0;
9592
for (;;) {
96-
type = (ltc_asn1_type)va_arg(args, int);
97-
size = va_arg(args, unsigned long);
98-
data = va_arg(args, void*);
93+
type = (ltc_asn1_type)va_arg(a2, int);
94+
size = va_arg(a2, unsigned long);
95+
data = va_arg(a2, void*);
9996

10097
if (type == LTC_ASN1_EOL) {
10198
break;
@@ -128,13 +125,63 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
128125
break;
129126
}
130127
}
131-
va_end(args);
132128

133-
err = der_decode_sequence(in, inlen, list, x);
129+
err = der_decode_sequence_ex(in, inlen, list, x, flags);
134130
XFREE(list);
135131
return err;
136132
}
137133

134+
/**
135+
Decode a SEQUENCE type using a VA list
136+
@param in Input buffer
137+
@param inlen Length of input in octets
138+
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
139+
@return CRYPT_OK on success
140+
*/
141+
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
142+
{
143+
va_list a1, a2;
144+
int err;
145+
146+
LTC_ARGCHK(in != NULL);
147+
148+
va_start(a1, inlen);
149+
va_start(a2, inlen);
150+
151+
err = _der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED);
152+
153+
va_end(a2);
154+
va_end(a1);
155+
156+
return err;
157+
}
158+
159+
/**
160+
Decode a SEQUENCE type using a VA list
161+
@param in Input buffer
162+
@param inlen Length of input in octets
163+
@param flags c.f. enum ltc_der_seq
164+
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
165+
@return CRYPT_OK on success
166+
*/
167+
int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...)
168+
{
169+
va_list a1, a2;
170+
int err;
171+
172+
LTC_ARGCHK(in != NULL);
173+
174+
va_start(a1, flags);
175+
va_start(a2, flags);
176+
177+
err = _der_decode_sequence_va(in, inlen, a1, a2, flags);
178+
179+
va_end(a2);
180+
va_end(a1);
181+
182+
return err;
183+
}
184+
138185
#endif
139186

140187

src/pk/dsa/dsa_verify_hash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
111111
LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL);
112112
LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL);
113113

114-
err = der_decode_sequence(sig, siglen, sig_seq, 2);
114+
err = der_decode_sequence_strict(sig, siglen, sig_seq, 2);
115115
if (err != CRYPT_OK) {
116116
goto LBL_ERR;
117117
}

src/pk/ecc/ecc_verify_hash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
6666
}
6767
else {
6868
/* ASN.1 format */
69-
if ((err = der_decode_sequence_multi(sig, siglen,
69+
if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT,
7070
LTC_ASN1_INTEGER, 1UL, r,
7171
LTC_ASN1_INTEGER, 1UL, s,
7272
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; }

src/pk/rsa/rsa_verify_hash.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,10 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
142142
LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
143143
LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);
144144

145-
if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
145+
if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
146146
/* fallback to Legacy:missing NULL */
147147
LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1);
148-
if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
148+
if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
149149
XFREE(out);
150150
goto bail_2;
151151
}

0 commit comments

Comments
 (0)