diff options
-rw-r--r-- | include/linux/asn1_ber_bytecode.h | 16 | ||||
-rw-r--r-- | lib/asn1_decoder.c | 27 | ||||
-rw-r--r-- | scripts/asn1_compiler.c | 23 |
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 | ||
444 | data_overrun_error: | 463 | data_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 | */ |
1377 | static void render_element(FILE *out, struct element *e, struct element *tag) | 1378 | static 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) |