next_tag: if (unlikely(datalen - dp < 2)) { if (datalen == dp) goto missing_eoc; goto data_overrun_error;
}
/* Extract a tag from the data */
tag = data[dp++]; if (tag == ASN1_EOC) { /* It appears to be an EOC. */ if (data[dp++] != 0) goto invalid_eoc; if (--indef_level <= 0) {
*_len = dp - *_dp;
*_dp = dp; return0;
} goto next_tag;
}
if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) { do { if (unlikely(datalen - dp < 2)) goto data_overrun_error;
tmp = data[dp++];
} while (tmp & 0x80);
}
/* Extract the length */
len = data[dp++]; if (len <= 0x7f) goto check_length;
unsignedchar 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.whetherornotwearegoingtoparse *acompoundtype.
*/
next_op:
pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n",
pc, machlen, dp, datalen, csp, jsp); if (unlikely(pc >= machlen)) goto machine_overrun_error;
op = machine[pc]; if (unlikely(pc + asn1_op_lengths[op] > machlen)) goto machine_overrun_error;
/* If this command is meant to match a tag, then do that before *evaluatingthecommand.
*/ if (op <= ASN1_OP__MATCHES_TAG) { unsignedchar tmp;
/* Skip conditional matches if possible */ 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;
}
flags = 0;
hdr = 2;
/* Extract a tag from the data */ if (unlikely(datalen - dp < 2)) goto data_overrun_error;
tag = data[dp++]; if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) goto long_tag_not_supported;
if (op & ASN1_OP_MATCH__ANY) {
pr_debug("- any %02x\n", tag);
} else { /* Extract the tag from the machine *-EitherCONSorPRIMarepermittedinthedataif *CONSisnotsetintheopstream,otherwiseCONS *ismandatory.
*/
optag = machine[pc + 1];
flags |= optag & FLAG_CONS;
/* Determine whether the tag matched */
tmp = optag ^ tag;
tmp &= ~(optag & ASN1_CONS_BIT);
pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); if (tmp != 0) { /* All odd-numbered tags are MATCH_OR_SKIP. */ if (op & ASN1_OP_MATCH__SKIP) {
pc += asn1_op_lengths[op];
dp--; goto next_op;
} goto tag_mismatch;
}
}
flags |= FLAG_MATCHED;
len = data[dp++]; if (len > 0x7f) { if (unlikely(len == ASN1_INDEFINITE_LENGTH)) { /* Indefinite length */ if (unlikely(!(tag & ASN1_CONS_BIT))) goto indefinite_len_primitive;
flags |= FLAG_INDEFINITE_LENGTH; if (unlikely(2 > datalen - dp)) goto data_overrun_error;
} else { int n = len - 0x80; if (unlikely(n > 2)) goto length_too_long; if (unlikely(n > datalen - dp)) goto data_overrun_error;
hdr += n; for (len = 0; n > 0; n--) {
len <<= 8;
len |= data[dp++];
} if (unlikely(len > datalen - dp)) goto data_overrun_error;
}
} else { if (unlikely(len > datalen - dp)) goto data_overrun_error;
}
if (flags & FLAG_CONS) { /* For expected compound forms, we stack the positions *ofthestartandendofthedata.
*/ if (unlikely(csp >= NR_CONS_STACK)) goto cons_stack_overflow;
cons_dp_stack[csp] = dp;
cons_hdrlen_stack[csp] = hdr; if (!(flags & FLAG_INDEFINITE_LENGTH)) {
cons_datalen_stack[csp] = datalen;
datalen = dp + len;
} else {
cons_datalen_stack[csp] = 0;
}
csp++;
}
/* Decide how to handle the operation */ switch (op) { case ASN1_OP_MATCH: case ASN1_OP_MATCH_OR_SKIP: case ASN1_OP_MATCH_ACT: case ASN1_OP_MATCH_ACT_OR_SKIP: case ASN1_OP_MATCH_ANY: case ASN1_OP_MATCH_ANY_OR_SKIP: case ASN1_OP_MATCH_ANY_ACT: case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: case ASN1_OP_COND_MATCH_OR_SKIP: case ASN1_OP_COND_MATCH_ACT_OR_SKIP: case ASN1_OP_COND_MATCH_ANY: case ASN1_OP_COND_MATCH_ANY_OR_SKIP: case ASN1_OP_COND_MATCH_ANY_ACT: case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
if (!(flags & FLAG_CONS)) { if (flags & FLAG_INDEFINITE_LENGTH) {
size_t tmp = dp;
ret = asn1_find_indefinite_length(
data, datalen, &tmp, &len, &errmsg); if (ret < 0) goto error;
}
pr_debug("- LEAF: %zu\n", len);
}
if (op & ASN1_OP_MATCH__ACT) { unsignedchar act;
if (op & ASN1_OP_MATCH__ANY)
act = machine[pc + 1]; else
act = machine[pc + 2];
ret = actions[act](context, hdr, tag, data + dp, len); if (ret < 0) return ret;
}
if (!(flags & FLAG_CONS))
dp += len;
pc += asn1_op_lengths[op]; goto next_op;
case ASN1_OP_MATCH_JUMP: case ASN1_OP_MATCH_JUMP_OR_SKIP: case ASN1_OP_COND_MATCH_JUMP_OR_SKIP:
pr_debug("- MATCH_JUMP\n"); if (unlikely(jsp == NR_JUMP_STACK)) goto jump_stack_overflow;
jump_stack[jsp++] = pc + asn1_op_lengths[op];
pc = machine[pc + 2]; goto next_op;
case ASN1_OP_COND_FAIL: if (unlikely(!(flags & FLAG_MATCHED))) goto tag_mismatch;
pc += asn1_op_lengths[op]; goto next_op;
case ASN1_OP_COMPLETE: if (unlikely(jsp != 0 || csp != 0)) {
pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n",
jsp, csp); return -EBADMSG;
} return0;
case ASN1_OP_END_SET: case ASN1_OP_END_SET_ACT: if (unlikely(!(flags & FLAG_MATCHED))) goto tag_mismatch;
fallthrough;
case ASN1_OP_END_SEQ: case ASN1_OP_END_SET_OF: case ASN1_OP_END_SEQ_OF: case ASN1_OP_END_SEQ_ACT: case ASN1_OP_END_SET_OF_ACT: case ASN1_OP_END_SEQ_OF_ACT: if (unlikely(csp <= 0)) goto cons_stack_underflow;
csp--;
tdp = cons_dp_stack[csp];
hdr = cons_hdrlen_stack[csp];
len = datalen;
datalen = cons_datalen_stack[csp];
pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n",
tdp, dp, len, datalen); if (datalen == 0) { /* Indefinite length - check for the EOC. */
datalen = len; if (unlikely(datalen - dp < 2)) goto data_overrun_error; if (data[dp++] != 0) { if (op & ASN1_OP_END__OF) {
dp--;
csp++;
pc = machine[pc + 1];
pr_debug("- continue\n"); goto next_op;
} goto missing_eoc;
} if (data[dp++] != 0) goto invalid_eoc;
len = dp - tdp - 2;
} else { if (dp < len && (op & ASN1_OP_END__OF)) {
datalen = len;
csp++;
pc = machine[pc + 1];
pr_debug("- continue\n"); goto next_op;
} if (dp != len) goto cons_length_error;
len -= tdp;
pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp);
}
if (op & ASN1_OP_END__ACT) { unsignedchar act; if (op & ASN1_OP_END__OF)
act = machine[pc + 2]; else
act = machine[pc + 1];
ret = actions[act](context, hdr, 0, data + tdp, len); if (ret < 0) return ret;
}
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;
}
fallthrough;
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;
case ASN1_OP_RETURN: if (unlikely(jsp <= 0)) goto jump_stack_underflow;
pc = jump_stack[--jsp];
flags |= FLAG_MATCHED | FLAG_LAST_MATCHED; goto next_op;
default: break;
}
/* Shouldn't reach here */
pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n",
op, pc); return -EBADMSG;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.