aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1_decoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asn1_decoder.c')
-rw-r--r--lib/asn1_decoder.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c
index 1a000bb050f9..2b3f46c049d4 100644
--- a/lib/asn1_decoder.c
+++ b/lib/asn1_decoder.c
@@ -24,15 +24,20 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = {
24 [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, 24 [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1,
25 [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, 25 [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
26 [ASN1_OP_MATCH_ANY] = 1, 26 [ASN1_OP_MATCH_ANY] = 1,
27 [ASN1_OP_MATCH_ANY_OR_SKIP] = 1,
27 [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, 28 [ASN1_OP_MATCH_ANY_ACT] = 1 + 1,
29 [ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
28 [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, 30 [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1,
29 [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, 31 [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1,
30 [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, 32 [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
31 [ASN1_OP_COND_MATCH_ANY] = 1, 33 [ASN1_OP_COND_MATCH_ANY] = 1,
34 [ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1,
32 [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, 35 [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1,
36 [ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
33 [ASN1_OP_COND_FAIL] = 1, 37 [ASN1_OP_COND_FAIL] = 1,
34 [ASN1_OP_COMPLETE] = 1, 38 [ASN1_OP_COMPLETE] = 1,
35 [ASN1_OP_ACT] = 1 + 1, 39 [ASN1_OP_ACT] = 1 + 1,
40 [ASN1_OP_MAYBE_ACT] = 1 + 1,
36 [ASN1_OP_RETURN] = 1, 41 [ASN1_OP_RETURN] = 1,
37 [ASN1_OP_END_SEQ] = 1, 42 [ASN1_OP_END_SEQ] = 1,
38 [ASN1_OP_END_SEQ_OF] = 1 + 1, 43 [ASN1_OP_END_SEQ_OF] = 1 + 1,
@@ -177,6 +182,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
177 unsigned char flags = 0; 182 unsigned char flags = 0;
178#define FLAG_INDEFINITE_LENGTH 0x01 183#define FLAG_INDEFINITE_LENGTH 0x01
179#define FLAG_MATCHED 0x02 184#define FLAG_MATCHED 0x02
185#define FLAG_LAST_MATCHED 0x04 /* Last tag matched */
180#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag 186#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag
181 * - ie. whether or not we are going to parse 187 * - ie. whether or not we are going to parse
182 * a compound type. 188 * a compound type.
@@ -208,9 +214,9 @@ next_op:
208 unsigned char tmp; 214 unsigned char tmp;
209 215
210 /* Skip conditional matches if possible */ 216 /* Skip conditional matches if possible */
211 if ((op & ASN1_OP_MATCH__COND && 217 if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) ||
212 flags & FLAG_MATCHED) || 218 (op & ASN1_OP_MATCH__SKIP && dp == datalen)) {
213 dp == datalen) { 219 flags &= ~FLAG_LAST_MATCHED;
214 pc += asn1_op_lengths[op]; 220 pc += asn1_op_lengths[op];
215 goto next_op; 221 goto next_op;
216 } 222 }
@@ -302,7 +308,9 @@ next_op:
302 /* Decide how to handle the operation */ 308 /* Decide how to handle the operation */
303 switch (op) { 309 switch (op) {
304 case ASN1_OP_MATCH_ANY_ACT: 310 case ASN1_OP_MATCH_ANY_ACT:
311 case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
305 case ASN1_OP_COND_MATCH_ANY_ACT: 312 case ASN1_OP_COND_MATCH_ANY_ACT:
313 case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
306 ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); 314 ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len);
307 if (ret < 0) 315 if (ret < 0)
308 return ret; 316 return ret;
@@ -319,8 +327,10 @@ next_op:
319 case ASN1_OP_MATCH: 327 case ASN1_OP_MATCH:
320 case ASN1_OP_MATCH_OR_SKIP: 328 case ASN1_OP_MATCH_OR_SKIP:
321 case ASN1_OP_MATCH_ANY: 329 case ASN1_OP_MATCH_ANY:
330 case ASN1_OP_MATCH_ANY_OR_SKIP:
322 case ASN1_OP_COND_MATCH_OR_SKIP: 331 case ASN1_OP_COND_MATCH_OR_SKIP:
323 case ASN1_OP_COND_MATCH_ANY: 332 case ASN1_OP_COND_MATCH_ANY:
333 case ASN1_OP_COND_MATCH_ANY_OR_SKIP:
324 skip_data: 334 skip_data:
325 if (!(flags & FLAG_CONS)) { 335 if (!(flags & FLAG_CONS)) {
326 if (flags & FLAG_INDEFINITE_LENGTH) { 336 if (flags & FLAG_INDEFINITE_LENGTH) {
@@ -422,8 +432,15 @@ next_op:
422 pc += asn1_op_lengths[op]; 432 pc += asn1_op_lengths[op];
423 goto next_op; 433 goto next_op;
424 434
435 case ASN1_OP_MAYBE_ACT:
436 if (!(flags & FLAG_LAST_MATCHED)) {
437 pc += asn1_op_lengths[op];
438 goto next_op;
439 }
425 case ASN1_OP_ACT: 440 case ASN1_OP_ACT:
426 ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); 441 ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len);
442 if (ret < 0)
443 return ret;
427 pc += asn1_op_lengths[op]; 444 pc += asn1_op_lengths[op];
428 goto next_op; 445 goto next_op;
429 446
@@ -431,6 +448,7 @@ next_op:
431 if (unlikely(jsp <= 0)) 448 if (unlikely(jsp <= 0))
432 goto jump_stack_underflow; 449 goto jump_stack_underflow;
433 pc = jump_stack[--jsp]; 450 pc = jump_stack[--jsp];
451 flags |= FLAG_MATCHED | FLAG_LAST_MATCHED;
434 goto next_op; 452 goto next_op;
435 453
436 default: 454 default:
@@ -438,7 +456,8 @@ next_op:
438 } 456 }
439 457
440 /* Shouldn't reach here */ 458 /* Shouldn't reach here */
441 pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); 459 pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n",
460 op, pc);
442 return -EBADMSG; 461 return -EBADMSG;
443 462
444data_overrun_error: 463data_overrun_error: