Unified · Split
| @@ -45,23 +45,27 @@ enum asn1_opcode { · 44 unmodified lines | |||
| 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 { · 8 unmodified lines | |||
| 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 | ||
| @@ -24,15 +24,20 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { · 23 unmodified lines | |||
| 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, · 138 unmodified lines | |||
| 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: · 25 unmodified lines | |||
| 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: · 85 unmodified lines | |||
| 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: · 10 unmodified lines | |||
| 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: · 95 unmodified lines | |||
| 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: · 1 unmodified line | |||
| 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: · 1 unmodified line | |||
| 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: |
| @@ -666,7 +666,7 @@ struct element { · 665 unmodified lines | |||
| 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, · 206 unmodified lines | |||
| 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) · 491 unmodified lines | |||
| 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) · 17 unmodified lines | |||
| 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) · 28 unmodified lines | |||
| 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: · 15 unmodified lines | |||
| 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: · 67 unmodified lines | |||
| 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) |