Loading include/linux/asn1_ber_bytecode.h +11 −5 Original line number Diff line number Diff line Loading @@ -45,23 +45,27 @@ enum asn1_opcode { ASN1_OP_MATCH_JUMP = 0x04, ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, ASN1_OP_MATCH_ANY = 0x08, ASN1_OP_MATCH_ANY_OR_SKIP = 0x09, ASN1_OP_MATCH_ANY_ACT = 0x0a, ASN1_OP_MATCH_ANY_ACT_OR_SKIP = 0x0b, /* Everything before here matches unconditionally */ ASN1_OP_COND_MATCH_OR_SKIP = 0x11, ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, ASN1_OP_COND_MATCH_ANY = 0x18, ASN1_OP_COND_MATCH_ANY_OR_SKIP = 0x19, ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP = 0x1b, /* Everything before here will want a tag from the data */ #define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT #define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP /* These are here to help fill up space */ ASN1_OP_COND_FAIL = 0x1b, ASN1_OP_COMPLETE = 0x1c, ASN1_OP_ACT = 0x1d, ASN1_OP_RETURN = 0x1e, ASN1_OP_COND_FAIL = 0x1c, ASN1_OP_COMPLETE = 0x1d, ASN1_OP_ACT = 0x1e, ASN1_OP_MAYBE_ACT = 0x1f, /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ ASN1_OP_END_SEQ = 0x20, Loading @@ -76,6 +80,8 @@ enum asn1_opcode { #define ASN1_OP_END__OF 0x02 #define ASN1_OP_END__ACT 0x04 ASN1_OP_RETURN = 0x28, ASN1_OP__NR }; Loading lib/asn1_decoder.c +23 −4 Original line number Diff line number Diff line Loading @@ -24,15 +24,20 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, [ASN1_OP_MATCH_ANY] = 1, [ASN1_OP_MATCH_ANY_OR_SKIP] = 1, [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, [ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, [ASN1_OP_COND_MATCH_ANY] = 1, [ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1, [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, [ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, [ASN1_OP_COND_FAIL] = 1, [ASN1_OP_COMPLETE] = 1, [ASN1_OP_ACT] = 1 + 1, [ASN1_OP_MAYBE_ACT] = 1 + 1, [ASN1_OP_RETURN] = 1, [ASN1_OP_END_SEQ] = 1, [ASN1_OP_END_SEQ_OF] = 1 + 1, Loading Loading @@ -177,6 +182,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, unsigned char flags = 0; #define FLAG_INDEFINITE_LENGTH 0x01 #define FLAG_MATCHED 0x02 #define FLAG_LAST_MATCHED 0x04 /* Last tag matched */ #define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag * - ie. whether or not we are going to parse * a compound type. Loading Loading @@ -208,9 +214,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, unsigned char tmp; /* Skip conditional matches if possible */ if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) || dp == datalen) { if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) || (op & ASN1_OP_MATCH__SKIP && dp == datalen)) { flags &= ~FLAG_LAST_MATCHED; pc += asn1_op_lengths[op]; goto next_op; } Loading Loading @@ -302,7 +308,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, /* Decide how to handle the operation */ switch (op) { case ASN1_OP_MATCH_ANY_ACT: case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: case ASN1_OP_COND_MATCH_ANY_ACT: case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); if (ret < 0) return ret; Loading @@ -319,8 +327,10 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, case ASN1_OP_MATCH: case ASN1_OP_MATCH_OR_SKIP: case ASN1_OP_MATCH_ANY: case ASN1_OP_MATCH_ANY_OR_SKIP: case ASN1_OP_COND_MATCH_OR_SKIP: case ASN1_OP_COND_MATCH_ANY: case ASN1_OP_COND_MATCH_ANY_OR_SKIP: skip_data: if (!(flags & FLAG_CONS)) { if (flags & FLAG_INDEFINITE_LENGTH) { Loading Loading @@ -422,8 +432,15 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, pc += asn1_op_lengths[op]; goto next_op; case ASN1_OP_MAYBE_ACT: if (!(flags & FLAG_LAST_MATCHED)) { pc += asn1_op_lengths[op]; goto next_op; } case ASN1_OP_ACT: ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); if (ret < 0) return ret; pc += asn1_op_lengths[op]; goto next_op; Loading @@ -431,6 +448,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, if (unlikely(jsp <= 0)) goto jump_stack_underflow; pc = jump_stack[--jsp]; flags |= FLAG_MATCHED | FLAG_LAST_MATCHED; goto next_op; default: Loading @@ -438,7 +456,8 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, } /* Shouldn't reach here */ pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n", op, pc); return -EBADMSG; data_overrun_error: Loading scripts/asn1_compiler.c +14 −9 Original line number Diff line number Diff line Loading @@ -666,7 +666,7 @@ struct element { unsigned flags; #define ELEMENT_IMPLICIT 0x0001 #define ELEMENT_EXPLICIT 0x0002 #define ELEMENT_MARKED 0x0004 #define ELEMENT_TAG_SPECIFIED 0x0004 #define ELEMENT_RENDERED 0x0008 #define ELEMENT_SKIPPABLE 0x0010 #define ELEMENT_CONDITIONAL 0x0020 Loading Loading @@ -879,6 +879,7 @@ static struct element *parse_type(struct token **_cursor, struct token *end, element->tag &= ~0x1f; element->tag |= strtoul(cursor->value, &p, 10); element->flags |= ELEMENT_TAG_SPECIFIED; if (p - cursor->value != cursor->size) abort(); cursor++; Loading Loading @@ -1376,7 +1377,7 @@ static void render_out_of_line_list(FILE *out) */ static void render_element(FILE *out, struct element *e, struct element *tag) { struct element *ec; struct element *ec, *x; const char *cond, *act; int entry, skippable = 0, outofline = 0; Loading @@ -1400,7 +1401,8 @@ static void render_element(FILE *out, struct element *e, struct element *tag) act = e->action ? "_ACT" : ""; switch (e->compound) { case ANY: render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,", cond, act, skippable ? "_OR_SKIP" : ""); if (e->name) render_more(out, "\t\t// %*.*s", (int)e->name->size, (int)e->name->size, Loading Loading @@ -1435,15 +1437,17 @@ static void render_element(FILE *out, struct element *e, struct element *tag) break; } if (e->name) x = tag ?: e; if (x->name) render_more(out, "\t\t// %*.*s", (int)e->name->size, (int)e->name->size, e->name->value); (int)x->name->size, (int)x->name->size, x->name->value); render_more(out, "\n"); /* Render the tag */ if (!tag) if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED)) tag = e; if (tag->class == ASN1_UNIV && tag->tag != 14 && tag->tag != 15 && Loading @@ -1465,7 +1469,8 @@ static void render_element(FILE *out, struct element *e, struct element *tag) case TYPE_REF: render_element(out, e->type->type->element, tag); if (e->action) render_opcode(out, "ASN1_OP_ACT,\n"); render_opcode(out, "ASN1_OP_%sACT,\n", skippable ? "MAYBE_" : ""); break; case SEQUENCE: Loading Loading @@ -1539,7 +1544,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag) case CHOICE: for (ec = e->children; ec; ec = ec->next) render_element(out, ec, NULL); render_element(out, ec, ec); if (!skippable) render_opcode(out, "ASN1_OP_COND_FAIL,\n"); if (e->action) Loading Loading
include/linux/asn1_ber_bytecode.h +11 −5 Original line number Diff line number Diff line Loading @@ -45,23 +45,27 @@ enum asn1_opcode { ASN1_OP_MATCH_JUMP = 0x04, ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, ASN1_OP_MATCH_ANY = 0x08, ASN1_OP_MATCH_ANY_OR_SKIP = 0x09, ASN1_OP_MATCH_ANY_ACT = 0x0a, ASN1_OP_MATCH_ANY_ACT_OR_SKIP = 0x0b, /* Everything before here matches unconditionally */ ASN1_OP_COND_MATCH_OR_SKIP = 0x11, ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, ASN1_OP_COND_MATCH_ANY = 0x18, ASN1_OP_COND_MATCH_ANY_OR_SKIP = 0x19, ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP = 0x1b, /* Everything before here will want a tag from the data */ #define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT #define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP /* These are here to help fill up space */ ASN1_OP_COND_FAIL = 0x1b, ASN1_OP_COMPLETE = 0x1c, ASN1_OP_ACT = 0x1d, ASN1_OP_RETURN = 0x1e, ASN1_OP_COND_FAIL = 0x1c, ASN1_OP_COMPLETE = 0x1d, ASN1_OP_ACT = 0x1e, ASN1_OP_MAYBE_ACT = 0x1f, /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ ASN1_OP_END_SEQ = 0x20, Loading @@ -76,6 +80,8 @@ enum asn1_opcode { #define ASN1_OP_END__OF 0x02 #define ASN1_OP_END__ACT 0x04 ASN1_OP_RETURN = 0x28, ASN1_OP__NR }; Loading
lib/asn1_decoder.c +23 −4 Original line number Diff line number Diff line Loading @@ -24,15 +24,20 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, [ASN1_OP_MATCH_ANY] = 1, [ASN1_OP_MATCH_ANY_OR_SKIP] = 1, [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, [ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, [ASN1_OP_COND_MATCH_ANY] = 1, [ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1, [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, [ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, [ASN1_OP_COND_FAIL] = 1, [ASN1_OP_COMPLETE] = 1, [ASN1_OP_ACT] = 1 + 1, [ASN1_OP_MAYBE_ACT] = 1 + 1, [ASN1_OP_RETURN] = 1, [ASN1_OP_END_SEQ] = 1, [ASN1_OP_END_SEQ_OF] = 1 + 1, Loading Loading @@ -177,6 +182,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, unsigned char flags = 0; #define FLAG_INDEFINITE_LENGTH 0x01 #define FLAG_MATCHED 0x02 #define FLAG_LAST_MATCHED 0x04 /* Last tag matched */ #define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag * - ie. whether or not we are going to parse * a compound type. Loading Loading @@ -208,9 +214,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, unsigned char tmp; /* Skip conditional matches if possible */ if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) || dp == datalen) { if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) || (op & ASN1_OP_MATCH__SKIP && dp == datalen)) { flags &= ~FLAG_LAST_MATCHED; pc += asn1_op_lengths[op]; goto next_op; } Loading Loading @@ -302,7 +308,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, /* Decide how to handle the operation */ switch (op) { case ASN1_OP_MATCH_ANY_ACT: case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: case ASN1_OP_COND_MATCH_ANY_ACT: case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); if (ret < 0) return ret; Loading @@ -319,8 +327,10 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, case ASN1_OP_MATCH: case ASN1_OP_MATCH_OR_SKIP: case ASN1_OP_MATCH_ANY: case ASN1_OP_MATCH_ANY_OR_SKIP: case ASN1_OP_COND_MATCH_OR_SKIP: case ASN1_OP_COND_MATCH_ANY: case ASN1_OP_COND_MATCH_ANY_OR_SKIP: skip_data: if (!(flags & FLAG_CONS)) { if (flags & FLAG_INDEFINITE_LENGTH) { Loading Loading @@ -422,8 +432,15 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, pc += asn1_op_lengths[op]; goto next_op; case ASN1_OP_MAYBE_ACT: if (!(flags & FLAG_LAST_MATCHED)) { pc += asn1_op_lengths[op]; goto next_op; } case ASN1_OP_ACT: ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); if (ret < 0) return ret; pc += asn1_op_lengths[op]; goto next_op; Loading @@ -431,6 +448,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, if (unlikely(jsp <= 0)) goto jump_stack_underflow; pc = jump_stack[--jsp]; flags |= FLAG_MATCHED | FLAG_LAST_MATCHED; goto next_op; default: Loading @@ -438,7 +456,8 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, } /* Shouldn't reach here */ pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n", op, pc); return -EBADMSG; data_overrun_error: Loading
scripts/asn1_compiler.c +14 −9 Original line number Diff line number Diff line Loading @@ -666,7 +666,7 @@ struct element { unsigned flags; #define ELEMENT_IMPLICIT 0x0001 #define ELEMENT_EXPLICIT 0x0002 #define ELEMENT_MARKED 0x0004 #define ELEMENT_TAG_SPECIFIED 0x0004 #define ELEMENT_RENDERED 0x0008 #define ELEMENT_SKIPPABLE 0x0010 #define ELEMENT_CONDITIONAL 0x0020 Loading Loading @@ -879,6 +879,7 @@ static struct element *parse_type(struct token **_cursor, struct token *end, element->tag &= ~0x1f; element->tag |= strtoul(cursor->value, &p, 10); element->flags |= ELEMENT_TAG_SPECIFIED; if (p - cursor->value != cursor->size) abort(); cursor++; Loading Loading @@ -1376,7 +1377,7 @@ static void render_out_of_line_list(FILE *out) */ static void render_element(FILE *out, struct element *e, struct element *tag) { struct element *ec; struct element *ec, *x; const char *cond, *act; int entry, skippable = 0, outofline = 0; Loading @@ -1400,7 +1401,8 @@ static void render_element(FILE *out, struct element *e, struct element *tag) act = e->action ? "_ACT" : ""; switch (e->compound) { case ANY: render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,", cond, act, skippable ? "_OR_SKIP" : ""); if (e->name) render_more(out, "\t\t// %*.*s", (int)e->name->size, (int)e->name->size, Loading Loading @@ -1435,15 +1437,17 @@ static void render_element(FILE *out, struct element *e, struct element *tag) break; } if (e->name) x = tag ?: e; if (x->name) render_more(out, "\t\t// %*.*s", (int)e->name->size, (int)e->name->size, e->name->value); (int)x->name->size, (int)x->name->size, x->name->value); render_more(out, "\n"); /* Render the tag */ if (!tag) if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED)) tag = e; if (tag->class == ASN1_UNIV && tag->tag != 14 && tag->tag != 15 && Loading @@ -1465,7 +1469,8 @@ static void render_element(FILE *out, struct element *e, struct element *tag) case TYPE_REF: render_element(out, e->type->type->element, tag); if (e->action) render_opcode(out, "ASN1_OP_ACT,\n"); render_opcode(out, "ASN1_OP_%sACT,\n", skippable ? "MAYBE_" : ""); break; case SEQUENCE: Loading Loading @@ -1539,7 +1544,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag) case CHOICE: for (ec = e->children; ec; ec = ec->next) render_element(out, ec, NULL); render_element(out, ec, ec); if (!skippable) render_opcode(out, "ASN1_OP_COND_FAIL,\n"); if (e->action) Loading