From 1d9f37a60e7fde720768f41e5680ee2e02b78ffc Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Mon, 9 Mar 2020 20:35:27 +0100 Subject: [PATCH] DER: remove the C parser for DER --- configure.ac | 1 - src/Makefile.am | 2 - src/app-layer-ssl.c | 34 +- src/suricata.c | 7 - src/util-decode-der-get.c | 441 --------------- src/util-decode-der-get.h | 45 -- src/util-decode-der.c | 1081 ------------------------------------- src/util-decode-der.h | 107 ---- 8 files changed, 1 insertion(+), 1717 deletions(-) delete mode 100644 src/util-decode-der-get.c delete mode 100644 src/util-decode-der-get.h delete mode 100644 src/util-decode-der.c delete mode 100644 src/util-decode-der.h diff --git a/configure.ac b/configure.ac index 0d73ef7741..dd053c134b 100644 --- a/configure.ac +++ b/configure.ac @@ -341,7 +341,6 @@ AC_DEFINE([AFLFUZZ_APPLAYER], [1], [Enable --afl-$proto-request commandline option]) AC_DEFINE([AFLFUZZ_MIME], [1], [Enable --afl-mime commandline option]) AC_DEFINE([AFLFUZZ_DECODER], [1], [Enable --afl-decoder-$proto commandline option]) - AC_DEFINE([AFLFUZZ_DER], [1], [Enable --afl-der commandline option]) AC_DEFINE([AFLFUZZ_RULES], [1], [Enable --afl-rules commandline option]) # test for AFL PERSISTANT_MODE support diff --git a/src/Makefile.am b/src/Makefile.am index 6788ee2dc0..28cf620071 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -444,8 +444,6 @@ 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-der.c util-decode-der.h \ -util-decode-der-get.c util-decode-der-get.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/app-layer-ssl.c b/src/app-layer-ssl.c index 8b3e43b2ca..e5e6619482 100644 --- a/src/app-layer-ssl.c +++ b/src/app-layer-ssl.c @@ -43,8 +43,6 @@ #include "conf.h" #include "util-crypt.h" -#include "util-decode-der.h" -#include "util-decode-der-get.h" #include "util-spm.h" #include "util-unittest.h" #include "util-debug.h" @@ -355,36 +353,6 @@ void SSLVersionToString(uint16_t version, char *buffer) } } -static void TlsDecodeHSCertificateErrSetEvent(SSLState *ssl_state, uint32_t err) -{ - switch (err) { - case ERR_DER_UNKNOWN_ELEMENT: - SSLSetEvent(ssl_state, - TLS_DECODER_EVENT_CERTIFICATE_UNKNOWN_ELEMENT); - break; - case ERR_DER_ELEMENT_SIZE_TOO_BIG: - case ERR_DER_INVALID_SIZE: - case ERR_DER_RECURSION_LIMIT: - SSLSetEvent(ssl_state, - TLS_DECODER_EVENT_CERTIFICATE_INVALID_LENGTH); - break; - case ERR_DER_UNSUPPORTED_STRING: - SSLSetEvent(ssl_state, - TLS_DECODER_EVENT_CERTIFICATE_INVALID_STRING); - break; - case ERR_DER_MISSING_ELEMENT: - SSLSetEvent(ssl_state, - TLS_DECODER_EVENT_CERTIFICATE_MISSING_ELEMENT); - break; - case ERR_DER_INVALID_TAG: - case ERR_DER_INVALID_OBJECT: - case ERR_DER_GENERIC: - default: - SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_CERTIFICATE); - break; - } -} - static inline int TlsDecodeHSCertificateFingerprint(SSLState *ssl_state, const uint8_t *input, uint32_t cert_len) @@ -464,7 +432,7 @@ static int TlsDecodeHSCertificate(SSLState *ssl_state, x509 = rs_x509_decode(input, cert_len); if (x509 == NULL) { - TlsDecodeHSCertificateErrSetEvent(ssl_state, ERR_DER_GENERIC); + SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_CERTIFICATE); goto next; } diff --git a/src/suricata.c b/src/suricata.c index 89e9cc69d9..a60fa74b7f 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -130,7 +130,6 @@ #include "app-layer-smb.h" #include "app-layer-dcerpc.h" -#include "util-decode-der.h" #include "util-ebpf.h" #include "util-radix-tree.h" #include "util-host-os-info.h" @@ -1403,12 +1402,6 @@ static void ParseCommandLineAFL(const char *opt_name, char *opt_arg) else exit(DecoderParseDataFromFileSerie(opt_arg, DecodeERSPAN)); } else -#endif -#ifdef AFLFUZZ_DER - if(strcmp(opt_name, "afl-der") == 0) { - //printf("arg: //%s\n", opt_arg); - exit(DerParseDataFromFile(opt_arg)); - } else #endif { abort(); diff --git a/src/util-decode-der-get.c b/src/util-decode-der-get.c deleted file mode 100644 index 3e90788f74..0000000000 --- a/src/util-decode-der-get.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (C) 2011-2012 ANSSI - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * \author Pierre Chifflier - * - */ - -#include "suricata-common.h" - -#include "util-decode-der.h" -#include "util-decode-der-get.h" - -static const uint8_t SEQ_IDX_SERIAL[] = { 0, 0 }; -static const uint8_t SEQ_IDX_ISSUER[] = { 0, 2 }; -static const uint8_t SEQ_IDX_VALIDITY[] = { 0, 3 }; -static const uint8_t SEQ_IDX_SUBJECT[] = { 0, 4 }; - -static const char *Oid2ShortStr(const char *oid) -{ - if (strcmp(oid, "1.2.840.113549.1.9.1") == 0) - return "emailAddress"; - - if (strcmp(oid, "2.5.4.3") == 0) - return "CN"; - - if (strcmp(oid, "2.5.4.5") == 0) - return "serialNumber"; - - if (strcmp(oid, "2.5.4.6") == 0) - return "C"; - - if (strcmp(oid, "2.5.4.7") == 0) - return "L"; - - if (strcmp(oid, "2.5.4.8") == 0) - return "ST"; - - if (strcmp(oid, "2.5.4.10") == 0) - return "O"; - - if (strcmp(oid, "2.5.4.11") == 0) - return "OU"; - - if (strcmp(oid, "0.9.2342.19200300.100.1.25") == 0) - return "DC"; - - return "unknown"; -} - -static time_t GentimeToTime(char *gentime) -{ - time_t time; - struct tm tm; - - /* GeneralizedTime values MUST be expressed in Greenwich Mean Time - * (Zulu) and MUST include seconds (rfc5280 4.1.2.5.2). It MUST NOT - * include fractional seconds. It should therefore be on the format - * YYYYmmddHHMMSSZ. */ - if (strlen(gentime) != 15) - goto error; - - memset(&tm, 0, sizeof(tm)); - strptime(gentime, "%Y%m%d%H%M%SZ", &tm); - time = SCMkTimeUtc(&tm); - - if (time < 0) - goto error; - - return time; - -error: - return -1; -} - -static time_t UtctimeToTime(char *utctime) -{ - time_t time; - unsigned int year; - char yy[3]; - char buf[20]; - - /* UTCTime values MUST be expressed in Greenwich Mean Time (Zulu) - * and MUST include seconds (rfc5280 4.1.2.5.1). It should - * therefore be on the format YYmmddHHMMSSZ. */ - if (strlen(utctime) != 13) - goto error; - - /* UTCTime use two digits to represent the year. The year field (YY) - * should be interpreted as 19YY when it is greater than or equal to - * 50. If it is less than 50 it should be interpreted as 20YY. - * Because of this, GeneralizedTime must be used for dates in the - * year 2050 or later. */ - strlcpy(yy, utctime, sizeof(yy)); - year = strtol(yy, NULL, 10); - if (year >= 50) - snprintf(buf, sizeof(buf), "%i%s", 19, utctime); - else - snprintf(buf, sizeof(buf), "%i%s", 20, utctime); - - time = GentimeToTime(buf); - if (time == -1) - goto error; - - return time; - -error: - return -1; -} - -/** - * \brief Iterate through an ASN.1 structure, following the index sequence. - * Context specific elements are skipped. - * - * \retval The matching node, or NULL - */ -const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index, - const uint32_t seqsz, uint32_t *errcode) -{ - const Asn1Generic * node; - uint8_t idx, i; - uint8_t offset = 0; - - if (errcode) - *errcode = ERR_DER_MISSING_ELEMENT; - - node = top; - if (node == NULL || seq_index == NULL) - return NULL; - - for (offset=0; offsetdata == NULL) - return NULL; - - /* skip context-specific elements */ - while (node->data->header.cls == ASN1_CLASS_CONTEXTSPEC) { - node = node->next; - if (node == NULL || node->data == NULL) - return NULL; - } - - node = node->next; - if (node == NULL || node->data == NULL) - return NULL; - } - - /* skip context-specific elements */ - if (node == NULL || node->data == NULL) - return NULL; - while (node->data->header.cls == ASN1_CLASS_CONTEXTSPEC) { - node = node->next; - if (node == NULL || node->data == NULL) - return NULL; - } - - node = node->data; - } - - if (errcode) - *errcode = 0; - - return node; -} - -int Asn1DerGetValidity(const Asn1Generic *cert, time_t *not_before, - time_t *not_after, uint32_t *errcode) -{ - const Asn1Generic *node, *it; - int rc = -1; - - if (errcode) - *errcode = ERR_DER_MISSING_ELEMENT; - - node = Asn1DerGet(cert, SEQ_IDX_VALIDITY, sizeof(SEQ_IDX_VALIDITY), errcode); - if ((node == NULL) || node->type != ASN1_SEQUENCE) - goto validity_error; - - it = node->data; - if (it == NULL || it->str == NULL) - goto validity_error; - - if (it->type == ASN1_UTCTIME) - *not_before = UtctimeToTime(it->str); - else if (it->type == ASN1_GENERALIZEDTIME) - *not_before = GentimeToTime(it->str); - else - goto validity_error; - - if (*not_before == -1) - goto validity_error; - - if (node->next == NULL) - goto validity_error; - - it = node->next->data; - - if (it == NULL || it->str == NULL) - goto validity_error; - - if (it->type == ASN1_UTCTIME) - *not_after = UtctimeToTime(it->str); - else if (it->type == ASN1_GENERALIZEDTIME) - *not_after = GentimeToTime(it->str); - else - goto validity_error; - - if (*not_after == -1) - goto validity_error; - - rc = 0; - -validity_error: - return rc; -} - -int Asn1DerGetSerial(const Asn1Generic *cert, char *buffer, uint32_t length, - uint32_t *errcode) -{ - const Asn1Generic *node; - uint32_t node_len, i; - int rc = -1; - - if (errcode) - *errcode = ERR_DER_MISSING_ELEMENT; - - buffer[0] = '\0'; - - node = Asn1DerGet(cert, SEQ_IDX_SERIAL, sizeof(SEQ_IDX_SERIAL), errcode); - if ((node == NULL) || node->type != ASN1_INTEGER || node->str == NULL) - goto serial_error; - - node_len = strlen(node->str); - - /* make sure the buffer is big enough */ - if (node_len + (node_len / 2) > length) - goto serial_error; - - /* format serial number (e.g. XX:XX:XX:XX:XX) */ - for (i = 0; i < node_len; i++) { - char c[3]; - /* insert separator before each even number */ - if (((i % 2) == 0) && (i != 0)) { - snprintf(c, sizeof(c), ":%c", node->str[i]); - } else { - snprintf(c, sizeof(c), "%c", node->str[i]); - } - - strlcat(buffer, c, length); - } - - if (errcode) - *errcode = 0; - - rc = 0; - -serial_error: - return rc; -} - -int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length, - uint32_t *errcode) -{ - const Asn1Generic *node_oid; - const Asn1Generic *node; - const Asn1Generic *it; - const Asn1Generic *node_set; - const Asn1Generic *node_str; - const char *shortname; - int rc = -1; - const char *separator = ", "; - - if (errcode) - *errcode = ERR_DER_MISSING_ELEMENT; - - if (length < 10) - goto issuer_dn_error; - - buffer[0] = '\0'; - - node = Asn1DerGet(cert, SEQ_IDX_ISSUER, sizeof(SEQ_IDX_ISSUER), errcode); - if ((node == NULL) || node->type != ASN1_SEQUENCE) - goto issuer_dn_error; - - it = node; - while (it != NULL) { - if (it->data == NULL) - goto issuer_dn_error; - node_set = it->data; - if (node_set->type != ASN1_SET || node_set->data == NULL) - goto issuer_dn_error; - node = node_set->data; - if (node->type != ASN1_SEQUENCE || node->data == NULL) - goto issuer_dn_error; - node_oid = node->data; - if (node_oid->str == NULL || node_oid->type != ASN1_OID) - goto issuer_dn_error; - shortname = Oid2ShortStr(node_oid->str); - if (node->next == NULL) - goto issuer_dn_error; - node = node->next; - node_str = node->data; - if (node_str == NULL || node_str->str == NULL) - goto issuer_dn_error; - - switch (node_str->type) { - case ASN1_PRINTSTRING: - case ASN1_IA5STRING: - case ASN1_T61STRING: - case ASN1_UTF8STRING: - case ASN1_OCTETSTRING: - strlcat(buffer, shortname, length); - strlcat(buffer, "=", length); - strlcat(buffer, node_str->str, length); - break; - default: - if (errcode) - *errcode = ERR_DER_UNSUPPORTED_STRING; - goto issuer_dn_error; - } - - if (strcmp(shortname,"CN") == 0) - separator = "/"; - if (it->next != NULL) - strlcat(buffer, separator, length); - it = it->next; - } - - if (errcode) - *errcode = 0; - - rc = 0; -issuer_dn_error: - return rc; -} - -int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length, - uint32_t *errcode) -{ - const Asn1Generic *node_oid; - const Asn1Generic *node; - const Asn1Generic *it; - const Asn1Generic *node_set; - const Asn1Generic *node_str; - const char *shortname; - int rc = -1; - const char *separator = ", "; - - if (errcode) - *errcode = ERR_DER_MISSING_ELEMENT; - - if (length < 10) - goto subject_dn_error; - - buffer[0] = '\0'; - - node = Asn1DerGet(cert, SEQ_IDX_SUBJECT, sizeof(SEQ_IDX_SUBJECT), errcode); - - if ((node == NULL) || node->type != ASN1_SEQUENCE) - goto subject_dn_error; - - it = node; - while (it != NULL) { - if (it == NULL || it->data == NULL) - goto subject_dn_error; - node_set = it->data; - if (node_set->type != ASN1_SET || node_set->data == NULL) - goto subject_dn_error; - node = node_set->data; - if (node->type != ASN1_SEQUENCE || node->data == NULL) - goto subject_dn_error; - node_oid = node->data; - if (node_oid->str == NULL || node_oid->type != ASN1_OID) - goto subject_dn_error; - shortname = Oid2ShortStr(node_oid->str); - if (node->next == NULL) - goto subject_dn_error; - node = node->next; - node_str = node->data; - if (node_str == NULL || node_str->str == NULL) - goto subject_dn_error; - - switch (node_str->type) { - case ASN1_PRINTSTRING: - case ASN1_IA5STRING: - case ASN1_T61STRING: - case ASN1_UTF8STRING: - case ASN1_OCTETSTRING: - strlcat(buffer, shortname, length); - strlcat(buffer, "=", length); - strlcat(buffer, node_str->str, length); - break; - default: - if (errcode) - *errcode = ERR_DER_UNSUPPORTED_STRING; - goto subject_dn_error; - } - - if (strcmp(shortname,"CN") == 0) - separator = "/"; - if (it->next != NULL) - strlcat(buffer, separator, length); - it = it->next; - } - - if (errcode) - *errcode = 0; - - rc = 0; -subject_dn_error: - return rc; -} - diff --git a/src/util-decode-der-get.h b/src/util-decode-der-get.h deleted file mode 100644 index bed1cfebed..0000000000 --- a/src/util-decode-der-get.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2011-2012 ANSSI - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * \author Pierre Chifflier - * - */ - -#ifndef __UTIL_DECODE_DER_GET_H__ -#define __UTIL_DECODE_DER_GET_H__ - -const Asn1Generic * Asn1DerGet(const Asn1Generic *top, const uint8_t *seq_index, const uint32_t seqsz, uint32_t *errcode); - -int Asn1DerGetIssuerDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode); -int Asn1DerGetSerial(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode); -int Asn1DerGetValidity(const Asn1Generic *cert, time_t *not_before, time_t *not_after, uint32_t *errcode); -int Asn1DerGetSubjectDN(const Asn1Generic *cert, char *buffer, uint32_t length, uint32_t *errcode); - -#endif /* __UTIL_DECODE_DER_GET_H__ */ diff --git a/src/util-decode-der.c b/src/util-decode-der.c deleted file mode 100644 index dbde7643cc..0000000000 --- a/src/util-decode-der.c +++ /dev/null @@ -1,1081 +0,0 @@ -/* - * Copyright (C) 2011-2015 ANSSI - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * \author Pierre Chifflier - * - */ - -/* - * An ASN.1 Parser for DER-encoded structures. - * This parser is not written to be complete or fast, but is rather - * focused on stability and security. - * It does not support all ASN.1 structure, only a meaningful subset - * to decode x509v3 certificates (See RFC 3280). - * - * References (like 8.19.4) are relative to the ISO/IEC 8825-1:2003 document - * - */ - -#include "suricata-common.h" -#include "util-decode-der.h" -#include "util-validate.h" - -#define MAX_OID_LENGTH 256 - -static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerBoolean(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerGeneralizedTime(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) __attribute__((nonnull)); -static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - int seq_index, uint32_t *errcode) __attribute__((nonnull)); - -static Asn1Generic * Asn1GenericNew(void) -{ - Asn1Generic *obj; - - obj = SCMalloc(sizeof(Asn1Generic)); - if (obj != NULL) - memset(obj, 0, sizeof(Asn1Generic)); - - return obj; -} - -/** - * \retval r 0 ok, -1 error - */ -static int Asn1SequenceAppend(Asn1Generic *seq, Asn1Generic *node) -{ - Asn1Generic *it, *new_container; - - if (seq->data == NULL) { - seq->data = node; - return 0; - } - - new_container = Asn1GenericNew(); - if (new_container == NULL) - return -1; - new_container->data = node; - - for (it=seq; it->next != NULL; it=it->next) - ; - - it->next = new_container; - return 0; -} - -/* openssl has set a limit of 30, so stay close to that. */ -#define DER_MAX_RECURSION_DEPTH 32 - -static Asn1Generic * DecodeAsn1DerGeneric(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - int seq_index, uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint32_t numbytes, el_max_size; - Asn1ElementType el; - uint8_t c; - uint32_t i; - Asn1Generic *child; - uint8_t el_type; - - /* refuse excessive recursion */ - if (unlikely(depth >= DER_MAX_RECURSION_DEPTH)) { - *errcode = ERR_DER_RECURSION_LIMIT; - return NULL; - } - if (max_size < 2) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - - el.cls = (d_ptr[0] & 0xc0) >> 6; - el.pc = (d_ptr[0] & 0x20) >> 5; - el.tag = (d_ptr[0] & 0x1f); - - el_type = el.tag; - - if (el.tag == 0x1f) { - *errcode = ERR_DER_INVALID_TAG; - return NULL; - } - - switch (el.cls) { - case ASN1_CLASS_CONTEXTSPEC: - /* get element type from definition, see: - http://www.ietf.org/rfc/rfc3280.txt */ - if (depth == 2 && el.tag == 0) { - /* TBSCertificate */ - el_type = ASN1_SEQUENCE; - break; - } - if (depth == 2 && el.tag == 1) { - /* issuerUniqueID */ - el_type = ASN1_BITSTRING; - break; - } - if (depth == 2 && el.tag == 2) { - /* subjectUniqueID */ - el_type = ASN1_BITSTRING; - break; - } - if (depth == 2 && el.tag == 3) { - /* extensions */ - el_type = ASN1_SEQUENCE; - break; - } - /* unknown context specific value - do not decode */ - break; - }; - - el_max_size = max_size - (d_ptr-buffer); - switch (el_type) { - case ASN1_INTEGER: - child = DecodeAsn1DerInteger(d_ptr, el_max_size, depth+1, errcode); - break; - case ASN1_BOOLEAN: - child = DecodeAsn1DerBoolean(d_ptr, el_max_size, depth+1, errcode); - break; - case ASN1_NULL: - child = DecodeAsn1DerNull(d_ptr, el_max_size, depth+1, errcode); - break; - case ASN1_BITSTRING: - child = DecodeAsn1DerBitstring(d_ptr, el_max_size, depth+1, - errcode); - break; - case ASN1_OID: - child = DecodeAsn1DerOid(d_ptr, el_max_size, depth+1, errcode); - break; - case ASN1_IA5STRING: - child = DecodeAsn1DerIA5String(d_ptr, el_max_size, depth+1, - errcode); - break; - case ASN1_OCTETSTRING: - child = DecodeAsn1DerOctetString(d_ptr, el_max_size, depth+1, - errcode); - break; - case ASN1_UTF8STRING: - child = DecodeAsn1DerUTF8String(d_ptr, el_max_size, depth+1, - errcode); - break; - case ASN1_PRINTSTRING: - child = DecodeAsn1DerPrintableString(d_ptr, el_max_size, depth+1, - errcode); - break; - case ASN1_SEQUENCE: - child = DecodeAsn1DerSequence(d_ptr, el_max_size, depth+1, errcode); - break; - case ASN1_SET: - child = DecodeAsn1DerSet(d_ptr, el_max_size, depth+1, errcode); - break; - case ASN1_T61STRING: - child = DecodeAsn1DerT61String(d_ptr, el_max_size, depth+1, - errcode); - break; - case ASN1_UTCTIME: - child = DecodeAsn1DerUTCTime(d_ptr, el_max_size, depth+1, errcode); - break; - case ASN1_GENERALIZEDTIME: - child = DecodeAsn1DerGeneralizedTime(d_ptr, el_max_size, depth+1, errcode); - break; - default: - /* unknown ASN.1 type */ - child = NULL; - child = Asn1GenericNew(); - if (child == NULL) - break; - - child->type = el.tag; - - /* total sequence length */ - const unsigned char * save_d_ptr = d_ptr; - d_ptr++; - el_max_size--; - c = d_ptr[0]; - - /* short form 8.1.3.4 */ - if ((c & (1<<7))>>7 == 0) { - child->length = c; - d_ptr++; - /* long form 8.1.3.5 */ - } else { - numbytes = c & 0x7f; - if (2 + numbytes > el_max_size) { - SCFree(child); - *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; - return NULL; - } - child->length = 0; - d_ptr++; - for (i=0; ilength = child->length<<8 | d_ptr[0]; - d_ptr++; - } - } - - /* fix the length for unknown objects, else sequence parsing - will fail */ - child->length += (d_ptr - save_d_ptr); - - if (child->length > max_size - (d_ptr - buffer)) { - *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; - SCFree(child); - return NULL; - } - - break; - }; - - if (child == NULL) { - if (*errcode == 0) - *errcode = ERR_DER_INVALID_OBJECT; - return NULL; - } - - /* child length should never be zero */ - if (child->length == 0) { - *errcode = ERR_DER_INVALID_OBJECT; - SCFree(child); - return NULL; - } - - child->header = el; - return child; -} - -static Asn1Generic * DecodeAsn1DerInteger(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint8_t numbytes; - uint32_t value; - uint32_t i; - Asn1Generic *a; - - numbytes = d_ptr[1]; - - if ((uint32_t)(numbytes + 2) > size) { - *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; - return NULL; - } - - d_ptr += 2; - - value = 0; - - /* Here we need to ensure that numbytes is less than 4 - so integer affectation is possible. We set the value - to 0xffffffff which is by convention the unknown value. - In this case, the hexadecimal value must be used. */ - if (numbytes > 4) { - value = 0xffffffff; - } else { - for (i=0; itype = ASN1_INTEGER; - a->length = (d_ptr - buffer) + numbytes; - a->value = value; - - a->str = SCMalloc(2*numbytes + 1); - if (a->str == NULL) { - *errcode = ERR_DER_GENERIC; - SCFree(a); - return NULL; - } - - for (i=0; istr + 2*i, 2*(numbytes-i)+1, "%02X", d_ptr[i]); - } - a->str[2*numbytes]= '\0'; - - return a; -} - -static int DecodeAsn1BuildValue(const unsigned char **d_ptr, uint32_t *val, - uint8_t numbytes, uint32_t *errcode) -{ - int i; - uint32_t value = 0; - - if (numbytes > 4) { - *errcode = ERR_DER_INVALID_SIZE; - - /* too big won't fit: set it to 0xffffffff by convention */ - value = 0xffffffff; - *val = value; - return -1; - } else { - for (i=0; i size) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - d_ptr += 2; - - if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) { - return NULL; - } - - a = Asn1GenericNew(); - if (a == NULL) { - *errcode = ERR_DER_GENERIC; - return NULL; - } - - a->type = ASN1_BOOLEAN; - a->length = (d_ptr - buffer); - a->value = value; - - return a; -} - -static Asn1Generic * DecodeAsn1DerNull(const unsigned char *buffer, - uint32_t size, uint8_t depth, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint8_t numbytes; - uint32_t value; - Asn1Generic *a; - - numbytes = d_ptr[1]; - if ((uint32_t)(numbytes + 2) > size) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - d_ptr += 2; - - if (DecodeAsn1BuildValue(&d_ptr, &value, numbytes, errcode) == -1) { - return NULL; - } - - a = Asn1GenericNew(); - if (a == NULL) { - *errcode = ERR_DER_GENERIC; - return NULL; - } - - a->type = ASN1_NULL; - a->length = (d_ptr - buffer); - a->value = 0; - - return a; -} - -static Asn1Generic * DecodeAsn1DerBitstring(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint32_t length; - uint8_t numbytes, c; - Asn1Generic *a; - - d_ptr++; - - /* size */ - c = d_ptr[0]; - /* short form 8.1.3.4 */ - if ((c & (1<<7))>>7 == 0) { - length = c; - d_ptr++; - /* long form 8.1.3.5 */ - } else { - numbytes = c & 0x7f; - if ((uint32_t)(numbytes + 2) > max_size) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - d_ptr++; - if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) { - return NULL; - } - } - - if ((d_ptr-buffer) + length > max_size) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - - a = Asn1GenericNew(); - if (a == NULL) { - *errcode = ERR_DER_GENERIC; - return NULL; - } - - a->type = ASN1_BITSTRING; - a->strlen = length; - - a->str = SCMalloc(length); - if (a->str == NULL) { - *errcode = ERR_DER_GENERIC; - SCFree(a); - return NULL; - } - memcpy(a->str, (const char*)d_ptr, length); - - d_ptr += length; - - a->length = (d_ptr - buffer); - return a; -} - -static Asn1Generic * DecodeAsn1DerOid(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint32_t oid_length, oid_value; - uint8_t numbytes, c; - Asn1Generic *a; - uint32_t i; - - d_ptr++; - - /* size */ - c = d_ptr[0]; - /* short form 8.1.3.4 */ - if ((c & (1<<7))>>7 == 0) { - oid_length = c; - d_ptr++; - /* long form 8.1.3.5 */ - } else { - numbytes = c & 0x7f; - if ((uint32_t)(numbytes + 2) > max_size) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - d_ptr++; - if (DecodeAsn1BuildValue(&d_ptr, &oid_length, numbytes, errcode) == -1) { - return NULL; - } - } - - if (oid_length == 0 || (d_ptr-buffer) + oid_length > max_size) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - - a = Asn1GenericNew(); - if (a == NULL) { - *errcode = ERR_DER_GENERIC; - return NULL; - } - - a->type = ASN1_OID; - - a->str = SCMalloc(MAX_OID_LENGTH); - if (a->str == NULL) { - *errcode = ERR_DER_GENERIC; - SCFree(a); - return NULL; - } - - /* first element = X*40 + Y (See 8.19.4) */ - snprintf(a->str, MAX_OID_LENGTH, "%d.%d", (d_ptr[0]/40), (d_ptr[0]%40)); - d_ptr++; - - if (oid_length + (d_ptr-buffer) > max_size) { - *errcode = ERR_DER_INVALID_SIZE; - SCFree(a->str); - SCFree(a); - return NULL; - } - - /* sub-identifiers are multi-valued, coded and 7 bits, first bit of - the 8bits is used to indicate, if a new value is starting */ - for (i=1; istr); - c = d_ptr[0]; - oid_value = 0; - while ( istr + s, MAX_OID_LENGTH - s, ".%d", oid_value); - } - - a->length = (d_ptr - buffer); - return a; -} - -static Asn1Generic * DecodeAsn1DerIA5String(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint32_t length, numbytes; - Asn1Generic *a; - unsigned char c; - - d_ptr++; - max_size--; - - /* total sequence length */ - c = d_ptr[0]; - /* short form 8.1.3.4 */ - if ((c & (1<<7))>>7 == 0) { - length = c; - d_ptr++; - max_size--; - /* long form 8.1.3.5 */ - } else { - numbytes = c & 0x7f; - if (max_size < 1 + numbytes) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - max_size -= 1 + numbytes; - d_ptr++; - if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) { - return NULL; - } - } - - if (length == UINT32_MAX || (d_ptr-buffer) + length > max_size) { - *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; - return NULL; - } - - a = Asn1GenericNew(); - if (a == NULL) { - *errcode = ERR_DER_GENERIC; - return NULL; - } - - a->type = ASN1_IA5STRING; - a->strlen = length; - - a->str = SCMalloc(length+1); - if (a->str == NULL) { - *errcode = ERR_DER_GENERIC; - SCFree(a); - return NULL; - } - memcpy(a->str, (const char*)d_ptr, length); - a->str[length] = 0; - - d_ptr += length; - - a->length = (d_ptr - buffer); - return a; -} - -static Asn1Generic * DecodeAsn1DerOctetString(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint32_t length, numbytes; - Asn1Generic *a; - unsigned char c; - - d_ptr++; - max_size--; - - /* total sequence length */ - c = d_ptr[0]; - /* short form 8.1.3.4 */ - if ((c & (1<<7))>>7 == 0) { - length = c; - d_ptr++; - max_size--; - /* long form 8.1.3.5 */ - } else { - numbytes = c & 0x7f; - if (max_size < 1 + numbytes) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - max_size -= 1 + numbytes; - d_ptr++; - if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) { - return NULL; - } - } - - if (length == UINT32_MAX || (d_ptr-buffer) + length > max_size) { - *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; - return NULL; - } - a = Asn1GenericNew(); - if (a == NULL) { - *errcode = ERR_DER_GENERIC; - return NULL; - } - - a->type = ASN1_OCTETSTRING; - a->strlen = length; - - /* add one to the octet string for the 0. This will then allow us to - use the string in printf */ - a->str = SCMalloc(length + 1); - if (a->str == NULL) { - *errcode = ERR_DER_GENERIC; - SCFree(a); - return NULL; - } - memcpy(a->str, (const char*)d_ptr, length); - a->str[length] = 0; - - d_ptr += length; - - a->length = (d_ptr - buffer); - return a; -} - -static Asn1Generic * DecodeAsn1DerUTF8String(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) -{ - Asn1Generic *a = DecodeAsn1DerOctetString(buffer, max_size, depth, errcode); - if (a != NULL) - a->type = ASN1_UTF8STRING; - - return a; -} - -static Asn1Generic * DecodeAsn1DerPrintableString(const unsigned char *buffer, - uint32_t max_size, - uint8_t depth, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint32_t length, numbytes; - Asn1Generic *a; - unsigned char c; - - d_ptr++; - - /* total sequence length */ - c = d_ptr[0]; - /* short form 8.1.3.4 */ - if ((c & (1<<7))>>7 == 0) { - length = c; - d_ptr++; - /* long form 8.1.3.5 */ - } else { - numbytes = c & 0x7f; - d_ptr++; - if (2 + numbytes > max_size) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - if (DecodeAsn1BuildValue(&d_ptr, &length, numbytes, errcode) == -1) { - return NULL; - } - } - - if (length == UINT32_MAX || (d_ptr-buffer) + length > max_size) { - *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; - return NULL; - } - - a = Asn1GenericNew(); - if (a == NULL) { - *errcode = ERR_DER_GENERIC; - return NULL; - } - - a->type = ASN1_PRINTSTRING; - a->strlen = length; - - a->str = SCMalloc(length+1); - if (a->str == NULL) { - *errcode = ERR_DER_GENERIC; - SCFree(a); - return NULL; - } - memcpy(a->str, (const char*)d_ptr, length); - a->str[length] = 0; - - d_ptr += length; - - a->length = (d_ptr - buffer); - return a; -} - -static Asn1Generic * DecodeAsn1DerSequence(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint32_t d_length, parsed_bytes, numbytes, el_max_size; - uint8_t c; - uint32_t seq_index; - Asn1Generic *node; - - d_ptr++; - - node = Asn1GenericNew(); - if (node == NULL) { - *errcode = ERR_DER_GENERIC; - return NULL; - } - - node->type = ASN1_SEQUENCE; - - /* total sequence length */ - c = d_ptr[0]; - /* short form 8.1.3.4 */ - if ((c & (1<<7))>>7 == 0) { - d_length = c; - d_ptr++; - /* long form 8.1.3.5 */ - } else { - numbytes = c & 0x7f; - d_ptr++; - if ( 2 + numbytes > max_size ) { - *errcode = ERR_DER_INVALID_SIZE; - SCFree(node); - return NULL; - } - if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) { - SCFree(node); - return NULL; - } - } - node->length = d_length + (d_ptr - buffer); - if (node->length > max_size || node->length < d_length /* wrap */) { - *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; - SCFree(node); - return NULL; - } - - parsed_bytes = 0; - seq_index = 0; - - /* decode child elements */ - while (parsed_bytes < d_length) { - el_max_size = max_size - (d_ptr-buffer); - - Asn1Generic *child = DecodeAsn1DerGeneric(d_ptr, - MIN(node->length, el_max_size), depth, - seq_index, errcode); - if (child == NULL) { - if (*errcode != 0) { - DerFree(node); - return NULL; - } - break; - } - - int ret = Asn1SequenceAppend(node, child); - if (ret == -1) { - DerFree(child); - break; - } - - parsed_bytes += child->length; - d_ptr += child->length; - seq_index++; - } - - return (Asn1Generic *)node; -} - -static Asn1Generic * DecodeAsn1DerSet(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint32_t d_length, numbytes, el_max_size; - uint8_t c; - uint32_t seq_index; - Asn1Generic *node; - Asn1Generic *child; - - d_ptr++; - - node = Asn1GenericNew(); - if (node == NULL) { - *errcode = ERR_DER_GENERIC; - return NULL; - } - node->type = ASN1_SET; - node->data = NULL; - - /* total sequence length */ - c = d_ptr[0]; - /* short form 8.1.3.4 */ - if ((c & (1<<7))>>7 == 0) { - d_length = c; - d_ptr++; - /* long form 8.1.3.5 */ - } else { - numbytes = c & 0x7f; - if (2 + numbytes > max_size) { - *errcode = ERR_DER_INVALID_SIZE; - SCFree(node); - return NULL; - } - d_ptr++; - if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) { - SCFree(node); - return NULL; - } - } - - node->length = d_length + (d_ptr - buffer); - - if (node->length > max_size || node->length < d_length /* wrap */) { - *errcode = ERR_DER_ELEMENT_SIZE_TOO_BIG; - SCFree(node); - return NULL; - } - - seq_index = 0; - - el_max_size = max_size - (d_ptr-buffer); - - child = DecodeAsn1DerGeneric(d_ptr, MIN(node->length, el_max_size), - depth, seq_index, errcode); - if (child == NULL) { - DerFree(node); - return NULL; - } - - node->data = child; - - return (Asn1Generic *)node; -} - -static Asn1Generic * DecodeAsn1DerT61String(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) -{ - Asn1Generic *a; - - a = DecodeAsn1DerIA5String(buffer, max_size, depth, errcode); - if (a != NULL) - a->type = ASN1_T61STRING; - - return a; -} - -static Asn1Generic * DecodeAsn1DerUTCTime(const unsigned char *buffer, - uint32_t max_size, uint8_t depth, - uint32_t *errcode) -{ - Asn1Generic *a; - - a = DecodeAsn1DerIA5String(buffer, max_size, depth, errcode); - if (a != NULL) - a->type = ASN1_UTCTIME; - - return a; -} - -static Asn1Generic * DecodeAsn1DerGeneralizedTime(const unsigned char *buffer, - uint32_t max_size, - uint8_t depth, - uint32_t *errcode) -{ - Asn1Generic *a; - - a = DecodeAsn1DerIA5String(buffer, max_size, depth, errcode); - if (a != NULL) - a->type = ASN1_GENERALIZEDTIME; - - return a; -} - -/** - * \param errcode pointer to error code variable. May not be NULL. - */ -Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size, - uint32_t *errcode) -{ - const unsigned char *d_ptr = buffer; - uint32_t d_length, numbytes; - Asn1Generic *cert; - uint8_t c; - - DEBUG_VALIDATE_BUG_ON(errcode == NULL); - *errcode = 0; - - if (size < 2) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - - /* check that buffer is an ASN.1 structure (basic checks) */ - if (d_ptr[0] != 0x30 && d_ptr[1] != 0x82) { /* Sequence */ - *errcode = ERR_DER_UNKNOWN_ELEMENT; - return NULL; - } - - c = d_ptr[1]; - if ((c & (1<<7))>>7 != 1) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - - numbytes = c & 0x7f; - d_ptr += 2; - if (size < numbytes + 2) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - if (DecodeAsn1BuildValue(&d_ptr, &d_length, numbytes, errcode) == -1) { - return NULL; - } - - if (d_length+(d_ptr-buffer) != size) { - *errcode = ERR_DER_INVALID_SIZE; - return NULL; - } - - cert = DecodeAsn1DerGeneric(buffer, size, 0 /* depth */, 0, errcode); - - return cert; -} - -#ifdef AFLFUZZ_DER -int DerParseDataFromFile(char *filename) -{ - uint8_t buffer[65536]; - uint32_t errcode = 0; - -#ifdef AFLFUZZ_PERSISTANT_MODE - while (__AFL_LOOP(1000)) { - /* reset state */ - memset(buffer, 0, sizeof(buffer)); -#endif /* AFLFUZZ_PERSISTANT_MODE */ - - FILE *fp = fopen(filename, "r"); - BUG_ON(fp == NULL); - - size_t result = fread(&buffer, 1, sizeof(buffer), fp); - Asn1Generic *a = DecodeDer(buffer, result, &errcode); - DerFree(a); - fclose(fp); - -#ifdef AFLFUZZ_PERSISTANT_MODE - } -#endif /* AFLFUZZ_PERSISTANT_MODE */ - - return 0; -} -#endif /* AFLFUZZ_DER */ - -void DerFree(Asn1Generic *a) -{ - Asn1Generic *it, *n; - - if (a == NULL) - return; - - it = a; - while (it) { - n = it->next; - if (it->data) { - DerFree(it->data); - } - if (it->str) - SCFree(it->str); - memset(it, 0xff, sizeof(Asn1Generic)); - SCFree(it); - it = n; - } -} diff --git a/src/util-decode-der.h b/src/util-decode-der.h deleted file mode 100644 index 5110a4e0f1..0000000000 --- a/src/util-decode-der.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2011-2012 ANSSI - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * \file - * - * \author Pierre Chifflier - * - */ - -#ifndef __UTIL_DECODE_DER_H__ -#define __UTIL_DECODE_DER_H__ - -#define ASN1_CLASS_UNIVERSAL 0 -#define ASN1_CLASS_APPLICATION 1 -#define ASN1_CLASS_CONTEXTSPEC 2 -#define ASN1_CLASS_PRIVATE 3 - -#define ASN1_UNKNOWN 0 -#define ASN1_BOOLEAN 0x01 -#define ASN1_INTEGER 0x02 -#define ASN1_BITSTRING 0x03 -#define ASN1_OCTETSTRING 0x04 -#define ASN1_NULL 0x05 -#define ASN1_OID 0x06 -#define ASN1_UTF8STRING 0x0c -#define ASN1_SEQUENCE 0x10 -#define ASN1_SET 0x11 -#define ASN1_PRINTSTRING 0x13 -#define ASN1_T61STRING 0x14 -#define ASN1_IA5STRING 0x16 -#define ASN1_UTCTIME 0x17 -#define ASN1_GENERALIZEDTIME 0x18 - -typedef struct Asn1ElementType_ { - uint8_t cls:2; - uint8_t pc:1; - uint8_t tag:5; -} __attribute__((packed)) Asn1ElementType; - -/* Generic ASN.1 element - * Presence and meaning of fields depends on the header and type values. - */ -typedef struct Asn1Generic_ { - Asn1ElementType header; - uint8_t type; - uint32_t length; /* length of node, including header */ - - struct Asn1Generic_ *data; /* only if type is structured */ - - char *str; - uint32_t strlen; - uint64_t value; - struct Asn1Generic_ *next; /* only if type is sequence */ -} Asn1Generic; - -/* Generic error (failed allocation, etc.) */ -#define ERR_DER_GENERIC 0x01 -/* Unknown ASN.1 element type */ -#define ERR_DER_UNKNOWN_ELEMENT 0x02 -/* One element requires to read more bytes than available */ -#define ERR_DER_ELEMENT_SIZE_TOO_BIG 0x03 -/* One element size is invalid (e.g more than 4 bytes long) */ -#define ERR_DER_INVALID_SIZE 0x04 -/* Unsupported string type */ -#define ERR_DER_UNSUPPORTED_STRING 0x05 -/* Missing field or element */ -#define ERR_DER_MISSING_ELEMENT 0x06 -/* Generic error */ -#define ERR_DER_RECURSION_LIMIT 0x07 -/* Unexpected or unknown tag */ -#define ERR_DER_INVALID_TAG 0x08 -/* Invalid element: empty object, etc. */ -#define ERR_DER_INVALID_OBJECT 0x09 - -Asn1Generic * DecodeDer(const unsigned char *buffer, uint32_t size, uint32_t *errcode) __attribute__((nonnull)); -void DerFree(Asn1Generic *a); - -#ifdef AFLFUZZ_DER -int DerParseDataFromFile(char *filename); -#endif - -#endif /* __UTIL_DECODE_DER_H__ */ -- 2.47.2