From: Emmanuel Thompson Date: Mon, 27 Apr 2020 17:18:37 +0000 (-0400) Subject: detect/asn1: Remove asn1 C parser X-Git-Tag: suricata-6.0.0-beta1~236 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=275f6ae96f47860e870fddd90c5e787e1b600868;p=thirdparty%2Fsuricata.git detect/asn1: Remove asn1 C parser - In favor of rust parser --- diff --git a/src/Makefile.am b/src/Makefile.am index 2b1bf986c2..8d08296451 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -446,7 +446,6 @@ util-crypt.c util-crypt.h \ util-daemon.c util-daemon.h \ util-debug.c util-debug.h \ util-debug-filters.c util-debug-filters.h \ -util-decode-asn1.c util-decode-asn1.h \ util-decode-mime.c util-decode-mime.h \ util-detect.c util-detect.h \ util-device.c util-device.h \ diff --git a/src/runmode-unittests.c b/src/runmode-unittests.c index 1cf6ba4d6c..60d5cf59cf 100644 --- a/src/runmode-unittests.c +++ b/src/runmode-unittests.c @@ -97,8 +97,6 @@ #include "util-mpm-ac.h" #include "util-mpm-hs.h" -#include "util-decode-asn1.h" - #include "conf.h" #include "conf-yaml-loader.h" #include "tmqh-flow.h" @@ -159,7 +157,6 @@ static void RegisterUnittests(void) DecodeTCPRegisterTests(); DecodeUDPV4RegisterTests(); DecodeGRERegisterTests(); - DecodeAsn1RegisterTests(); DecodeMPLSRegisterTests(); AppLayerProtoDetectUnittestsRegister(); ConfRegisterTests(); diff --git a/src/suricata.c b/src/suricata.c index b58e3dab67..09c3ba3f90 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -154,7 +154,6 @@ #include "runmodes.h" #include "runmode-unittests.h" -#include "util-decode-asn1.h" #include "util-debug.h" #include "util-error.h" #include "util-daemon.h" @@ -2587,7 +2586,6 @@ int PostConfLoadedSetup(SCInstance *suri) } HostInitConfig(HOST_VERBOSE); - SCAsn1LoadConfig(); CoredumpLoadConfig(); diff --git a/src/tests/fuzz/fuzz_sigpcap.c b/src/tests/fuzz/fuzz_sigpcap.c index 4c752fcbda..5204af46a7 100644 --- a/src/tests/fuzz/fuzz_sigpcap.c +++ b/src/tests/fuzz/fuzz_sigpcap.c @@ -18,7 +18,6 @@ #include "host-bit.h" #include "ippair-bit.h" #include "app-layer-htp.h" -#include "util-decode-asn1.h" #include "detect-fast-pattern.h" #include "util-unittest-helper.h" #include "conf-yaml-loader.h" diff --git a/src/util-decode-asn1.c b/src/util-decode-asn1.c deleted file mode 100644 index b45ebd8f5a..0000000000 --- a/src/util-decode-asn1.c +++ /dev/null @@ -1,906 +0,0 @@ -/* Copyright (C) 2007-2013 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Pablo Rincon Crespo - * - * Implements ASN1 decoding (needed for the asn1 keyword, BER, CER & DER) - */ - -#include "suricata.h" -#include "suricata-common.h" -#include "decode.h" -#include "util-debug.h" -#include "util-unittest.h" -#include "util-print.h" - -#include "util-decode-asn1.h" -#include "conf.h" - -uint16_t asn1_max_frames_config = ASN1_MAX_FRAMES; - -void SCAsn1LoadConfig() -{ - intmax_t value = 0; - - /** set config defaults */ - if ((ConfGetInt("asn1-max-frames", &value)) == 1) { - asn1_max_frames_config = (uint16_t)value; - SCLogDebug("Max stack frame set to %"PRIu16, asn1_max_frames_config); - } - -} - -/** - * \brief Decode and check the identifier information of the - * current node that is in extended format - * - * \param ac pointer to the ASN1 Context data - * - * \retval byte of the status of the parser - */ -static uint8_t SCAsn1GetHighTagNumber(Asn1Ctx *ac) -{ - uint8_t ret = 0; - uint32_t tag_num = 0; - - /* If we have a high tag num, skip the id octet */ - ac->iter++; - - Asn1Node *node = ASN1CTX_CUR_NODE(ac); - - ret = SCAsn1CheckBounds(ac); - if (ret == ASN1_PARSER_ERR) { - ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; - return ret; - } - - uint8_t raw_id = *ac->iter; - - tag_num += ASN1_BER_GET_HIGH_TAG_NUM(raw_id); - - if (ASN1_BER_GET_HIGH_TAG_NUM(raw_id) == 0) { - /* Set event, invalid id */ - node->flags |= ASN1_BER_EVENT_INVALID_ID; - ac->parser_status |= ASN1_STATUS_INVALID; - return ASN1_PARSER_ERR; - } - - ac->iter++; - if (!ASN1_BER_IS_HIGH_TAG_END(raw_id)) { - do { - ret = SCAsn1CheckBounds(ac); - if (ret == ASN1_PARSER_ERR) { - ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; - return ret; - } - - raw_id = *ac->iter; - - if ((uint64_t) ((uint64_t)tag_num + - (uint64_t)ASN1_BER_GET_HIGH_TAG_NUM(raw_id)) > UINT32_MAX) - { - node->flags |= ASN1_BER_EVENT_ID_TOO_LONG; - ac->parser_status |= ASN1_STATUS_INVALID; - return ASN1_PARSER_ERR; - } - - tag_num += ASN1_BER_GET_HIGH_TAG_NUM(raw_id); - ac->iter++; - } while (!ASN1_BER_IS_HIGH_TAG_END(raw_id)); - } - node->id.tag_num = tag_num; - - return ASN1_PARSER_OK; -} - -/** - * \brief Decode and check the length, of the current node - * in definite but extended format, that we are parsing, - * checking invalid opts - * - * \param ac pointer to the ASN1 Context data - * - * \retval byte of the status of the parser - */ -static uint32_t SCAsn1GetLengthLongForm(Asn1Ctx *ac) -{ - uint8_t raw_len = *ac->iter; - uint8_t ret = 0; - uint32_t content_len = 0; - uint8_t oct_len = ASN1_BER_GET_LONG_LEN_OCTETS(raw_len); - uint8_t i = 0; - - Asn1Node *node = ASN1CTX_CUR_NODE(ac); - - for (; i < oct_len; i++) { - ac->iter++; - - ret = SCAsn1CheckBounds(ac); - if (ret == ASN1_PARSER_ERR) { - ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; - return ASN1_PARSER_ERR; - } - - raw_len = *ac->iter; - if (raw_len == 0xFF && ac->iter == node->len.ptr + 1) { - /* 8.1.3.5, 0xFF shall not be used */ - node->flags |= ASN1_BER_EVENT_INVALID_LEN; - ac->parser_status = ASN1_STATUS_INVALID; - return ASN1_PARSER_ERR; - } - - if ((uint64_t) ((uint64_t)content_len + - (uint64_t) ASN1_BER_GET_HIGH_TAG_NUM(raw_len)) > UINT32_MAX) - { - node->flags |= ASN1_BER_EVENT_LEN_TOO_LONG; - ac->parser_status = ASN1_STATUS_INVALID; - return ASN1_PARSER_ERR; - } - - content_len += raw_len; - } - - ac->iter++; - - node->len.len = content_len; - return ASN1_PARSER_OK; -} - - -/** - * \brief Check the content length and perform other inspections - * and decodings if necessary - * - * \param ac pointer to the ASN1 Context data - * - * \retval byte of the status of the parser - */ -uint8_t SCAsn1DecodeContent(Asn1Ctx *ac) -{ - - Asn1Node *node = ASN1CTX_CUR_NODE(ac); - - /* Uops, if we are done, we break here */ - if (node->flags & ASN1_NODE_IS_EOC) - return ASN1_PARSER_OK; - - /* First check the form of length (BER, DER, CER) - * and if we are on a zero length */ - if (node->len.form != ASN1_BER_LEN_INDEFINITE && - node->len.len == 0) - { - node->data.len = 0; - return ASN1_PARSER_OK; - } - - node->data.ptr = ac->iter; - /* If we have a complete length, check that - * it is in bounds */ - if (ac->iter + node->len.len > ac->end) { - /* We do not have all the content octets! */ - node->data.len = ac->end - ac->iter; - } else { - /* We have all the content octets */ - node->data.len = node->len.len; - } - - return ASN1_PARSER_OK; -} - -/** - * \brief Decode and check the length, of the current node - * that we are parsing, also check invalid opts - * - * \param ac pointer to the ASN1 Context data - * - * \retval byte of the status of the parser - */ -uint8_t SCAsn1DecodeLength(Asn1Ctx *ac) -{ - uint8_t ret = 0; - ret = SCAsn1CheckBounds(ac); - if (ret == ASN1_PARSER_ERR) { - ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; - return ASN1_PARSER_ERR; - } - - Asn1Node *node = ASN1CTX_CUR_NODE(ac); - /* Store the position */ - node->len.ptr = ac->iter; - - uint8_t len_byte = *ac->iter; - - //SCPrintByteBin(len_byte); - - if (*node->id.ptr == 0 && len_byte == 0) { - node->flags |= ASN1_NODE_IS_EOC; - ac->iter++; - return ASN1_PARSER_OK; - } - - if (ASN1_BER_IS_INDEFINITE_LEN(len_byte)) { - node->len.form = ASN1_BER_LEN_INDEFINITE; - node->len.len = 0; - ac->iter++; - - const uint8_t *tmp_iter = ac->iter; - - /* Check that e-o-c is in bounds */ - for (; tmp_iter < ac->end - 1; tmp_iter++) { - if (ASN1_BER_IS_EOC(tmp_iter)) { - node->data.len = tmp_iter - ac->iter; - node->len.len = tmp_iter - ac->iter; - return ASN1_PARSER_OK; - } - } - - /* EOC Not found */ - ac->parser_status |= ASN1_STATUS_INVALID; - node->flags |= ASN1_BER_EVENT_EOC_NOT_FOUND; - - return ASN1_PARSER_ERR; - - } else { - /* Look which form we get (and if it apply to the id type) */ - if (ASN1_BER_IS_SHORT_LEN(len_byte)) { - node->len.form = ASN1_BER_LEN_SHORT; - node->len.len = ASN1_BER_GET_SHORT_LEN(len_byte); - ac->iter++; - } else { - node->len.form = ASN1_BER_LEN_LONG; - - /* Ok, let's parse the long form */ - return SCAsn1GetLengthLongForm(ac); - } - - } - return ASN1_PARSER_OK; -} - -/** - * \brief Decode and check the identifier information of the - * current node that we are parsing, also check invalid opts - * - * \param ac pointer to the ASN1 Context data - * - * \retval byte of the status of the parser - */ -uint8_t SCAsn1DecodeIdentifier(Asn1Ctx *ac) -{ - uint8_t ret = 0; - ret = SCAsn1CheckBounds(ac); - if (ret == ASN1_PARSER_ERR) { - ac->parser_status |= ASN1_STATUS_INVALID | ASN1_STATUS_OOB; - return ret; - } - - Asn1Node *node = ASN1CTX_CUR_NODE(ac); - /* Store the position */ - node->id.ptr = ac->iter; - - //SCPrintByteBin(*ac->iter); - - node->id.class_tag = ASN1_BER_GET_CLASS_TAG(*ac->iter); - node->id.tag_type = ASN1_BER_IS_CONSTRUCTED(*ac->iter); - - if (ASN1_BER_IS_HIGH_TAG(*ac->iter)) { - return SCAsn1GetHighTagNumber(ac); - } else { - node->id.tag_num = ASN1_BER_GET_LOW_TAG_NUM(*ac->iter); - ac->iter++; - } - - return ASN1_PARSER_OK; -} - -/** - * \brief Helper function that print the bits of a byte - * to check encoding internals - * \param byte value of the byte - */ -void SCPrintByteBin(uint8_t byte) -{ - uint8_t i = 0; - for (i = 8; i > 0; i--) { - printf("%"PRIu8, (uint8_t)((byte >> (i - 1)) & 0x01)); - if (i == 5) - printf(" "); - } - printf("\n"); -} - -/** - * \brief check if we have remaining data available, - * otherwise the parser should stop - * \param ac Asn1Ctx pointer initialized - * \retval 1 if we are out of bounds, 0 if not - */ -uint8_t SCAsn1CheckBounds(Asn1Ctx *ac) -{ - return (ac->iter < ac->end && ac->iter >= ac->data)? ASN1_PARSER_OK : ASN1_PARSER_ERR; -} - - -/** - * \brief Create a new ASN1 Parsing context - * - * \retval Asn1Ctx pointer to the new ctx - */ -Asn1Ctx *SCAsn1CtxNew(void) -{ - Asn1Ctx *ac = SCMalloc(sizeof(Asn1Ctx)); - - if (unlikely(ac == NULL)) { - SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); - return NULL; - } - memset(ac, 0, sizeof(Asn1Ctx)); - - ac->asn1_stack = SCMalloc(sizeof(Asn1Node *) * asn1_max_frames_config); - if (ac->asn1_stack == NULL) { - SCFree(ac); - return NULL; - } - memset(ac->asn1_stack, 0, sizeof(Asn1Node *) * asn1_max_frames_config); - - return ac; -} - -/** - * \brief Destroy an ASN1 Parsing context - * - * \param Asn1Ctx pointer to the new ctx - */ -void SCAsn1CtxDestroy(Asn1Ctx *ac) -{ - if (ac == NULL) - return; - - for (uint16_t i = 0; i < asn1_max_frames_config; i++) { - Asn1Node *node = ASN1CTX_GET_NODE(ac, i); - if (node == NULL) { - break; - } - SCFree(node); - } - - SCFree(ac->asn1_stack); - SCFree(ac); -} - -/** - * \brief Create a new node at the array stack of frames in the ctx - * - * \param ac pointer to the ASN1 ctx - * \param node index of the frame that we are going to allocate - * at the asn1 stack in the parser - * - * \retval Asn1Node pointer to the new node allocated - */ -static Asn1Node *SCAsn1CtxNewFrame(Asn1Ctx *ac, uint16_t node) -{ - if (node >= asn1_max_frames_config) { - return NULL; - } - - if (ac->asn1_stack[node] == NULL) - ac->asn1_stack[node] = SCMalloc(sizeof(Asn1Node)); - - if (ac->asn1_stack[node] == NULL) - return NULL; - - memset(ac->asn1_stack[node], 0, sizeof(Asn1Node)); - return ac->asn1_stack[node]; -} - -/** - * \brief Initialize the data of the ASN1 parser ctx with the asn1 raw buffer - * - * \param ac pointer to the ASN1 ctx - * \param data pointer to the data to process (binary raw of asn1) - * \param length length of the asn1 raw buffer - * - * \retval void - */ -void SCAsn1CtxInit(Asn1Ctx *ac, const uint8_t *data, uint16_t length) -{ - ac->data = data; - ac->iter = data; - ac->len = length; - ac->end = data + length; - ac->parser_status = ASN1_STATUS_OK; -} - -/** - * \brief Decode the nodes/frames located at certain position/level - * - * \param ac pointer to the ASN1 ctx - * \param node_id node index at the asn1 stack of the ctx - * - * \retval byte of parser status - */ -uint8_t SCAsn1Decode(Asn1Ctx *ac, uint16_t node_id) -{ - Asn1Node *node = NULL; - uint8_t ret = 0; - - /* while remaining data, and no fatal error, or end, or max stack frames */ - while (ac->iter < ac->end - && !(ac->parser_status & ASN1_STATUS_DONE) - && ac->cur_frame < asn1_max_frames_config) - { - /* Prepare a new frame */ - if (SCAsn1CtxNewFrame(ac, node_id) == NULL) - break; - - ac->cur_frame = node_id; - node = ASN1CTX_GET_NODE(ac, node_id); - - SCLogDebug("ASN1 Getting ID, cur:%x remaining %"PRIu32, (uint8_t)*ac->iter, (uint32_t)(ac->end - ac->iter)); - - /* Get identifier/tag */ - ret = SCAsn1DecodeIdentifier(ac); - if (ret == ASN1_PARSER_ERR) { - SCLogDebug("Error parsing identifier"); - - node->flags |= ASN1_BER_EVENT_INVALID_ID; - ac->ctx_flags |= node->flags; - - break; - } - - SCLogDebug("ASN1 Getting LEN"); - - /* Get length of content */ - ret = SCAsn1DecodeLength(ac); - if (ret == ASN1_PARSER_ERR) { - SCLogDebug("Error parsing length"); - - node->flags |= ASN1_BER_EVENT_INVALID_LEN; - ac->ctx_flags |= node->flags; - - break; - } - - if ( !(node->flags & ASN1_NODE_IS_EOC)) { - SCLogDebug("ASN1 Getting CONTENT"); - - /* Inspect content */ - ret = SCAsn1DecodeContent(ac); - if (ret == ASN1_PARSER_ERR) { - SCLogDebug("Error parsing content"); - - break; - } - - /* Skip to the next record (if any) */ - if (node->id.tag_type != ASN1_TAG_TYPE_CONSTRUCTED) - /* Is primitive, skip it all (no need to decode it)*/ - ac->iter += node->data.len; - } - - /* Check if we are done with data */ - ret = SCAsn1CheckBounds(ac); - if (ret == ASN1_PARSER_ERR) { - - ac->parser_status |= ASN1_STATUS_DONE; - /* There's no more data available */ - ret = ASN1_PARSER_OK; - - break; - } -#if 0 - printf("Tag Num: %"PRIu32", Tag Type: %"PRIu8", Class:%"PRIu8", Length: %"PRIu32"\n", node->id.tag_num, node->id.tag_type, node->id.class_tag, node->len.len); - printf("Data: \n"); - PrintRawDataFp(stdout, node->data.ptr, node->len.len); - printf(" -- EOD --\n"); -#endif - - /* Stack flags/events here, so we have the resume at the ctx flags */ - ac->ctx_flags |= node->flags; - - /* Check if it's not a primitive type, - * then we need to decode contents */ - if (node->id.tag_type == ASN1_TAG_TYPE_CONSTRUCTED) { - ret = SCAsn1Decode(ac, node_id + 1); - } /* Else we have reached a primitive type and stop the recursion, - * look if we have other branches at the same level */ - - /* But first check if it's a constructed node, and the sum of child - * lengths was more than the length of this frame - * this would mean that we have an overflow at the attributes */ - if (ac->iter > node->data.ptr + node->data.len + 1) { - /* We decoded more length on this frame */ - } - - node_id = ac->cur_frame + 1; - } - - return ret; -} - -/* ----------------------- Unit tests ------------------------ */ -#ifdef UNITTESTS - -/** - * \test Check we handle extended identifiers correctly - */ -static int DecodeAsn1Test01(void) -{ - uint8_t *str = (uint8_t *) "\x3F\x84\x06"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = 3; - - SCAsn1CtxInit(ac, str, len); - - SCAsn1Decode(ac, ac->cur_frame); - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if (node->id.tag_num != 10) { - ret = 0; - printf("Error, expected tag_num 10, got %"PRIu32" :", node->id.tag_num); - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -/** - * \test Check we handle extended identifiers correctly - */ -static int DecodeAsn1Test02(void) -{ - uint8_t *str = (uint8_t *) "\x3F\x81\x81\x81\x81\x06"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = 6; - - SCAsn1CtxInit(ac, str, len); - - SCAsn1Decode(ac, ac->cur_frame); - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if (node->id.tag_num != 10) { - ret = 0; - printf("Error, expected tag_num 10, got %"PRIu32": ", node->id.tag_num); - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -/** - * \test Check we handle short identifiers correctly - */ -static int DecodeAsn1Test03(void) -{ - uint8_t *str = (uint8_t *) "\x28"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = 1; - - SCAsn1CtxInit(ac, str, len); - - SCAsn1Decode(ac, ac->cur_frame); - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if (node->id.tag_num != 8) { - ret = 0; - printf("Error, expected tag_num 10, got %"PRIu32": ", node->id.tag_num); - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -/** - * \test Check we handle extended lengths correctly with indefinite form - */ -static int DecodeAsn1Test04(void) -{ - uint8_t *str = (uint8_t *) "\x3F\x84\x06\x80\x12\x12\x12\x00\x00"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = 9; - - SCAsn1CtxInit(ac, str, len); - - SCAsn1Decode(ac, ac->cur_frame); - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if (node->len.len != 3) { - ret = 0; - printf("Error, expected length 3, got %"PRIu32": ", node->len.len); - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -/** - * \test Check we handle extended lengths correctly - * in the definite form - */ -static int DecodeAsn1Test05(void) -{ - uint8_t *str = (uint8_t *) "\x3F\x84\x06\x82\x10\x10"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = 6; - - SCAsn1CtxInit(ac, str, len); - - SCAsn1Decode(ac, ac->cur_frame); - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if (node->len.len!= 32) { - ret = 0; - printf("Error, expected length 10, got %"PRIu32": ", node->len.len); - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -/** - * \test Check we handle short lengths correctly - */ -static int DecodeAsn1Test06(void) -{ - uint8_t *str = (uint8_t *) "\x3F\x84\x06\x26"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = 4; - - SCAsn1CtxInit(ac, str, len); - - SCAsn1Decode(ac, ac->cur_frame); - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if (node->len.len != 38) { - ret = 0; - printf("Error, expected length 10, got %"PRIu32": ", node->len.len); - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -/** - * \test Check we handle events correctly - */ -static int DecodeAsn1Test07(void) -{ - uint8_t *str = (uint8_t *) "\x3F\x00\x84\x06"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = 4; - - SCAsn1CtxInit(ac, str, len); - - SCAsn1Decode(ac, ac->cur_frame); - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if ( !(ac->ctx_flags & ASN1_BER_EVENT_INVALID_ID) - || !(node->flags & ASN1_BER_EVENT_INVALID_ID)) - { - ret = 0; - printf("Error, expected invalid id, got flags %"PRIu8": ", ac->ctx_flags); - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -/** - * \test Check we handle events correctly - */ -static int DecodeAsn1Test08(void) -{ - uint8_t *str = (uint8_t *) "\x3F\x84\x06\x81\xFF"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = 5; - - SCAsn1CtxInit(ac, str, len); - - SCAsn1Decode(ac, ac->cur_frame); - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if ( !(ac->ctx_flags & ASN1_BER_EVENT_INVALID_LEN) - || !(node->flags & ASN1_BER_EVENT_INVALID_LEN)) - { - ret = 0; - printf("Error, expected invalid length, got flags %"PRIu8": ", ac->ctx_flags); - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -/** - * \test Check we handle events correctly - */ -static int DecodeAsn1Test09(void) -{ - uint8_t *str = (uint8_t *) "\x3F\x84\x06\x80\xAB\xCD\xEF"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = 7; - - SCAsn1CtxInit(ac, str, len); - - SCAsn1Decode(ac, ac->cur_frame); - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if ( !(ac->ctx_flags & ASN1_BER_EVENT_EOC_NOT_FOUND) - || !(node->flags & ASN1_BER_EVENT_EOC_NOT_FOUND)) - { - ret = 0; - printf("Error, expected eoc not found, got flags %"PRIu8": ", ac->ctx_flags); - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -/** - * \test Decode a big chunk of data - */ -static int DecodeAsn1Test10(void) -{ - // Example from the specification X.690-0207 Appendix A.3 - uint8_t *str = (uint8_t *) "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01" - "P""\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director" - "\x42\x01\x33\xA1\x0A\x43\x08""19710917" - "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05" - "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01" - "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111" - "\x31\x1F\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05" - "Jones""\xA0\x0A\x43\x08""19590717" - "\x60\x81\x85\x61\x10\x1A\x04""John""\x1A\x01""P" - "\x1A\x05""Smith""\xA0\x0A\x1A\x08""Director" - "\x42\x01\x33\xA1\x0A\x43\x08""19710917" - "\xA2\x12\x61\x10\x1A\x04""Mary""\x1A\x01""T""\x1A\x05" - "Smith""\xA3\x42\x31\x1F\x61\x11\x1A\x05""Ralph""\x1A\x01" - "T""\x1A\x05""Smith""\xA0\x0A\x43\x08""19571111""\x31\x1F" - "\x61\x11\x1A\x05""Susan""\x1A\x01""B""\x1A\x05""Jones" - "\xA0\x0A\x43\x08""19590717"; - - Asn1Ctx *ac = SCAsn1CtxNew(); - if (ac == NULL) - return 0; - uint8_t ret = 1; - - uint16_t len = strlen((char *)str)-1; - - SCAsn1CtxInit(ac, str, len); - - ret = SCAsn1Decode(ac, ac->cur_frame); - - /* General checks */ - if (ret != ASN1_PARSER_OK) { - printf("Error decoding asn1 data: "); - ret = 0; - goto end; - } - - if (ac->cur_frame != 59) { - printf("Error decoding asn1 data, not all the nodes" - "were correctly decoded: "); - ret = 0; - goto end; - } - - if (ac->iter != ac->end) { - printf("Error decoding asn1 data, not all the nodes" - "were correctly decoded: "); - ret = 0; - goto end; - } - - Asn1Node *node = ASN1CTX_GET_NODE(ac, 0); - if (node->len.len != 133) { - printf("Error decoding asn1 data, not all the nodes" - "were correctly decoded: "); - ret = 0; - goto end; - } - - node = ASN1CTX_GET_NODE(ac, 30); - if (node->len.len != 133) { - printf("Error decoding asn1 data, not all the nodes" - "were correctly decoded: "); - ret = 0; - goto end; - } - -end: - SCAsn1CtxDestroy(ac); - return ret; -} - -#endif - -void DecodeAsn1RegisterTests(void) -{ -#ifdef UNITTESTS - UtRegisterTest("DecodeAsn1Test01", DecodeAsn1Test01); - UtRegisterTest("DecodeAsn1Test02", DecodeAsn1Test02); - UtRegisterTest("DecodeAsn1Test03", DecodeAsn1Test03); - - UtRegisterTest("DecodeAsn1Test04", DecodeAsn1Test04); - UtRegisterTest("DecodeAsn1Test05", DecodeAsn1Test05); - UtRegisterTest("DecodeAsn1Test06", DecodeAsn1Test06); - - UtRegisterTest("DecodeAsn1Test07", DecodeAsn1Test07); - UtRegisterTest("DecodeAsn1Test08", DecodeAsn1Test08); - UtRegisterTest("DecodeAsn1Test09", DecodeAsn1Test09); - - UtRegisterTest("DecodeAsn1Test10", DecodeAsn1Test10); -#endif -} - diff --git a/src/util-decode-asn1.h b/src/util-decode-asn1.h deleted file mode 100644 index b913aeee9b..0000000000 --- a/src/util-decode-asn1.h +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright (C) 2007-2010 Open Information Security Foundation - * - * You can copy, redistribute or modify this Program under the terms of - * the GNU General Public License version 2 as published by the Free - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Pablo Rincon Crespo - * - * Implements ASN1 decoding (needed for the asn1 keyword) - */ - -#ifndef __DECODE_ASN1_H__ -#define __DECODE_ASN1_H__ -#include -#include -#include -#include -#include -#include -#include -#include - -#define ASN1_MAX_FRAMES 256 - -/* For future enconding type implementations */ -enum { - ASN1_BER_ENC, - ASN1_ENC_UNKNOWN -}; - -/* Class of tag */ -#define ASN1_BER_CLASS_UNIV 0 -#define ASN1_BER_CLASS_APP 1 -#define ASN1_BER_CLASS_CTX_SPECIFIC 2 -#define ASN1_BER_CLASS_PRIV 3 - -/* For low tag numbers */ -#define ASN1_BER_GET_CLASS_TAG(id_octet) \ - ((id_octet >> 6) & 0x03) /* (8.1.2.2a) */ -#define ASN1_BER_IS_CONSTRUCTED(id_octet) \ - ((id_octet >> 5) & 0x01) /* (8.1.2.5) Constructed Tag */ -#define ASN1_BER_IS_PRIMITIVE(id_octet) \ - (((id_octet >> 5) & 0x01)?0:1) /* (8.1.2.5) Primitive Tag */ -#define ASN1_BER_IS_LOW_TAG(id_octet) \ - ASN1_BER_IS_PRIMITIVE(id_octet) /* (8.1.2.5) Is Low Tag - Number */ -#define ASN1_BER_GET_LOW_TAG_NUM(id_octet) \ - (id_octet & 0x1F) /* (8.1.2.2c) Get LowTag Number */ - -/* For high tag numbers */ -#define ASN1_BER_IS_HIGH_TAG(id_octet) \ - ((ASN1_BER_GET_LOW_TAG_NUM(id_octet) == 0x1F) && \ - ASN1_BER_IS_CONSTRUCTED(id_octet)) /* (8.1.2.4) High Tag Number */ -#define ASN1_BER_IS_HIGH_TAG_END(id_octet) \ - ( !((id_octet >> 7) & 0x01)) /* (8.1.2.4) Is End of Tag Num */ -#define ASN1_BER_GET_HIGH_TAG_NUM(id_octet) \ - (id_octet & 0x7F) /* (8.1.2.4) Part of High Tag - Number */ - - -#define ASN1_BER_IS_SHORT_LEN(id_octet) \ - ( !((id_octet >> 7) & 0x01)) /* (8.1.3.3) Is short form */ -#define ASN1_BER_GET_SHORT_LEN(id_octet) \ - (id_octet & 0x7F) /* (8.1.3.3) length value */ -#define ASN1_BER_GET_LONG_LEN_OCTETS(id_octet) \ - (id_octet & 0x7F) /* (8.1.3.5) the number of - bytes */ -#define ASN1_BER_GET_LONG_LEN(id_octet) \ - (id_octet) /* (8.1.3.5) the byte itself*/ -#define ASN1_BER_LONG_LEN_HAS_NEXT(id_octet) \ - ( !((id_octet >> 7) & 0x01)) /* (8.1.3.5) Has next octets - lenght */ -#define ASN1_BER_IS_INDEFINITE_LEN(id_octet) \ - (id_octet == 0x80) /* (8.1.3.6) Need end-of-ccontent */ -#define ASN1_BER_IS_EOC(tmp_iter) (*tmp_iter == 0 && *(tmp_iter + 1) == 0) - -/* Return the current node/frame that we are filling */ -#define ASN1CTX_CUR_NODE(ac) (ac->asn1_stack[ac->cur_frame]) -#define ASN1CTX_GET_NODE(ac, node) (ac->asn1_stack[node]) - -/* BER Universal tags */ -#define ASN1_UNITAG_EOC 0 /* EOC */ -#define ASN1_UNITAG_BOOLEAN 1 -#define ASN1_UNITAG_INTEGER 2 -#define ASN1_UNITAG_BIT_STRING 3 -#define ASN1_UNITAG_OCTET_STRING 4 -#define ASN1_UNITAG_NULL 5 -#define ASN1_UNITAG_OID 6 -#define ASN1_UNITAG_OBJECT_DESCRIPTOR 7 -#define ASN1_UNITAG_EXTERNAL 8 -#define ASN1_UNITAG_REAL 9 -#define ASN1_UNITAG_ENUMERATED 10 -#define ASN1_UNITAG_EMBEDDED_PDV 11 -#define ASN1_UNITAG_UTF8_STRING 12 -#define ASN1_UNITAG_RELATIVE_OID 13 -#define ASN1_UNITAG_SEQUENCE 16 -#define ASN1_UNITAG_SET 17 -#define ASN1_UNITAG_NUMERIC_STRING 18 -#define ASN1_UNITAG_PRINTABLE_STRING 19 -#define ASN1_UNITAG_TELETEX_STRING 20 -#define ASN1_UNITAG_VIDEOTEX_STRING 21 -#define ASN1_UNITAG_IA5_STRING 22 -#define ASN1_UNITAG_UTCTIME 23 -#define ASN1_UNITAG_GENERALIZED_TIME 24 -#define ASN1_UNITAG_GRAPHIC_STRING 25 -#define ASN1_UNITAG_VISIBLE_STRING 26 -#define ASN1_UNITAG_GENERAL_STRING 27 -#define ASN1_UNITAG_UNIVERSAL_STRING 28 -#define ASN1_UNITAG_CHARACTER_STRING 29 -#define ASN1_UNITAG_BMP_STRING 30 - -/* Length form */ -#define ASN1_BER_LEN_SHORT 0 -#define ASN1_BER_LEN_LONG 1 -#define ASN1_BER_LEN_INDEFINITE 2 - - -/* Error events/flags */ -#define ASN1_BER_EVENT_ID_TOO_LONG 0x01 -#define ASN1_BER_EVENT_INVALID_ID 0x02 /* (8.1.2.4.2c) First subsequent - id val (from bit 7 to 0) Shall - not be 0 */ -#define ASN1_BER_EVENT_INVALID_LEN 0x04 /* (8.1.3.2a) we expect a simple - form, or (8.1.3.5c) we got - 0xFF, or not enough data */ -#define ASN1_BER_EVENT_LEN_TOO_LONG 0x08 -#define ASN1_BER_EVENT_EOC_NOT_FOUND 0x10 /* EOC not found */ - - -/* Helper flags */ -#define ASN1_NODE_IS_EOC 1 -#define ASN1_TAG_TYPE_PRIMITIVE 0 -#define ASN1_TAG_TYPE_CONSTRUCTED 1 - -typedef struct Asn1Len_ { - uint8_t form; - uint32_t len; - const uint8_t *ptr; -} Asn1Len; - -typedef struct Asn1Id_ { - const uint8_t *ptr; - uint8_t class_tag; - uint8_t tag_type; - uint32_t tag_num; -} Asn1Id; - -typedef struct Asn1Data_ { - const uint8_t *ptr; - uint32_t len; - uint8_t type; -} Asn1Data; - -typedef struct Asn1Node_ { - uint8_t *raw_str; - uint8_t data_len; - Asn1Len len; - Asn1Id id; - Asn1Data data; - uint8_t flags; -} Asn1Node; - -typedef struct Asn1Ctx_ { - const uint8_t *data; - const uint8_t *end; - uint16_t len; - - const uint8_t *iter; - - uint16_t cur_frame; - Asn1Node *asn1_stack2[ASN1_MAX_FRAMES]; - Asn1Node **asn1_stack; - - uint8_t parser_status; - - uint8_t ctx_flags; -} Asn1Ctx; - -/* Return codes of the decoder */ -#define ASN1_PARSER_OK 0x01 /* Everything ok */ -#define ASN1_PARSER_ERR 0x02 /* Internal error, fatal error, we can't continue decoding */ - -/* Status of the parser */ -#define ASN1_STATUS_OK 0x00 /* On the road */ -#define ASN1_STATUS_INVALID 0x01 /* We found something weird/invalid by the specification, but we can try to continue parsing */ -#define ASN1_STATUS_OOB 0x02 /* We don't have enough data or ran out of bounds */ -#define ASN1_STATUS_DONE 0x04 /* We have finished cleanly */ - -void SCPrintByteBin(uint8_t); - -Asn1Ctx *SCAsn1CtxNew(void); -void SCAsn1CtxInit(Asn1Ctx *, const uint8_t *, uint16_t); -void SCAsn1CtxDestroy(Asn1Ctx *); - -uint8_t SCAsn1Decode(Asn1Ctx *, uint16_t); -uint8_t SCAsn1DecodeIdentifier(Asn1Ctx *); -uint8_t SCAsn1DecodeLength(Asn1Ctx *); -uint8_t SCAsn1DecodeContent(Asn1Ctx *); - -uint8_t SCAsn1CheckBounds(Asn1Ctx *); - -void DecodeAsn1RegisterTests(void); -void SCAsn1LoadConfig(void); - -#endif /* __DECODE_ASN1_H__ */ -