^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Decoder for ASN.1 BER/DER/CER encoded bytestream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Written by David Howells (dhowells@redhat.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/asn1_decoder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/asn1_ber_bytecode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static const unsigned char asn1_op_lengths[ASN1_OP__NR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* OPC TAG JMP ACT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) [ASN1_OP_MATCH] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) [ASN1_OP_MATCH_OR_SKIP] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) [ASN1_OP_MATCH_ACT] = 1 + 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) [ASN1_OP_MATCH_ANY] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) [ASN1_OP_MATCH_ANY_OR_SKIP] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) [ASN1_OP_MATCH_ANY_ACT] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) [ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) [ASN1_OP_COND_MATCH_ANY] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) [ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) [ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) [ASN1_OP_COND_FAIL] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) [ASN1_OP_COMPLETE] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) [ASN1_OP_ACT] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) [ASN1_OP_MAYBE_ACT] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) [ASN1_OP_RETURN] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) [ASN1_OP_END_SEQ] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) [ASN1_OP_END_SEQ_OF] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) [ASN1_OP_END_SET] = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) [ASN1_OP_END_SET_OF] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) [ASN1_OP_END_SEQ_ACT] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) [ASN1_OP_END_SET_ACT] = 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * Find the length of an indefinite length object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * @data: The data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * @datalen: The end of the innermost containing element in the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * @_dp: The data parse cursor (updated before returning)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * @_len: Where to return the size of the element.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * @_errmsg: Where to return a pointer to an error message on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) size_t *_dp, size_t *_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const char **_errmsg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned char tag, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) size_t dp = *_dp, len, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int indef_level = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) next_tag:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (unlikely(datalen - dp < 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (datalen == dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) goto missing_eoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* Extract a tag from the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) tag = data[dp++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (tag == ASN1_EOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* It appears to be an EOC. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (data[dp++] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) goto invalid_eoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (--indef_level <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) *_len = dp - *_dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) *_dp = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) goto next_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (unlikely(datalen - dp < 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) tmp = data[dp++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) } while (tmp & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Extract the length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) len = data[dp++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (len <= 0x7f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) goto check_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* Indefinite length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) goto indefinite_len_primitive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) indef_level++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) goto next_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) n = len - 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (unlikely(n > sizeof(len) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) goto length_too_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (unlikely(n > datalen - dp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) for (; n > 0; n--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) len <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) len |= data[dp++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) check_length:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (len > datalen - dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) dp += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) goto next_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) length_too_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *_errmsg = "Unsupported length";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) indefinite_len_primitive:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *_errmsg = "Indefinite len primitive not permitted";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) invalid_eoc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *_errmsg = "Invalid length EOC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) data_overrun_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *_errmsg = "Data overrun error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) missing_eoc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) *_errmsg = "Missing EOC in indefinite len cons";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *_dp = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @decoder: The decoder definition (produced by asn1_compiler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @context: The caller's context (to be passed to the action functions)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * @data: The encoded data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * @datalen: The size of the encoded data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * produced by asn1_compiler. Action functions are called on marked tags to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * allow the caller to retrieve significant data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * LIMITATIONS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * To keep down the amount of stack used by this function, the following limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * have been imposed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * (1) This won't handle datalen > 65535 without increasing the size of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * cons stack elements and length_too_long checking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * (2) The stack of constructed types is 10 deep. If the depth of non-leaf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * constructed types exceeds this, the decode will fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * (3) The SET type (not the SET OF type) isn't really supported as tracking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * what members of the set have been seen is a pain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int asn1_ber_decoder(const struct asn1_decoder *decoder,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) void *context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) const unsigned char *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) size_t datalen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) const unsigned char *machine = decoder->machine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) const asn1_action_t *actions = decoder->actions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) size_t machlen = decoder->machlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) enum asn1_opcode op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) const char *errmsg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) size_t pc = 0, dp = 0, tdp = 0, len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned char flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define FLAG_INDEFINITE_LENGTH 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define FLAG_MATCHED 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define FLAG_LAST_MATCHED 0x04 /* Last tag matched */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * - ie. whether or not we are going to parse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * a compound type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #define NR_CONS_STACK 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned short cons_dp_stack[NR_CONS_STACK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned short cons_datalen_stack[NR_CONS_STACK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) unsigned char cons_hdrlen_stack[NR_CONS_STACK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #define NR_JUMP_STACK 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) unsigned char jump_stack[NR_JUMP_STACK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (datalen > 65535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) next_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) pc, machlen, dp, datalen, csp, jsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (unlikely(pc >= machlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) goto machine_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) op = machine[pc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (unlikely(pc + asn1_op_lengths[op] > machlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) goto machine_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* If this command is meant to match a tag, then do that before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * evaluating the command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (op <= ASN1_OP__MATCHES_TAG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) unsigned char tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* Skip conditional matches if possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) (op & ASN1_OP_MATCH__SKIP && dp == datalen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) flags &= ~FLAG_LAST_MATCHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) pc += asn1_op_lengths[op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) hdr = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* Extract a tag from the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (unlikely(datalen - dp < 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) tag = data[dp++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (unlikely((tag & 0x1f) == ASN1_LONG_TAG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) goto long_tag_not_supported;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (op & ASN1_OP_MATCH__ANY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) pr_debug("- any %02x\n", tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /* Extract the tag from the machine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * - Either CONS or PRIM are permitted in the data if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * CONS is not set in the op stream, otherwise CONS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * is mandatory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) optag = machine[pc + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) flags |= optag & FLAG_CONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* Determine whether the tag matched */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) tmp = optag ^ tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) tmp &= ~(optag & ASN1_CONS_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (tmp != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* All odd-numbered tags are MATCH_OR_SKIP. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (op & ASN1_OP_MATCH__SKIP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) pc += asn1_op_lengths[op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) dp--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) goto tag_mismatch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) flags |= FLAG_MATCHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) len = data[dp++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (len > 0x7f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* Indefinite length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (unlikely(!(tag & ASN1_CONS_BIT)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) goto indefinite_len_primitive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) flags |= FLAG_INDEFINITE_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (unlikely(2 > datalen - dp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int n = len - 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (unlikely(n > 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) goto length_too_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (unlikely(n > datalen - dp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) hdr += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) for (len = 0; n > 0; n--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) len <<= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) len |= data[dp++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (unlikely(len > datalen - dp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (unlikely(len > datalen - dp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (flags & FLAG_CONS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* For expected compound forms, we stack the positions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * of the start and end of the data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (unlikely(csp >= NR_CONS_STACK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) goto cons_stack_overflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) cons_dp_stack[csp] = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) cons_hdrlen_stack[csp] = hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!(flags & FLAG_INDEFINITE_LENGTH)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) cons_datalen_stack[csp] = datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) datalen = dp + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) cons_datalen_stack[csp] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) csp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) pr_debug("- TAG: %02x %zu%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) tag, len, flags & FLAG_CONS ? " CONS" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) tdp = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* Decide how to handle the operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) switch (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case ASN1_OP_MATCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) case ASN1_OP_MATCH_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) case ASN1_OP_MATCH_ACT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) case ASN1_OP_MATCH_ACT_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) case ASN1_OP_MATCH_ANY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) case ASN1_OP_MATCH_ANY_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case ASN1_OP_MATCH_ANY_ACT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) case ASN1_OP_COND_MATCH_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case ASN1_OP_COND_MATCH_ACT_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) case ASN1_OP_COND_MATCH_ANY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) case ASN1_OP_COND_MATCH_ANY_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) case ASN1_OP_COND_MATCH_ANY_ACT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (!(flags & FLAG_CONS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (flags & FLAG_INDEFINITE_LENGTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) size_t tmp = dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ret = asn1_find_indefinite_length(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) data, datalen, &tmp, &len, &errmsg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) pr_debug("- LEAF: %zu\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (op & ASN1_OP_MATCH__ACT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) unsigned char act;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (op & ASN1_OP_MATCH__ANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) act = machine[pc + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) act = machine[pc + 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ret = actions[act](context, hdr, tag, data + dp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!(flags & FLAG_CONS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) dp += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) pc += asn1_op_lengths[op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) case ASN1_OP_MATCH_JUMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) case ASN1_OP_MATCH_JUMP_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) case ASN1_OP_COND_MATCH_JUMP_OR_SKIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) pr_debug("- MATCH_JUMP\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (unlikely(jsp == NR_JUMP_STACK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) goto jump_stack_overflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) jump_stack[jsp++] = pc + asn1_op_lengths[op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pc = machine[pc + 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) case ASN1_OP_COND_FAIL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (unlikely(!(flags & FLAG_MATCHED)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) goto tag_mismatch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) pc += asn1_op_lengths[op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case ASN1_OP_COMPLETE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (unlikely(jsp != 0 || csp != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) jsp, csp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -EBADMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) case ASN1_OP_END_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) case ASN1_OP_END_SET_ACT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (unlikely(!(flags & FLAG_MATCHED)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto tag_mismatch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) case ASN1_OP_END_SEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) case ASN1_OP_END_SET_OF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case ASN1_OP_END_SEQ_OF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) case ASN1_OP_END_SEQ_ACT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) case ASN1_OP_END_SET_OF_ACT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) case ASN1_OP_END_SEQ_OF_ACT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (unlikely(csp <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) goto cons_stack_underflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) csp--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) tdp = cons_dp_stack[csp];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) hdr = cons_hdrlen_stack[csp];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) len = datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) datalen = cons_datalen_stack[csp];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) tdp, dp, len, datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (datalen == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* Indefinite length - check for the EOC. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) datalen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (unlikely(datalen - dp < 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) goto data_overrun_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (data[dp++] != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (op & ASN1_OP_END__OF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) dp--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) csp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) pc = machine[pc + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) pr_debug("- continue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) goto missing_eoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (data[dp++] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) goto invalid_eoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) len = dp - tdp - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (dp < len && (op & ASN1_OP_END__OF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) datalen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) csp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) pc = machine[pc + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) pr_debug("- continue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (dp != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) goto cons_length_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) len -= tdp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (op & ASN1_OP_END__ACT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) unsigned char act;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (op & ASN1_OP_END__OF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) act = machine[pc + 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) act = machine[pc + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) ret = actions[act](context, hdr, 0, data + tdp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) pc += asn1_op_lengths[op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) case ASN1_OP_MAYBE_ACT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (!(flags & FLAG_LAST_MATCHED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) pc += asn1_op_lengths[op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) case ASN1_OP_ACT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) pc += asn1_op_lengths[op];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) case ASN1_OP_RETURN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (unlikely(jsp <= 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) goto jump_stack_underflow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) pc = jump_stack[--jsp];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) flags |= FLAG_MATCHED | FLAG_LAST_MATCHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) goto next_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* Shouldn't reach here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) op, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return -EBADMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) data_overrun_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) errmsg = "Data overrun error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) machine_overrun_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) errmsg = "Machine overrun error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) jump_stack_underflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) errmsg = "Jump stack underflow";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) jump_stack_overflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) errmsg = "Jump stack overflow";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) cons_stack_underflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) errmsg = "Cons stack underflow";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) cons_stack_overflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) errmsg = "Cons stack overflow";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) cons_length_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) errmsg = "Cons length error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) missing_eoc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) errmsg = "Missing EOC in indefinite len cons";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) invalid_eoc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) errmsg = "Invalid length EOC";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) length_too_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) errmsg = "Unsupported length";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) indefinite_len_primitive:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) errmsg = "Indefinite len primitive not permitted";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) tag_mismatch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) errmsg = "Unexpected tag";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) long_tag_not_supported:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) errmsg = "Long tag not supported";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) errmsg, pc, dp, optag, tag, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return -EBADMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) EXPORT_SYMBOL_GPL(asn1_ber_decoder);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) MODULE_LICENSE("GPL");