aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/asn1_ber_bytecode.h16
-rw-r--r--lib/asn1_decoder.c27
-rw-r--r--scripts/asn1_compiler.c23
3 files changed, 48 insertions, 18 deletions
diff --git a/include/linux/asn1_ber_bytecode.h b/include/linux/asn1_ber_bytecode.h
index 945d44ae529c..ab3a6c002f7b 100644
--- a/include/linux/asn1_ber_bytecode.h
+++ b/include/linux/asn1_ber_bytecode.h
@@ -45,23 +45,27 @@ enum asn1_opcode {
45 ASN1_OP_MATCH_JUMP = 0x04, 45 ASN1_OP_MATCH_JUMP = 0x04,
46 ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, 46 ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05,
47 ASN1_OP_MATCH_ANY = 0x08, 47 ASN1_OP_MATCH_ANY = 0x08,
48 ASN1_OP_MATCH_ANY_OR_SKIP = 0x09,
48 ASN1_OP_MATCH_ANY_ACT = 0x0a, 49 ASN1_OP_MATCH_ANY_ACT = 0x0a,
50 ASN1_OP_MATCH_ANY_ACT_OR_SKIP = 0x0b,
49 /* Everything before here matches unconditionally */ 51 /* Everything before here matches unconditionally */
50 52
51 ASN1_OP_COND_MATCH_OR_SKIP = 0x11, 53 ASN1_OP_COND_MATCH_OR_SKIP = 0x11,
52 ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, 54 ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13,
53 ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, 55 ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15,
54 ASN1_OP_COND_MATCH_ANY = 0x18, 56 ASN1_OP_COND_MATCH_ANY = 0x18,
57 ASN1_OP_COND_MATCH_ANY_OR_SKIP = 0x19,
55 ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, 58 ASN1_OP_COND_MATCH_ANY_ACT = 0x1a,
59 ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP = 0x1b,
56 60
57 /* Everything before here will want a tag from the data */ 61 /* Everything before here will want a tag from the data */
58#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT 62#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP
59 63
60 /* These are here to help fill up space */ 64 /* These are here to help fill up space */
61 ASN1_OP_COND_FAIL = 0x1b, 65 ASN1_OP_COND_FAIL = 0x1c,
62 ASN1_OP_COMPLETE = 0x1c, 66 ASN1_OP_COMPLETE = 0x1d,
63 ASN1_OP_ACT = 0x1d, 67 ASN1_OP_ACT = 0x1e,
64 ASN1_OP_RETURN = 0x1e, 68 ASN1_OP_MAYBE_ACT = 0x1f,
65 69
66 /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ 70 /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */
67 ASN1_OP_END_SEQ = 0x20, 71 ASN1_OP_END_SEQ = 0x20,
@@ -76,6 +80,8 @@ enum asn1_opcode {
76#define ASN1_OP_END__OF 0x02 80#define ASN1_OP_END__OF 0x02
77#define ASN1_OP_END__ACT 0x04 81#define ASN1_OP_END__ACT 0x04
78 82
83 ASN1_OP_RETURN = 0x28,
84
79 ASN1_OP__NR 85 ASN1_OP__NR
80}; 86};
81 87
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:
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c
index 7750e9c31483..1c75e22b6385 100644
--- a/scripts/asn1_compiler.c
+++ b/scripts/asn1_compiler.c
@@ -666,7 +666,7 @@ struct element {
666 unsigned flags; 666 unsigned flags;
667#define ELEMENT_IMPLICIT 0x0001 667#define ELEMENT_IMPLICIT 0x0001
668#define ELEMENT_EXPLICIT 0x0002 668#define ELEMENT_EXPLICIT 0x0002
669#define ELEMENT_MARKED 0x0004 669#define ELEMENT_TAG_SPECIFIED 0x0004
670#define ELEMENT_RENDERED 0x0008 670#define ELEMENT_RENDERED 0x0008
671#define ELEMENT_SKIPPABLE 0x0010 671#define ELEMENT_SKIPPABLE 0x0010
672#define ELEMENT_CONDITIONAL 0x0020 672#define ELEMENT_CONDITIONAL 0x0020
@@ -879,6 +879,7 @@ static struct element *parse_type(struct token **_cursor, struct token *end,
879 879
880 element->tag &= ~0x1f; 880 element->tag &= ~0x1f;
881 element->tag |= strtoul(cursor->value, &p, 10); 881 element->tag |= strtoul(cursor->value, &p, 10);
882 element->flags |= ELEMENT_TAG_SPECIFIED;
882 if (p - cursor->value != cursor->size) 883 if (p - cursor->value != cursor->size)
883 abort(); 884 abort();
884 cursor++; 885 cursor++;
@@ -1376,7 +1377,7 @@ static void render_out_of_line_list(FILE *out)
1376 */ 1377 */
1377static void render_element(FILE *out, struct element *e, struct element *tag) 1378static void render_element(FILE *out, struct element *e, struct element *tag)
1378{ 1379{
1379 struct element *ec; 1380 struct element *ec, *x;
1380 const char *cond, *act; 1381 const char *cond, *act;
1381 int entry, skippable = 0, outofline = 0; 1382 int entry, skippable = 0, outofline = 0;
1382 1383
@@ -1400,7 +1401,8 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
1400 act = e->action ? "_ACT" : ""; 1401 act = e->action ? "_ACT" : "";
1401 switch (e->compound) { 1402 switch (e->compound) {
1402 case ANY: 1403 case ANY:
1403 render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); 1404 render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,",
1405 cond, act, skippable ? "_OR_SKIP" : "");
1404 if (e->name) 1406 if (e->name)
1405 render_more(out, "\t\t// %*.*s", 1407 render_more(out, "\t\t// %*.*s",
1406 (int)e->name->size, (int)e->name->size, 1408 (int)e->name->size, (int)e->name->size,
@@ -1435,15 +1437,17 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
1435 break; 1437 break;
1436 } 1438 }
1437 1439
1438 if (e->name) 1440 x = tag ?: e;
1441 if (x->name)
1439 render_more(out, "\t\t// %*.*s", 1442 render_more(out, "\t\t// %*.*s",
1440 (int)e->name->size, (int)e->name->size, 1443 (int)x->name->size, (int)x->name->size,
1441 e->name->value); 1444 x->name->value);
1442 render_more(out, "\n"); 1445 render_more(out, "\n");
1443 1446
1444 /* Render the tag */ 1447 /* Render the tag */
1445 if (!tag) 1448 if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED))
1446 tag = e; 1449 tag = e;
1450
1447 if (tag->class == ASN1_UNIV && 1451 if (tag->class == ASN1_UNIV &&
1448 tag->tag != 14 && 1452 tag->tag != 14 &&
1449 tag->tag != 15 && 1453 tag->tag != 15 &&
@@ -1465,7 +1469,8 @@ dont_render_tag:
1465 case TYPE_REF: 1469 case TYPE_REF:
1466 render_element(out, e->type->type->element, tag); 1470 render_element(out, e->type->type->element, tag);
1467 if (e->action) 1471 if (e->action)
1468 render_opcode(out, "ASN1_OP_ACT,\n"); 1472 render_opcode(out, "ASN1_OP_%sACT,\n",
1473 skippable ? "MAYBE_" : "");
1469 break; 1474 break;
1470 1475
1471 case SEQUENCE: 1476 case SEQUENCE:
@@ -1539,7 +1544,7 @@ dont_render_tag:
1539 1544
1540 case CHOICE: 1545 case CHOICE:
1541 for (ec = e->children; ec; ec = ec->next) 1546 for (ec = e->children; ec; ec = ec->next)
1542 render_element(out, ec, NULL); 1547 render_element(out, ec, ec);
1543 if (!skippable) 1548 if (!skippable)
1544 render_opcode(out, "ASN1_OP_COND_FAIL,\n"); 1549 render_opcode(out, "ASN1_OP_COND_FAIL,\n");
1545 if (e->action) 1550 if (e->action)