diff --git a/.github/workflows/build-ci.yml b/.github/workflows/build-ci.yml index b06ccf5c..1fca26cf 100644 --- a/.github/workflows/build-ci.yml +++ b/.github/workflows/build-ci.yml @@ -32,11 +32,12 @@ jobs: run: | echo "version=$(cat Makefile | grep "PKG_VERSION :=" | sed 's/PKG_VERSION := //')" >> $GITHUB_OUTPUT echo "release=$(cat Makefile | grep "PKG_RELEASE :=" | sed 's/PKG_RELEASE := //')" >> $GITHUB_OUTPUT - if [[ "${{ github.event_name }}" != "pull_request" ]]; then - echo "sha=$(echo ${GITHUB_SHA::7})" >> $GITHUB_OUTPUT - else - echo "sha=$(gh api repos/$REPO/commits/main --jq '.sha[:7]')" >> $GITHUB_OUTPUT + + if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then + GITHUB_SHA=$(cat $GITHUB_EVENT_PATH | jq -r .pull_request.head.sha) fi + echo "sha=$(echo ${GITHUB_SHA::7})" >> $GITHUB_OUTPUT + cat $GITHUB_OUTPUT build-static: needs: prepare diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5518ef98..65ce0ca7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -70,6 +70,29 @@ jobs: name: static-youtubeUnblock-${{ matrix.arch }} path: ./**/static-youtubeUnblock*.tar.gz + test: + needs: prepare + name: test + runs-on: ubuntu-latest + strategy: + matrix: + arch: [x86_64] + branch: [latest-stable] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build + id: build + shell: bash + run: | + make build_test -j$(nproc) + + - name: Test + id: test + run: + ./build/testYoutubeUnblock + build-kmod: needs: prepare name: build-kmod ${{ matrix.kernel_version }} diff --git a/Kbuild b/Kbuild index 3dbbfe39..871269b5 100644 --- a/Kbuild +++ b/Kbuild @@ -1,3 +1,3 @@ obj-m := kyoutubeUnblock.o -kyoutubeUnblock-objs := kytunblock.o mangle.o quic.o utils.o kargs.o tls.o getopt.o args.o -ccflags-y := -std=gnu99 -DKERNEL_SPACE -Wno-error -Wno-declaration-after-statement +kyoutubeUnblock-objs := src/kytunblock.o src/mangle.o src/quic.o src/quic_crypto.o src/utils.o src/kargs.o src/tls.o src/getopt.o src/args.o deps/cyclone/aes.o deps/cyclone/cpu_endian.o deps/cyclone/ecb.o deps/cyclone/gcm.o deps/cyclone/hkdf.o deps/cyclone/hmac.o deps/cyclone/sha256.o +ccflags-y := -std=gnu99 -DKERNEL_SPACE -Wno-error -Wno-declaration-after-statement -I$(src)/src -I$(src)/deps/cyclone/include diff --git a/Makefile b/Makefile index c2a7b2d2..60b18c51 100644 --- a/Makefile +++ b/Makefile @@ -8,13 +8,19 @@ PKG_FULLVERSION := $(PKG_VERSION)-$(PKG_RELEASE) export PKG_VERSION PKG_RELEASE PKG_FULLVERSION -.PHONY: $(USPACE_TARGETS) $(KMAKE_TARGETS) clean +.PHONY: $(USPACE_TARGETS) $(KMAKE_TARGETS) test build_test clean distclean kclean $(USPACE_TARGETS): @$(MAKE) -f uspace.mk $@ $(KMAKE_TARGETS): @$(MAKE) -f kmake.mk $@ +build_test: + -@$(MAKE) -f uspace.mk build_test + +test: + -@$(MAKE) -f uspace.mk test + clean: -@$(MAKE) -f uspace.mk clean diff --git a/README.md b/README.md index 380dd329..f18d11be 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ - [IPv6](#ipv6) - [Check it](#check-it) - [Flags](#flags) - - [UDP](#udp) + - [UDP/QUIC](#udp/quic) - [Troubleshooting](#troubleshooting) - [TV](#tv) - [Troubleshooting EPERMS (Operation not permitted)](#troubleshooting-eperms-operation-not-permitted) @@ -270,13 +270,21 @@ Flags that do not scoped to a specific section, used over all the youtubeUnblock - `--udp-faking-strategy={checksum|ttl|none}` Faking strategy for udp. `checksum` will fake UDP checksum, `ttl` won't fake but will make UDP content relatively small, `none` is no faking. Defaults to none. -- `--udp-filter-quic={disabled|all}` Enables QUIC filtering for UDP handler. If disabled, quic won't be processed, if all, all quic initial packets will be handled. Defaults to disabled. +- `--udp-filter-quic={disabled|all|parse}` Enables QUIC filtering for UDP handler. If disabled, quic won't be processed, if all, all quic initial packets will be handled. `parse` will decrypt and parse QUIC initial message and match it with `--sni-domains`. Defaults to disabled. - `--quic-drop` Drop all QUIC packets which goes to youtubeUnblock. Won't affect any other UDP packets. Just an alias for `--udp-filter-quic=all --udp-mode=drop`. -## UDP +## UDP/QUIC -UDP is another communication protocol. Well-known technologies that use it are DNS, QUIC, voice chats. UDP does not provide reliable connection and its header is much simpler than TCP thus fragmentation is limited. The support provided primarily by faking. For QUIC faking may not work well, so use `--quic-drop` if you want to drop all quic traffic. For other technologies I recommend to configure UDP support in the separate section from TCP, like `--fbegin --udp-dport-filter=50000-50099 --tls=disabled`. See more in flags related to udp and [issues tagged with udp label](https://github.com/Waujito/youtubeUnblock/issues?q=label%3Audp+). +UDP is another communication protocol. Well-known technologies that use it are DNS, QUIC, voice chats. UDP does not provide reliable connection and its header is much simpler than TCP thus fragmentation is limited. The support provided primarily by faking. + +Right now, QUIC faking may not work well, so use `--udp-mode=drop` option. + +QUIC is enabled with `--udp-filter-quic` flag. The flag supports two modes: `all` will handle all the QUIC initial messages and `parse` will decrypt and parse the QUIC initial message, and then compare it with `--sni-domains` flag. + +**I recommend to use** `--udp-mode=drop --udp-filter-quic=parse`. + +For **other UDP protocols** I recommend to configure UDP support in the separate section from TCP, like `--fbegin --udp-dport-filter=50000-50099 --tls=disabled`. See more in flags related to udp and [tickets tagged with udp label](https://github.com/Waujito/youtubeUnblock/issues?q=label%3Audp+). ## Troubleshooting diff --git a/args.h b/args.h deleted file mode 100644 index 8c4e88fe..00000000 --- a/args.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef ARGS_H -#define ARGS_H -#include "types.h" -#include "config.h" - -void print_version(void); -void print_usage(const char *argv0); -int yparse_args(int argc, char *argv[]); -size_t print_config(char *buffer, size_t buffer_size); - -// Initializes configuration storage. -int init_config(struct config_t *config); -// Allocates and initializes configuration section. -int init_section_config(struct section_config_t **section, struct section_config_t *prev); -// Frees configuration section -void free_config_section(struct section_config_t *config); -// Frees sections under config -void free_config(struct config_t config); - -/* Prints starting messages */ -void print_welcome(void); - -#endif /* ARGS_H */ diff --git a/deps/cyclone/Makefile b/deps/cyclone/Makefile new file mode 100644 index 00000000..4027c0e4 --- /dev/null +++ b/deps/cyclone/Makefile @@ -0,0 +1,24 @@ +SRCS := $(shell find -name "*.c") +OBJS := $(SRCS:%.c=build/%.o) +override CFLAGS += -Iinclude -Wno-pedantic +LIBNAME := libcyclone.a +CC := gcc + + +run: $(OBJS) + @echo "AR $(LIBNAME)" + @ar rcs libcyclone.a $(OBJS) + +prep_dirs: + mkdir -p build + + +build/%.o: %.c prep_dirs + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + @rm $(OBJS) || true + @rm libcyclone.a || true + @rm -rf build || true + + diff --git a/deps/cyclone/aes.c b/deps/cyclone/aes.c new file mode 100644 index 00000000..78a3cdf5 --- /dev/null +++ b/deps/cyclone/aes.c @@ -0,0 +1,577 @@ +/** + * @file aes.c + * @brief AES (Advanced Encryption Standard) + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @section Description + * + * AES is an encryption standard based on Rijndael algorithm, a symmetric block + * cipher that can process data blocks of 128 bits, using cipher keys with + * lengths of 128, 192, and 256 bits. Refer to FIPS 197 for more details + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "cipher/aes.h" + +//Check crypto library configuration +#if (AES_SUPPORT == ENABLED) + +//Substitution table used by encryption algorithm (S-box) +static const uint8_t sbox[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +//Substitution table used by decryption algorithm (inverse S-box) +static const uint8_t isbox[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +//Precalculated table (encryption) +static const uint32_t te[256] = +{ + 0xA56363C6, 0x847C7CF8, 0x997777EE, 0x8D7B7BF6, 0x0DF2F2FF, 0xBD6B6BD6, 0xB16F6FDE, 0x54C5C591, + 0x50303060, 0x03010102, 0xA96767CE, 0x7D2B2B56, 0x19FEFEE7, 0x62D7D7B5, 0xE6ABAB4D, 0x9A7676EC, + 0x45CACA8F, 0x9D82821F, 0x40C9C989, 0x877D7DFA, 0x15FAFAEF, 0xEB5959B2, 0xC947478E, 0x0BF0F0FB, + 0xECADAD41, 0x67D4D4B3, 0xFDA2A25F, 0xEAAFAF45, 0xBF9C9C23, 0xF7A4A453, 0x967272E4, 0x5BC0C09B, + 0xC2B7B775, 0x1CFDFDE1, 0xAE93933D, 0x6A26264C, 0x5A36366C, 0x413F3F7E, 0x02F7F7F5, 0x4FCCCC83, + 0x5C343468, 0xF4A5A551, 0x34E5E5D1, 0x08F1F1F9, 0x937171E2, 0x73D8D8AB, 0x53313162, 0x3F15152A, + 0x0C040408, 0x52C7C795, 0x65232346, 0x5EC3C39D, 0x28181830, 0xA1969637, 0x0F05050A, 0xB59A9A2F, + 0x0907070E, 0x36121224, 0x9B80801B, 0x3DE2E2DF, 0x26EBEBCD, 0x6927274E, 0xCDB2B27F, 0x9F7575EA, + 0x1B090912, 0x9E83831D, 0x742C2C58, 0x2E1A1A34, 0x2D1B1B36, 0xB26E6EDC, 0xEE5A5AB4, 0xFBA0A05B, + 0xF65252A4, 0x4D3B3B76, 0x61D6D6B7, 0xCEB3B37D, 0x7B292952, 0x3EE3E3DD, 0x712F2F5E, 0x97848413, + 0xF55353A6, 0x68D1D1B9, 0x00000000, 0x2CEDEDC1, 0x60202040, 0x1FFCFCE3, 0xC8B1B179, 0xED5B5BB6, + 0xBE6A6AD4, 0x46CBCB8D, 0xD9BEBE67, 0x4B393972, 0xDE4A4A94, 0xD44C4C98, 0xE85858B0, 0x4ACFCF85, + 0x6BD0D0BB, 0x2AEFEFC5, 0xE5AAAA4F, 0x16FBFBED, 0xC5434386, 0xD74D4D9A, 0x55333366, 0x94858511, + 0xCF45458A, 0x10F9F9E9, 0x06020204, 0x817F7FFE, 0xF05050A0, 0x443C3C78, 0xBA9F9F25, 0xE3A8A84B, + 0xF35151A2, 0xFEA3A35D, 0xC0404080, 0x8A8F8F05, 0xAD92923F, 0xBC9D9D21, 0x48383870, 0x04F5F5F1, + 0xDFBCBC63, 0xC1B6B677, 0x75DADAAF, 0x63212142, 0x30101020, 0x1AFFFFE5, 0x0EF3F3FD, 0x6DD2D2BF, + 0x4CCDCD81, 0x140C0C18, 0x35131326, 0x2FECECC3, 0xE15F5FBE, 0xA2979735, 0xCC444488, 0x3917172E, + 0x57C4C493, 0xF2A7A755, 0x827E7EFC, 0x473D3D7A, 0xAC6464C8, 0xE75D5DBA, 0x2B191932, 0x957373E6, + 0xA06060C0, 0x98818119, 0xD14F4F9E, 0x7FDCDCA3, 0x66222244, 0x7E2A2A54, 0xAB90903B, 0x8388880B, + 0xCA46468C, 0x29EEEEC7, 0xD3B8B86B, 0x3C141428, 0x79DEDEA7, 0xE25E5EBC, 0x1D0B0B16, 0x76DBDBAD, + 0x3BE0E0DB, 0x56323264, 0x4E3A3A74, 0x1E0A0A14, 0xDB494992, 0x0A06060C, 0x6C242448, 0xE45C5CB8, + 0x5DC2C29F, 0x6ED3D3BD, 0xEFACAC43, 0xA66262C4, 0xA8919139, 0xA4959531, 0x37E4E4D3, 0x8B7979F2, + 0x32E7E7D5, 0x43C8C88B, 0x5937376E, 0xB76D6DDA, 0x8C8D8D01, 0x64D5D5B1, 0xD24E4E9C, 0xE0A9A949, + 0xB46C6CD8, 0xFA5656AC, 0x07F4F4F3, 0x25EAEACF, 0xAF6565CA, 0x8E7A7AF4, 0xE9AEAE47, 0x18080810, + 0xD5BABA6F, 0x887878F0, 0x6F25254A, 0x722E2E5C, 0x241C1C38, 0xF1A6A657, 0xC7B4B473, 0x51C6C697, + 0x23E8E8CB, 0x7CDDDDA1, 0x9C7474E8, 0x211F1F3E, 0xDD4B4B96, 0xDCBDBD61, 0x868B8B0D, 0x858A8A0F, + 0x907070E0, 0x423E3E7C, 0xC4B5B571, 0xAA6666CC, 0xD8484890, 0x05030306, 0x01F6F6F7, 0x120E0E1C, + 0xA36161C2, 0x5F35356A, 0xF95757AE, 0xD0B9B969, 0x91868617, 0x58C1C199, 0x271D1D3A, 0xB99E9E27, + 0x38E1E1D9, 0x13F8F8EB, 0xB398982B, 0x33111122, 0xBB6969D2, 0x70D9D9A9, 0x898E8E07, 0xA7949433, + 0xB69B9B2D, 0x221E1E3C, 0x92878715, 0x20E9E9C9, 0x49CECE87, 0xFF5555AA, 0x78282850, 0x7ADFDFA5, + 0x8F8C8C03, 0xF8A1A159, 0x80898909, 0x170D0D1A, 0xDABFBF65, 0x31E6E6D7, 0xC6424284, 0xB86868D0, + 0xC3414182, 0xB0999929, 0x772D2D5A, 0x110F0F1E, 0xCBB0B07B, 0xFC5454A8, 0xD6BBBB6D, 0x3A16162C +}; + +//Precalculated table (decryption) +static const uint32_t td[256] = +{ + 0x50A7F451, 0x5365417E, 0xC3A4171A, 0x965E273A, 0xCB6BAB3B, 0xF1459D1F, 0xAB58FAAC, 0x9303E34B, + 0x55FA3020, 0xF66D76AD, 0x9176CC88, 0x254C02F5, 0xFCD7E54F, 0xD7CB2AC5, 0x80443526, 0x8FA362B5, + 0x495AB1DE, 0x671BBA25, 0x980EEA45, 0xE1C0FE5D, 0x02752FC3, 0x12F04C81, 0xA397468D, 0xC6F9D36B, + 0xE75F8F03, 0x959C9215, 0xEB7A6DBF, 0xDA595295, 0x2D83BED4, 0xD3217458, 0x2969E049, 0x44C8C98E, + 0x6A89C275, 0x78798EF4, 0x6B3E5899, 0xDD71B927, 0xB64FE1BE, 0x17AD88F0, 0x66AC20C9, 0xB43ACE7D, + 0x184ADF63, 0x82311AE5, 0x60335197, 0x457F5362, 0xE07764B1, 0x84AE6BBB, 0x1CA081FE, 0x942B08F9, + 0x58684870, 0x19FD458F, 0x876CDE94, 0xB7F87B52, 0x23D373AB, 0xE2024B72, 0x578F1FE3, 0x2AAB5566, + 0x0728EBB2, 0x03C2B52F, 0x9A7BC586, 0xA50837D3, 0xF2872830, 0xB2A5BF23, 0xBA6A0302, 0x5C8216ED, + 0x2B1CCF8A, 0x92B479A7, 0xF0F207F3, 0xA1E2694E, 0xCDF4DA65, 0xD5BE0506, 0x1F6234D1, 0x8AFEA6C4, + 0x9D532E34, 0xA055F3A2, 0x32E18A05, 0x75EBF6A4, 0x39EC830B, 0xAAEF6040, 0x069F715E, 0x51106EBD, + 0xF98A213E, 0x3D06DD96, 0xAE053EDD, 0x46BDE64D, 0xB58D5491, 0x055DC471, 0x6FD40604, 0xFF155060, + 0x24FB9819, 0x97E9BDD6, 0xCC434089, 0x779ED967, 0xBD42E8B0, 0x888B8907, 0x385B19E7, 0xDBEEC879, + 0x470A7CA1, 0xE90F427C, 0xC91E84F8, 0x00000000, 0x83868009, 0x48ED2B32, 0xAC70111E, 0x4E725A6C, + 0xFBFF0EFD, 0x5638850F, 0x1ED5AE3D, 0x27392D36, 0x64D90F0A, 0x21A65C68, 0xD1545B9B, 0x3A2E3624, + 0xB1670A0C, 0x0FE75793, 0xD296EEB4, 0x9E919B1B, 0x4FC5C080, 0xA220DC61, 0x694B775A, 0x161A121C, + 0x0ABA93E2, 0xE52AA0C0, 0x43E0223C, 0x1D171B12, 0x0B0D090E, 0xADC78BF2, 0xB9A8B62D, 0xC8A91E14, + 0x8519F157, 0x4C0775AF, 0xBBDD99EE, 0xFD607FA3, 0x9F2601F7, 0xBCF5725C, 0xC53B6644, 0x347EFB5B, + 0x7629438B, 0xDCC623CB, 0x68FCEDB6, 0x63F1E4B8, 0xCADC31D7, 0x10856342, 0x40229713, 0x2011C684, + 0x7D244A85, 0xF83DBBD2, 0x1132F9AE, 0x6DA129C7, 0x4B2F9E1D, 0xF330B2DC, 0xEC52860D, 0xD0E3C177, + 0x6C16B32B, 0x99B970A9, 0xFA489411, 0x2264E947, 0xC48CFCA8, 0x1A3FF0A0, 0xD82C7D56, 0xEF903322, + 0xC74E4987, 0xC1D138D9, 0xFEA2CA8C, 0x360BD498, 0xCF81F5A6, 0x28DE7AA5, 0x268EB7DA, 0xA4BFAD3F, + 0xE49D3A2C, 0x0D927850, 0x9BCC5F6A, 0x62467E54, 0xC2138DF6, 0xE8B8D890, 0x5EF7392E, 0xF5AFC382, + 0xBE805D9F, 0x7C93D069, 0xA92DD56F, 0xB31225CF, 0x3B99ACC8, 0xA77D1810, 0x6E639CE8, 0x7BBB3BDB, + 0x097826CD, 0xF418596E, 0x01B79AEC, 0xA89A4F83, 0x656E95E6, 0x7EE6FFAA, 0x08CFBC21, 0xE6E815EF, + 0xD99BE7BA, 0xCE366F4A, 0xD4099FEA, 0xD67CB029, 0xAFB2A431, 0x31233F2A, 0x3094A5C6, 0xC066A235, + 0x37BC4E74, 0xA6CA82FC, 0xB0D090E0, 0x15D8A733, 0x4A9804F1, 0xF7DAEC41, 0x0E50CD7F, 0x2FF69117, + 0x8DD64D76, 0x4DB0EF43, 0x544DAACC, 0xDF0496E4, 0xE3B5D19E, 0x1B886A4C, 0xB81F2CC1, 0x7F516546, + 0x04EA5E9D, 0x5D358C01, 0x737487FA, 0x2E410BFB, 0x5A1D67B3, 0x52D2DB92, 0x335610E9, 0x1347D66D, + 0x8C61D79A, 0x7A0CA137, 0x8E14F859, 0x893C13EB, 0xEE27A9CE, 0x35C961B7, 0xEDE51CE1, 0x3CB1477A, + 0x59DFD29C, 0x3F73F255, 0x79CE1418, 0xBF37C773, 0xEACDF753, 0x5BAAFD5F, 0x146F3DDF, 0x86DB4478, + 0x81F3AFCA, 0x3EC468B9, 0x2C342438, 0x5F40A3C2, 0x72C31D16, 0x0C25E2BC, 0x8B493C28, 0x41950DFF, + 0x7101A839, 0xDEB30C08, 0x9CE4B4D8, 0x90C15664, 0x6184CB7B, 0x70B632D5, 0x745C6C48, 0x4257B8D0 +}; + +//Round constant word array +static const uint32_t rcon[11] = +{ + 0x00000000, + 0x00000001, + 0x00000002, + 0x00000004, + 0x00000008, + 0x00000010, + 0x00000020, + 0x00000040, + 0x00000080, + 0x0000001B, + 0x00000036 +}; + +//AES128-ECB OID (2.16.840.1.101.3.4.1.1) +const uint8_t AES128_ECB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x01}; +//AES128-CBC OID (2.16.840.1.101.3.4.1.2) +const uint8_t AES128_CBC_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02}; +//AES128-OFB OID (2.16.840.1.101.3.4.1.3) +const uint8_t AES128_OFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x03}; +//AES128-CFB OID (2.16.840.1.101.3.4.1.4) +const uint8_t AES128_CFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x04}; +//AES128-GCM OID (2.16.840.1.101.3.4.1.6) +const uint8_t AES128_GCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x06}; +//AES128-CCM OID (2.16.840.1.101.3.4.1.7) +const uint8_t AES128_CCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x07}; + +//AES192-ECB OID (2.16.840.1.101.3.4.1.21) +const uint8_t AES192_ECB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x15}; +//AES192-CBC OID (2.16.840.1.101.3.4.1.22) +const uint8_t AES192_CBC_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16}; +//AES192-OFB OID (2.16.840.1.101.3.4.1.23) +const uint8_t AES192_OFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x17}; +//AES192-CFB OID (2.16.840.1.101.3.4.1.24) +const uint8_t AES192_CFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x18}; +//AES192-GCM OID (2.16.840.1.101.3.4.1.26) +const uint8_t AES192_GCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x1A}; +//AES192-CCM OID (2.16.840.1.101.3.4.1.27) +const uint8_t AES192_CCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x1B}; + +//AES256-ECB OID (2.16.840.1.101.3.4.1.41) +const uint8_t AES256_ECB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x29}; +//AES256-CBC OID (2.16.840.1.101.3.4.1.42) +const uint8_t AES256_CBC_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2A}; +//AES256-OFB OID (2.16.840.1.101.3.4.1.43) +const uint8_t AES256_OFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2B}; +//AES256-CFB OID (2.16.840.1.101.3.4.1.44) +const uint8_t AES256_CFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2C}; +//AES256-GCM OID (2.16.840.1.101.3.4.1.46) +const uint8_t AES256_GCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2E}; +//AES256-CCM OID (2.16.840.1.101.3.4.1.47) +const uint8_t AES256_CCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2F}; + +//Common interface for encryption algorithms +const CipherAlgo aesCipherAlgo = +{ + "AES", + sizeof(AesContext), + CIPHER_ALGO_TYPE_BLOCK, + AES_BLOCK_SIZE, + (CipherAlgoInit) aesInit, + NULL, + NULL, + (CipherAlgoEncryptBlock) aesEncryptBlock, + (CipherAlgoDecryptBlock) aesDecryptBlock, + (CipherAlgoDeinit) aesDeinit +}; + + +/** + * @brief Key expansion + * @param[in] context Pointer to the AES context to initialize + * @param[in] key Pointer to the key + * @param[in] keyLen Length of the key + * @return Error code + **/ + +__weak_func error_t aesInit(AesContext *context, const uint8_t *key, + size_t keyLen) +{ + uint_t i; + uint32_t temp; + size_t keyScheduleSize; + + //Check parameters + if(context == NULL || key == NULL) + return ERROR_INVALID_PARAMETER; + + //Check the length of the key + if(keyLen == 16) + { + //10 rounds are required for 128-bit key + context->nr = 10; + } + else if(keyLen == 24) + { + //12 rounds are required for 192-bit key + context->nr = 12; + } + else if(keyLen == 32) + { + //14 rounds are required for 256-bit key + context->nr = 14; + } + else + { + //Report an error + return ERROR_INVALID_KEY_LENGTH; + } + + //Determine the number of 32-bit words in the key + keyLen /= 4; + + //Copy the original key + for(i = 0; i < keyLen; i++) + { + context->ek[i] = LOAD32LE(key + (i * 4)); + } + + //The size of the key schedule depends on the number of rounds + keyScheduleSize = 4 * (context->nr + 1); + + //Generate the key schedule (encryption) + for(i = keyLen; i < keyScheduleSize; i++) + { + //Save previous word + temp = context->ek[i - 1]; + + //Apply transformation + if((i % keyLen) == 0) + { + context->ek[i] = sbox[(temp >> 8) & 0xFF]; + context->ek[i] |= (sbox[(temp >> 16) & 0xFF] << 8); + context->ek[i] |= (sbox[(temp >> 24) & 0xFF] << 16); + context->ek[i] |= (sbox[temp & 0xFF] << 24); + context->ek[i] ^= rcon[i / keyLen]; + } + else if(keyLen > 6 && (i % keyLen) == 4) + { + context->ek[i] = sbox[temp & 0xFF]; + context->ek[i] |= (sbox[(temp >> 8) & 0xFF] << 8); + context->ek[i] |= (sbox[(temp >> 16) & 0xFF] << 16); + context->ek[i] |= (sbox[(temp >> 24) & 0xFF] << 24); + } + else + { + context->ek[i] = temp; + } + + //Update the key schedule + context->ek[i] ^= context->ek[i - keyLen]; + } + + //Generate the key schedule (decryption) + for(i = 0; i < keyScheduleSize; i++) + { + //Apply the InvMixColumns transformation to all round keys but the first + //and the last + if(i < 4 || i >= (keyScheduleSize - 4)) + { + context->dk[i] = context->ek[i]; + } + else + { + context->dk[i] = td[sbox[context->ek[i] & 0xFF]]; + temp = td[sbox[(context->ek[i] >> 8) & 0xFF]]; + context->dk[i] ^= ROL32(temp, 8); + temp = td[sbox[(context->ek[i] >> 16) & 0xFF]]; + context->dk[i] ^= ROL32(temp, 16); + temp = td[sbox[(context->ek[i] >> 24) & 0xFF]]; + context->dk[i] ^= ROL32(temp, 24); + } + } + + //No error to report + return NO_ERROR; +} + + +/** + * @brief Encrypt a 16-byte block using AES algorithm + * @param[in] context Pointer to the AES context + * @param[in] input Plaintext block to encrypt + * @param[out] output Ciphertext block resulting from encryption + **/ + +__weak_func void aesEncryptBlock(AesContext *context, const uint8_t *input, + uint8_t *output) +{ + uint_t i; + uint32_t s0; + uint32_t s1; + uint32_t s2; + uint32_t s3; + uint32_t t0; + uint32_t t1; + uint32_t t2; + uint32_t t3; + uint32_t temp; + + //Copy the plaintext to the state array + s0 = LOAD32LE(input + 0); + s1 = LOAD32LE(input + 4); + s2 = LOAD32LE(input + 8); + s3 = LOAD32LE(input + 12); + + //Initial round key addition + s0 ^= context->ek[0]; + s1 ^= context->ek[1]; + s2 ^= context->ek[2]; + s3 ^= context->ek[3]; + + //The number of rounds depends on the key length + for(i = 1; i < context->nr; i++) + { + //Apply round function + t0 = te[s0 & 0xFF]; + temp = te[(s1 >> 8) & 0xFF]; + t0 ^= ROL32(temp, 8); + temp = te[(s2 >> 16) & 0xFF]; + t0 ^= ROL32(temp, 16); + temp = te[(s3 >> 24) & 0xFF]; + t0 ^= ROL32(temp, 24); + + t1 = te[s1 & 0xFF]; + temp = te[(s2 >> 8) & 0xFF]; + t1 ^= ROL32(temp, 8); + temp = te[(s3 >> 16) & 0xFF]; + t1 ^= ROL32(temp, 16); + temp = te[(s0 >> 24) & 0xFF]; + t1 ^= ROL32(temp, 24); + + t2 = te[s2 & 0xFF]; + temp = te[(s3 >> 8) & 0xFF]; + t2 ^= ROL32(temp, 8); + temp = te[(s0 >> 16) & 0xFF]; + t2 ^= ROL32(temp, 16); + temp = te[(s1 >> 24) & 0xFF]; + t2 ^= ROL32(temp, 24); + + t3 = te[s3 & 0xFF]; + temp = te[(s0 >> 8) & 0xFF]; + t3 ^= ROL32(temp, 8); + temp = te[(s1 >> 16) & 0xFF]; + t3 ^= ROL32(temp, 16); + temp = te[(s2 >> 24) & 0xFF]; + t3 ^= ROL32(temp, 24); + + //Round key addition + s0 = t0 ^ context->ek[i * 4]; + s1 = t1 ^ context->ek[i * 4 + 1]; + s2 = t2 ^ context->ek[i * 4 + 2]; + s3 = t3 ^ context->ek[i * 4 + 3]; + } + + //The last round differs slightly from the first rounds + t0 = sbox[s0 & 0xFF]; + t0 |= sbox[(s1 >> 8) & 0xFF] << 8; + t0 |= sbox[(s2 >> 16) & 0xFF] << 16; + t0 |= sbox[(s3 >> 24) & 0xFF] << 24; + + t1 = sbox[s1 & 0xFF]; + t1 |= sbox[(s2 >> 8) & 0xFF] << 8; + t1 |= sbox[(s3 >> 16) & 0xFF] << 16; + t1 |= sbox[(s0 >> 24) & 0xFF] << 24; + + t2 = sbox[s2 & 0xFF]; + t2 |= sbox[(s3 >> 8) & 0xFF] << 8; + t2 |= sbox[(s0 >> 16) & 0xFF] << 16; + t2 |= sbox[(s1 >> 24) & 0xFF] << 24; + + t3 = sbox[s3 & 0xFF]; + t3 |= sbox[(s0 >> 8) & 0xFF] << 8; + t3 |= sbox[(s1 >> 16) & 0xFF] << 16; + t3 |= sbox[(s2 >> 24) & 0xFF] << 24; + + //Last round key addition + s0 = t0 ^ context->ek[context->nr * 4]; + s1 = t1 ^ context->ek[context->nr * 4 + 1]; + s2 = t2 ^ context->ek[context->nr * 4 + 2]; + s3 = t3 ^ context->ek[context->nr * 4 + 3]; + + //The final state is then copied to the output + STORE32LE(s0, output + 0); + STORE32LE(s1, output + 4); + STORE32LE(s2, output + 8); + STORE32LE(s3, output + 12); +} + + +/** + * @brief Decrypt a 16-byte block using AES algorithm + * @param[in] context Pointer to the AES context + * @param[in] input Ciphertext block to decrypt + * @param[out] output Plaintext block resulting from decryption + **/ + +__weak_func void aesDecryptBlock(AesContext *context, const uint8_t *input, + uint8_t *output) +{ + uint_t i; + uint32_t s0; + uint32_t s1; + uint32_t s2; + uint32_t s3; + uint32_t t0; + uint32_t t1; + uint32_t t2; + uint32_t t3; + uint32_t temp; + + //Copy the ciphertext to the state array + s0 = LOAD32LE(input + 0); + s1 = LOAD32LE(input + 4); + s2 = LOAD32LE(input + 8); + s3 = LOAD32LE(input + 12); + + //Initial round key addition + s0 ^= context->dk[context->nr * 4]; + s1 ^= context->dk[context->nr * 4 + 1]; + s2 ^= context->dk[context->nr * 4 + 2]; + s3 ^= context->dk[context->nr * 4 + 3]; + + //The number of rounds depends on the key length + for(i = context->nr - 1; i >= 1; i--) + { + //Apply round function + t0 = td[s0 & 0xFF]; + temp = td[(s3 >> 8) & 0xFF]; + t0 ^= ROL32(temp, 8); + temp = td[(s2 >> 16) & 0xFF]; + t0 ^= ROL32(temp, 16); + temp = td[(s1 >> 24) & 0xFF]; + t0 ^= ROL32(temp, 24); + + t1 = td[s1 & 0xFF]; + temp = td[(s0 >> 8) & 0xFF]; + t1 ^= ROL32(temp, 8); + temp = td[(s3 >> 16) & 0xFF]; + t1 ^= ROL32(temp, 16); + temp = td[(s2 >> 24) & 0xFF]; + t1 ^= ROL32(temp, 24); + + t2 = td[s2 & 0xFF]; + temp = td[(s1 >> 8) & 0xFF]; + t2 ^= ROL32(temp, 8); + temp = td[(s0 >> 16) & 0xFF]; + t2 ^= ROL32(temp, 16); + temp = td[(s3 >> 24) & 0xFF]; + t2 ^= ROL32(temp, 24); + + t3 = td[s3 & 0xFF]; + temp = td[(s2 >> 8) & 0xFF]; + t3 ^= ROL32(temp, 8); + temp = td[(s1 >> 16) & 0xFF]; + t3 ^= ROL32(temp, 16); + temp = td[(s0 >> 24) & 0xFF]; + t3 ^= ROL32(temp, 24); + + //Round key addition + s0 = t0 ^ context->dk[i * 4]; + s1 = t1 ^ context->dk[i * 4 + 1]; + s2 = t2 ^ context->dk[i * 4 + 2]; + s3 = t3 ^ context->dk[i * 4 + 3]; + } + + //The last round differs slightly from the first rounds + t0 = isbox[s0 & 0xFF]; + t0 |= isbox[(s3 >> 8) & 0xFF] << 8; + t0 |= isbox[(s2 >> 16) & 0xFF] << 16; + t0 |= isbox[(s1 >> 24) & 0xFF] << 24; + + t1 = isbox[s1 & 0xFF]; + t1 |= isbox[(s0 >> 8) & 0xFF] << 8; + t1 |= isbox[(s3 >> 16) & 0xFF] << 16; + t1 |= isbox[(s2 >> 24) & 0xFF] << 24; + + t2 = isbox[s2 & 0xFF]; + t2 |= isbox[(s1 >> 8) & 0xFF] << 8; + t2 |= isbox[(s0 >> 16) & 0xFF] << 16; + t2 |= isbox[(s3 >> 24) & 0xFF] << 24; + + t3 = isbox[s3 & 0xFF]; + t3 |= isbox[(s2 >> 8) & 0xFF] << 8; + t3 |= isbox[(s1 >> 16) & 0xFF] << 16; + t3 |= isbox[(s0 >> 24) & 0xFF] << 24; + + //Last round key addition + s0 = t0 ^ context->dk[0]; + s1 = t1 ^ context->dk[1]; + s2 = t2 ^ context->dk[2]; + s3 = t3 ^ context->dk[3]; + + //The final state is then copied to the output + STORE32LE(s0, output + 0); + STORE32LE(s1, output + 4); + STORE32LE(s2, output + 8); + STORE32LE(s3, output + 12); +} + + +/** + * @brief Release AES context + * @param[in] context Pointer to the AES context + **/ + +__weak_func void aesDeinit(AesContext *context) +{ + //Clear AES context + osMemset(context, 0, sizeof(AesContext)); +} + +#endif diff --git a/deps/cyclone/cpu_endian.c b/deps/cyclone/cpu_endian.c new file mode 100644 index 00000000..fd49899c --- /dev/null +++ b/deps/cyclone/cpu_endian.c @@ -0,0 +1,151 @@ +/** + * @file cpu_endian.c + * @brief Byte order conversion + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +//Dependencies +#include "cpu_endian.h" + + +/** + * @brief Reverse the byte order of a 16-bit word + * @param[in] value 16-bit value + * @return 16-bit value with byte order swapped + **/ + +uint16_t swapInt16(uint16_t value) +{ + return SWAPINT16(value); +} + + +/** + * @brief Reverse the byte order of a 32-bit word + * @param[in] value 32-bit value + * @return 32-bit value with byte order swapped + **/ + +uint32_t swapInt32(uint32_t value) +{ + return SWAPINT32(value); +} + + +/** + * @brief Reverse the byte order of a 64-bit word + * @param[in] value 64-bit value + * @return 64-bit value with byte order swapped + **/ + +uint64_t swapInt64(uint64_t value) +{ + return SWAPINT64(value); +} + + +/** + * @brief Reverse bit order in a 4-bit word + * @param[in] value 4-bit value + * @return 4-bit value with bit order reversed + **/ + +uint8_t reverseInt4(uint8_t value) +{ + value = ((value & 0x0C) >> 2) | ((value & 0x03) << 2); + value = ((value & 0x0A) >> 1) | ((value & 0x05) << 1); + + return value; +} + + +/** + * @brief Reverse bit order in a byte + * @param[in] value 8-bit value + * @return 8-bit value with bit order reversed + **/ + +uint8_t reverseInt8(uint8_t value) +{ + value = ((value & 0xF0) >> 4) | ((value & 0x0F) << 4); + value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2); + value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1); + + return value; +} + + +/** + * @brief Reverse bit order in a 16-bit word + * @param[in] value 16-bit value + * @return 16-bit value with bit order reversed + **/ + +uint16_t reverseInt16(uint16_t value) +{ + value = ((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8); + value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4); + value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2); + value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1); + + return value; +} + + +/** + * @brief Reverse bit order in a 32-bit word + * @param[in] value 32-bit value + * @return 32-bit value with bit order reversed + **/ + +uint32_t reverseInt32(uint32_t value) +{ + value = ((value & 0xFFFF0000UL) >> 16) | ((value & 0x0000FFFFUL) << 16); + value = ((value & 0xFF00FF00UL) >> 8) | ((value & 0x00FF00FFUL) << 8); + value = ((value & 0xF0F0F0F0UL) >> 4) | ((value & 0x0F0F0F0FUL) << 4); + value = ((value & 0xCCCCCCCCUL) >> 2) | ((value & 0x33333333UL) << 2); + value = ((value & 0xAAAAAAAAUL) >> 1) | ((value & 0x55555555UL) << 1); + + return value; +} + + +/** + * @brief Reverse bit order in a 64-bit word + * @param[in] value 64-bit value + * @return 64-bit value with bit order reversed + **/ + +uint64_t reverseInt64(uint64_t value) +{ + value = ((value & 0xFFFFFFFF00000000ULL) >> 32) | ((value & 0x00000000FFFFFFFFULL) << 32); + value = ((value & 0xFFFF0000FFFF0000ULL) >> 16) | ((value & 0x0000FFFF0000FFFFULL) << 16); + value = ((value & 0xFF00FF00FF00FF00ULL) >> 8) | ((value & 0x00FF00FF00FF00FFULL) << 8); + value = ((value & 0xF0F0F0F0F0F0F0F0ULL) >> 4) | ((value & 0x0F0F0F0F0F0F0F0FULL) << 4); + value = ((value & 0xCCCCCCCCCCCCCCCCULL) >> 2) | ((value & 0x3333333333333333ULL) << 2); + value = ((value & 0xAAAAAAAAAAAAAAAAULL) >> 1) | ((value & 0x5555555555555555ULL) << 1); + + return value; +} diff --git a/deps/cyclone/ecb.c b/deps/cyclone/ecb.c new file mode 100644 index 00000000..83cd5802 --- /dev/null +++ b/deps/cyclone/ecb.c @@ -0,0 +1,116 @@ +/** + * @file ecb.c + * @brief Electronic Codebook (ECB) mode + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @section Description + * + * The Electronic Codebook (ECB) mode is a confidentiality mode that features, + * for a given key, the assignment of a fixed ciphertext block to each + * plaintext block, analogous to the assignment of code words in a codebook. + * Refer to SP 800-38A for more details + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "cipher_modes/ecb.h" + +//Check crypto library configuration +#if (ECB_SUPPORT == ENABLED) + + +/** + * @brief ECB encryption + * @param[in] cipher Cipher algorithm + * @param[in] context Cipher algorithm context + * @param[in] p Plaintext to be encrypted + * @param[out] c Ciphertext resulting from the encryption + * @param[in] length Total number of data bytes to be encrypted + * @return Error code + **/ + +__weak_func error_t ecbEncrypt(const CipherAlgo *cipher, void *context, + const uint8_t *p, uint8_t *c, size_t length) +{ + //ECB mode operates in a block-by-block fashion + while(length >= cipher->blockSize) + { + //Encrypt current block + cipher->encryptBlock(context, p, c); + + //Next block + p += cipher->blockSize; + c += cipher->blockSize; + length -= cipher->blockSize; + } + + //The plaintext must be a multiple of the block size + if(length != 0) + return ERROR_INVALID_LENGTH; + + //Successful encryption + return NO_ERROR; +} + + +/** + * @brief ECB decryption + * @param[in] cipher Cipher algorithm + * @param[in] context Cipher algorithm context + * @param[in] c Ciphertext to be decrypted + * @param[out] p Plaintext resulting from the decryption + * @param[in] length Total number of data bytes to be decrypted + * @return Error code + **/ + +__weak_func error_t ecbDecrypt(const CipherAlgo *cipher, void *context, + const uint8_t *c, uint8_t *p, size_t length) +{ + //ECB mode operates in a block-by-block fashion + while(length >= cipher->blockSize) + { + //Decrypt current block + cipher->decryptBlock(context, c, p); + + //Next block + c += cipher->blockSize; + p += cipher->blockSize; + length -= cipher->blockSize; + } + + //The ciphertext must be a multiple of the block size + if(length != 0) + return ERROR_INVALID_LENGTH; + + //Successful encryption + return NO_ERROR; +} + +#endif diff --git a/deps/cyclone/gcm.c b/deps/cyclone/gcm.c new file mode 100644 index 00000000..22cadbd8 --- /dev/null +++ b/deps/cyclone/gcm.c @@ -0,0 +1,629 @@ +/** + * @file gcm.c + * @brief Galois/Counter Mode (GCM) + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @section Description + * + * The Galois/Counter Mode (GCM) is an authenticated encryption algorithm + * designed to provide both data authenticity (integrity) and confidentiality. + * Refer to SP 800-38D for more details + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "aead/gcm.h" + +//Check crypto library configuration +#if (GCM_SUPPORT == ENABLED) + +//Reduction table +static const uint32_t r[GCM_TABLE_N] = +{ +#if (GCM_TABLE_W == 4) + 0x00000000, 0x1C200000, 0x38400000, 0x24600000, 0x70800000, 0x6CA00000, 0x48C00000, 0x54E00000, + 0xE1000000, 0xFD200000, 0xD9400000, 0xC5600000, 0x91800000, 0x8DA00000, 0xA9C00000, 0xB5E00000 +#else + 0x00000000, 0x01C20000, 0x03840000, 0x02460000, 0x07080000, 0x06CA0000, 0x048C0000, 0x054E0000, + 0x0E100000, 0x0FD20000, 0x0D940000, 0x0C560000, 0x09180000, 0x08DA0000, 0x0A9C0000, 0x0B5E0000, + 0x1C200000, 0x1DE20000, 0x1FA40000, 0x1E660000, 0x1B280000, 0x1AEA0000, 0x18AC0000, 0x196E0000, + 0x12300000, 0x13F20000, 0x11B40000, 0x10760000, 0x15380000, 0x14FA0000, 0x16BC0000, 0x177E0000, + 0x38400000, 0x39820000, 0x3BC40000, 0x3A060000, 0x3F480000, 0x3E8A0000, 0x3CCC0000, 0x3D0E0000, + 0x36500000, 0x37920000, 0x35D40000, 0x34160000, 0x31580000, 0x309A0000, 0x32DC0000, 0x331E0000, + 0x24600000, 0x25A20000, 0x27E40000, 0x26260000, 0x23680000, 0x22AA0000, 0x20EC0000, 0x212E0000, + 0x2A700000, 0x2BB20000, 0x29F40000, 0x28360000, 0x2D780000, 0x2CBA0000, 0x2EFC0000, 0x2F3E0000, + 0x70800000, 0x71420000, 0x73040000, 0x72C60000, 0x77880000, 0x764A0000, 0x740C0000, 0x75CE0000, + 0x7E900000, 0x7F520000, 0x7D140000, 0x7CD60000, 0x79980000, 0x785A0000, 0x7A1C0000, 0x7BDE0000, + 0x6CA00000, 0x6D620000, 0x6F240000, 0x6EE60000, 0x6BA80000, 0x6A6A0000, 0x682C0000, 0x69EE0000, + 0x62B00000, 0x63720000, 0x61340000, 0x60F60000, 0x65B80000, 0x647A0000, 0x663C0000, 0x67FE0000, + 0x48C00000, 0x49020000, 0x4B440000, 0x4A860000, 0x4FC80000, 0x4E0A0000, 0x4C4C0000, 0x4D8E0000, + 0x46D00000, 0x47120000, 0x45540000, 0x44960000, 0x41D80000, 0x401A0000, 0x425C0000, 0x439E0000, + 0x54E00000, 0x55220000, 0x57640000, 0x56A60000, 0x53E80000, 0x522A0000, 0x506C0000, 0x51AE0000, + 0x5AF00000, 0x5B320000, 0x59740000, 0x58B60000, 0x5DF80000, 0x5C3A0000, 0x5E7C0000, 0x5FBE0000, + 0xE1000000, 0xE0C20000, 0xE2840000, 0xE3460000, 0xE6080000, 0xE7CA0000, 0xE58C0000, 0xE44E0000, + 0xEF100000, 0xEED20000, 0xEC940000, 0xED560000, 0xE8180000, 0xE9DA0000, 0xEB9C0000, 0xEA5E0000, + 0xFD200000, 0xFCE20000, 0xFEA40000, 0xFF660000, 0xFA280000, 0xFBEA0000, 0xF9AC0000, 0xF86E0000, + 0xF3300000, 0xF2F20000, 0xF0B40000, 0xF1760000, 0xF4380000, 0xF5FA0000, 0xF7BC0000, 0xF67E0000, + 0xD9400000, 0xD8820000, 0xDAC40000, 0xDB060000, 0xDE480000, 0xDF8A0000, 0xDDCC0000, 0xDC0E0000, + 0xD7500000, 0xD6920000, 0xD4D40000, 0xD5160000, 0xD0580000, 0xD19A0000, 0xD3DC0000, 0xD21E0000, + 0xC5600000, 0xC4A20000, 0xC6E40000, 0xC7260000, 0xC2680000, 0xC3AA0000, 0xC1EC0000, 0xC02E0000, + 0xCB700000, 0xCAB20000, 0xC8F40000, 0xC9360000, 0xCC780000, 0xCDBA0000, 0xCFFC0000, 0xCE3E0000, + 0x91800000, 0x90420000, 0x92040000, 0x93C60000, 0x96880000, 0x974A0000, 0x950C0000, 0x94CE0000, + 0x9F900000, 0x9E520000, 0x9C140000, 0x9DD60000, 0x98980000, 0x995A0000, 0x9B1C0000, 0x9ADE0000, + 0x8DA00000, 0x8C620000, 0x8E240000, 0x8FE60000, 0x8AA80000, 0x8B6A0000, 0x892C0000, 0x88EE0000, + 0x83B00000, 0x82720000, 0x80340000, 0x81F60000, 0x84B80000, 0x857A0000, 0x873C0000, 0x86FE0000, + 0xA9C00000, 0xA8020000, 0xAA440000, 0xAB860000, 0xAEC80000, 0xAF0A0000, 0xAD4C0000, 0xAC8E0000, + 0xA7D00000, 0xA6120000, 0xA4540000, 0xA5960000, 0xA0D80000, 0xA11A0000, 0xA35C0000, 0xA29E0000, + 0xB5E00000, 0xB4220000, 0xB6640000, 0xB7A60000, 0xB2E80000, 0xB32A0000, 0xB16C0000, 0xB0AE0000, + 0xBBF00000, 0xBA320000, 0xB8740000, 0xB9B60000, 0xBCF80000, 0xBD3A0000, 0xBF7C0000, 0xBEBE0000 +#endif +}; + + +/** + * @brief Initialize GCM context + * @param[in] context Pointer to the GCM context + * @param[in] cipherAlgo Cipher algorithm + * @param[in] cipherContext Pointer to the cipher algorithm context + * @return Error code + **/ + +__weak_func error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo, + void *cipherContext) +{ + uint_t i; + uint_t j; + uint32_t c; + uint32_t h[4]; + + //Check parameters + if(context == NULL || cipherAlgo == NULL || cipherContext == NULL) + return ERROR_INVALID_PARAMETER; + + //GCM supports only symmetric block ciphers whose block size is 128 bits + if(cipherAlgo->type != CIPHER_ALGO_TYPE_BLOCK || cipherAlgo->blockSize != 16) + return ERROR_INVALID_PARAMETER; + + //Save cipher algorithm context + context->cipherAlgo = cipherAlgo; + context->cipherContext = cipherContext; + + //Let H = 0 + h[0] = 0; + h[1] = 0; + h[2] = 0; + h[3] = 0; + + //Generate the hash subkey H + context->cipherAlgo->encryptBlock(context->cipherContext, (uint8_t *) h, + (uint8_t *) h); + + //Pre-compute M(0) = H * 0 + j = GCM_REVERSE_BITS(0); + context->m[j][0] = 0; + context->m[j][1] = 0; + context->m[j][2] = 0; + context->m[j][3] = 0; + + //Pre-compute M(1) = H * 1 + j = GCM_REVERSE_BITS(1); + context->m[j][0] = betoh32(h[3]); + context->m[j][1] = betoh32(h[2]); + context->m[j][2] = betoh32(h[1]); + context->m[j][3] = betoh32(h[0]); + + //Pre-compute all multiples of H (Shoup's method) + for(i = 2; i < GCM_TABLE_N; i++) + { + //Odd value? + if((i & 1) != 0) + { + //Compute M(i) = M(i - 1) + H + j = GCM_REVERSE_BITS(i - 1); + h[0] = context->m[j][0]; + h[1] = context->m[j][1]; + h[2] = context->m[j][2]; + h[3] = context->m[j][3]; + + //An addition in GF(2^128) is identical to a bitwise exclusive-OR + //operation + j = GCM_REVERSE_BITS(1); + h[0] ^= context->m[j][0]; + h[1] ^= context->m[j][1]; + h[2] ^= context->m[j][2]; + h[3] ^= context->m[j][3]; + } + else + { + //Compute M(i) = M(i / 2) * x + j = GCM_REVERSE_BITS(i / 2); + h[0] = context->m[j][0]; + h[1] = context->m[j][1]; + h[2] = context->m[j][2]; + h[3] = context->m[j][3]; + + //The multiplication of a polynomial by x in GF(2^128) corresponds + //to a shift of indices + c = h[0] & 0x01; + h[0] = (h[0] >> 1) | (h[1] << 31); + h[1] = (h[1] >> 1) | (h[2] << 31); + h[2] = (h[2] >> 1) | (h[3] << 31); + h[3] >>= 1; + + //If the highest term of the result is equal to one, then perform + //reduction + h[3] ^= r[GCM_REVERSE_BITS(1)] & ~(c - 1); + } + + //Save M(i) + j = GCM_REVERSE_BITS(i); + context->m[j][0] = h[0]; + context->m[j][1] = h[1]; + context->m[j][2] = h[2]; + context->m[j][3] = h[3]; + } + + //Successful initialization + return NO_ERROR; +} + + +/** + * @brief Authenticated encryption using GCM + * @param[in] context Pointer to the GCM context + * @param[in] iv Initialization vector + * @param[in] ivLen Length of the initialization vector + * @param[in] a Additional authenticated data + * @param[in] aLen Length of the additional data + * @param[in] p Plaintext to be encrypted + * @param[out] c Ciphertext resulting from the encryption + * @param[in] length Total number of data bytes to be encrypted + * @param[out] t Authentication tag + * @param[in] tLen Length of the authentication tag + * @return Error code + **/ + +__weak_func error_t gcmEncrypt(GcmContext *context, const uint8_t *iv, + size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p, + uint8_t *c, size_t length, uint8_t *t, size_t tLen) +{ + size_t k; + size_t n; + uint8_t b[16]; + uint8_t j[16]; + uint8_t s[16]; + + //Make sure the GCM context is valid + if(context == NULL) + return ERROR_INVALID_PARAMETER; + + //The length of the IV shall meet SP 800-38D requirements + if(ivLen < 1) + return ERROR_INVALID_LENGTH; + + //Check the length of the authentication tag + if(tLen < 4 || tLen > 16) + return ERROR_INVALID_LENGTH; + + //Check whether the length of the IV is 96 bits + if(ivLen == 12) + { + //When the length of the IV is 96 bits, the padding string is appended + //to the IV to form the pre-counter block + osMemcpy(j, iv, 12); + STORE32BE(1, j + 12); + } + else + { + //Initialize GHASH calculation + osMemset(j, 0, 16); + + //Length of the IV + n = ivLen; + + //Process the initialization vector + while(n > 0) + { + //The IV is processed in a block-by-block fashion + k = MIN(n, 16); + + //Apply GHASH function + gcmXorBlock(j, j, iv, k); + gcmMul(context, j); + + //Next block + iv += k; + n -= k; + } + + //The string is appended with 64 additional 0 bits, followed by the + //64-bit representation of the length of the IV + osMemset(b, 0, 8); + STORE64BE(ivLen * 8, b + 8); + + //The GHASH function is applied to the resulting string to form the + //pre-counter block + gcmXorBlock(j, j, b, 16); + gcmMul(context, j); + } + + //Compute MSB(CIPH(J(0))) + context->cipherAlgo->encryptBlock(context->cipherContext, j, b); + osMemcpy(t, b, tLen); + + //Initialize GHASH calculation + osMemset(s, 0, 16); + //Length of the AAD + n = aLen; + + //Process AAD + while(n > 0) + { + //Additional data are processed in a block-by-block fashion + k = MIN(n, 16); + + //Apply GHASH function + gcmXorBlock(s, s, a, k); + gcmMul(context, s); + + //Next block + a += k; + n -= k; + } + + //Length of the plaintext + n = length; + + //Process plaintext + while(n > 0) + { + //The encryption operates in a block-by-block fashion + k = MIN(n, 16); + + //Increment counter + gcmIncCounter(j); + + //Encrypt plaintext + context->cipherAlgo->encryptBlock(context->cipherContext, j, b); + gcmXorBlock(c, p, b, k); + + //Apply GHASH function + gcmXorBlock(s, s, c, k); + gcmMul(context, s); + + //Next block + p += k; + c += k; + n -= k; + } + + //Append the 64-bit representation of the length of the AAD and the + //ciphertext + STORE64BE(aLen * 8, b); + STORE64BE(length * 8, b + 8); + + //The GHASH function is applied to the result to produce a single output + //block S + gcmXorBlock(s, s, b, 16); + gcmMul(context, s); + + //Let T = MSB(GCTR(J(0), S) + gcmXorBlock(t, t, s, tLen); + + //Successful encryption + return NO_ERROR; +} + + +/** + * @brief Authenticated decryption using GCM + * @param[in] context Pointer to the GCM context + * @param[in] iv Initialization vector + * @param[in] ivLen Length of the initialization vector + * @param[in] a Additional authenticated data + * @param[in] aLen Length of the additional data + * @param[in] c Ciphertext to be decrypted + * @param[out] p Plaintext resulting from the decryption + * @param[in] length Total number of data bytes to be decrypted + * @param[in] t Authentication tag + * @param[in] tLen Length of the authentication tag + * @return Error code + **/ + +__weak_func error_t gcmDecrypt(GcmContext *context, const uint8_t *iv, + size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c, + uint8_t *p, size_t length, const uint8_t *t, size_t tLen) +{ + uint8_t mask; + size_t k; + size_t n; + uint8_t b[16]; + uint8_t j[16]; + uint8_t r[16]; + uint8_t s[16]; + + //Make sure the GCM context is valid + if(context == NULL) + return ERROR_INVALID_PARAMETER; + + //The length of the IV shall meet SP 800-38D requirements + if(ivLen < 1) + return ERROR_INVALID_LENGTH; + + //Check the length of the authentication tag + if(tLen < 4 || tLen > 16) + return ERROR_INVALID_LENGTH; + + //Check whether the length of the IV is 96 bits + if(ivLen == 12) + { + //When the length of the IV is 96 bits, the padding string is appended + //to the IV to form the pre-counter block + osMemcpy(j, iv, 12); + STORE32BE(1, j + 12); + } + else + { + //Initialize GHASH calculation + osMemset(j, 0, 16); + + //Length of the IV + n = ivLen; + + //Process the initialization vector + while(n > 0) + { + //The IV is processed in a block-by-block fashion + k = MIN(n, 16); + + //Apply GHASH function + gcmXorBlock(j, j, iv, k); + gcmMul(context, j); + + //Next block + iv += k; + n -= k; + } + + //The string is appended with 64 additional 0 bits, followed by the + //64-bit representation of the length of the IV + osMemset(b, 0, 8); + STORE64BE(ivLen * 8, b + 8); + + //The GHASH function is applied to the resulting string to form the + //pre-counter block + gcmXorBlock(j, j, b, 16); + gcmMul(context, j); + } + + //Compute MSB(CIPH(J(0))) + context->cipherAlgo->encryptBlock(context->cipherContext, j, b); + osMemcpy(r, b, tLen); + + //Initialize GHASH calculation + osMemset(s, 0, 16); + //Length of the AAD + n = aLen; + + //Process AAD + while(n > 0) + { + //Additional data are processed in a block-by-block fashion + k = MIN(n, 16); + + //Apply GHASH function + gcmXorBlock(s, s, a, k); + gcmMul(context, s); + + //Next block + a += k; + n -= k; + } + + //Length of the ciphertext + n = length; + + //Process ciphertext + while(n > 0) + { + //The decryption operates in a block-by-block fashion + k = MIN(n, 16); + + //Apply GHASH function + gcmXorBlock(s, s, c, k); + gcmMul(context, s); + + //Increment counter + gcmIncCounter(j); + + //Decrypt ciphertext + context->cipherAlgo->encryptBlock(context->cipherContext, j, b); + gcmXorBlock(p, c, b, k); + + //Next block + c += k; + p += k; + n -= k; + } + + //Append the 64-bit representation of the length of the AAD and the + //ciphertext + STORE64BE(aLen * 8, b); + STORE64BE(length * 8, b + 8); + + //The GHASH function is applied to the result to produce a single output + //block S + gcmXorBlock(s, s, b, 16); + gcmMul(context, s); + + //Let R = MSB(GCTR(J(0), S)) + gcmXorBlock(r, r, s, tLen); + + //The calculated tag is bitwise compared to the received tag. The message + //is authenticated if and only if the tags match + for(mask = 0, n = 0; n < tLen; n++) + { + mask |= r[n] ^ t[n]; + } + + //Return status code + return (mask == 0) ? NO_ERROR : ERROR_FAILURE; +} + + +/** + * @brief Multiplication operation in GF(2^128) + * @param[in] context Pointer to the GCM context + * @param[in, out] x 16-byte block to be multiplied by H + **/ + +__weak_func void gcmMul(GcmContext *context, uint8_t *x) +{ + int_t i; + uint8_t b; + uint8_t c; + uint32_t z[4]; + + //Let Z = 0 + z[0] = 0; + z[1] = 0; + z[2] = 0; + z[3] = 0; + + //Fast table-driven implementation (Shoup's method) + for(i = 15; i >= 0; i--) + { +#if (GCM_TABLE_W == 4) + //Get the lower nibble + b = x[i] & 0x0F; + + //Multiply 4 bits at a time + c = z[0] & 0x0F; + z[0] = (z[0] >> 4) | (z[1] << 28); + z[1] = (z[1] >> 4) | (z[2] << 28); + z[2] = (z[2] >> 4) | (z[3] << 28); + z[3] >>= 4; + + z[0] ^= context->m[b][0]; + z[1] ^= context->m[b][1]; + z[2] ^= context->m[b][2]; + z[3] ^= context->m[b][3]; + + //Perform reduction + z[3] ^= r[c]; + + //Get the upper nibble + b = (x[i] >> 4) & 0x0F; + + //Multiply 4 bits at a time + c = z[0] & 0x0F; + z[0] = (z[0] >> 4) | (z[1] << 28); + z[1] = (z[1] >> 4) | (z[2] << 28); + z[2] = (z[2] >> 4) | (z[3] << 28); + z[3] >>= 4; + + z[0] ^= context->m[b][0]; + z[1] ^= context->m[b][1]; + z[2] ^= context->m[b][2]; + z[3] ^= context->m[b][3]; + + //Perform reduction + z[3] ^= r[c]; +#else + //Get current byte + b = x[i]; + + //Multiply 8 bits at a time + c = z[0] & 0xFF; + z[0] = (z[0] >> 8) | (z[1] << 24); + z[1] = (z[1] >> 8) | (z[2] << 24); + z[2] = (z[2] >> 8) | (z[3] << 24); + z[3] >>= 8; + + z[0] ^= context->m[b][0]; + z[1] ^= context->m[b][1]; + z[2] ^= context->m[b][2]; + z[3] ^= context->m[b][3]; + + //Perform reduction + z[3] ^= r[c]; +#endif + } + + //Save the result + STORE32BE(z[3], x); + STORE32BE(z[2], x + 4); + STORE32BE(z[1], x + 8); + STORE32BE(z[0], x + 12); +} + + +/** + * @brief XOR operation + * @param[out] x Block resulting from the XOR operation + * @param[in] a First block + * @param[in] b Second block + * @param[in] n Size of the block + **/ + +void gcmXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n) +{ + size_t i; + + //Perform XOR operation + for(i = 0; i < n; i++) + { + x[i] = a[i] ^ b[i]; + } +} + + +/** + * @brief Increment counter block + * @param[in,out] ctr Pointer to the counter block + **/ + +void gcmIncCounter(uint8_t *ctr) +{ + uint16_t temp; + + //The function increments the right-most 32 bits of the block. The remaining + //left-most 96 bits remain unchanged + temp = ctr[15] + 1; + ctr[15] = temp & 0xFF; + temp = (temp >> 8) + ctr[14]; + ctr[14] = temp & 0xFF; + temp = (temp >> 8) + ctr[13]; + ctr[13] = temp & 0xFF; + temp = (temp >> 8) + ctr[12]; + ctr[12] = temp & 0xFF; +} + +#endif diff --git a/deps/cyclone/hkdf.c b/deps/cyclone/hkdf.c new file mode 100644 index 00000000..0c8c9124 --- /dev/null +++ b/deps/cyclone/hkdf.c @@ -0,0 +1,226 @@ +/** + * @file hkdf.c + * @brief HKDF (HMAC-based Key Derivation Function) + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @section Description + * + * HKDF is a simple HMAC-based key derivation function which can be used as a + * building block in various protocols and applications. Refer to RFC 5869 for + * more details + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "kdf/hkdf.h" +#include "mac/hmac.h" + +//Check crypto library configuration +#if (HKDF_SUPPORT == ENABLED) + + +/** + * @brief HKDF key derivation function + * @param[in] hash Underlying hash function + * @param[in] ikm input keying material + * @param[in] ikmLen Length in the input keying material + * @param[in] salt Optional salt value (a non-secret random value) + * @param[in] saltLen Length of the salt + * @param[in] info Optional application specific information + * @param[in] infoLen Length of the application specific information + * @param[out] okm output keying material + * @param[in] okmLen Length of the output keying material + * @return Error code + **/ + +error_t hkdf(const HashAlgo *hash, const uint8_t *ikm, size_t ikmLen, + const uint8_t *salt, size_t saltLen, const uint8_t *info, size_t infoLen, + uint8_t *okm, size_t okmLen) +{ + error_t error; + uint8_t prk[MAX_HASH_DIGEST_SIZE]; + + //Perform HKDF extract step + error = hkdfExtract(hash, ikm, ikmLen, salt, saltLen, prk); + + //Check status code + if(!error) + { + //Perform HKDF expand step + error = hkdfExpand(hash, prk, hash->digestSize, info, infoLen, + okm, okmLen); + } + + //Return status code + return error; +} + + +/** + * @brief HKDF extract step + * @param[in] hash Underlying hash function + * @param[in] ikm input keying material + * @param[in] ikmLen Length in the input keying material + * @param[in] salt Optional salt value (a non-secret random value) + * @param[in] saltLen Length of the salt + * @param[out] prk Pseudorandom key + * @return Error code + **/ + +error_t hkdfExtract(const HashAlgo *hash, const uint8_t *ikm, size_t ikmLen, + const uint8_t *salt, size_t saltLen, uint8_t *prk) +{ +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + HmacContext *hmacContext; +#else + HmacContext hmacContext[1]; +#endif + + //Check parameters + if(hash == NULL || ikm == NULL || prk == NULL) + return ERROR_INVALID_PARAMETER; + + //The salt parameter is optional + if(salt == NULL && saltLen != 0) + return ERROR_INVALID_PARAMETER; + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Allocate a memory buffer to hold the HMAC context + hmacContext = cryptoAllocMem(sizeof(HmacContext)); + //Failed to allocate memory? + if(hmacContext == NULL) + return ERROR_OUT_OF_MEMORY; +#endif + + //The salt parameter is optional + if(salt == NULL) + { + //If the salt is not provided, it is set to a string of HashLen zeros + osMemset(hmacContext->digest, 0, hash->digestSize); + salt = hmacContext->digest; + saltLen = hash->digestSize; + } + + //Compute PRK = HMAC-Hash(salt, IKM) + hmacInit(hmacContext, hash, salt, saltLen); + hmacUpdate(hmacContext, ikm, ikmLen); + hmacFinal(hmacContext, prk); + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Free previously allocated memory + cryptoFreeMem(hmacContext); +#endif + + //Successful processing + return NO_ERROR; +} + + +/** + * @brief HKDF expand step + * @param[in] hash Underlying hash function + * @param[in] prk Pseudorandom key + * @param[in] prkLen Length of the pseudorandom key + * @param[in] info Optional application specific information + * @param[in] infoLen Length of the application specific information + * @param[out] okm output keying material + * @param[in] okmLen Length of the output keying material + * @return Error code + **/ + +error_t hkdfExpand(const HashAlgo *hash, const uint8_t *prk, size_t prkLen, + const uint8_t *info, size_t infoLen, uint8_t *okm, size_t okmLen) +{ + uint8_t i; + size_t tLen; + uint8_t t[MAX_HASH_DIGEST_SIZE]; +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + HmacContext *hmacContext; +#else + HmacContext hmacContext[1]; +#endif + + //Check parameters + if(hash == NULL || prk == NULL || okm == NULL) + return ERROR_INVALID_PARAMETER; + + //The application specific information parameter is optional + if(info == NULL && infoLen != 0) + return ERROR_INVALID_PARAMETER; + + //PRK must be at least HashLen octets + if(prkLen < hash->digestSize) + return ERROR_INVALID_LENGTH; + + //Check the length of the output keying material + if(okmLen > (255 * hash->digestSize)) + return ERROR_INVALID_LENGTH; + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Allocate a memory buffer to hold the HMAC context + hmacContext = cryptoAllocMem(sizeof(HmacContext)); + //Failed to allocate memory? + if(hmacContext == NULL) + return ERROR_OUT_OF_MEMORY; +#endif + + //T(0) is an empty string (zero length) + tLen = 0; + + //Iterate as many times as required + for(i = 1; okmLen > 0; i++) + { + //Compute T(i) = HMAC-Hash(PRK, T(i-1) | info | i) + hmacInit(hmacContext, hash, prk, prkLen); + hmacUpdate(hmacContext, t, tLen); + hmacUpdate(hmacContext, info, infoLen); + hmacUpdate(hmacContext, &i, sizeof(i)); + hmacFinal(hmacContext, t); + + //Number of octets in the current block + tLen = MIN(okmLen, hash->digestSize); + //Save the resulting block + osMemcpy(okm, t, tLen); + + //Point to the next block + okm += tLen; + okmLen -= tLen; + } + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Free previously allocated memory + cryptoFreeMem(hmacContext); +#endif + + //Successful processing + return NO_ERROR; +} + +#endif diff --git a/deps/cyclone/hmac.c b/deps/cyclone/hmac.c new file mode 100644 index 00000000..6bfb582f --- /dev/null +++ b/deps/cyclone/hmac.c @@ -0,0 +1,303 @@ +/** + * @file hmac.c + * @brief HMAC (Keyed-Hashing for Message Authentication) + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @section Description + * + * HMAC is a mechanism for message authentication using cryptographic hash + * functions. HMAC can be used with any iterative cryptographic hash + * function (MD5, SHA-1 or SHA-256) in combination with a secret shared + * key. Refer to RFC 2104 for more details + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "mac/hmac.h" + +//Check crypto library configuration +#if (HMAC_SUPPORT == ENABLED) + +//HMAC with MD5 OID (1.3.6.1.5.5.8.1.1) +const uint8_t HMAC_WITH_MD5_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x01}; +//HMAC with Tiger OID (1.3.6.1.5.5.8.1.3) +const uint8_t HMAC_WITH_TIGER_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x03}; +//HMAC with RIPEMD-160 OID (1.3.6.1.5.5.8.1.4) +const uint8_t HMAC_WITH_RIPEMD160_OID[8] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x04}; +//HMAC with SHA-1 OID (1.2.840.113549.2.7) +const uint8_t HMAC_WITH_SHA1_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x07}; +//HMAC with SHA-224 OID (1.2.840.113549.2.8) +const uint8_t HMAC_WITH_SHA224_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x08}; +//HMAC with SHA-256 OID (1.2.840.113549.2.9) +const uint8_t HMAC_WITH_SHA256_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x09}; +//HMAC with SHA-384 OID (1.2.840.113549.2.10) +const uint8_t HMAC_WITH_SHA384_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x0A}; +//HMAC with SHA-512 OID (1.2.840.113549.2.11) +const uint8_t HMAC_WITH_SHA512_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x0B}; +//HMAC with SHA-512/224 OID (1.2.840.113549.2.12) +const uint8_t HMAC_WITH_SHA512_224_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x0C}; +//HMAC with SHA-512/256 OID (1.2.840.113549.2.13) +const uint8_t HMAC_WITH_SHA512_256_OID[8] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x0D}; +//HMAC with SHA-3-224 OID (2.16.840.1.101.3.4.2.13) +const uint8_t HMAC_WITH_SHA3_224_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0D}; +//HMAC with SHA-3-256 OID (2.16.840.1.101.3.4.2.14) +const uint8_t HMAC_WITH_SHA3_256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0E}; +//HMAC with SHA-3-384 OID (2.16.840.1.101.3.4.2.15) +const uint8_t HMAC_WITH_SHA3_384_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0F}; +//HMAC with SHA-3-512 OID (2.16.840.1.101.3.4.2.16) +const uint8_t HMAC_WITH_SHA3_512_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x10}; +//HMAC with SM3 OID (1.2.156.10197.1.401.3.1) +const uint8_t HMAC_WITH_SM3_OID[10] = {0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x82, 0x91, 0x03, 0x01}; + + +/** + * @brief Compute HMAC using the specified hash function + * @param[in] hash Hash algorithm used to compute HMAC + * @param[in] key Key to use in the hash algorithm + * @param[in] keyLen Length of the key + * @param[in] data The input data for which to compute the hash code + * @param[in] dataLen Length of the input data + * @param[out] digest The computed HMAC value + * @return Error code + **/ + +__weak_func error_t hmacCompute(const HashAlgo *hash, const void *key, size_t keyLen, + const void *data, size_t dataLen, uint8_t *digest) +{ + error_t error; +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + HmacContext *context; +#else + HmacContext context[1]; +#endif + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Allocate a memory buffer to hold the HMAC context + context = cryptoAllocMem(sizeof(HmacContext)); + //Failed to allocate memory? + if(context == NULL) + return ERROR_OUT_OF_MEMORY; +#endif + + //Initialize the HMAC context + error = hmacInit(context, hash, key, keyLen); + + //Check status code + if(!error) + { + //Digest the message + hmacUpdate(context, data, dataLen); + //Finalize the HMAC computation + hmacFinal(context, digest); + } + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Free previously allocated memory + cryptoFreeMem(context); +#endif + + //Return status code + return error; +} + + +/** + * @brief Initialize HMAC calculation + * @param[in] context Pointer to the HMAC context to initialize + * @param[in] hash Hash algorithm used to compute HMAC + * @param[in] key Key to use in the hash algorithm + * @param[in] keyLen Length of the key + * @return Error code + **/ + +__weak_func error_t hmacInit(HmacContext *context, const HashAlgo *hash, + const void *key, size_t keyLen) +{ + uint_t i; + + //Check parameters + if(context == NULL || hash == NULL) + return ERROR_INVALID_PARAMETER; + + //Make sure the supplied key is valid + if(key == NULL && keyLen != 0) + return ERROR_INVALID_PARAMETER; + + //Hash algorithm used to compute HMAC + context->hash = hash; + + //The key is longer than the block size? + if(keyLen > hash->blockSize) + { + //Initialize the hash function context + hash->init(&context->hashContext); + //Digest the original key + hash->update(&context->hashContext, key, keyLen); + //Finalize the message digest computation + hash->final(&context->hashContext, context->key); + + //Key is padded to the right with extra zeros + osMemset(context->key + hash->digestSize, 0, + hash->blockSize - hash->digestSize); + } + else + { + //Copy the key + osMemcpy(context->key, key, keyLen); + //Key is padded to the right with extra zeros + osMemset(context->key + keyLen, 0, hash->blockSize - keyLen); + } + + //XOR the resulting key with ipad + for(i = 0; i < hash->blockSize; i++) + { + context->key[i] ^= HMAC_IPAD; + } + + //Initialize context for the first pass + hash->init(&context->hashContext); + //Start with the inner pad + hash->update(&context->hashContext, context->key, hash->blockSize); + + //Successful initialization + return NO_ERROR; +} + + +/** + * @brief Update the HMAC context with a portion of the message being hashed + * @param[in] context Pointer to the HMAC context + * @param[in] data Pointer to the buffer being hashed + * @param[in] length Length of the buffer + **/ + +__weak_func void hmacUpdate(HmacContext *context, const void *data, size_t length) +{ + const HashAlgo *hash; + + //Hash algorithm used to compute HMAC + hash = context->hash; + //Digest the message (first pass) + hash->update(&context->hashContext, data, length); +} + + +/** + * @brief Finish the HMAC calculation + * @param[in] context Pointer to the HMAC context + * @param[out] digest Calculated HMAC value (optional parameter) + **/ + +__weak_func void hmacFinal(HmacContext *context, uint8_t *digest) +{ + uint_t i; + const HashAlgo *hash; + + //Hash algorithm used to compute HMAC + hash = context->hash; + //Finish the first pass + hash->final(&context->hashContext, context->digest); + + //XOR the original key with opad + for(i = 0; i < hash->blockSize; i++) + { + context->key[i] ^= HMAC_IPAD ^ HMAC_OPAD; + } + + //Initialize context for the second pass + hash->init(&context->hashContext); + //Start with outer pad + hash->update(&context->hashContext, context->key, hash->blockSize); + //Then digest the result of the first hash + hash->update(&context->hashContext, context->digest, hash->digestSize); + //Finish the second pass + hash->final(&context->hashContext, context->digest); + + //Copy the resulting HMAC value + if(digest != NULL) + { + osMemcpy(digest, context->digest, hash->digestSize); + } +} + + +/** + * @brief Release HMAC context + * @param[in] context Pointer to the HMAC context + **/ + +void hmacDeinit(HmacContext *context) +{ + //Make sure the HMAC context is valid + if(context != NULL) + { + //Clear HMAC context + osMemset(context, 0, sizeof(HmacContext)); + } +} + + +/** + * @brief Finish the HMAC calculation (no padding added) + * @param[in] context Pointer to the HMAC context + * @param[out] digest Calculated HMAC value (optional parameter) + **/ + +void hmacFinalRaw(HmacContext *context, uint8_t *digest) +{ + uint_t i; + const HashAlgo *hash; + + //Hash algorithm used to compute HMAC + hash = context->hash; + + //XOR the original key with opad + for(i = 0; i < hash->blockSize; i++) + { + context->key[i] ^= HMAC_IPAD ^ HMAC_OPAD; + } + + //Initialize context for the second pass + hash->init(&context->hashContext); + //Start with outer pad + hash->update(&context->hashContext, context->key, hash->blockSize); + //Then digest the result of the first hash + hash->update(&context->hashContext, context->digest, hash->digestSize); + //Finish the second pass + hash->final(&context->hashContext, context->digest); + + //Copy the resulting HMAC value + if(digest != NULL) + { + osMemcpy(digest, context->digest, hash->digestSize); + } +} + +#endif diff --git a/deps/cyclone/include/aead/gcm.h b/deps/cyclone/include/aead/gcm.h new file mode 100644 index 00000000..3d355e10 --- /dev/null +++ b/deps/cyclone/include/aead/gcm.h @@ -0,0 +1,92 @@ +/** + * @file gcm.h + * @brief Galois/Counter Mode (GCM) + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +#ifndef _GCM_H +#define _GCM_H + +//Dependencies +#include "core/crypto.h" + +//Precalculated table width, in bits +#ifndef GCM_TABLE_W + #define GCM_TABLE_W 4 +#elif (GCM_TABLE_W != 4 && GCM_TABLE_W != 8) + #error GCM_TABLE_W parameter is not valid +#endif + +//4-bit or 8-bit precalculated table? +#if (GCM_TABLE_W == 4) + #define GCM_TABLE_N 16 + #define GCM_REVERSE_BITS(n) reverseInt4(n) +#else + #define GCM_TABLE_N 256 + #define GCM_REVERSE_BITS(n) reverseInt8(n) +#endif + +//C++ guard +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief GCM context + **/ + +typedef struct +{ + const CipherAlgo *cipherAlgo; ///= 6010050) + #include +#endif + +//C++ guard +#ifdef __cplusplus +extern "C" { +#endif + +//Types +typedef char char_t; +typedef signed int int_t; +typedef unsigned int uint_t; + +#if !defined(R_TYPEDEFS_H) && !defined(USE_CHIBIOS_2) + typedef int bool_t; +#endif + +//ARM compiler? +#if defined(__CC_ARM) + #undef PRIu8 + #undef PRIu16 + #define PRIu8 "u" + #define PRIu16 "u" + #define PRIuSIZE "u" + #define PRIXSIZE "X" + #define PRIuTIME "lu" +//Microchip XC32 compiler? +#elif defined(__XC32) + #if defined(__C32_LEGACY_LIBC__) + #define PRIuSIZE "lu" + #define PRIXSIZE "lX" + #define PRIuTIME "lu" + #else + #define PRIuSIZE "u" + #define PRIXSIZE "X" + #define PRIuTIME "u" + #endif +//NXP MCUXpresso compiler? +#elif defined(__MCUXPRESSO) + #undef PRIu64 + #define PRIu64 "llu" + #define PRIuSIZE "u" + #define PRIXSIZE "X" + #define PRIuTIME "lu" +//NXP CodeWarrior compiler? +#elif defined(__CWCC__) + #define PRIu8 "u" + #define PRIu16 "u" + #define PRIu32 "u" + #define PRIx8 "x" + #define PRIx16 "x" + #define PRIx32 "x" + #define PRIX8 "X" + #define PRIX16 "X" + #define PRIX32 "X" + #define PRIuSIZE "u" + #define PRIXSIZE "X" + #define PRIuTIME "u" +//Espressif ESP-IDF compiler? +#elif defined(IDF_VER) + #undef PRIu8 + #undef PRIu16 + #undef PRIx8 + #undef PRIx16 + #undef PRIX8 + #undef PRIX16 + #define PRIu8 "u" + #define PRIu16 "u" + #define PRIx8 "x" + #define PRIx16 "x" + #define PRIX8 "X" + #define PRIX16 "X" + #define PRIuSIZE "u" + #define PRIXSIZE "X" + #define PRIuTIME "lu" +//Linux/FreeBSD GCC compiler +#elif defined(__linux__) || defined(__FreeBSD__) + #define PRIuSIZE "zu" + #define PRIXSIZE "zX" + #define PRIuTIME "lu" +//Win32 compiler? +#elif defined(_WIN32) + #define PRIuSIZE "Iu" + #define PRIXSIZE "IX" + #define PRIuTIME "lu" +//GCC compiler (with newlib-nano runtime library)? +#elif defined(__GNUC__) && defined(_NANO_FORMATTED_IO) && (_NANO_FORMATTED_IO != 0) + #undef PRIu8 + #undef PRIu16 + #undef PRIx8 + #undef PRIx16 + #undef PRIX8 + #undef PRIX16 + #define PRIu8 "u" + #define PRIu16 "u" + #define PRIx8 "x" + #define PRIx16 "x" + #define PRIX8 "X" + #define PRIX16 "X" + #define PRIuSIZE "u" + #define PRIXSIZE "X" + #define PRIuTIME "u" +//GCC compiler (with newlib-standard runtime library)? +#else + #define PRIuSIZE "u" + #define PRIXSIZE "X" + #define PRIuTIME "lu" +#endif + +//ARM compiler V6? +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + int vsnprintf(char *dest, size_t size, const char *format, va_list ap); + char *strtok_r(char *s, const char *delim, char **last); +//GCC compiler (for PowerPC architecture)? +#elif defined(__GNUC__) && defined(__PPC_EABI__) + typedef uint32_t time_t; + int strcasecmp(const char *s1, const char *s2); + int strncasecmp(const char *s1, const char *s2, size_t n); + char *strtok_r(char *s, const char *delim, char **last); +//GCC compiler? +#elif defined(__GNUC__) + int strcasecmp(const char *s1, const char *s2); + int strncasecmp(const char *s1, const char *s2, size_t n); + char *strtok_r(char *s, const char *delim, char **last); +//Tasking compiler? +#elif defined(__TASKING__) + char *strtok_r(char *s, const char *delim, char **last); +//Microchip XC32 compiler? +#elif defined(__XC32) + #define sprintf _sprintf + int sprintf(char *str, const char *format, ...); + int strcasecmp(const char *s1, const char *s2); + int strncasecmp(const char *s1, const char *s2, size_t n); + char *strtok_r(char *s, const char *delim, char **last); +//NXP CodeWarrior compiler? +#elif defined(__CWCC__) + typedef uint32_t time_t; + int strcasecmp(const char *s1, const char *s2); + int strncasecmp(const char *s1, const char *s2, size_t n); + char *strtok_r(char *s, const char *delim, char **last); +//Renesas CC-RX compiler? +#elif defined(__CCRX__) + int strcasecmp(const char *s1, const char *s2); + int strncasecmp(const char *s1, const char *s2, size_t n); + char *strtok_r(char *s, const char *delim, char **last); +//TI ARM compiler? +#elif defined(__TI_ARM__) + int strcasecmp(const char *s1, const char *s2); + int strncasecmp(const char *s1, const char *s2, size_t n); + char *strtok_r(char *s, const char *delim, char **last); +#endif + +//ARM compiler V6? +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #undef __packed_struct + #define __packed_struct struct __attribute__((packed)) + #undef __packed_union + #define __packed_union union __attribute__((packed)) +//GCC compiler? +#elif defined(__GNUC__) + #undef __packed_struct + #define __packed_struct struct __attribute__((__packed__)) + #undef __packed_union + #define __packed_union union __attribute__((__packed__)) +//ARM compiler? +#elif defined(__CC_ARM) + #pragma anon_unions + #undef __packed_struct + #define __packed_struct __packed struct + #undef __packed_union + #define __packed_union __packed union +//IAR compiler? +#elif defined(__IAR_SYSTEMS_ICC__) + #undef __packed_struct + #define __packed_struct __packed struct + #undef __packed_union + #define __packed_union __packed union +//Tasking compiler? +#elif defined(__TASKING__) + #undef __packed_struct + #define __packed_struct struct __packed__ + #undef __packed_union + #define __packed_union union __packed__ +//NXP CodeWarrior compiler? +#elif defined(__CWCC__) + #undef __packed_struct + #define __packed_struct struct + #undef __packed_union + #define __packed_union union +//Renesas CC-RX compiler? +#elif defined(__CCRX__) + #undef __packed_struct + #define __packed_struct struct + #undef __packed_union + #define __packed_union union +//TI ARM compiler? +#elif defined(__TI_ARM__) + #undef __packed_struct + #define __packed_struct struct __attribute__((__packed__)) + #undef __packed_union + #define __packed_union union __attribute__((__packed__)) +//Win32 compiler? +#elif defined(_WIN32) + #undef interface + #undef __packed_struct + #define __packed_struct struct + #undef __packed_union + #define __packed_union union +#endif + +#ifndef __weak_func + //ARM compiler V6? + #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __weak_func __attribute__((weak)) + //GCC compiler? + #elif defined(__GNUC__) + #define __weak_func __attribute__((weak)) + //ARM compiler? + #elif defined(__CC_ARM) + #define __weak_func __weak + //IAR compiler? + #elif defined(__IAR_SYSTEMS_ICC__) + #define __weak_func __weak + //Tasking compiler? + #elif defined(__TASKING__) + #define __weak_func __attribute__((weak)) + //NXP CodeWarrior compiler? + #elif defined(__CWCC__) + #define __weak_func + //Renesas CC-RX compiler? + #elif defined(__CCRX__) + #define __weak_func + //TI ARM compiler? + #elif defined(__TI_ARM__) + #define __weak_func __attribute__((weak)) + //Win32 compiler? + #elif defined(_WIN32) + #define __weak_func + #endif +#endif + +//C++ guard +#ifdef __cplusplus +} +#endif + +#endif diff --git a/deps/cyclone/include/core/crypto.h b/deps/cyclone/include/core/crypto.h new file mode 100644 index 00000000..e06aa3c8 --- /dev/null +++ b/deps/cyclone/include/core/crypto.h @@ -0,0 +1,1119 @@ +/** + * @file crypto.h + * @brief General definitions for cryptographic algorithms + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +#ifndef _CRYPTO_H +#define _CRYPTO_H + +//Dependencies +#include "os_port.h" +#include "crypto_config.h" +#include "crypto_legacy.h" +#include "cpu_endian.h" +#include "error.h" + + +/* + * CycloneCRYPTO Open is licensed under GPL version 2. In particular: + * + * - If you link your program to CycloneCRYPTO Open, the result is a derivative + * work that can only be distributed under the same GPL license terms. + * + * - If additions or changes to CycloneCRYPTO Open are made, the result is a + * derivative work that can only be distributed under the same license terms. + * + * - The GPL license requires that you make the source code available to + * whoever you make the binary available to. + * + * - If you sell or distribute a hardware product that runs CycloneCRYPTO Open, + * the GPL license requires you to provide public and full access to all + * source code on a nondiscriminatory basis. + * + * If you fully understand and accept the terms of the GPL license, then edit + * the os_port_config.h header and add the following directive: + * + * #define GPL_LICENSE_TERMS_ACCEPTED + */ + +#ifndef GPL_LICENSE_TERMS_ACCEPTED +#endif + +//Version string +#define CYCLONE_CRYPTO_VERSION_STRING "2.4.4" +//Major version +#define CYCLONE_CRYPTO_MAJOR_VERSION 2 +//Minor version +#define CYCLONE_CRYPTO_MINOR_VERSION 4 +//Revision number +#define CYCLONE_CRYPTO_REV_NUMBER 4 + +//Static memory allocation +#ifndef CRYPTO_STATIC_MEM_SUPPORT + #define CRYPTO_STATIC_MEM_SUPPORT DISABLED +#elif (CRYPTO_STATIC_MEM_SUPPORT != ENABLED && CRYPTO_STATIC_MEM_SUPPORT != DISABLED) + #error CRYPTO_STATIC_MEM_SUPPORT parameter is not valid +#endif + +//Multiple precision integer support +#ifndef MPI_SUPPORT + #define MPI_SUPPORT ENABLED +#elif (MPI_SUPPORT != ENABLED && MPI_SUPPORT != DISABLED) + #error MPI_SUPPORT parameter is not valid +#endif + +//Assembly optimizations for time-critical routines +#ifndef MPI_ASM_SUPPORT + #define MPI_ASM_SUPPORT DISABLED +#elif (MPI_ASM_SUPPORT != ENABLED && MPI_ASM_SUPPORT != DISABLED) + #error MPI_ASM_SUPPORT parameter is not valid +#endif + +//Base64 encoding support +#ifndef BASE64_SUPPORT + #define BASE64_SUPPORT ENABLED +#elif (BASE64_SUPPORT != ENABLED && BASE64_SUPPORT != DISABLED) + #error BASE64_SUPPORT parameter is not valid +#endif + +//Base64url encoding support +#ifndef BASE64URL_SUPPORT + #define BASE64URL_SUPPORT ENABLED +#elif (BASE64URL_SUPPORT != ENABLED && BASE64URL_SUPPORT != DISABLED) + #error BASE64URL_SUPPORT parameter is not valid +#endif + +//Radix64 encoding support +#ifndef RADIX64_SUPPORT + #define RADIX64_SUPPORT ENABLED +#elif (RADIX64_SUPPORT != ENABLED && RADIX64_SUPPORT != DISABLED) + #error RADIX64_SUPPORT parameter is not valid +#endif + +//MD2 hash support +#ifndef MD2_SUPPORT + #define MD2_SUPPORT DISABLED +#elif (MD2_SUPPORT != ENABLED && MD2_SUPPORT != DISABLED) + #error MD2_SUPPORT parameter is not valid +#endif + +//MD4 hash support +#ifndef MD4_SUPPORT + #define MD4_SUPPORT DISABLED +#elif (MD4_SUPPORT != ENABLED && MD4_SUPPORT != DISABLED) + #error MD4_SUPPORT parameter is not valid +#endif + +//MD5 hash support +#ifndef MD5_SUPPORT + #define MD5_SUPPORT DISABLED +#elif (MD5_SUPPORT != ENABLED && MD5_SUPPORT != DISABLED) + #error MD5_SUPPORT parameter is not valid +#endif + +//RIPEMD-128 hash support +#ifndef RIPEMD128_SUPPORT + #define RIPEMD128_SUPPORT DISABLED +#elif (RIPEMD128_SUPPORT != ENABLED && RIPEMD128_SUPPORT != DISABLED) + #error RIPEMD128_SUPPORT parameter is not valid +#endif + +//RIPEMD-160 hash support +#ifndef RIPEMD160_SUPPORT + #define RIPEMD160_SUPPORT DISABLED +#elif (RIPEMD160_SUPPORT != ENABLED && RIPEMD160_SUPPORT != DISABLED) + #error RIPEMD160_SUPPORT parameter is not valid +#endif + +//SHA-1 hash support +#ifndef SHA1_SUPPORT + #define SHA1_SUPPORT ENABLED +#elif (SHA1_SUPPORT != ENABLED && SHA1_SUPPORT != DISABLED) + #error SHA1_SUPPORT parameter is not valid +#endif + +//SHA-224 hash support +#ifndef SHA224_SUPPORT + #define SHA224_SUPPORT ENABLED +#elif (SHA224_SUPPORT != ENABLED && SHA224_SUPPORT != DISABLED) + #error SHA224_SUPPORT parameter is not valid +#endif + +//SHA-256 hash support +#ifndef SHA256_SUPPORT + #define SHA256_SUPPORT ENABLED +#elif (SHA256_SUPPORT != ENABLED && SHA256_SUPPORT != DISABLED) + #error SHA256_SUPPORT parameter is not valid +#endif + +//SHA-384 hash support +#ifndef SHA384_SUPPORT + #define SHA384_SUPPORT ENABLED +#elif (SHA384_SUPPORT != ENABLED && SHA384_SUPPORT != DISABLED) + #error SHA384_SUPPORT parameter is not valid +#endif + +//SHA-512 hash support +#ifndef SHA512_SUPPORT + #define SHA512_SUPPORT ENABLED +#elif (SHA512_SUPPORT != ENABLED && SHA512_SUPPORT != DISABLED) + #error SHA512_SUPPORT parameter is not valid +#endif + +//SHA-512/224 hash support +#ifndef SHA512_224_SUPPORT + #define SHA512_224_SUPPORT DISABLED +#elif (SHA512_224_SUPPORT != ENABLED && SHA512_224_SUPPORT != DISABLED) + #error SHA512_224_SUPPORT parameter is not valid +#endif + +//SHA-512/256 hash support +#ifndef SHA512_256_SUPPORT + #define SHA512_256_SUPPORT DISABLED +#elif (SHA512_256_SUPPORT != ENABLED && SHA512_256_SUPPORT != DISABLED) + #error SHA512_256_SUPPORT parameter is not valid +#endif + +//SHA3-224 hash support +#ifndef SHA3_224_SUPPORT + #define SHA3_224_SUPPORT DISABLED +#elif (SHA3_224_SUPPORT != ENABLED && SHA3_224_SUPPORT != DISABLED) + #error SHA3_224_SUPPORT parameter is not valid +#endif + +//SHA3-256 hash support +#ifndef SHA3_256_SUPPORT + #define SHA3_256_SUPPORT DISABLED +#elif (SHA3_256_SUPPORT != ENABLED && SHA3_256_SUPPORT != DISABLED) + #error SHA3_256_SUPPORT parameter is not valid +#endif + +//SHA3-384 hash support +#ifndef SHA3_384_SUPPORT + #define SHA3_384_SUPPORT DISABLED +#elif (SHA3_384_SUPPORT != ENABLED && SHA3_384_SUPPORT != DISABLED) + #error SHA3_384_SUPPORT parameter is not valid +#endif + +//SHA3-512 hash support +#ifndef SHA3_512_SUPPORT + #define SHA3_512_SUPPORT DISABLED +#elif (SHA3_512_SUPPORT != ENABLED && SHA3_512_SUPPORT != DISABLED) + #error SHA3_512_SUPPORT parameter is not valid +#endif + +//SHAKE support +#ifndef SHAKE_SUPPORT + #define SHAKE_SUPPORT DISABLED +#elif (SHAKE_SUPPORT != ENABLED && SHAKE_SUPPORT != DISABLED) + #error SHAKE_SUPPORT parameter is not valid +#endif + +//cSHAKE support +#ifndef CSHAKE_SUPPORT + #define CSHAKE_SUPPORT DISABLED +#elif (CSHAKE_SUPPORT != ENABLED && CSHAKE_SUPPORT != DISABLED) + #error CSHAKE_SUPPORT parameter is not valid +#endif + +//Keccak support +#ifndef KECCAK_SUPPORT + #define KECCAK_SUPPORT DISABLED +#elif (KECCAK_SUPPORT != ENABLED && KECCAK_SUPPORT != DISABLED) + #error KECCAK_SUPPORT parameter is not valid +#endif + +//BLAKE2b support +#ifndef BLAKE2B_SUPPORT + #define BLAKE2B_SUPPORT DISABLED +#elif (BLAKE2B_SUPPORT != ENABLED && BLAKE2B_SUPPORT != DISABLED) + #error BLAKE2B_SUPPORT parameter is not valid +#endif + +//BLAKE2b-160 hash support +#ifndef BLAKE2B160_SUPPORT + #define BLAKE2B160_SUPPORT DISABLED +#elif (BLAKE2B160_SUPPORT != ENABLED && BLAKE2B160_SUPPORT != DISABLED) + #error BLAKE2B160_SUPPORT parameter is not valid +#endif + +//BLAKE2b-256 hash support +#ifndef BLAKE2B256_SUPPORT + #define BLAKE2B256_SUPPORT DISABLED +#elif (BLAKE2B256_SUPPORT != ENABLED && BLAKE2B256_SUPPORT != DISABLED) + #error BLAKE2B256_SUPPORT parameter is not valid +#endif + +//BLAKE2b-384 hash support +#ifndef BLAKE2B384_SUPPORT + #define BLAKE2B384_SUPPORT DISABLED +#elif (BLAKE2B384_SUPPORT != ENABLED && BLAKE2B384_SUPPORT != DISABLED) + #error BLAKE2B384_SUPPORT parameter is not valid +#endif + +//BLAKE2b-512 hash support +#ifndef BLAKE2B512_SUPPORT + #define BLAKE2B512_SUPPORT DISABLED +#elif (BLAKE2B512_SUPPORT != ENABLED && BLAKE2B512_SUPPORT != DISABLED) + #error BLAKE2B512_SUPPORT parameter is not valid +#endif + +//BLAKE2s support +#ifndef BLAKE2S_SUPPORT + #define BLAKE2S_SUPPORT DISABLED +#elif (BLAKE2S_SUPPORT != ENABLED && BLAKE2S_SUPPORT != DISABLED) + #error BLAKE2S_SUPPORT parameter is not valid +#endif + +//BLAKE2s-128 hash support +#ifndef BLAKE2S128_SUPPORT + #define BLAKE2S128_SUPPORT DISABLED +#elif (BLAKE2S128_SUPPORT != ENABLED && BLAKE2S128_SUPPORT != DISABLED) + #error BLAKE2S128_SUPPORT parameter is not valid +#endif + +//BLAKE2s-160 hash support +#ifndef BLAKE2S160_SUPPORT + #define BLAKE2S160_SUPPORT DISABLED +#elif (BLAKE2S160_SUPPORT != ENABLED && BLAKE2S160_SUPPORT != DISABLED) + #error BLAKE2S160_SUPPORT parameter is not valid +#endif + +//BLAKE2s-224 hash support +#ifndef BLAKE2S224_SUPPORT + #define BLAKE2S224_SUPPORT DISABLED +#elif (BLAKE2S224_SUPPORT != ENABLED && BLAKE2S224_SUPPORT != DISABLED) + #error BLAKE2S224_SUPPORT parameter is not valid +#endif + +//BLAKE2s-256 hash support +#ifndef BLAKE2S256_SUPPORT + #define BLAKE2S256_SUPPORT DISABLED +#elif (BLAKE2S256_SUPPORT != ENABLED && BLAKE2S256_SUPPORT != DISABLED) + #error BLAKE2S256_SUPPORT parameter is not valid +#endif + +//SM3 hash support +#ifndef SM3_SUPPORT + #define SM3_SUPPORT DISABLED +#elif (SM3_SUPPORT != ENABLED && SM3_SUPPORT != DISABLED) + #error SM3_SUPPORT parameter is not valid +#endif + +//Tiger hash support +#ifndef TIGER_SUPPORT + #define TIGER_SUPPORT DISABLED +#elif (TIGER_SUPPORT != ENABLED && TIGER_SUPPORT != DISABLED) + #error TIGER_SUPPORT parameter is not valid +#endif + +//Whirlpool hash support +#ifndef WHIRLPOOL_SUPPORT + #define WHIRLPOOL_SUPPORT DISABLED +#elif (WHIRLPOOL_SUPPORT != ENABLED && WHIRLPOOL_SUPPORT != DISABLED) + #error WHIRLPOOL_SUPPORT parameter is not valid +#endif + +//CMAC support +#ifndef CMAC_SUPPORT + #define CMAC_SUPPORT DISABLED +#elif (CMAC_SUPPORT != ENABLED && CMAC_SUPPORT != DISABLED) + #error CMAC_SUPPORT parameter is not valid +#endif + +//HMAC support +#ifndef HMAC_SUPPORT + #define HMAC_SUPPORT ENABLED +#elif (HMAC_SUPPORT != ENABLED && HMAC_SUPPORT != DISABLED) + #error HMAC_SUPPORT parameter is not valid +#endif + +//GMAC support +#ifndef GMAC_SUPPORT + #define GMAC_SUPPORT DISABLED +#elif (GMAC_SUPPORT != ENABLED && GMAC_SUPPORT != DISABLED) + #error GMAC_SUPPORT parameter is not valid +#endif + +//KMAC support +#ifndef KMAC_SUPPORT + #define KMAC_SUPPORT DISABLED +#elif (KMAC_SUPPORT != ENABLED && KMAC_SUPPORT != DISABLED) + #error KMAC_SUPPORT parameter is not valid +#endif + +//XCBC-MAC support +#ifndef XCBC_MAC_SUPPORT + #define XCBC_MAC_SUPPORT DISABLED +#elif (XCBC_MAC_SUPPORT != ENABLED && XCBC_MAC_SUPPORT != DISABLED) + #error XCBC_MAC_SUPPORT parameter is not valid +#endif + +//RC2 block cipher support +#ifndef RC2_SUPPORT + #define RC2_SUPPORT DISABLED +#elif (RC2_SUPPORT != ENABLED && RC2_SUPPORT != DISABLED) + #error RC2_SUPPORT parameter is not valid +#endif + +//RC4 stream cipher support +#ifndef RC4_SUPPORT + #define RC4_SUPPORT DISABLED +#elif (RC4_SUPPORT != ENABLED && RC4_SUPPORT != DISABLED) + #error RC4_SUPPORT parameter is not valid +#endif + +//RC6 block cipher support +#ifndef RC6_SUPPORT + #define RC6_SUPPORT DISABLED +#elif (RC6_SUPPORT != ENABLED && RC6_SUPPORT != DISABLED) + #error RC6_SUPPORT parameter is not valid +#endif + +//CAST-128 block cipher support +#ifndef CAST128_SUPPORT + #define CAST128_SUPPORT DISABLED +#elif (CAST128_SUPPORT != ENABLED && CAST128_SUPPORT != DISABLED) + #error CAST128_SUPPORT parameter is not valid +#endif + +//CAST-256 block cipher support +#ifndef CAST256_SUPPORT + #define CAST256_SUPPORT DISABLED +#elif (CAST256_SUPPORT != ENABLED && CAST256_SUPPORT != DISABLED) + #error CAST256_SUPPORT parameter is not valid +#endif + +//IDEA block cipher support +#ifndef IDEA_SUPPORT + #define IDEA_SUPPORT DISABLED +#elif (IDEA_SUPPORT != ENABLED && IDEA_SUPPORT != DISABLED) + #error IDEA_SUPPORT parameter is not valid +#endif + +//DES block cipher support +#ifndef DES_SUPPORT + #define DES_SUPPORT DISABLED +#elif (DES_SUPPORT != ENABLED && DES_SUPPORT != DISABLED) + #error DES_SUPPORT parameter is not valid +#endif + +//Triple DES block cipher support +#ifndef DES3_SUPPORT + #define DES3_SUPPORT DISABLED +#elif (DES3_SUPPORT != ENABLED && DES3_SUPPORT != DISABLED) + #error DES3_SUPPORT parameter is not valid +#endif + +//AES block cipher support +#ifndef AES_SUPPORT + #define AES_SUPPORT ENABLED +#elif (AES_SUPPORT != ENABLED && AES_SUPPORT != DISABLED) + #error AES_SUPPORT parameter is not valid +#endif + +//Blowfish block cipher support +#ifndef BLOWFISH_SUPPORT + #define BLOWFISH_SUPPORT DISABLED +#elif (BLOWFISH_SUPPORT != ENABLED && BLOWFISH_SUPPORT != DISABLED) + #error BLOWFISH_SUPPORT parameter is not valid +#endif + +//Twofish block cipher support +#ifndef TWOFISH_SUPPORT + #define TWOFISH_SUPPORT DISABLED +#elif (TWOFISH_SUPPORT != ENABLED && TWOFISH_SUPPORT != DISABLED) + #error TWOFISH_SUPPORT parameter is not valid +#endif + +//MARS block cipher support +#ifndef MARS_SUPPORT + #define MARS_SUPPORT DISABLED +#elif (MARS_SUPPORT != ENABLED && MARS_SUPPORT != DISABLED) + #error MARS_SUPPORT parameter is not valid +#endif + +//Serpent block cipher support +#ifndef SERPENT_SUPPORT + #define SERPENT_SUPPORT DISABLED +#elif (SERPENT_SUPPORT != ENABLED && SERPENT_SUPPORT != DISABLED) + #error SERPENT_SUPPORT parameter is not valid +#endif + +//Camellia block cipher support +#ifndef CAMELLIA_SUPPORT + #define CAMELLIA_SUPPORT DISABLED +#elif (CAMELLIA_SUPPORT != ENABLED && CAMELLIA_SUPPORT != DISABLED) + #error CAMELLIA_SUPPORT parameter is not valid +#endif + +//ARIA block cipher support +#ifndef ARIA_SUPPORT + #define ARIA_SUPPORT DISABLED +#elif (ARIA_SUPPORT != ENABLED && ARIA_SUPPORT != DISABLED) + #error ARIA_SUPPORT parameter is not valid +#endif + +//SEED block cipher support +#ifndef SEED_SUPPORT + #define SEED_SUPPORT DISABLED +#elif (SEED_SUPPORT != ENABLED && SEED_SUPPORT != DISABLED) + #error SEED_SUPPORT parameter is not valid +#endif + +//SM4 block cipher support +#ifndef SM4_SUPPORT + #define SM4_SUPPORT DISABLED +#elif (SM4_SUPPORT != ENABLED && SM4_SUPPORT != DISABLED) + #error SM4_SUPPORT parameter is not valid +#endif + +//PRESENT block cipher support +#ifndef PRESENT_SUPPORT + #define PRESENT_SUPPORT DISABLED +#elif (PRESENT_SUPPORT != ENABLED && PRESENT_SUPPORT != DISABLED) + #error PRESENT_SUPPORT parameter is not valid +#endif + +//TEA block cipher support +#ifndef TEA_SUPPORT + #define TEA_SUPPORT DISABLED +#elif (TEA_SUPPORT != ENABLED && TEA_SUPPORT != DISABLED) + #error TEA_SUPPORT parameter is not valid +#endif + +//XTEA block cipher support +#ifndef XTEA_SUPPORT + #define XTEA_SUPPORT DISABLED +#elif (XTEA_SUPPORT != ENABLED && XTEA_SUPPORT != DISABLED) + #error XTEA_SUPPORT parameter is not valid +#endif + +//Trivium stream cipher support +#ifndef TRIVIUM_SUPPORT + #define TRIVIUM_SUPPORT DISABLED +#elif (TRIVIUM_SUPPORT != ENABLED && TRIVIUM_SUPPORT != DISABLED) + #error TRIVIUM_SUPPORT parameter is not valid +#endif + +//ZUC stream cipher support +#ifndef ZUC_SUPPORT + #define ZUC_SUPPORT DISABLED +#elif (ZUC_SUPPORT != ENABLED && ZUC_SUPPORT != DISABLED) + #error ZUC_SUPPORT parameter is not valid +#endif + +//ECB mode support +#ifndef ECB_SUPPORT + #define ECB_SUPPORT ENABLED +#elif (ECB_SUPPORT != ENABLED && ECB_SUPPORT != DISABLED) + #error ECB_SUPPORT parameter is not valid +#endif + +//CBC mode support +#ifndef CBC_SUPPORT + #define CBC_SUPPORT ENABLED +#elif (CBC_SUPPORT != ENABLED && CBC_SUPPORT != DISABLED) + #error CBC_SUPPORT parameter is not valid +#endif + +//CFB mode support +#ifndef CFB_SUPPORT + #define CFB_SUPPORT ENABLED +#elif (CFB_SUPPORT != ENABLED && CFB_SUPPORT != DISABLED) + #error CFB_SUPPORT parameter is not valid +#endif + +//OFB mode support +#ifndef OFB_SUPPORT + #define OFB_SUPPORT ENABLED +#elif (OFB_SUPPORT != ENABLED && OFB_SUPPORT != DISABLED) + #error OFB_SUPPORT parameter is not valid +#endif + +//CTR mode support +#ifndef CTR_SUPPORT + #define CTR_SUPPORT ENABLED +#elif (CTR_SUPPORT != ENABLED && CTR_SUPPORT != DISABLED) + #error CTR_SUPPORT parameter is not valid +#endif + +//XTS mode support +#ifndef XTS_SUPPORT + #define XTS_SUPPORT ENABLED +#elif (XTS_SUPPORT != ENABLED && XTS_SUPPORT != DISABLED) + #error XTS_SUPPORT parameter is not valid +#endif + +//CCM mode support +#ifndef CCM_SUPPORT + #define CCM_SUPPORT ENABLED +#elif (CCM_SUPPORT != ENABLED && CCM_SUPPORT != DISABLED) + #error CCM_SUPPORT parameter is not valid +#endif + +//GCM mode support +#ifndef GCM_SUPPORT + #define GCM_SUPPORT ENABLED +#elif (GCM_SUPPORT != ENABLED && GCM_SUPPORT != DISABLED) + #error GCM_SUPPORT parameter is not valid +#endif + +//SIV mode support +#ifndef SIV_SUPPORT + #define SIV_SUPPORT DISABLED +#elif (SIV_SUPPORT != ENABLED && SIV_SUPPORT != DISABLED) + #error SIV_SUPPORT parameter is not valid +#endif + +//Salsa20 stream cipher support +#ifndef SALSA20_SUPPORT + #define SALSA20_SUPPORT DISABLED +#elif (SALSA20_SUPPORT != ENABLED && SALSA20_SUPPORT != DISABLED) + #error SALSA20_SUPPORT parameter is not valid +#endif + +//ChaCha stream cipher support +#ifndef CHACHA_SUPPORT + #define CHACHA_SUPPORT DISABLED +#elif (CHACHA_SUPPORT != ENABLED && CHACHA_SUPPORT != DISABLED) + #error CHACHA_SUPPORT parameter is not valid +#endif + +//Poly1305 support +#ifndef POLY1305_SUPPORT + #define POLY1305_SUPPORT DISABLED +#elif (POLY1305_SUPPORT != ENABLED && POLY1305_SUPPORT != DISABLED) + #error POLY1305_SUPPORT parameter is not valid +#endif + +//ChaCha20Poly1305 support +#ifndef CHACHA20_POLY1305_SUPPORT + #define CHACHA20_POLY1305_SUPPORT DISABLED +#elif (CHACHA20_POLY1305_SUPPORT != ENABLED && CHACHA20_POLY1305_SUPPORT != DISABLED) + #error CHACHA20_POLY1305_SUPPORT parameter is not valid +#endif + +//Diffie-Hellman support +#ifndef DH_SUPPORT + #define DH_SUPPORT DISABLED +#elif (DH_SUPPORT != ENABLED && DH_SUPPORT != DISABLED) + #error DH_SUPPORT parameter is not valid +#endif + +//RSA support +#ifndef RSA_SUPPORT + #define RSA_SUPPORT ENABLED +#elif (RSA_SUPPORT != ENABLED && RSA_SUPPORT != DISABLED) + #error RSA_SUPPORT parameter is not valid +#endif + +//DSA support +#ifndef DSA_SUPPORT + #define DSA_SUPPORT DISABLED +#elif (DSA_SUPPORT != ENABLED && DSA_SUPPORT != DISABLED) + #error DSA_SUPPORT parameter is not valid +#endif + +//Elliptic curve cryptography support +#ifndef EC_SUPPORT + #define EC_SUPPORT ENABLED +#elif (EC_SUPPORT != ENABLED && EC_SUPPORT != DISABLED) + #error EC_SUPPORT parameter is not valid +#endif + +//ECDH support +#ifndef ECDH_SUPPORT + #define ECDH_SUPPORT ENABLED +#elif (ECDH_SUPPORT != ENABLED && ECDH_SUPPORT != DISABLED) + #error ECDH_SUPPORT parameter is not valid +#endif + +//ECDSA support +#ifndef ECDSA_SUPPORT + #define ECDSA_SUPPORT ENABLED +#elif (ECDSA_SUPPORT != ENABLED && ECDSA_SUPPORT != DISABLED) + #error ECDSA_SUPPORT parameter is not valid +#endif + +//ML-KEM-512 key encapsulation mechanism support +#ifndef MLKEM512_SUPPORT + #define MLKEM512_SUPPORT DISABLED +#elif (MLKEM512_SUPPORT != ENABLED && MLKEM512_SUPPORT != DISABLED) + #error MLKEM512_SUPPORT parameter is not valid +#endif + +//ML-KEM-768 key encapsulation mechanism support +#ifndef MLKEM768_SUPPORT + #define MLKEM768_SUPPORT DISABLED +#elif (MLKEM768_SUPPORT != ENABLED && MLKEM768_SUPPORT != DISABLED) + #error MLKEM768_SUPPORT parameter is not valid +#endif + +//ML-KEM-1024 key encapsulation mechanism support +#ifndef MLKEM1024_SUPPORT + #define MLKEM1024_SUPPORT DISABLED +#elif (MLKEM1024_SUPPORT != ENABLED && MLKEM1024_SUPPORT != DISABLED) + #error MLKEM1024_SUPPORT parameter is not valid +#endif + +//Streamlined NTRU Prime 761 key encapsulation mechanism support +#ifndef SNTRUP761_SUPPORT + #define SNTRUP761_SUPPORT DISABLED +#elif (SNTRUP761_SUPPORT != ENABLED && SNTRUP761_SUPPORT != DISABLED) + #error SNTRUP761_SUPPORT parameter is not valid +#endif + +//HKDF support +#ifndef HKDF_SUPPORT + #define HKDF_SUPPORT DISABLED +#elif (HKDF_SUPPORT != ENABLED && HKDF_SUPPORT != DISABLED) + #error HKDF_SUPPORT parameter is not valid +#endif + +//PBKDF support +#ifndef PBKDF_SUPPORT + #define PBKDF_SUPPORT DISABLED +#elif (PBKDF_SUPPORT != ENABLED && PBKDF_SUPPORT != DISABLED) + #error PBKDF_SUPPORT parameter is not valid +#endif + +//Concat KDF support +#ifndef CONCAT_KDF_SUPPORT + #define CONCAT_KDF_SUPPORT DISABLED +#elif (CONCAT_KDF_SUPPORT != ENABLED && CONCAT_KDF_SUPPORT != DISABLED) + #error CONCAT_KDF_SUPPORT parameter is not valid +#endif + +//bcrypt support +#ifndef BCRYPT_SUPPORT + #define BCRYPT_SUPPORT DISABLED +#elif (BCRYPT_SUPPORT != ENABLED && BCRYPT_SUPPORT != DISABLED) + #error BCRYPT_SUPPORT parameter is not valid +#endif + +//scrypt support +#ifndef SCRYPT_SUPPORT + #define SCRYPT_SUPPORT DISABLED +#elif (SCRYPT_SUPPORT != ENABLED && SCRYPT_SUPPORT != DISABLED) + #error SCRYPT_SUPPORT parameter is not valid +#endif + +//MD5-crypt support +#ifndef MD5_CRYPT_SUPPORT + #define MD5_CRYPT_SUPPORT DISABLED +#elif (MD5_CRYPT_SUPPORT != ENABLED && MD5_CRYPT_SUPPORT != DISABLED) + #error MD5_CRYPT_SUPPORT parameter is not valid +#endif + +//SHA-crypt support +#ifndef SHA_CRYPT_SUPPORT + #define SHA_CRYPT_SUPPORT DISABLED +#elif (SHA_CRYPT_SUPPORT != ENABLED && SHA_CRYPT_SUPPORT != DISABLED) + #error SHA_CRYPT_SUPPORT parameter is not valid +#endif + +//Yarrow PRNG support +#ifndef YARROW_SUPPORT + #define YARROW_SUPPORT ENABLED +#elif (YARROW_SUPPORT != ENABLED && YARROW_SUPPORT != DISABLED) + #error YARROW_SUPPORT parameter is not valid +#endif + +//Object identifier support +#ifndef OID_SUPPORT + #define OID_SUPPORT ENABLED +#elif (OID_SUPPORT != ENABLED && OID_SUPPORT != DISABLED) + #error OID_SUPPORT parameter is not valid +#endif + +//ASN.1 syntax support +#ifndef ASN1_SUPPORT + #define ASN1_SUPPORT ENABLED +#elif (ASN1_SUPPORT != ENABLED && ASN1_SUPPORT != DISABLED) + #error ASN1_SUPPORT parameter is not valid +#endif + +//PEM file support +#ifndef PEM_SUPPORT + #define PEM_SUPPORT ENABLED +#elif (PEM_SUPPORT != ENABLED && PEM_SUPPORT != DISABLED) + #error PEM_SUPPORT parameter is not valid +#endif + +//X.509 certificate support +#ifndef X509_SUPPORT + #define X509_SUPPORT ENABLED +#elif (X509_SUPPORT != ENABLED && X509_SUPPORT != DISABLED) + #error X509_SUPPORT parameter is not valid +#endif + +//PKCS #5 support +#ifndef PKCS5_SUPPORT + #define PKCS5_SUPPORT DISABLED +#elif (PKCS5_SUPPORT != ENABLED && PKCS5_SUPPORT != DISABLED) + #error PKCS5_SUPPORT parameter is not valid +#endif + +//Allocate memory block +#ifndef cryptoAllocMem + #define cryptoAllocMem(size) osAllocMem(size) +#endif + +//Deallocate memory block +#ifndef cryptoFreeMem + #define cryptoFreeMem(p) osFreeMem(p) +#endif + +//Rotate left operation +#define ROL8(a, n) (((a) << (n)) | ((a) >> (8 - (n)))) +#define ROL16(a, n) (((a) << (n)) | ((a) >> (16 - (n)))) +#define ROL32(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) +#define ROL64(a, n) (((a) << (n)) | ((a) >> (64 - (n)))) + +//Rotate right operation +#define ROR8(a, n) (((a) >> (n)) | ((a) << (8 - (n)))) +#define ROR16(a, n) (((a) >> (n)) | ((a) << (16 - (n)))) +#define ROR32(a, n) (((a) >> (n)) | ((a) << (32 - (n)))) +#define ROR64(a, n) (((a) >> (n)) | ((a) << (64 - (n)))) + +//Shift left operation +#define SHL8(a, n) ((a) << (n)) +#define SHL16(a, n) ((a) << (n)) +#define SHL32(a, n) ((a) << (n)) +#define SHL64(a, n) ((a) << (n)) + +//Shift right operation +#define SHR8(a, n) ((a) >> (n)) +#define SHR16(a, n) ((a) >> (n)) +#define SHR32(a, n) ((a) >> (n)) +#define SHR64(a, n) ((a) >> (n)) + +//Micellaneous macros +#define _U8(x) ((uint8_t) (x)) +#define _U16(x) ((uint16_t) (x)) +#define _U32(x) ((uint32_t) (x)) +#define _U64(x) ((uint64_t) (x)) + +//Test if a 8-bit integer is zero +#define CRYPTO_TEST_Z_8(a) \ + _U8((_U8((_U8(a) | (~_U8(a) + 1U))) >> 7U) ^ 1U) + +//Test if a 8-bit integer is nonzero +#define CRYPTO_TEST_NZ_8(a) \ + _U8(_U8((_U8(a) | (~_U8(a) + 1U))) >> 7U) + +//Test if two 8-bit integers are equal +#define CRYPTO_TEST_EQ_8(a, b) \ + _U8((_U8(((_U8(a) ^ _U8(b)) | (~(_U8(a) ^ _U8(b)) + 1U))) >> 7U) ^ 1U) + +//Test if two 8-bit integers are not equal +#define CRYPTO_TEST_NEQ_8(a, b) \ + _U8(_U8(((_U8(a) ^ _U8(b)) | (~(_U8(a) ^ _U8(b)) + 1U))) >> 7U) + +//Test if a 8-bit integer is lower than another 8-bit integer +#define CRYPTO_TEST_LT_8(a, b) \ + _U8(_U8((((_U8(a) - _U8(b)) ^ _U8(b)) | (_U8(a) ^ _U8(b))) ^ _U8(a)) >> 7U) + +//Test if a 8-bit integer is lower or equal than another 8-bit integer +#define CRYPTO_TEST_LTE_8(a, b) \ + _U8((_U8((((_U8(b) - _U8(a)) ^ _U8(a)) | (_U8(a) ^ _U8(b))) ^ _U8(b)) >> 7U) ^ 1U) + +//Test if a 8-bit integer is greater than another 8-bit integer +#define CRYPTO_TEST_GT_8(a, b) \ + _U8(_U8((((_U8(b) - _U8(a)) ^ _U8(a)) | (_U8(a) ^ _U8(b))) ^ _U8(b)) >> 7U) + +//Test if a 8-bit integer is greater or equal than another 8-bit integer +#define CRYPTO_TEST_GTE_8(a, b) \ + _U8((_U8((((_U8(a) - _U8(b)) ^ _U8(b)) | (_U8(a) ^ _U8(b))) ^ _U8(a)) >> 7U) ^ 1U) + +//Select between two 8-bit integers +#define CRYPTO_SELECT_8(a, b, c) \ + _U8((_U8(a) & (_U8(c) - 1U)) | (_U8(b) & ~(_U8(c) - 1U))) + +//Test if a 16-bit integer is zero +#define CRYPTO_TEST_Z_16(a) \ + _U16((_U16((_U16(a) | (~_U16(a) + 1U))) >> 15U) ^ 1U) + +//Test if a 16-bit integer is nonzero +#define CRYPTO_TEST_NZ_16(a) \ + _U16(_U16((_U16(a) | (~_U16(a) + 1U))) >> 15U) + +//Test if two 16-bit integers are equal +#define CRYPTO_TEST_EQ_16(a, b) \ + _U16((_U16(((_U16(a) ^ _U16(b)) | (~(_U16(a) ^ _U16(b)) + 1U))) >> 15U) ^ 1U) + +//Test if two 16-bit integers are not equal +#define CRYPTO_TEST_NEQ_16(a, b) \ + _U16(_U16(((_U16(a) ^ _U16(b)) | (~(_U16(a) ^ _U16(b)) + 1U))) >> 15U) + +//Test if a 16-bit integer is lower than another 16-bit integer +#define CRYPTO_TEST_LT_16(a, b) \ + _U16(_U16((((_U16(a) - _U16(b)) ^ _U16(b)) | (_U16(a) ^ _U16(b))) ^ _U16(a)) >> 15U) + +//Test if a 16-bit integer is lower or equal than another 16-bit integer +#define CRYPTO_TEST_LTE_16(a, b) \ + _U16((_U16((((_U16(b) - _U16(a)) ^ _U16(a)) | (_U16(a) ^ _U16(b))) ^ _U16(b)) >> 15U) ^ 1U) + +//Test if a 16-bit integer is greater than another 16-bit integer +#define CRYPTO_TEST_GT_16(a, b) \ + _U16(_U16((((_U16(b) - _U16(a)) ^ _U16(a)) | (_U16(a) ^ _U16(b))) ^ _U16(b)) >> 15U) + +//Test if a 16-bit integer is greater or equal than another 16-bit integer +#define CRYPTO_TEST_GTE_16(a, b) \ + _U16((_U16((((_U16(a) - _U16(b)) ^ _U16(b)) | (_U16(a) ^ _U16(b))) ^ _U16(a)) >> 15U) ^ 1U) + +//Select between two 16-bit integers +#define CRYPTO_SELECT_16(a, b, c) \ + _U16((_U16(a) & (_U16(c) - 1U)) | (_U16(b) & ~(_U16(c) - 1U))) + +//Test if a 32-bit integer is zero +#define CRYPTO_TEST_Z_32(a) \ + _U32((_U32((_U32(a) | (~_U32(a) + 1U))) >> 31U) ^ 1U) + +//Test if a 32-bit integer is nonzero +#define CRYPTO_TEST_NZ_32(a) \ + _U32(_U32((_U32(a) | (~_U32(a) + 1U))) >> 31U) + +//Test if two 32-bit integers are equal +#define CRYPTO_TEST_EQ_32(a, b) \ + _U32((_U32(((_U32(a) ^ _U32(b)) | (~(_U32(a) ^ _U32(b)) + 1U))) >> 31U) ^ 1U) + +//Test if two 32-bit integers are not equal +#define CRYPTO_TEST_NEQ_32(a, b) \ + _U32(_U32(((_U32(a) ^ _U32(b)) | (~(_U32(a) ^ _U32(b)) + 1U))) >> 31U) + +//Test if a 32-bit integer is lower than another 32-bit integer +#define CRYPTO_TEST_LT_32(a, b) \ + _U32(_U32((((_U32(a) - _U32(b)) ^ _U32(b)) | (_U32(a) ^ _U32(b))) ^ _U32(a)) >> 31U) + +//Test if a 32-bit integer is lower or equal than another 32-bit integer +#define CRYPTO_TEST_LTE_32(a, b) \ + _U32((_U32((((_U32(b) - _U32(a)) ^ _U32(a)) | (_U32(a) ^ _U32(b))) ^ _U32(b)) >> 31U) ^ 1U) + +//Test if a 32-bit integer is greater than another 32-bit integer +#define CRYPTO_TEST_GT_32(a, b) \ + _U32(_U32((((_U32(b) - _U32(a)) ^ _U32(a)) | (_U32(a) ^ _U32(b))) ^ _U32(b)) >> 31U) + +//Test if a 32-bit integer is greater or equal than another 32-bit integer +#define CRYPTO_TEST_GTE_32(a, b) \ + _U32((_U32((((_U32(a) - _U32(b)) ^ _U32(b)) | (_U32(a) ^ _U32(b))) ^ _U32(a)) >> 31U) ^ 1U) + +//Select between two 32-bit integers +#define CRYPTO_SELECT_32(a, b, c) \ + _U32((_U32(a) & (_U32(c) - 1U)) | (_U32(b) & ~(_U32(c) - 1U))) + +//Select between two 64-bit integers +#define CRYPTO_SELECT_64(a, b, c) \ + _U64((_U64(a) & (_U64(c) - 1U)) | (_U64(b) & ~(_U64(c) - 1U))) + +//Forward declaration of PrngAlgo structure +struct _PrngAlgo; +#define PrngAlgo struct _PrngAlgo + +//C++ guard +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Encryption algorithm type + **/ + +typedef enum +{ + CIPHER_ALGO_TYPE_STREAM = 0, + CIPHER_ALGO_TYPE_BLOCK = 1 +} CipherAlgoType; + + +/** + * @brief Cipher operation modes + **/ + +typedef enum +{ + CIPHER_MODE_NULL = 0, + CIPHER_MODE_STREAM = 1, + CIPHER_MODE_ECB = 2, + CIPHER_MODE_CBC = 3, + CIPHER_MODE_CFB = 4, + CIPHER_MODE_OFB = 5, + CIPHER_MODE_CTR = 6, + CIPHER_MODE_CCM = 7, + CIPHER_MODE_GCM = 8, + CIPHER_MODE_CHACHA20_POLY1305 = 9, +} CipherMode; + + +/** + * @brief Data chunk descriptor + **/ + +typedef struct +{ + const void *buffer; + size_t length; +} DataChunk; + + +//Common API for hash algorithms +typedef error_t (*HashAlgoCompute)(const void *data, size_t length, + uint8_t *digest); + +typedef void (*HashAlgoInit)(void *context); + +typedef void (*HashAlgoUpdate)(void *context, const void *data, size_t length); + +typedef void (*HashAlgoFinal)(void *context, uint8_t *digest); + +typedef void (*HashAlgoFinalRaw)(void *context, uint8_t *digest); + +//Common API for encryption algorithms +typedef error_t (*CipherAlgoInit)(void *context, const uint8_t *key, + size_t keyLen); + +typedef void (*CipherAlgoEncryptStream)(void *context, const uint8_t *input, + uint8_t *output, size_t length); + +typedef void (*CipherAlgoDecryptStream)(void *context, const uint8_t *input, + uint8_t *output, size_t length); + +typedef void (*CipherAlgoEncryptBlock)(void *context, const uint8_t *input, + uint8_t *output); + +typedef void (*CipherAlgoDecryptBlock)(void *context, const uint8_t *input, + uint8_t *output); + +typedef void (*CipherAlgoDeinit)(void *context); + +//Common interface for key encapsulation mechanisms (KEM) +typedef error_t (*KemAlgoGenerateKeyPair)(const PrngAlgo *prngAlgo, + void *prngContext, uint8_t *pk, uint8_t *sk); + +typedef error_t (*KemAlgoEncapsulate)(const PrngAlgo *prngAlgo, + void *prngContext, uint8_t *ct, uint8_t *ss, const uint8_t *pk); + +typedef error_t (*KemAlgoDecapsulate)(uint8_t *ss, const uint8_t *ct, + const uint8_t *sk); + +//Common API for pseudo-random number generators (PRNG) +typedef error_t (*PrngAlgoInit)(void *context); + +typedef error_t (*PrngAlgoSeed)(void *context, const uint8_t *input, + size_t length); + +typedef error_t (*PrngAlgoAddEntropy)(void *context, uint_t source, + const uint8_t *input, size_t length, size_t entropy); + +typedef error_t (*PrngAlgoRead)(void *context, uint8_t *output, size_t length); + +typedef void (*PrngAlgoDeinit)(void *context); + + +/** + * @brief Common interface for hash algorithms + **/ + +typedef struct +{ + const char_t *name; + const uint8_t *oid; + size_t oidSize; + size_t contextSize; + size_t blockSize; + size_t digestSize; + size_t minPadSize; + bool_t bigEndian; + HashAlgoCompute compute; + HashAlgoInit init; + HashAlgoUpdate update; + HashAlgoFinal final; + HashAlgoFinalRaw finalRaw; +} HashAlgo; + + +/** + * @brief Common interface for encryption algorithms + **/ + +typedef struct +{ + const char_t *name; + size_t contextSize; + CipherAlgoType type; + size_t blockSize; + CipherAlgoInit init; + CipherAlgoEncryptStream encryptStream; + CipherAlgoDecryptStream decryptStream; + CipherAlgoEncryptBlock encryptBlock; + CipherAlgoDecryptBlock decryptBlock; + CipherAlgoDeinit deinit; +} CipherAlgo; + + +/** + * @brief Common interface for key encapsulation mechanisms (KEM) + **/ + +typedef struct +{ + const char_t *name; + size_t publicKeySize; + size_t secretKeySize; + size_t ciphertextSize; + size_t sharedSecretSize; + KemAlgoGenerateKeyPair generateKeyPair; + KemAlgoEncapsulate encapsulate; + KemAlgoDecapsulate decapsulate; +} KemAlgo; + + +/** + * @brief Common interface for pseudo-random number generators (PRNG) + **/ + +struct _PrngAlgo +{ + const char_t *name; + size_t contextSize; + PrngAlgoInit init; + PrngAlgoSeed seed; + PrngAlgoAddEntropy addEntropy; + PrngAlgoRead read; + PrngAlgoDeinit deinit; +}; + + +//C++ guard +#ifdef __cplusplus +} +#endif + +#endif diff --git a/deps/cyclone/include/core/crypto_legacy.h b/deps/cyclone/include/core/crypto_legacy.h new file mode 100644 index 00000000..08ab5fd0 --- /dev/null +++ b/deps/cyclone/include/core/crypto_legacy.h @@ -0,0 +1,68 @@ +/** + * @file crypto_legacy.h + * @brief Legacy definitions + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +#ifndef _CRYPTO_LEGACY_H +#define _CRYPTO_LEGACY_H + +//Deprecated functions +#define mpiReadRaw(r, data, length) mpiImport(r, data, length, MPI_FORMAT_BIG_ENDIAN) +#define mpiWriteRaw(a, data, length) mpiExport(a, data, length, MPI_FORMAT_BIG_ENDIAN) + +#ifdef CURVE25519_SUPPORT + #define X25519_SUPPORT CURVE25519_SUPPORT +#endif + +#ifdef CURVE448_SUPPORT + #define X448_SUPPORT CURVE448_SUPPORT +#endif + +#define ecdsaGenerateKeyPair ecGenerateKeyPair +#define ecdsaGeneratePrivateKey ecGeneratePrivateKey +#define ecdsaGeneratePublicKey ecGeneratePublicKey + +#define MAX_HASH_CONTEXT_SIZE sizeof(HashContext) +#define MAX_CIPHER_CONTEXT_SIZE sizeof(CipherContext) + +#ifdef SAMD51_CRYPTO_PUKCC_SUPPORT + #define SAMD51_CRYPTO_PKC_SUPPORT SAMD51_CRYPTO_PUKCC_SUPPORT +#endif + +#ifdef SAME54_CRYPTO_PUKCC_SUPPORT + #define SAME54_CRYPTO_PKC_SUPPORT SAME54_CRYPTO_PUKCC_SUPPORT +#endif + +#define yarrowRelease yarrowDeinit + +#define X509CertificateInfo X509CertInfo +#define X509SignatureAlgoId X509SignAlgoId + +#define EddsaMessageChunk DataChunk + +#endif diff --git a/deps/cyclone/include/cpu_endian.h b/deps/cyclone/include/cpu_endian.h new file mode 100644 index 00000000..d89d1e1c --- /dev/null +++ b/deps/cyclone/include/cpu_endian.h @@ -0,0 +1,481 @@ +/** + * @file cpu_endian.h + * @brief Byte order conversion + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +#ifndef _CPU_ENDIAN_H +#define _CPU_ENDIAN_H + +//Dependencies +#include "os_port.h" +#include "types.h" + +//Undefine conflicting definitions +#ifdef HTONS + #undef HTONS +#endif + +#ifdef HTONL + #undef HTONL +#endif + +#ifdef HTONLL + #undef HTONLL +#endif + +#ifdef htons + #undef htons +#endif + +#ifdef htonl + #undef htonl +#endif + +#ifdef htonll + #undef htonll +#endif + +#ifdef NTOHS + #undef NTOHS +#endif + +#ifdef NTOHL + #undef NTOHL +#endif + +#ifdef NTOHLL + #undef NTOHLL +#endif + +#ifdef ntohs + #undef ntohs +#endif + +#ifdef ntohl + #undef ntohl +#endif + +#ifdef ntohll + #undef ntohll +#endif + +#ifdef HTOLE16 + #undef HTOLE16 +#endif + +#ifdef HTOLE32 + #undef HTOLE32 +#endif + +#ifdef HTOLE64 + #undef HTOLE64 +#endif + +#ifdef htole16 + #undef htole16 +#endif + +#ifdef htole32 + #undef htole32 +#endif + +#ifdef htole64 + #undef htole64 +#endif + +#ifdef LETOH16 + #undef LETOH16 +#endif + +#ifdef LETOH32 + #undef LETOH32 +#endif + +#ifdef LETOH64 + #undef LETOH64 +#endif + +#ifdef letoh16 + #undef letoh16 +#endif + +#ifdef letoh32 + #undef letoh32 +#endif + +#ifdef letoh64 + #undef letoh64 +#endif + +#ifdef HTOBE16 + #undef HTOBE16 +#endif + +#ifdef HTOBE32 + #undef HTOBE32 +#endif + +#ifdef HTOBE64 + #undef HTOBE64 +#endif + +#ifdef htobe16 + #undef htobe16 +#endif + +#ifdef htobe32 + #undef htobe32 +#endif + +#ifdef htobe64 + #undef htobe64 +#endif + +#ifdef BETOH16 + #undef BETOH16 +#endif + +#ifdef BETOH32 + #undef BETOH32 +#endif + +#ifdef BETOH64 + #undef BETOH64 +#endif + +#ifdef betoh16 + #undef betoh16 +#endif + +#ifdef betoh32 + #undef betoh32 +#endif + +#ifdef betoh64 + #undef betoh64 +#endif + +//Load unaligned 16-bit integer (little-endian encoding) +#define LOAD16LE(p) ( \ + ((uint16_t)(((uint8_t *)(p))[0]) << 0) | \ + ((uint16_t)(((uint8_t *)(p))[1]) << 8)) + +//Load unaligned 16-bit integer (big-endian encoding) +#define LOAD16BE(p) ( \ + ((uint16_t)(((uint8_t *)(p))[0]) << 8) | \ + ((uint16_t)(((uint8_t *)(p))[1]) << 0)) + +//Load unaligned 24-bit integer (little-endian encoding) +#define LOAD24LE(p) ( \ + ((uint32_t)(((uint8_t *)(p))[0]) << 0)| \ + ((uint32_t)(((uint8_t *)(p))[1]) << 8) | \ + ((uint32_t)(((uint8_t *)(p))[2]) << 16)) + +//Load unaligned 24-bit integer (big-endian encoding) +#define LOAD24BE(p) ( \ + ((uint32_t)(((uint8_t *)(p))[0]) << 16) | \ + ((uint32_t)(((uint8_t *)(p))[1]) << 8) | \ + ((uint32_t)(((uint8_t *)(p))[2]) << 0)) + +//Load unaligned 32-bit integer (little-endian encoding) +#define LOAD32LE(p) ( \ + ((uint32_t)(((uint8_t *)(p))[0]) << 0) | \ + ((uint32_t)(((uint8_t *)(p))[1]) << 8) | \ + ((uint32_t)(((uint8_t *)(p))[2]) << 16) | \ + ((uint32_t)(((uint8_t *)(p))[3]) << 24)) + +//Load unaligned 32-bit integer (big-endian encoding) +#define LOAD32BE(p) ( \ + ((uint32_t)(((uint8_t *)(p))[0]) << 24) | \ + ((uint32_t)(((uint8_t *)(p))[1]) << 16) | \ + ((uint32_t)(((uint8_t *)(p))[2]) << 8) | \ + ((uint32_t)(((uint8_t *)(p))[3]) << 0)) + +//Load unaligned 48-bit integer (little-endian encoding) +#define LOAD48LE(p) ( \ + ((uint64_t)(((uint8_t *)(p))[0]) << 0) | \ + ((uint64_t)(((uint8_t *)(p))[1]) << 8) | \ + ((uint64_t)(((uint8_t *)(p))[2]) << 16) | \ + ((uint64_t)(((uint8_t *)(p))[3]) << 24) | \ + ((uint64_t)(((uint8_t *)(p))[4]) << 32) | \ + ((uint64_t)(((uint8_t *)(p))[5]) << 40) + +//Load unaligned 48-bit integer (big-endian encoding) +#define LOAD48BE(p) ( \ + ((uint64_t)(((uint8_t *)(p))[0]) << 40) | \ + ((uint64_t)(((uint8_t *)(p))[1]) << 32) | \ + ((uint64_t)(((uint8_t *)(p))[2]) << 24) | \ + ((uint64_t)(((uint8_t *)(p))[3]) << 16) | \ + ((uint64_t)(((uint8_t *)(p))[4]) << 8) | \ + ((uint64_t)(((uint8_t *)(p))[5]) << 0)) + +//Load unaligned 64-bit integer (little-endian encoding) +#define LOAD64LE(p) ( \ + ((uint64_t)(((uint8_t *)(p))[0]) << 0) | \ + ((uint64_t)(((uint8_t *)(p))[1]) << 8) | \ + ((uint64_t)(((uint8_t *)(p))[2]) << 16) | \ + ((uint64_t)(((uint8_t *)(p))[3]) << 24) | \ + ((uint64_t)(((uint8_t *)(p))[4]) << 32) | \ + ((uint64_t)(((uint8_t *)(p))[5]) << 40) | \ + ((uint64_t)(((uint8_t *)(p))[6]) << 48) | \ + ((uint64_t)(((uint8_t *)(p))[7]) << 56)) + +//Load unaligned 64-bit integer (big-endian encoding) +#define LOAD64BE(p) ( \ + ((uint64_t)(((uint8_t *)(p))[0]) << 56) | \ + ((uint64_t)(((uint8_t *)(p))[1]) << 48) | \ + ((uint64_t)(((uint8_t *)(p))[2]) << 40) | \ + ((uint64_t)(((uint8_t *)(p))[3]) << 32) | \ + ((uint64_t)(((uint8_t *)(p))[4]) << 24) | \ + ((uint64_t)(((uint8_t *)(p))[5]) << 16) | \ + ((uint64_t)(((uint8_t *)(p))[6]) << 8) | \ + ((uint64_t)(((uint8_t *)(p))[7]) << 0)) + +//Store unaligned 16-bit integer (little-endian encoding) +#define STORE16LE(a, p) \ + ((uint8_t *)(p))[0] = ((uint16_t)(a) >> 0) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint16_t)(a) >> 8) & 0xFFU + +//Store unaligned 16-bit integer (big-endian encoding) +#define STORE16BE(a, p) \ + ((uint8_t *)(p))[0] = ((uint16_t)(a) >> 8) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint16_t)(a) >> 0) & 0xFFU + +//Store unaligned 24-bit integer (little-endian encoding) +#define STORE24LE(a, p) \ + ((uint8_t *)(p))[0] = ((uint32_t)(a) >> 0) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint32_t)(a) >> 8) & 0xFFU, \ + ((uint8_t *)(p))[2] = ((uint32_t)(a) >> 16) & 0xFFU + +//Store unaligned 24-bit integer (big-endian encoding) +#define STORE24BE(a, p) \ + ((uint8_t *)(p))[0] = ((uint32_t)(a) >> 16) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint32_t)(a) >> 8) & 0xFFU, \ + ((uint8_t *)(p))[2] = ((uint32_t)(a) >> 0) & 0xFFU + +//Store unaligned 32-bit integer (little-endian encoding) +#define STORE32LE(a, p) \ + ((uint8_t *)(p))[0] = ((uint32_t)(a) >> 0) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint32_t)(a) >> 8) & 0xFFU, \ + ((uint8_t *)(p))[2] = ((uint32_t)(a) >> 16) & 0xFFU, \ + ((uint8_t *)(p))[3] = ((uint32_t)(a) >> 24) & 0xFFU + +//Store unaligned 32-bit integer (big-endian encoding) +#define STORE32BE(a, p) \ + ((uint8_t *)(p))[0] = ((uint32_t)(a) >> 24) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint32_t)(a) >> 16) & 0xFFU, \ + ((uint8_t *)(p))[2] = ((uint32_t)(a) >> 8) & 0xFFU, \ + ((uint8_t *)(p))[3] = ((uint32_t)(a) >> 0) & 0xFFU + +//Store unaligned 48-bit integer (little-endian encoding) +#define STORE48LE(a, p) \ + ((uint8_t *)(p))[0] = ((uint64_t)(a) >> 0) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint64_t)(a) >> 8) & 0xFFU, \ + ((uint8_t *)(p))[2] = ((uint64_t)(a) >> 16) & 0xFFU, \ + ((uint8_t *)(p))[3] = ((uint64_t)(a) >> 24) & 0xFFU, \ + ((uint8_t *)(p))[4] = ((uint64_t)(a) >> 32) & 0xFFU, \ + ((uint8_t *)(p))[5] = ((uint64_t)(a) >> 40) & 0xFFU, + +//Store unaligned 48-bit integer (big-endian encoding) +#define STORE48BE(a, p) \ + ((uint8_t *)(p))[0] = ((uint64_t)(a) >> 40) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint64_t)(a) >> 32) & 0xFFU, \ + ((uint8_t *)(p))[2] = ((uint64_t)(a) >> 24) & 0xFFU, \ + ((uint8_t *)(p))[3] = ((uint64_t)(a) >> 16) & 0xFFU, \ + ((uint8_t *)(p))[4] = ((uint64_t)(a) >> 8) & 0xFFU, \ + ((uint8_t *)(p))[5] = ((uint64_t)(a) >> 0) & 0xFFU + +//Store unaligned 64-bit integer (little-endian encoding) +#define STORE64LE(a, p) \ + ((uint8_t *)(p))[0] = ((uint64_t)(a) >> 0) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint64_t)(a) >> 8) & 0xFFU, \ + ((uint8_t *)(p))[2] = ((uint64_t)(a) >> 16) & 0xFFU, \ + ((uint8_t *)(p))[3] = ((uint64_t)(a) >> 24) & 0xFFU, \ + ((uint8_t *)(p))[4] = ((uint64_t)(a) >> 32) & 0xFFU, \ + ((uint8_t *)(p))[5] = ((uint64_t)(a) >> 40) & 0xFFU, \ + ((uint8_t *)(p))[6] = ((uint64_t)(a) >> 48) & 0xFFU, \ + ((uint8_t *)(p))[7] = ((uint64_t)(a) >> 56) & 0xFFU + +//Store unaligned 64-bit integer (big-endian encoding) +#define STORE64BE(a, p) \ + ((uint8_t *)(p))[0] = ((uint64_t)(a) >> 56) & 0xFFU, \ + ((uint8_t *)(p))[1] = ((uint64_t)(a) >> 48) & 0xFFU, \ + ((uint8_t *)(p))[2] = ((uint64_t)(a) >> 40) & 0xFFU, \ + ((uint8_t *)(p))[3] = ((uint64_t)(a) >> 32) & 0xFFU, \ + ((uint8_t *)(p))[4] = ((uint64_t)(a) >> 24) & 0xFFU, \ + ((uint8_t *)(p))[5] = ((uint64_t)(a) >> 16) & 0xFFU, \ + ((uint8_t *)(p))[6] = ((uint64_t)(a) >> 8) & 0xFFU, \ + ((uint8_t *)(p))[7] = ((uint64_t)(a) >> 0) & 0xFFU + +//Swap a 16-bit integer +#define SWAPINT16(x) ( \ + (((uint16_t)(x) & 0x00FFU) << 8) | \ + (((uint16_t)(x) & 0xFF00U) >> 8)) + +//Swap a 32-bit integer +#define SWAPINT32(x) ( \ + (((uint32_t)(x) & 0x000000FFUL) << 24) | \ + (((uint32_t)(x) & 0x0000FF00UL) << 8) | \ + (((uint32_t)(x) & 0x00FF0000UL) >> 8) | \ + (((uint32_t)(x) & 0xFF000000UL) >> 24)) + +//Swap a 64-bit integer +#define SWAPINT64(x) ( \ + (((uint64_t)(x) & 0x00000000000000FFULL) << 56) | \ + (((uint64_t)(x) & 0x000000000000FF00ULL) << 40) | \ + (((uint64_t)(x) & 0x0000000000FF0000ULL) << 24) | \ + (((uint64_t)(x) & 0x00000000FF000000ULL) << 8) | \ + (((uint64_t)(x) & 0x000000FF00000000ULL) >> 8) | \ + (((uint64_t)(x) & 0x0000FF0000000000ULL) >> 24) | \ + (((uint64_t)(x) & 0x00FF000000000000ULL) >> 40) | \ + (((uint64_t)(x) & 0xFF00000000000000ULL) >> 56)) + +//Big-endian machine? +#if (__BYTE_ORDER == __BIG_ENDIAN) +//Host byte order to network byte order +#define HTONS(value) (value) +#define HTONL(value) (value) +#define HTONLL(value) (value) +#define htons(value) ((uint16_t) (value)) +#define htonl(value) ((uint32_t) (value)) +#define htonll(value) ((uint64_t) (value)) + +//Network byte order to host byte order +#define NTOHS(value) (value) +#define NTOHL(value) (value) +#define NTOHLL(value) (value) +#define ntohs(value) ((uint16_t) (value)) +#define ntohl(value) ((uint32_t) (value)) +#define ntohll(value) ((uint64_t) (value)) + +//Host byte order to little-endian byte order +#define HTOLE16(value) SWAPINT16(value) +#define HTOLE32(value) SWAPINT32(value) +#define HTOLE64(value) SWAPINT64(value) +#define htole16(value) swapInt16((uint16_t) (value)) +#define htole32(value) swapInt32((uint32_t) (value)) +#define htole64(value) swapInt64((uint64_t) (value)) + +//Little-endian byte order to host byte order +#define LETOH16(value) SWAPINT16(value) +#define LETOH32(value) SWAPINT32(value) +#define LETOH64(value) SWAPINT64(value) +#define letoh16(value) swapInt16((uint16_t) (value)) +#define letoh32(value) swapInt32((uint32_t) (value)) +#define letoh64(value) swapInt64((uint64_t) (value)) + +//Host byte order to big-endian byte order +#define HTOBE16(value) (value) +#define HTOBE32(value) (value) +#define HTOBE64(value) (value) +#define htobe16(value) ((uint16_t) (value)) +#define htobe32(value) ((uint32_t) (value)) +#define htobe64(value) ((uint64_t) (value)) + +//Big-endian byte order to host byte order +#define BETOH16(value) (value) +#define BETOH32(value) (value) +#define BETOH64(value) (value) +#define betoh16(value) ((uint16_t) (value)) +#define betoh32(value) ((uint32_t) (value)) +#define betoh64(value) ((uint64_t) (value)) + +//Little-endian machine? +#else + +//Host byte order to network byte order +#define HTONS(value) SWAPINT16(value) +#define HTONL(value) SWAPINT32(value) +#define HTONLL(value) SWAPINT64(value) +#define htons(value) swapInt16((uint16_t) (value)) +#define htonl(value) swapInt32((uint32_t) (value)) +#define htonll(value) swapInt64((uint64_t) (value)) + +//Network byte order to host byte order +#define NTOHS(value) SWAPINT16(value) +#define NTOHL(value) SWAPINT32(value) +#define NTOHLL(value) SWAPINT64(value) +#define ntohs(value) swapInt16((uint16_t) (value)) +#define ntohl(value) swapInt32((uint32_t) (value)) +#define ntohll(value) swapInt64((uint64_t) (value)) + +//Host byte order to little-endian byte order +#define HTOLE16(value) (value) +#define HTOLE32(value) (value) +#define HTOLE64(value) (value) +#define htole16(value) ((uint16_t) (value)) +#define htole32(value) ((uint32_t) (value)) +#define htole64(value) ((uint64_t) (value)) + +//Little-endian byte order to host byte order +#define LETOH16(value) (value) +#define LETOH32(value) (value) +#define LETOH64(value) (value) +#define letoh16(value) ((uint16_t) (value)) +#define letoh32(value) ((uint32_t) (value)) +#define letoh64(value) ((uint64_t) (value)) + +//Host byte order to big-endian byte order +#define HTOBE16(value) SWAPINT16(value) +#define HTOBE32(value) SWAPINT32(value) +#define HTOBE64(value) SWAPINT64(value) +#define htobe16(value) swapInt16((uint16_t) (value)) +#define htobe32(value) swapInt32((uint32_t) (value)) +#define htobe64(value) swapInt64((uint64_t) (value)) + +//Big-endian byte order to host byte order +#define BETOH16(value) SWAPINT16(value) +#define BETOH32(value) SWAPINT32(value) +#define BETOH64(value) SWAPINT64(value) +#define betoh16(value) swapInt16((uint16_t) (value)) +#define betoh32(value) swapInt32((uint32_t) (value)) +#define betoh64(value) swapInt64((uint64_t) (value)) + +#endif + +//C++ guard +#ifdef __cplusplus +extern "C" { +#endif + +//Byte order conversion functions +uint16_t swapInt16(uint16_t value); +uint32_t swapInt32(uint32_t value); +uint64_t swapInt64(uint64_t value); + +//Bit reversal functions +uint8_t reverseInt4(uint8_t value); +uint8_t reverseInt8(uint8_t value); +uint16_t reverseInt16(uint16_t value); +uint32_t reverseInt32(uint32_t value); +uint64_t reverseInt64(uint64_t value); + +//C++ guard +#ifdef __cplusplus +} +#endif + +#endif diff --git a/deps/cyclone/include/crypto_config.h b/deps/cyclone/include/crypto_config.h new file mode 100644 index 00000000..7485edaa --- /dev/null +++ b/deps/cyclone/include/crypto_config.h @@ -0,0 +1,7 @@ +#include "os_port.h" + +#define HKDF_SUPPORT ENABLED +#define SHA256_SUPPORT ENABLED +#define AES_SUPPORT ENABLED +#define ECB_SUPPORT ENABLED +#define GCM_SUPPORT ENABLED diff --git a/deps/cyclone/include/error.h b/deps/cyclone/include/error.h new file mode 100644 index 00000000..a7c3c8df --- /dev/null +++ b/deps/cyclone/include/error.h @@ -0,0 +1,320 @@ +/** + * @file error.h + * @brief Error codes description + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +#ifndef _ERROR_H +#define _ERROR_H + +//C++ guard +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Error codes + **/ + +typedef enum cyc_error_st +{ + NO_ERROR = 0, ///> 8) & 0xFF) +#endif + +#ifndef MIN + #define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef arraysize + #define arraysize(a) (sizeof(a) / sizeof(a[0])) +#endif + +//Memory management +#ifndef osAllocMem + #define osAllocMem malloc +#endif +#ifndef osFreeMem + #define osFreeMem free +#endif + +//Fill block of memory +#ifndef osMemset + #define osMemset(p, value, length) (void) memset(p, value, length) +#endif + +//Copy block of memory +#ifndef osMemcpy + #define osMemcpy(dest, src, length) (void) memcpy(dest, src, length) +#endif + +//Move block of memory +#ifndef osMemmove + #define osMemmove(dest, src, length) (void) memmove(dest, src, length) +#endif + +//Compare two blocks of memory +#ifndef osMemcmp + #define osMemcmp(p1, p2, length) memcmp(p1, p2, length) +#endif + +//Search for the first occurrence of a given character +#ifndef osMemchr + #define osMemchr(p, c, length) memchr(p, c, length) +#endif +#endif diff --git a/deps/cyclone/libcyclone.a b/deps/cyclone/libcyclone.a new file mode 100644 index 00000000..ca3fc903 Binary files /dev/null and b/deps/cyclone/libcyclone.a differ diff --git a/deps/cyclone/sha256.c b/deps/cyclone/sha256.c new file mode 100644 index 00000000..9b7f095c --- /dev/null +++ b/deps/cyclone/sha256.c @@ -0,0 +1,361 @@ +/** + * @file sha256.c + * @brief SHA-256 (Secure Hash Algorithm 256) + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @section Description + * + * SHA-256 is a secure hash algorithm for computing a condensed representation + * of an electronic message. Refer to FIPS 180-4 for more details + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.4 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "hash/sha256.h" + +//Check crypto library configuration +#if (SHA224_SUPPORT == ENABLED || SHA256_SUPPORT == ENABLED) + +//Macro to access the workspace as a circular buffer +#define W(n) w[(n) & 0x0F] + +//SHA-256 auxiliary functions +#define CH(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define MAJ(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define SIGMA1(x) (ROR32(x, 2) ^ ROR32(x, 13) ^ ROR32(x, 22)) +#define SIGMA2(x) (ROR32(x, 6) ^ ROR32(x, 11) ^ ROR32(x, 25)) +#define SIGMA3(x) (ROR32(x, 7) ^ ROR32(x, 18) ^ SHR32(x, 3)) +#define SIGMA4(x) (ROR32(x, 17) ^ ROR32(x, 19) ^ SHR32(x, 10)) + +//SHA-256 padding +static const uint8_t padding[64] = +{ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +//SHA-256 constants +static const uint32_t k[64] = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 +}; + +//SHA-256 object identifier (2.16.840.1.101.3.4.2.1) +const uint8_t SHA256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}; + +//Common interface for hash algorithms +const HashAlgo sha256HashAlgo = +{ + "SHA-256", + SHA256_OID, + sizeof(SHA256_OID), + sizeof(Sha256Context), + SHA256_BLOCK_SIZE, + SHA256_DIGEST_SIZE, + SHA256_MIN_PAD_SIZE, + TRUE, + (HashAlgoCompute) sha256Compute, + (HashAlgoInit) sha256Init, + (HashAlgoUpdate) sha256Update, + (HashAlgoFinal) sha256Final, +#if ((defined(MIMXRT1050_CRYPTO_HASH_SUPPORT) && MIMXRT1050_CRYPTO_HASH_SUPPORT == ENABLED) || \ + (defined(MIMXRT1060_CRYPTO_HASH_SUPPORT) && MIMXRT1060_CRYPTO_HASH_SUPPORT == ENABLED) || \ + (defined(MIMXRT1160_CRYPTO_HASH_SUPPORT) && MIMXRT1160_CRYPTO_HASH_SUPPORT == ENABLED) || \ + (defined(MIMXRT1170_CRYPTO_HASH_SUPPORT) && MIMXRT1170_CRYPTO_HASH_SUPPORT == ENABLED)) + NULL, +#else + (HashAlgoFinalRaw) sha256FinalRaw +#endif +}; + + +/** + * @brief Digest a message using SHA-256 + * @param[in] data Pointer to the message being hashed + * @param[in] length Length of the message + * @param[out] digest Pointer to the calculated digest + * @return Error code + **/ + +__weak_func error_t sha256Compute(const void *data, size_t length, uint8_t *digest) +{ +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + Sha256Context *context; +#else + Sha256Context context[1]; +#endif + + //Check parameters + if(data == NULL && length != 0) + return ERROR_INVALID_PARAMETER; + + if(digest == NULL) + return ERROR_INVALID_PARAMETER; + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Allocate a memory buffer to hold the SHA-256 context + context = cryptoAllocMem(sizeof(Sha256Context)); + //Failed to allocate memory? + if(context == NULL) + return ERROR_OUT_OF_MEMORY; +#endif + + //Initialize the SHA-256 context + sha256Init(context); + //Digest the message + sha256Update(context, data, length); + //Finalize the SHA-256 message digest + sha256Final(context, digest); + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Free previously allocated memory + cryptoFreeMem(context); +#endif + + //Successful processing + return NO_ERROR; +} + + +/** + * @brief Initialize SHA-256 message digest context + * @param[in] context Pointer to the SHA-256 context to initialize + **/ + +__weak_func void sha256Init(Sha256Context *context) +{ + //Set initial hash value + context->h[0] = 0x6A09E667; + context->h[1] = 0xBB67AE85; + context->h[2] = 0x3C6EF372; + context->h[3] = 0xA54FF53A; + context->h[4] = 0x510E527F; + context->h[5] = 0x9B05688C; + context->h[6] = 0x1F83D9AB; + context->h[7] = 0x5BE0CD19; + + //Number of bytes in the buffer + context->size = 0; + //Total length of the message + context->totalSize = 0; +} + + +/** + * @brief Update the SHA-256 context with a portion of the message being hashed + * @param[in] context Pointer to the SHA-256 context + * @param[in] data Pointer to the buffer being hashed + * @param[in] length Length of the buffer + **/ + +__weak_func void sha256Update(Sha256Context *context, const void *data, size_t length) +{ + size_t n; + + //Process the incoming data + while(length > 0) + { + //The buffer can hold at most 64 bytes + n = MIN(length, 64 - context->size); + + //Copy the data to the buffer + osMemcpy(context->buffer + context->size, data, n); + + //Update the SHA-256 context + context->size += n; + context->totalSize += n; + //Advance the data pointer + data = (uint8_t *) data + n; + //Remaining bytes to process + length -= n; + + //Process message in 16-word blocks + if(context->size == 64) + { + //Transform the 16-word block + sha256ProcessBlock(context); + //Empty the buffer + context->size = 0; + } + } +} + + +/** + * @brief Finish the SHA-256 message digest + * @param[in] context Pointer to the SHA-256 context + * @param[out] digest Calculated digest (optional parameter) + **/ + +__weak_func void sha256Final(Sha256Context *context, uint8_t *digest) +{ + uint_t i; + size_t paddingSize; + uint64_t totalSize; + + //Length of the original message (before padding) + totalSize = context->totalSize * 8; + + //Pad the message so that its length is congruent to 56 modulo 64 + if(context->size < 56) + { + paddingSize = 56 - context->size; + } + else + { + paddingSize = 64 + 56 - context->size; + } + + //Append padding + sha256Update(context, padding, paddingSize); + + //Append the length of the original message + context->w[14] = htobe32((uint32_t) (totalSize >> 32)); + context->w[15] = htobe32((uint32_t) totalSize); + + //Calculate the message digest + sha256ProcessBlock(context); + + //Convert from host byte order to big-endian byte order + for(i = 0; i < 8; i++) + { + context->h[i] = htobe32(context->h[i]); + } + + //Copy the resulting digest + if(digest != NULL) + { + osMemcpy(digest, context->digest, SHA256_DIGEST_SIZE); + } +} + + +/** + * @brief Finish the SHA-256 message digest (no padding added) + * @param[in] context Pointer to the SHA-256 context + * @param[out] digest Calculated digest + **/ + +__weak_func void sha256FinalRaw(Sha256Context *context, uint8_t *digest) +{ + uint_t i; + + //Convert from host byte order to big-endian byte order + for(i = 0; i < 8; i++) + { + context->h[i] = htobe32(context->h[i]); + } + + //Copy the resulting digest + osMemcpy(digest, context->digest, SHA256_DIGEST_SIZE); + + //Convert from big-endian byte order to host byte order + for(i = 0; i < 8; i++) + { + context->h[i] = betoh32(context->h[i]); + } +} + + +/** + * @brief Process message in 16-word blocks + * @param[in] context Pointer to the SHA-256 context + **/ + +__weak_func void sha256ProcessBlock(Sha256Context *context) +{ + uint_t i; + uint32_t temp1; + uint32_t temp2; + + //Initialize the 8 working registers + uint32_t a = context->h[0]; + uint32_t b = context->h[1]; + uint32_t c = context->h[2]; + uint32_t d = context->h[3]; + uint32_t e = context->h[4]; + uint32_t f = context->h[5]; + uint32_t g = context->h[6]; + uint32_t h = context->h[7]; + + //Process message in 16-word blocks + uint32_t *w = context->w; + + //Convert from big-endian byte order to host byte order + for(i = 0; i < 16; i++) + { + w[i] = betoh32(w[i]); + } + + //SHA-256 hash computation (alternate method) + for(i = 0; i < 64; i++) + { + //Prepare the message schedule + if(i >= 16) + { + W(i) += SIGMA4(W(i + 14)) + W(i + 9) + SIGMA3(W(i + 1)); + } + + //Calculate T1 and T2 + temp1 = h + SIGMA2(e) + CH(e, f, g) + k[i] + W(i); + temp2 = SIGMA1(a) + MAJ(a, b, c); + + //Update working registers + h = g; + g = f; + f = e; + e = d + temp1; + d = c; + c = b; + b = a; + a = temp1 + temp2; + } + + //Update the hash value + context->h[0] += a; + context->h[1] += b; + context->h[2] += c; + context->h[3] += d; + context->h[4] += e; + context->h[5] += f; + context->h[6] += g; + context->h[7] += h; +} + +#endif diff --git a/quic.c b/quic.c deleted file mode 100644 index 339616b6..00000000 --- a/quic.c +++ /dev/null @@ -1,321 +0,0 @@ -#include "quic.h" -#include "logging.h" - - -/** - * Packet number. - */ -struct quic_pnumber { - uint8_t d1; - uint8_t d2; - uint8_t d3; - uint8_t d4; -}; - -uint64_t quic_parse_varlength(uint8_t *variable, uint64_t *mlen) { - if (mlen && *mlen == 0) return 0; - uint64_t vr = (*variable & 0x3F); - uint8_t len = 1 << (*variable >> 6); - - if (mlen) { - if (*mlen < len) return 0; - *mlen = len; - } - - ++variable; - for (uint8_t i = 1; i < len; i++) { - vr = (vr << 8) + *variable; - ++variable; - } - - return vr; -} - -int quic_parse_data(uint8_t *raw_payload, uint32_t raw_payload_len, - struct quic_lhdr **qch, uint32_t *qch_len, - struct quic_cids *qci, - uint8_t **payload, uint32_t *plen) { - if ( raw_payload == NULL || - raw_payload_len < sizeof(struct quic_lhdr)) - goto invalid_packet; - - struct quic_lhdr *nqch = (struct quic_lhdr *)raw_payload; - uint32_t left_len = raw_payload_len - sizeof(struct quic_lhdr); - uint8_t *cur_rawptr = raw_payload + sizeof(struct quic_lhdr); - if (!nqch->fixed) { - lgtrace_addp("quic fixed unset"); - return -EPROTO; - } - - uint8_t found = 0; - for (uint8_t i = 0; i < 2; i++) { - if (ntohl(nqch->version) == supported_versions[i]) { - found = 1; - } - } - - if (!found) { - lgtrace_addp("quic version undefined %d", ntohl(nqch->version)); - return -EPROTO; - } - - lgtrace_addp("quic version valid %d", ntohl(nqch->version)); - - if (left_len < 2) goto invalid_packet; - struct quic_cids nqci = {0}; - - nqci.dst_len = *cur_rawptr++; - left_len--; - if (left_len < nqci.dst_len) goto invalid_packet; - nqci.dst_id = cur_rawptr; - cur_rawptr += nqci.dst_len; - left_len -= nqci.dst_len; - - nqci.src_len = *cur_rawptr++; - left_len--; - if (left_len < nqci.src_len) goto invalid_packet; - nqci.src_id = cur_rawptr; - cur_rawptr += nqci.src_len; - left_len -= nqci.src_len; - - if (qch) *qch = nqch; - if (qch_len) { - *qch_len = sizeof(struct quic_lhdr) + - nqci.src_len + nqci.dst_len; - } - if (qci) *qci = nqci; - if (payload) *payload = cur_rawptr; - if (plen) *plen = left_len; - - return 0; - -invalid_packet: - return -EINVAL; -} - -int quic_parse_initial_message(uint8_t *inpayload, uint32_t inplen, - const struct quic_lhdr *qch, - struct quici_hdr *qhdr, - uint8_t **payload, uint32_t *plen) { - if (inplen < 3) goto invalid_packet; - struct quici_hdr nqhdr; - - uint8_t *cur_ptr = inpayload; - uint32_t left_len = inplen; - uint64_t tlen = left_len; - - nqhdr.token_len = quic_parse_varlength(cur_ptr, &tlen); - nqhdr.token = cur_ptr + tlen; - - if (left_len < nqhdr.token_len + tlen) - goto invalid_packet; - cur_ptr += tlen + nqhdr.token_len; - left_len -= tlen + nqhdr.token_len; - - tlen = left_len; - nqhdr.length = quic_parse_varlength(cur_ptr, &tlen); - - if (left_len != nqhdr.length + tlen && - left_len <= qch->number_length + 1) - goto invalid_packet; - - uint32_t packet_number = 0; - - for (uint8_t i = 0; i <= qch->number_length; i++) { - packet_number = (packet_number << 8) + *cur_ptr++; - left_len--; - } - - nqhdr.packet_number = packet_number; - - if (qhdr) *qhdr = nqhdr; - if (payload) *payload = cur_ptr; - if (plen) *plen = left_len; - - return 0; - -invalid_packet: - lgerror(-EINVAL, "QUIC invalid Initial packet"); - return -EINVAL; -} - -int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen) { - void *iph; - uint32_t iph_len; - struct udphdr *udph; - uint8_t *data; - uint32_t dlen; - int ret; - - ret = udp_payload_split(payload, *plen, - &iph, &iph_len, &udph, - &data, &dlen); - - uint32_t ipxv = netproto_version(payload, *plen); - - if (ret < 0) { - return ret; - } - - - if (strategy.strategy == FAKE_STRAT_TTL) { - lgtrace_addp("Set fake ttl to %d", strategy.faking_ttl); - - if (ipxv == IP4VERSION) { - ((struct iphdr *)iph)->ttl = strategy.faking_ttl; - } else if (ipxv == IP6VERSION) { - ((struct ip6_hdr *)iph)->ip6_hops = strategy.faking_ttl; - } else { - lgerror(-EINVAL, "fail_packet: IP version is unsupported"); - return -EINVAL; - } - } - - if (ipxv == IP4VERSION) { - ((struct iphdr *)iph)->frag_off = 0; - } - - - set_ip_checksum(iph, iph_len); - - if (strategy.strategy == FAKE_STRAT_UDP_CHECK) { - lgtrace_addp("break fake udp checksum"); - udph->check += 1; - } - - return 0; -} - -int gen_fake_udp(struct udp_fake_type type, - const void *ipxh, uint32_t iph_len, - const struct udphdr *udph, - uint8_t *buf, uint32_t *buflen) { - uint32_t data_len = type.fake_len; - - if (!ipxh || !udph || !buf || !buflen) - return -EINVAL; - - int ipxv = netproto_version(ipxh, iph_len); - - if (ipxv == IP4VERSION) { - const struct iphdr *iph = ipxh; - - memcpy(buf, iph, iph_len); - struct iphdr *niph = (struct iphdr *)buf; - - niph->protocol = IPPROTO_UDP; - } else if (ipxv == IP6VERSION) { - const struct ip6_hdr *iph = ipxh; - - iph_len = sizeof(struct ip6_hdr); - memcpy(buf, iph, iph_len); - struct ip6_hdr *niph = (struct ip6_hdr *)buf; - - niph->ip6_nxt = IPPROTO_UDP; - } else { - return -EINVAL; - } - - uint32_t dlen = iph_len + sizeof(struct udphdr) + data_len; - - if (*buflen < dlen) - return -ENOMEM; - - memcpy(buf + iph_len, udph, sizeof(struct udphdr)); - uint8_t *bfdptr = buf + iph_len + sizeof(struct udphdr); - - memset(bfdptr, 0, data_len); - - if (ipxv == IP4VERSION) { - struct iphdr *niph = (struct iphdr *)buf; - niph->tot_len = htons(dlen); - niph->id = randint(); - } else if (ipxv == IP6VERSION) { - struct ip6_hdr *niph = (struct ip6_hdr *)buf; - niph->ip6_plen = htons(dlen - iph_len); - } - - struct udphdr *nudph = (struct udphdr *)(buf + iph_len); - nudph->len = htons(sizeof(struct udphdr) + data_len); - - set_udp_checksum(nudph, buf, iph_len); - - udp_fail_packet(type.strategy, buf, &dlen, *buflen); - - *buflen = dlen; - - return 0; -} - -int detect_udp_filtered(const struct section_config_t *section, - const uint8_t *payload, uint32_t plen) { - const void *iph; - uint32_t iph_len; - const struct udphdr *udph; - const uint8_t *data; - uint32_t dlen; - int ret; - - ret = udp_payload_split((uint8_t *)payload, plen, - (void **)&iph, &iph_len, - (struct udphdr **)&udph, - (uint8_t **)&data, &dlen); - int udp_dport = ntohs(udph->dest); - lgtrace_addp("UDP dport: %d", udp_dport); - - - if (ret < 0) { - goto skip; - } - - if (section->udp_filter_quic) { - const struct quic_lhdr *qch; - uint32_t qch_len; - struct quic_cids qci; - uint8_t *quic_raw_payload; - uint32_t quic_raw_plen; - - lgtrace_addp("QUIC probe"); - - ret = quic_parse_data((uint8_t *)data, dlen, - (struct quic_lhdr **)&qch, &qch_len, &qci, - &quic_raw_payload, &quic_raw_plen); - - if (ret < 0) { - lgtrace_addp("QUIC undefined type"); - goto match_port; - } - - lgtrace_addp("QUIC detected"); - - uint8_t qtype = qch->type; - if (qch->version == QUIC_V1) - qtype = quic_convtype_v1(qtype); - else if (qch->version == QUIC_V2) - qtype = quic_convtype_v2(qtype); - - if (qtype != QUIC_INITIAL_TYPE) { - lgtrace_addp("QUIC message type: %d", qtype); - goto match_port; - } - - lgtrace_addp("QUIC initial message"); - - goto approve; - } - -match_port: - - for (int i = 0; i < section->udp_dport_range_len; i++) { - struct udp_dport_range crange = section->udp_dport_range[i]; - if (udp_dport >= crange.start && udp_dport <= crange.end) { - lgtrace_addp("matched to %d-%d", crange.start, crange.end); - goto approve; - } - } - -skip: - return 0; -approve: - return 1; -} diff --git a/quic.h b/quic.h deleted file mode 100644 index 04229417..00000000 --- a/quic.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef QUIC_H -#define QUIC_H -#include "types.h" -#include "utils.h" - - -/** -* @macro -* -* :macro:`NGTCP2_INITIAL_SALT_V1` is a salt value which is used to -* derive initial secret. It is used for QUIC v1. -*/ -#define QUIC_INITIAL_SALT_V1 \ - "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17\x9a\xe6\xa4\xc8\x0c\xad" \ - "\xcc\xbb\x7f\x0a" - -/** -* @macro -* -* :macro:`NGTCP2_INITIAL_SALT_V2` is a salt value which is used to -* derive initial secret. It is used for QUIC v2. -*/ -#define QUIC_INITIAL_SALT_V2 \ - "\x0d\xed\xe3\xde\xf7\x00\xa6\xdb\x81\x93\x81\xbe\x6e\x26\x9d\xcb" \ - "\xf9\xbd\x2e\xd9" - -#define QUIC_INITIAL_TYPE 0 -#define QUIC_0_RTT_TYPE 1 -#define QUIC_HANDSHAKE_TYPE 2 -#define QUIC_RETRY_TYPE 3 - -#define QUIC_INITIAL_TYPE_V1 0b00 -#define QUIC_0_RTT_TYPE_V1 0b01 -#define QUIC_HANDSHAKE_TYPE_V1 0b10 -#define QUIC_RETRY_TYPE_V1 0b11 -#define quic_convtype_v1(type) (type) - -#define QUIC_INITIAL_TYPE_V2 0b01 -#define QUIC_0_RTT_TYPE_V2 0b10 -#define QUIC_HANDSHAKE_TYPE_V2 0b11 -#define QUIC_RETRY_TYPE_V2 0b00 -#define quic_convtype_v2(type) (((type) + 1) & 0b11) - -#define QUIC_V1 1 // RFC 9000 -#define QUIC_V2 0x6b3343cf // RFC 9369 - -static const uint32_t supported_versions[] = { - QUIC_V1, - QUIC_V2, -}; - -/** - * Quic Large Header - */ -struct quic_lhdr { -#if __BYTE_ORDER == __LITTLE_ENDIAN - uint8_t number_length:2; - uint8_t reserved:2; - uint8_t type:2; - uint8_t fixed:1; - uint8_t form:1; -#elif __BYTE_ORDER == __BIG_ENDIAN - uint8_t form:1; - uint8_t fixed:1; - uint8_t type:2; - uint8_t reserved:2; - uint8_t number_length:2; -#else -#error "Undefined endian" -#endif - uint32_t version; -}__attribute__((packed)); - -/** - * Quic Large Header Ids - * (separated from the original header because of varying dst - */ -struct quic_cids { - uint8_t dst_len; - uint8_t *dst_id; - uint8_t src_len; - uint8_t *src_id; -}; - -/** - * Parses QUIС raw data (UDP payload) to quic large header and - * quic payload. - * - * \qch_len is sizeof(qch) + qci->dst_len + qci->src_id - * \payload is Type-Specific payload (#17.2). - */ -int quic_parse_data(uint8_t *raw_payload, uint32_t raw_payload_len, - struct quic_lhdr **qch, uint32_t *qch_len, - struct quic_cids *qci, - uint8_t **payload, uint32_t *plen); - - -/** - * Parses QUIC variable-length integer. (#16) - * \variable is a pointer to the sequence to be parsed - * (varlen integer in big endian format) - * - * \mlen Used to signal about variable length and validate left length - * in the buffer. - */ -uint64_t quic_parse_varlength(uint8_t *variable, uint64_t *mlen); - -// quici stands for QUIC Initial - -/** - * This structure should be parsed - */ -struct quici_hdr { - uint64_t token_len; - uint8_t *token; - uint64_t length; - uint32_t packet_number; -}; - -/** - * Parses QUIC initial payload. - * \inpayload is a raw QUIC payload (payload after quic large header) - */ -int quic_parse_initial_message(uint8_t *inpayload, uint32_t inplen, - const struct quic_lhdr *qch, - struct quici_hdr *qhdr, - uint8_t **payload, uint32_t *plen); - -// Like fail_packet for TCP -int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen); - -// Like gen_fake_sni for TCP -int gen_fake_udp(struct udp_fake_type type, - const void *ipxh, uint32_t iph_len, - const struct udphdr *udph, - uint8_t *buf, uint32_t *buflen); - -int detect_udp_filtered(const struct section_config_t *section, - const uint8_t *payload, uint32_t plen); - -#endif /* QUIC_H */ diff --git a/args.c b/src/args.c similarity index 93% rename from args.c rename to src/args.c index b0cae9ef..957d4eb4 100644 --- a/args.c +++ b/src/args.c @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #include "config.h" #include "types.h" @@ -349,7 +368,7 @@ void print_usage(const char *argv0) { printf("\t--udp-fake-len=\n"); printf("\t--udp-faking-strategy={checksum|ttl|none}\n"); printf("\t--udp-dport-filter=<5,6,200-500>\n"); - printf("\t--udp-filter-quic={disabled|all}\n"); + printf("\t--udp-filter-quic={disabled|all|parse}\n"); printf("\t--threads=\n"); printf("\t--packet-mark=\n"); printf("\t--connbytes-limit=\n"); @@ -745,6 +764,8 @@ int yparse_args(int argc, char *argv[]) { sect_config->udp_filter_quic = UDP_FILTER_QUIC_DISABLED; } else if (strcmp(optarg, "all") == 0) { sect_config->udp_filter_quic = UDP_FILTER_QUIC_ALL; + } else if (strcmp(optarg, "parse") == 0) { + sect_config->udp_filter_quic = UDP_FILTER_QUIC_PARSED; } else { goto invalid_opt; } @@ -803,23 +824,7 @@ static size_t print_config_section(const struct section_config_t *section, char size_t sz; if (section->tls_enabled) { - print_cnf_buf("--tls=enabled"); - if (section->all_domains) { - print_cnf_buf("--sni-domains=all"); - } else if (section->sni_domains != NULL) { - print_cnf_raw("--sni-domains="); - for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) { - print_cnf_raw("%s,", sne->domain_name); - } - print_cnf_raw(" "); - } - if (section->exclude_sni_domains != NULL) { - print_cnf_raw("--exclude-domains="); - for (struct domains_list *sne = section->exclude_sni_domains; sne != NULL; sne = sne->next) { - print_cnf_raw("%s,", sne->domain_name); - } - print_cnf_raw(" "); - } + print_cnf_buf("--tls=enabled"); switch(section->fragmentation_strategy) { case FRAG_STRAT_IP: @@ -874,17 +879,7 @@ static size_t print_config_section(const struct section_config_t *section, char print_cnf_buf("--fake-seq-offset=%d", section->fakeseq_offset); break; - } - - switch(section->sni_detection) { - case SNI_DETECTION_BRUTE: - print_cnf_buf("--sni-detection=brute"); - break; - case SNI_DETECTION_PARSE: - print_cnf_buf("--sni-detection=parse"); - break; - - } + } print_cnf_buf("--seg2delay=%d", section->seg2_delay); } @@ -892,6 +887,33 @@ static size_t print_config_section(const struct section_config_t *section, char print_cnf_buf("--tls=disabled"); } + if (section->all_domains) { + print_cnf_buf("--sni-domains=all"); + } else if (section->sni_domains != NULL) { + print_cnf_raw("--sni-domains="); + for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) { + print_cnf_raw("%s,", sne->domain_name); + } + print_cnf_raw(" "); + } + if (section->exclude_sni_domains != NULL) { + print_cnf_raw("--exclude-domains="); + for (struct domains_list *sne = section->exclude_sni_domains; sne != NULL; sne = sne->next) { + print_cnf_raw("%s,", sne->domain_name); + } + print_cnf_raw(" "); + } + + switch(section->sni_detection) { + case SNI_DETECTION_BRUTE: + print_cnf_buf("--sni-detection=brute"); + break; + case SNI_DETECTION_PARSE: + print_cnf_buf("--sni-detection=parse"); + break; + + } + if (section->synfake) { print_cnf_buf("--synfake=1"); print_cnf_buf("--synfake-len=%d", section->synfake_len); @@ -911,6 +933,9 @@ static size_t print_config_section(const struct section_config_t *section, char case UDP_FILTER_QUIC_DISABLED: print_cnf_buf("--udp-filter-quic=disabled"); break; + case UDP_FILTER_QUIC_PARSED: + print_cnf_buf("--udp-filter-quic=parse"); + break; } if (section->udp_dport_range_len != 0) { diff --git a/src/args.h b/src/args.h new file mode 100644 index 00000000..8860dbda --- /dev/null +++ b/src/args.h @@ -0,0 +1,42 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + +#ifndef ARGS_H +#define ARGS_H +#include "types.h" +#include "config.h" + +void print_version(void); +void print_usage(const char *argv0); +int yparse_args(int argc, char *argv[]); +size_t print_config(char *buffer, size_t buffer_size); + +// Initializes configuration storage. +int init_config(struct config_t *config); +// Allocates and initializes configuration section. +int init_section_config(struct section_config_t **section, struct section_config_t *prev); +// Frees configuration section +void free_config_section(struct section_config_t *config); +// Frees sections under config +void free_config(struct config_t config); + +/* Prints starting messages */ +void print_welcome(void); + +#endif /* ARGS_H */ diff --git a/config.h b/src/config.h similarity index 85% rename from config.h rename to src/config.h index b0ba1830..e685383b 100644 --- a/config.h +++ b/src/config.h @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #ifndef YTB_CONFIG_H #define YTB_CONFIG_H @@ -7,12 +26,12 @@ #include "types.h" -typedef int (*raw_send_t)(const unsigned char *data, unsigned int data_len); +typedef int (*raw_send_t)(const unsigned char *data, size_t data_len); /** * Sends the packet after delay_ms. The function should schedule send and return immediately * (for example, open daemon thread) */ -typedef int (*delayed_send_t)(const unsigned char *data, unsigned int data_len, unsigned int delay_ms); +typedef int (*delayed_send_t)(const unsigned char *data, size_t data_len, unsigned int delay_ms); struct instance_config_t { raw_send_t send_raw_packet; @@ -187,7 +206,7 @@ if ((fake_bitmask) & strategy) #define MAX_PACKET_SIZE 8192 -#define DEFAULT_SNISTR "googlevideo.com,ggpht.com,ytimg.com,youtube.com,play.google.com,youtu.be,googleapis.com,googleusercontent.com,gstatic.com,l.google.com" +#define DEFAULT_SNISTR "googlevideo.com,ggpht.com,ytimg.com,youtube.com,play.google.com,youtu.be,youtubei.googleapis.com,youtube.googleapis.com,youtubeembeddedplayer.googleapis.com,googleusercontent.com,gstatic.com,l.google.com" static const char default_snistr[] = DEFAULT_SNISTR; @@ -199,6 +218,7 @@ enum { enum { UDP_FILTER_QUIC_DISABLED, UDP_FILTER_QUIC_ALL, + UDP_FILTER_QUIC_PARSED, }; #define default_section_config { \ diff --git a/getopt.c b/src/getopt.c similarity index 80% rename from getopt.c rename to src/getopt.c index 48e76e17..f778168d 100644 --- a/getopt.c +++ b/src/getopt.c @@ -1,3 +1,27 @@ +/* + Copyright 2005-2014 Rich Felker, et al. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + + #include "types.h" #include "logging.h" #include "getopt.h" diff --git a/getopt.h b/src/getopt.h similarity index 100% rename from getopt.h rename to src/getopt.h diff --git a/kargs.c b/src/kargs.c similarity index 95% rename from kargs.c rename to src/kargs.c index 4b555537..de62e716 100644 --- a/kargs.c +++ b/src/kargs.c @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #include "config.h" #include "types.h" #include diff --git a/kytunblock.c b/src/kytunblock.c similarity index 89% rename from kytunblock.c rename to src/kytunblock.c index 7d079c56..013706b8 100644 --- a/kytunblock.c +++ b/src/kytunblock.c @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #ifndef KERNEL_SPACE #error "You are trying to compile the kernel module not in the kernel space" #endif @@ -60,7 +79,7 @@ static void close_raw_socket(void) { sock_release(rawsocket); } -static int send_raw_ipv4(const uint8_t *pkt, uint32_t pktlen) { +static int send_raw_ipv4(const uint8_t *pkt, size_t pktlen) { int ret = 0; if (pktlen > AVAILABLE_MTU) return -ENOMEM; @@ -122,7 +141,7 @@ static void close_raw6_socket(void) { sock_release(raw6socket); } -static int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen) { +static int send_raw_ipv6(const uint8_t *pkt, size_t pktlen) { int ret = 0; if (pktlen > AVAILABLE_MTU) return -ENOMEM; @@ -158,7 +177,7 @@ static int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen) { return ret; } -static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) { +static int send_raw_socket(const uint8_t *pkt, size_t pktlen) { int ret; if (pktlen > AVAILABLE_MTU) { @@ -175,8 +194,8 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) { NETBUF_FREE(buff2); return -ENOMEM; } - uint32_t buff1_size = MAX_PACKET_SIZE; - uint32_t buff2_size = MAX_PACKET_SIZE; + size_t buff1_size = MAX_PACKET_SIZE; + size_t buff2_size = MAX_PACKET_SIZE; if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128, buff1, &buff1_size, buff2, &buff2_size)) < 0) { @@ -222,7 +241,7 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) { return ret; } -static int delay_packet_send(const unsigned char *data, unsigned int data_len, unsigned int delay_ms) { +static int delay_packet_send(const unsigned char *data, size_t data_len, unsigned int delay_ms) { lginfo("delay_packet_send won't work on current youtubeUnblock version"); return send_raw_socket(data, data_len); } diff --git a/logging.h b/src/logging.h similarity index 70% rename from logging.h rename to src/logging.h index 31788e4b..25c36f25 100644 --- a/logging.h +++ b/src/logging.h @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #ifndef LOGGING_H #define LOGGING_H #include "config.h" diff --git a/mangle.c b/src/mangle.c similarity index 83% rename from mangle.c rename to src/mangle.c index 3cf210b3..e3bbafad 100644 --- a/mangle.c +++ b/src/mangle.c @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #define _GNU_SOURCE #include "types.h" // IWYU pragma: keep #include "mangle.h" @@ -11,16 +30,16 @@ #include #endif -int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) { +int process_packet(const uint8_t *raw_payload, size_t raw_payload_len) { if (raw_payload_len > MAX_PACKET_SIZE) { return PKT_ACCEPT; } const struct iphdr *iph; const struct ip6_hdr *ip6h; - uint32_t iph_len; + size_t iph_len; const uint8_t *ip_payload; - uint32_t ip_payload_len; + size_t ip_payload_len; int transport_proto = -1; int ipver = netproto_version(raw_payload, raw_payload_len); @@ -102,13 +121,13 @@ int process_packet(const uint8_t *raw_payload, uint32_t raw_payload_len) { return verdict; } -int process_tcp_packet(const struct section_config_t *section, const uint8_t *raw_payload, uint32_t raw_payload_len) { +int process_tcp_packet(const struct section_config_t *section, const uint8_t *raw_payload, size_t raw_payload_len) { const void *ipxh; - uint32_t iph_len; + size_t iph_len; const struct tcphdr *tcph; - uint32_t tcph_len; + size_t tcph_len; const uint8_t *data; - uint32_t dlen; + size_t dlen; int ipxv = netproto_version(raw_payload, raw_payload_len); @@ -134,7 +153,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra memcpy(payload, ipxh, iph_len); memcpy(payload + iph_len, tcph, tcph_len); - uint32_t fake_len = section->fake_sni_pkt_sz; + size_t fake_len = section->fake_sni_pkt_sz; if (section->synfake_len) fake_len = min(section->synfake_len, fake_len); @@ -177,13 +196,15 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra lgtrace_addp("TLS analyzed"); if (vrd.sni_len != 0) { - lgtrace_addp("SNI detected: %.*s", vrd.sni_len, data + vrd.sni_offset); + lgtrace_addp("SNI detected: %.*s", vrd.sni_len, vrd.sni_ptr); } if (vrd.target_sni) { - lgdebugmsg("Target SNI detected: %.*s", vrd.sni_len, data + vrd.sni_offset); + lgdebugmsg("Target SNI detected: %.*s", vrd.sni_len, vrd.sni_ptr); + size_t sni_offset = vrd.sni_ptr - data; + size_t target_sni_offset = vrd.target_sni_ptr - data; - uint32_t payload_len = raw_payload_len; + size_t payload_len = raw_payload_len; NETBUF_ALLOC(payload, MAX_PACKET_SIZE); if (!NETBUF_CHECK(payload)) { lgerror(-ENOMEM, "Allocation error"); @@ -193,11 +214,11 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra memcpy(payload, raw_payload, raw_payload_len); void *iph; - uint32_t iph_len; + size_t iph_len; struct tcphdr *tcph; - uint32_t tcph_len; + size_t tcph_len; uint8_t *data; - uint32_t dlen; + size_t dlen; int ret = tcp_payload_split(payload, payload_len, &iph, &iph_len, &tcph, &tcph_len, @@ -238,10 +259,10 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra switch (section->fragmentation_strategy) { case FRAG_STRAT_TCP: { - ipd_offset = vrd.sni_target_offset; - mid_offset = ipd_offset + vrd.sni_target_len / 2; + ipd_offset = target_sni_offset; + mid_offset = ipd_offset + vrd.target_sni_len / 2; - uint32_t poses[2]; + size_t poses[2]; int cnt = 0; if (section->frag_sni_pos && dlen > section->frag_sni_pos) { @@ -253,7 +274,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra } if (cnt > 1 && poses[0] > poses[1]) { - uint32_t tmp = poses[0]; + size_t tmp = poses[0]; poses[0] = poses[1]; poses[1] = tmp; } @@ -269,11 +290,11 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra break; case FRAG_STRAT_IP: if (ipxv == IP4VERSION) { - ipd_offset = ((char *)data - (char *)tcph) + vrd.sni_target_offset; - mid_offset = ipd_offset + vrd.sni_target_len / 2; + ipd_offset = ((char *)data - (char *)tcph) + target_sni_offset; + mid_offset = ipd_offset + vrd.target_sni_len / 2; mid_offset += 8 - mid_offset % 8; - uint32_t poses[2]; + size_t poses[2]; int cnt = 0; if (section->frag_sni_pos && dlen > section->frag_sni_pos) { @@ -287,7 +308,7 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra } if (cnt > 1 && poses[0] > poses[1]) { - uint32_t tmp = poses[0]; + size_t tmp = poses[0]; poses[0] = poses[1]; poses[1] = tmp; } @@ -335,12 +356,12 @@ int process_tcp_packet(const struct section_config_t *section, const uint8_t *ra return PKT_DROP; } -int process_udp_packet(const struct section_config_t *section, const uint8_t *pkt, uint32_t pktlen) { +int process_udp_packet(const struct section_config_t *section, const uint8_t *pkt, size_t pktlen) { const void *iph; - uint32_t iph_len; + size_t iph_len; const struct udphdr *udph; const uint8_t *data; - uint32_t dlen; + size_t dlen; int ret = udp_payload_split((uint8_t *)pkt, pktlen, (void **)&iph, &iph_len, @@ -377,7 +398,7 @@ int process_udp_packet(const struct section_config_t *section, const uint8_t *pk lgerror(-ENOMEM, "Allocation error"); return -ENOMEM; } - uint32_t fsn_len = MAX_PACKET_SIZE; + size_t fsn_len = MAX_PACKET_SIZE; struct udp_fake_type fake_type = { .fake_len = section->udp_fake_len, @@ -420,20 +441,20 @@ int process_udp_packet(const struct section_config_t *section, const uint8_t *pk return PKT_DROP; } -int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) { +int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet, size_t pktlen, const size_t *poses, size_t poses_sz, size_t dvs) { if (poses_sz == 0) { if (section->seg2_delay && ((dvs > 0) ^ section->frag_sni_reverse)) { if (!instance_config.send_delayed_packet) { return -EINVAL; } - lgtrace_addp("Sent %d delayed for %d", pktlen, section->seg2_delay); + lgtrace_addp("Sent %zu delayed for %d", pktlen, section->seg2_delay); instance_config.send_delayed_packet( packet, pktlen, section->seg2_delay); return 0; } else { - lgtrace_addp("Sent %d bytes", pktlen); + lgtrace_addp("Sent %zu bytes", pktlen); return instance_config.send_raw_packet( packet, pktlen); } @@ -461,26 +482,26 @@ int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet } */ - uint32_t f1len = MAX_PACKET_SIZE; - uint32_t f2len = MAX_PACKET_SIZE; - // uint32_t fake_pad_len = MAX_PACKET_SIZE; + size_t f1len = MAX_PACKET_SIZE; + size_t f2len = MAX_PACKET_SIZE; + // size_t fake_pad_len = MAX_PACKET_SIZE; int ret; if (dvs > poses[0]) { - lgerror(-EINVAL, "send_frags: Recursive dvs(%d) is more than poses0(%d)", dvs, poses[0]); + lgerror(-EINVAL, "send_frags: Recursive dvs(%zu) is more than poses0(%zu)", dvs, poses[0]); ret = -EINVAL; goto erret_lc; } - uint32_t frag_pos = poses[0] - dvs; + size_t frag_pos = poses[0] - dvs; frag_pos += 8 - frag_pos % 8; ret = ip4_frag(packet, pktlen, frag_pos, frag1, &f1len, frag2, &f2len); if (ret < 0) { - lgerror(ret, "send_frags: frag: with context packet with size %d, position: %d, recursive dvs: %d", pktlen, poses[0], dvs); + lgerror(ret, "send_frags: frag: with context packet with size %zu, position: %zu, recursive dvs: %zu", pktlen, poses[0], dvs); goto erret_lc; } @@ -501,7 +522,7 @@ int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet /* if (section->frag_sni_faked) { ITER_FAKE_STRAT(section->faking_strategy, strategy) { - uint32_t iphfl; + size_t iphfl; fake_pad_len = f2len; ret = ip4_payload_split(frag2, f2len, NULL, &iphfl, NULL, NULL); if (ret < 0) { @@ -552,7 +573,7 @@ int send_ip4_frags(const struct section_config_t *section, const uint8_t *packet return 0; } -int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet, uint32_t pktlen, const uint32_t *poses, uint32_t poses_sz, uint32_t dvs) { +int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet, size_t pktlen, const size_t *poses, size_t poses_sz, size_t dvs) { if (poses_sz == 0) { if (section->seg2_delay && ((dvs > 0) ^ section->frag_sni_reverse)) { if (!instance_config.send_delayed_packet) { @@ -564,7 +585,7 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet return 0; } else { - lgtrace_addp("raw send packet of %d bytes with %d dvs", pktlen, dvs); + lgtrace_addp("raw send packet of %zu bytes with %zu dvs", pktlen, dvs); return instance_config.send_raw_packet( packet, pktlen); } @@ -582,13 +603,13 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet return -ENOMEM; } - uint32_t f1len = MAX_PACKET_SIZE; - uint32_t f2len = MAX_PACKET_SIZE; + size_t f1len = MAX_PACKET_SIZE; + size_t f2len = MAX_PACKET_SIZE; int ret; if (dvs > poses[0]) { - lgerror(-EINVAL, "send_frags: Recursive dvs(%d) is more than poses0(%d)", dvs, poses[0]); + lgerror(-EINVAL, "send_frags: Recursive dvs(%zu) is more than poses0(%zu)", dvs, poses[0]); ret = -EINVAL; goto erret_lc; } @@ -598,16 +619,14 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet frag1, &f1len, frag2, &f2len); - lgtrace_addp("Packet split in %d bytes position of payload start, dvs: %d to two packets of %d and %d lengths", poses[0], dvs, f1len, f2len); + lgtrace_addp("Packet split in %zu bytes position of payload start, dvs: %zu to two packets of %zu and %zu lengths", poses[0], dvs, f1len, f2len); if (ret < 0) { - lgerror(ret, "send_frags: tcp_frag: with context packet with size %d, position: %d, recursive dvs: %d", pktlen, poses[0], dvs); + lgerror(ret, "send_frags: tcp_frag: with context packet with size %zu, position: %zu", pktlen, poses[0]); goto erret_lc; } - dvs += poses[0]; - if (section->frag_sni_reverse) goto send_frag2; @@ -624,7 +643,7 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet send_fake: if (section->frag_sni_faked) { - uint32_t iphfl, tcphfl; + size_t iphfl, tcphfl; void *iph; struct tcphdr *tcph; ret = tcp_payload_split(frag2, f2len, &iph, &iphfl, &tcph, &tcphfl, NULL, NULL); @@ -645,7 +664,7 @@ int send_tcp_frags(const struct section_config_t *section, const uint8_t *packet send_frag2: { - ret = send_tcp_frags(section, frag2, f2len, poses + 1, poses_sz - 1, dvs); + ret = send_tcp_frags(section, frag2, f2len, poses + 1, poses_sz - 1, poses[0]); if (ret < 0) { goto erret_lc; } @@ -693,7 +712,7 @@ int post_fake_sni(struct fake_type f_type, lgerror(-ENOMEM, "Allocation error"); return -ENOMEM; } - uint32_t fsn_len = MAX_PACKET_SIZE; + size_t fsn_len = MAX_PACKET_SIZE; ret = gen_fake_sni( fake_seq_type, @@ -715,9 +734,9 @@ int post_fake_sni(struct fake_type f_type, lgerror(ret, "send fake sni"); goto erret_lc; } - uint32_t iph_len; - uint32_t tcph_len; - uint32_t plen; + size_t iph_len; + size_t tcph_len; + size_t plen; ret = tcp_payload_split( fake_sni, fsn_len, &fsiph, &iph_len, diff --git a/mangle.h b/src/mangle.h similarity index 50% rename from mangle.h rename to src/mangle.h index 0644d6cd..51f190d3 100644 --- a/mangle.h +++ b/src/mangle.h @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #ifndef YU_MANGLE_H #define YU_MANGLE_H @@ -13,21 +32,21 @@ * Processes the packet and returns verdict. * This is the primary function that traverses the packet. */ -int process_packet(const uint8_t *packet, uint32_t packet_len); +int process_packet(const uint8_t *packet, size_t packet_len); /** * Processe the TCP packet. * Returns verdict. */ -int process_tcp_packet(const struct section_config_t *section, const uint8_t *raw_payload, uint32_t raw_payload_len); +int process_tcp_packet(const struct section_config_t *section, const uint8_t *raw_payload, size_t raw_payload_len); /** * Processes the UDP packet. * Returns verdict. */ -int process_udp_packet(const struct section_config_t *section, const uint8_t *pkt, uint32_t pktlen); +int process_udp_packet(const struct section_config_t *section, const uint8_t *pkt, size_t pktlen); @@ -44,8 +63,8 @@ int post_fake_sni(struct fake_type f_type, * dvs used internally and should be zero. */ int send_tcp_frags(const struct section_config_t *section, - const uint8_t *packet, uint32_t pktlen, - const uint32_t *poses, uint32_t poses_len, uint32_t dvs); + const uint8_t *packet, size_t pktlen, + const size_t *poses, size_t poses_len, size_t dvs); /** * Splits packet by poses and posts. @@ -53,6 +72,6 @@ int send_tcp_frags(const struct section_config_t *section, * dvs used internally and should be zero. */ int send_ip4_frags(const struct section_config_t *section, - const uint8_t *packet, uint32_t pktlen, - const uint32_t *poses, uint32_t poses_len, uint32_t dvs); + const uint8_t *packet, size_t pktlen, + const size_t *poses, size_t poses_len, size_t dvs); #endif /* YU_MANGLE_H */ diff --git a/src/quic.c b/src/quic.c new file mode 100644 index 00000000..b4c36476 --- /dev/null +++ b/src/quic.c @@ -0,0 +1,534 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + +#include "quic.h" +#include "tls.h" +#include "logging.h" + + +/** + * Packet number. + */ +struct quic_pnumber { + uint8_t d1; + uint8_t d2; + uint8_t d3; + uint8_t d4; +}; + +uint64_t quic_parse_varlength(const uint8_t *variable, size_t *mlen) { + if (mlen && *mlen == 0) return 0; + uint64_t vr = (*variable & 0x3F); + uint8_t len = 1 << (*variable >> 6); + + if (mlen) { + if (*mlen < len) { + *mlen = 0; + return 0; + } + *mlen = len; + } + + ++variable; + for (uint8_t i = 1; i < len; i++) { + vr = (vr << 8) + *variable; + ++variable; + } + + return vr; +} + +int quic_get_version(uint32_t *version, const struct quic_lhdr *qch) { + uint32_t qversion = ntohl(qch->version); + *version = qversion; + + switch (qversion) { + case QUIC_V1: + case QUIC_V2: + return 0; + default: + return -EINVAL; + } +} + +int quic_check_is_initial(const struct quic_lhdr *qch) { + uint32_t qversion; + int ret; + ret = quic_get_version(&qversion, qch); + if (qversion < 0) return 0; + + uint8_t qtype = qch->type; + + switch (qversion) { + case QUIC_V1: + qtype = quic_convtype_v1(qtype); + break; + case QUIC_V2: + qtype = quic_convtype_v2(qtype); + break; + default: + return 0; + } + + if (qtype != QUIC_INITIAL_TYPE) { + return 0; + } + + return 1; +} + +int quic_parse_data(const uint8_t *raw_payload, size_t raw_payload_len, + const struct quic_lhdr **qch, size_t *qch_len, + struct quic_cids *qci, + const uint8_t **payload, size_t *plen) { + if ( raw_payload == NULL || + raw_payload_len < sizeof(struct quic_lhdr)) + goto invalid_packet; + + const struct quic_lhdr *nqch = (const struct quic_lhdr *)raw_payload; + size_t left_len = raw_payload_len - sizeof(struct quic_lhdr); + const uint8_t *cur_rawptr = raw_payload + sizeof(struct quic_lhdr); + int ret; + uint32_t qversion; + + if (!nqch->fixed) { + lgtrace_addp("quic fixed unset"); + return -EPROTO; + } + + ret = quic_get_version(&qversion, nqch); + + if (ret < 0) { + lgtrace_addp("quic version undefined %u", qversion); + return -EPROTO; + } + + lgtrace_addp("quic version valid %u", qversion); + + if (left_len < 2) goto invalid_packet; + struct quic_cids nqci = {0}; + + nqci.dst_len = *cur_rawptr++; + left_len--; + if (left_len < nqci.dst_len) goto invalid_packet; + nqci.dst_id = cur_rawptr; + cur_rawptr += nqci.dst_len; + left_len -= nqci.dst_len; + + nqci.src_len = *cur_rawptr++; + left_len--; + if (left_len < nqci.src_len) goto invalid_packet; + nqci.src_id = cur_rawptr; + cur_rawptr += nqci.src_len; + left_len -= nqci.src_len; + + if (qch) *qch = nqch; + if (qch_len) { + *qch_len = sizeof(struct quic_lhdr) + + nqci.src_len + nqci.dst_len; + } + if (qci) *qci = nqci; + if (payload) *payload = cur_rawptr; + if (plen) *plen = left_len; + + return 0; + +invalid_packet: + return -EINVAL; +} + +int quic_parse_initial_header(const uint8_t *inpayload, size_t inplen, + struct quici_hdr *qhdr) { + if (inplen < 3) goto invalid_packet; + struct quici_hdr nqhdr; + + const uint8_t *cur_ptr = inpayload; + size_t left_len = inplen; + size_t tlen = left_len; + + nqhdr.token_len = quic_parse_varlength(cur_ptr, &tlen); + nqhdr.token = cur_ptr + tlen; + + if (left_len < nqhdr.token_len + tlen) + goto invalid_packet; + cur_ptr += tlen + nqhdr.token_len; + left_len -= tlen + nqhdr.token_len; + + tlen = left_len; + nqhdr.length = quic_parse_varlength(cur_ptr, &tlen); + + if (left_len < nqhdr.length + tlen || + nqhdr.length < QUIC_SAMPLE_SIZE + + QUIC_SAMPLE_OFFSET + ) + goto invalid_packet; + cur_ptr += tlen; + + nqhdr.protected_payload = cur_ptr; + nqhdr.sample = cur_ptr + QUIC_SAMPLE_OFFSET; + nqhdr.sample_length = QUIC_SAMPLE_SIZE; + + if (qhdr) *qhdr = nqhdr; + + return 0; + +invalid_packet: + lgerror(-EINVAL, "QUIC invalid Initial packet"); + return -EINVAL; +} + +ssize_t quic_parse_crypto(struct quic_frame_crypto *crypto_frame, + const uint8_t *frame, size_t flen) { + const uint8_t *curptr = frame; + size_t curptr_len = flen; + size_t vln; + *crypto_frame = (struct quic_frame_crypto){0}; + + if (flen == 0 || *frame != QUIC_FRAME_CRYPTO || + crypto_frame == NULL) + return -EINVAL; + + + curptr++, curptr_len--; + + vln = curptr_len; + size_t offset = quic_parse_varlength(curptr, &vln); + curptr += vln, curptr_len -= vln; + if (vln == 0) { + return -EINVAL; + } + + + vln = curptr_len; + size_t length = quic_parse_varlength(curptr, &vln); + curptr += vln, curptr_len -= vln; + if (vln == 0) { + return -EINVAL; + } + + if (length > curptr_len) + return -EINVAL; + + crypto_frame->offset = offset; + crypto_frame->payload_length = length; + crypto_frame->payload = curptr; + + curptr += length; + curptr_len -= length; + + return flen - curptr_len; +} + +int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, size_t *plen, size_t avail_buflen) { + void *iph; + size_t iph_len; + struct udphdr *udph; + uint8_t *data; + size_t dlen; + int ret; + + ret = udp_payload_split(payload, *plen, + &iph, &iph_len, &udph, + &data, &dlen); + + uint32_t ipxv = netproto_version(payload, *plen); + + if (ret < 0) { + return ret; + } + + + if (strategy.strategy == FAKE_STRAT_TTL) { + lgtrace_addp("Set fake ttl to %d", strategy.faking_ttl); + + if (ipxv == IP4VERSION) { + ((struct iphdr *)iph)->ttl = strategy.faking_ttl; + } else if (ipxv == IP6VERSION) { + ((struct ip6_hdr *)iph)->ip6_hops = strategy.faking_ttl; + } else { + lgerror(-EINVAL, "fail_packet: IP version is unsupported"); + return -EINVAL; + } + } + + if (ipxv == IP4VERSION) { + ((struct iphdr *)iph)->frag_off = 0; + } + + + set_ip_checksum(iph, iph_len); + + if (strategy.strategy == FAKE_STRAT_UDP_CHECK) { + lgtrace_addp("break fake udp checksum"); + udph->check += 1; + } + + return 0; +} + +int gen_fake_udp(struct udp_fake_type type, + const void *ipxh, size_t iph_len, + const struct udphdr *udph, + uint8_t *buf, size_t *buflen) { + size_t data_len = type.fake_len; + + if (!ipxh || !udph || !buf || !buflen) + return -EINVAL; + + int ipxv = netproto_version(ipxh, iph_len); + + if (ipxv == IP4VERSION) { + const struct iphdr *iph = ipxh; + + memcpy(buf, iph, iph_len); + struct iphdr *niph = (struct iphdr *)buf; + + niph->protocol = IPPROTO_UDP; + } else if (ipxv == IP6VERSION) { + const struct ip6_hdr *iph = ipxh; + + iph_len = sizeof(struct ip6_hdr); + memcpy(buf, iph, iph_len); + struct ip6_hdr *niph = (struct ip6_hdr *)buf; + + niph->ip6_nxt = IPPROTO_UDP; + } else { + return -EINVAL; + } + + size_t dlen = iph_len + sizeof(struct udphdr) + data_len; + + if (*buflen < dlen) + return -ENOMEM; + + memcpy(buf + iph_len, udph, sizeof(struct udphdr)); + uint8_t *bfdptr = buf + iph_len + sizeof(struct udphdr); + + memset(bfdptr, 0, data_len); + + if (ipxv == IP4VERSION) { + struct iphdr *niph = (struct iphdr *)buf; + niph->tot_len = htons(dlen); + niph->id = randint(); + } else if (ipxv == IP6VERSION) { + struct ip6_hdr *niph = (struct ip6_hdr *)buf; + niph->ip6_plen = htons(dlen - iph_len); + } + + struct udphdr *nudph = (struct udphdr *)(buf + iph_len); + nudph->len = htons(sizeof(struct udphdr) + data_len); + + set_udp_checksum(nudph, buf, iph_len); + + udp_fail_packet(type.strategy, buf, &dlen, *buflen); + + *buflen = dlen; + + return 0; +} + +int parse_quic_decrypted( + const struct section_config_t *section, + const uint8_t *decrypted_message, size_t decrypted_message_len, + uint8_t **crypto_message_buf, size_t *crypto_message_buf_len +) { + const uint8_t *curptr = decrypted_message; + ssize_t curptr_len = decrypted_message_len; + ssize_t fret; + int ret; + struct tls_verdict tlsv = {0}; + struct quic_frame_crypto fr_cr; + + uint8_t *crypto_message = calloc(AVAILABLE_MTU, 1); + if (crypto_message == NULL) { + lgerror(-ENOMEM, "No memory"); + return -ENOMEM; + } + + int crypto_message_len = AVAILABLE_MTU; + + while (curptr_len > 0) { + uint8_t type = curptr[0]; + switch (type) { + case QUIC_FRAME_PING: + lgtrace_addp("ping"); + goto pl_incr; + case QUIC_FRAME_PADDING: + if (curptr == decrypted_message || + *(curptr - 1) != QUIC_FRAME_PADDING) { + lgtrace_addp("padding"); + } +pl_incr: + curptr++, curptr_len--; + break; + case QUIC_FRAME_CRYPTO: + fret = quic_parse_crypto(&fr_cr, curptr, curptr_len); + lgtrace_addp("crypto len=%zu offset=%zu fret=%zd", fr_cr.payload_length, fr_cr.offset, fret); + if (fret < 0) { + lgtrace_addp("Crypto parse error"); + goto out; + } + + curptr += fret; + curptr_len -= fret; + + if (fr_cr.offset <= crypto_message_len && + fr_cr.payload_length <= crypto_message_len && + fr_cr.payload_length <= crypto_message_len + ) { + + memcpy(crypto_message + fr_cr.offset, + fr_cr.payload, fr_cr.payload_length); + } + + break; + default: + lgtrace_addp("Frame invalid hash: %02x", type); + goto out; + } + } + +out: + *crypto_message_buf = crypto_message; + *crypto_message_buf_len = crypto_message_len; + + return 0; +} + +int detect_udp_filtered(const struct section_config_t *section, + const uint8_t *payload, size_t plen) { + const void *iph; + size_t iph_len; + const struct udphdr *udph; + const uint8_t *data; + size_t dlen; + int ret; + + ret = udp_payload_split((uint8_t *)payload, plen, + (void **)&iph, &iph_len, + (struct udphdr **)&udph, + (uint8_t **)&data, &dlen); + int udp_dport = ntohs(udph->dest); + lgtrace_addp("UDP dport: %d", udp_dport); + + + if (ret < 0) { + goto skip; + } + + if (section->udp_filter_quic != UDP_FILTER_QUIC_DISABLED) { + const struct quic_lhdr *qch; + size_t qch_len; + struct quic_cids qci; + const uint8_t *quic_in_payload; + size_t quic_in_plen; + + lgtrace_addp("QUIC probe"); + + ret = quic_parse_data((uint8_t *)data, dlen, + &qch, &qch_len, &qci, + &quic_in_payload, &quic_in_plen); + + if (ret < 0) { + lgtrace_addp("QUIC undefined type"); + goto match_port; + } + + lgtrace_addp("QUIC detected"); + + + if (!quic_check_is_initial(qch)) { + lgtrace_addp("QUIC not initial"); + goto match_port; + } + + lgtrace_addp("QUIC initial message"); + + if (section->udp_filter_quic == UDP_FILTER_QUIC_ALL) { + lgtrace_addp("QUIC early approve"); + goto approve; + } + + uint8_t *decrypted_payload; + size_t decrypted_payload_len; + const uint8_t *decrypted_message; + size_t decrypted_message_len; + uint8_t *crypto_message; + size_t crypto_message_len; + struct tls_verdict tlsv; + + ret = quic_parse_initial_message( + data, dlen, + &decrypted_payload, &decrypted_payload_len, + &decrypted_message, &decrypted_message_len + ); + + if (ret < 0) { + goto match_port; + } + + ret = parse_quic_decrypted(section, + decrypted_message, decrypted_message_len, + &crypto_message, &crypto_message_len + ); + free(decrypted_payload); + decrypted_payload = NULL; + + if (ret < 0) { + goto match_port; + } + + if (section->sni_detection == SNI_DETECTION_BRUTE) { + ret = bruteforce_analyze_sni_str(section, crypto_message, crypto_message_len, &tlsv); + } else { + ret = analyze_tls_message( + section, crypto_message, crypto_message_len, &tlsv + ); + } + + if (tlsv.sni_len != 0) { + lgtrace_addp("QUIC SNI detected: %.*s", tlsv.sni_len, tlsv.sni_ptr); + } + + if (tlsv.target_sni) { + lgdebugmsg("QUIC target SNI detected: %.*s", tlsv.sni_len, tlsv.sni_ptr); + free(crypto_message); + crypto_message = NULL; + goto approve; + } + + free(crypto_message); + crypto_message = NULL; + } + +match_port: + + for (int i = 0; i < section->udp_dport_range_len; i++) { + struct udp_dport_range crange = section->udp_dport_range[i]; + if (udp_dport >= crange.start && udp_dport <= crange.end) { + lgtrace_addp("matched to %d-%d", crange.start, crange.end); + goto approve; + } + } + +skip: + return 0; +approve: + return 1; +} diff --git a/src/quic.h b/src/quic.h new file mode 100644 index 00000000..6c3f810e --- /dev/null +++ b/src/quic.h @@ -0,0 +1,246 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + +#ifndef QUIC_H +#define QUIC_H +#include "types.h" +#include "utils.h" + + +/** +* @macro +* +* :macro:`NGTCP2_INITIAL_SALT_V1` is a salt value which is used to +* derive initial secret. It is used for QUIC v1. +*/ +#define QUIC_INITIAL_SALT_V1 \ + "\x38\x76\x2c\xf7\xf5\x59\x34\xb3\x4d\x17\x9a\xe6\xa4\xc8\x0c\xad" \ + "\xcc\xbb\x7f\x0a" + +/** +* @macro +* +* :macro:`NGTCP2_INITIAL_SALT_V2` is a salt value which is used to +* derive initial secret. It is used for QUIC v2. +*/ +#define QUIC_INITIAL_SALT_V2 \ + "\x0d\xed\xe3\xde\xf7\x00\xa6\xdb\x81\x93\x81\xbe\x6e\x26\x9d\xcb" \ + "\xf9\xbd\x2e\xd9" + +#define QUIC_INITIAL_TYPE 0 +#define QUIC_0_RTT_TYPE 1 +#define QUIC_HANDSHAKE_TYPE 2 +#define QUIC_RETRY_TYPE 3 + +#define QUIC_INITIAL_TYPE_V1 0b00 +#define QUIC_0_RTT_TYPE_V1 0b01 +#define QUIC_HANDSHAKE_TYPE_V1 0b10 +#define QUIC_RETRY_TYPE_V1 0b11 +#define quic_convtype_v1(type) (type) + +#define QUIC_INITIAL_TYPE_V2 0b01 +#define QUIC_0_RTT_TYPE_V2 0b10 +#define QUIC_HANDSHAKE_TYPE_V2 0b11 +#define QUIC_RETRY_TYPE_V2 0b00 +#define quic_convtype_v2(type) (((type) + 1) & 0b11) + +#define QUIC_FRAME_CRYPTO 0x06 +#define QUIC_FRAME_PADDING 0x00 +#define QUIC_FRAME_PING 0x01 + +#define QUIC_V1 1 // RFC 9000 +#define QUIC_V2 0x6b3343cf // RFC 9369 + +static const uint32_t supported_versions[] = { + QUIC_V1, + QUIC_V2, +}; + +// In bytes +#define QUIC_SAMPLE_OFFSET 4 + +#define QUIC_SAMPLE_SIZE 16 +#define QUIC_INITIAL_SECRET_SIZE 32 +#define QUIC_CLIENT_IN_SIZE 32 +#define QUIC_KEY_SIZE 16 +#define QUIC_IV_SIZE 12 +#define QUIC_HP_SIZE 16 +// Altough tag is not defined, it present in the end of message +#define QUIC_TAG_SIZE 16 + + +/** + * Describes type-specific bytes for Initial message + */ +struct quici_lhdr_typespec { +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t number_length:2;//protected + uint8_t reserved:2; //protected + uint8_t discard:4; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint8_t discard:4; + uint8_t reserved:2; //protected + uint8_t number_length:2;//protected +#else +#error "Undefined endian" +#endif +}__attribute__((packed)); + +/** + * Quic Large Header + */ +struct quic_lhdr { +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t type_specific:4;// protected + uint8_t type:2; + uint8_t fixed:1; + uint8_t form:1; +#elif __BYTE_ORDER == __BIG_ENDIAN + uint8_t form:1; + uint8_t fixed:1; + uint8_t type:2; + uint8_t type_specific:4;// protected +#else +#error "Undefined endian" +#endif + uint32_t version; +}__attribute__((packed)); + +/** + * Quic Large Header Ids + * (separated from the original header because of varying dst + */ +struct quic_cids { + uint8_t dst_len; + const uint8_t *dst_id; + uint8_t src_len; + const uint8_t *src_id; +}; + +/** + * Parses QUIС raw data (UDP payload) to quic large header and + * quic payload. + * + * \qch_len is sizeof(qch) + qci->dst_len + qci->src_id + * \payload is Type-Specific payload (#17.2). + */ +int quic_parse_data(const uint8_t *raw_payload, size_t raw_payload_len, + const struct quic_lhdr **qch, size_t *qch_len, + struct quic_cids *qci, + const uint8_t **payload, size_t *plen); + + +/** + * Parses QUIC variable-length integer. (#16) + * \variable is a pointer to the sequence to be parsed + * (varlen integer in big endian format) + * + * \mlen Used to signal about variable length and validate left length + * in the buffer. + * + * On error/buffer overflow mlen set to 0, otherwise it is higher + */ +uint64_t quic_parse_varlength(const uint8_t *variable, size_t *mlen); + +// quici stands for QUIC Initial + +/** + * This structure should be parsed + */ +struct quici_hdr { + size_t token_len; + const uint8_t *token; + size_t length; + + const uint8_t *protected_payload; // with packet number + + // RFC 9001 5.4.2 + size_t sample_length; + const uint8_t *sample; +}; + +/** + * Checks for quic version and checks if it is supported + */ +int quic_get_version(uint32_t *version, const struct quic_lhdr *qch); + +/** +* Checks quic message to be initial according to version. +* 0 on false, 1 on true +*/ +int quic_check_is_initial(const struct quic_lhdr *qch); + +struct quic_frame_crypto { + size_t offset; + size_t payload_length; + const uint8_t *payload; +}; +/** + * Parses quic crypto frame + * Returns parsed size or -EINVAL on error + */ +ssize_t quic_parse_crypto(struct quic_frame_crypto *crypto_frame, + const uint8_t *frame, size_t flen); + + +/** + * Parses QUIC initial message header. + * \inpayload is a QUIC Initial message payload (payload after quic large header) + */ +int quic_parse_initial_header(const uint8_t *inpayload, size_t inplen, + struct quici_hdr *qhdr); + +/** + * Parses and decrypts QUIC Initial Message. + * + * \quic_header QUIC payload, the start of UDP payload + * \udecrypted_payload QUIC decrypted payload. Contains all the QUIC packet, with all headers + * \udecrypted_message QUIC decrypted message, typically TLS Client Hello + * + */ +int quic_parse_initial_message( + const uint8_t *quic_payload, size_t quic_plen, + uint8_t **udecrypted_payload, size_t *udecrypted_payload_len, + const uint8_t **udecrypted_message, size_t *udecrypted_message_len +); + +/** + * CRYPTO frames may be randomly spried in the message. + * This function _allocates_ crypto_message_buf and fills it with CRYPTO frames + * according to offset and payload_length + */ +int parse_quic_decrypted( + const struct section_config_t *section, + const uint8_t *decrypted_message, size_t decrypted_message_len, + uint8_t **crypto_message_buf, size_t *crypto_message_buf_len +); + +// Like fail_packet for TCP +int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, size_t *plen, size_t avail_buflen); + +// Like gen_fake_sni for TCP +int gen_fake_udp(struct udp_fake_type type, + const void *ipxh, size_t iph_len, + const struct udphdr *udph, + uint8_t *buf, size_t *buflen); + +int detect_udp_filtered(const struct section_config_t *section, + const uint8_t *payload, size_t plen); + +#endif /* QUIC_H */ diff --git a/src/quic_crypto.c b/src/quic_crypto.c new file mode 100644 index 00000000..5e498b37 --- /dev/null +++ b/src/quic_crypto.c @@ -0,0 +1,276 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + +#include "quic.h" +#include "kdf/hkdf.h" +#include "hash/sha256.h" +#include "cipher/aes.h" +#include "cipher_modes/ecb.h" +#include "aead/gcm.h" +#include "logging.h" + +const uint8_t quic_client_in_info[] = "\0\x20\x0ftls13 client in\0"; +const uint8_t quic_key_info[] = "\0\x10\x0etls13 quic key\0"; +const uint8_t quic_iv_info[] = "\0\x0c\x0dtls13 quic iv\0"; +const uint8_t quic_hp_info[] = "\0\x10\x0dtls13 quic hp\0"; +const uint8_t quic2_key_info[] = "\0\x10\x10tls13 quicv2 key\0"; +const uint8_t quic2_iv_info[] = "\0\x0c\x0ftls13 quicv2 iv\0"; +const uint8_t quic2_hp_info[] = "\0\x10\x0ftls13 quicv2 hp\0"; + +int quic_parse_initial_message( + const uint8_t *quic_payload, size_t quic_plen, + uint8_t **udecrypted_payload, size_t *udecrypted_payload_len, + const uint8_t **udecrypted_message, size_t *udecrypted_message_len +) { + int ret; + const struct quic_lhdr *qch; + size_t qch_len; + struct quic_cids qci; + const uint8_t *inpayload; + size_t inplen; + struct quici_hdr qich; + + size_t quic_header_len; + size_t inheader_len; + struct quici_lhdr_typespec qich_ltspc; + int packet_number_length; + const uint8_t *packet_number = NULL; + const uint8_t *protected_payload = NULL; + size_t protected_payload_length; + + uint8_t initial_secret[QUIC_INITIAL_SECRET_SIZE]; + uint8_t client_initial_secret[QUIC_CLIENT_IN_SIZE]; + uint8_t quic_key[QUIC_KEY_SIZE]; + uint8_t quic_iv[QUIC_IV_SIZE]; + uint8_t quic_hp[QUIC_HP_SIZE]; + uint8_t mask[QUIC_SAMPLE_SIZE]; + uint8_t *decrypted_payload = NULL; + size_t decrypted_payload_len; + uint8_t *decrypted_packet_number = NULL; + uint8_t *dcptr = NULL; + // Decrypted plain message without header + uint8_t *decrypted_message = NULL; + size_t decrypted_message_len; + AesContext actx; + GcmContext gctx; + uint32_t qversion; + const uint8_t *iv_info; + size_t iv_info_size; + const uint8_t *key_info; + size_t key_info_size; + const uint8_t *hp_info; + size_t hp_info_size; + const uint8_t *initial_salt; + size_t initial_salt_size; + + ret = quic_parse_data(quic_payload, quic_plen, + &qch, &qch_len, &qci, &inpayload, &inplen + ); + + ret = quic_get_version(&qversion, qch); + if (ret < 0) { + return -EINVAL; + } + if (!quic_check_is_initial(qch)) { + return -EINVAL; + } + + switch (qversion) { + case QUIC_V1: + iv_info = quic_iv_info; + iv_info_size = sizeof(quic_iv_info) - 1; + key_info = quic_key_info; + key_info_size = sizeof(quic_key_info) - 1; + hp_info = quic_hp_info; + hp_info_size = sizeof(quic_hp_info) - 1; + initial_salt = (const uint8_t *)QUIC_INITIAL_SALT_V1; + initial_salt_size = sizeof(QUIC_INITIAL_SALT_V1) - 1; + break; + case QUIC_V2: + iv_info = quic2_iv_info; + iv_info_size = sizeof(quic2_iv_info) - 1; + key_info = quic2_key_info; + key_info_size = sizeof(quic2_key_info) - 1; + hp_info = quic2_hp_info; + hp_info_size = sizeof(quic2_hp_info) - 1; + initial_salt = (const uint8_t *)QUIC_INITIAL_SALT_V2; + initial_salt_size = sizeof(QUIC_INITIAL_SALT_V2) - 1; + break; + default: + return -EINVAL; + } + + quic_header_len = inpayload - quic_payload; + if (ret < 0) { + lgerror(ret, "quic_parse_data"); + goto error_nfr; + } + + ret = quic_parse_initial_header(inpayload, inplen, &qich); + if (ret < 0) { + lgerror(ret, "quic_parse_initial_header"); + goto error_nfr; + } + + inheader_len = qich.protected_payload - inpayload; + + decrypted_payload_len = quic_header_len + inplen; + decrypted_payload = malloc(decrypted_payload_len); + if (decrypted_payload == NULL) { + ret = -ENOMEM; + goto error_nfr; + } + dcptr = decrypted_payload; + // Copy quic large header + memcpy(dcptr, quic_payload, quic_header_len); + dcptr += quic_header_len; + + + // Copy quic initial large header (until packet number) + memcpy(dcptr, inpayload, inheader_len); + dcptr += inheader_len; + + + ret = hkdfExtract(SHA256_HASH_ALGO, (const unsigned char *)qci.dst_id, qci.dst_len, initial_salt, initial_salt_size, initial_secret); + if (ret) { + lgerr("hkdfExtract initial_secret: %d", ret); + ret = -EINVAL; + goto error; + } + + ret = hkdfExpand(SHA256_HASH_ALGO, initial_secret, SHA256_DIGEST_SIZE, quic_client_in_info, sizeof(quic_client_in_info) - 1, client_initial_secret, QUIC_CLIENT_IN_SIZE); + if (ret) { + lgerr("hkdfExpand client_initial_secret: %d", ret); + ret = -EINVAL; + goto error; + } + + ret = hkdfExpand(SHA256_HASH_ALGO, client_initial_secret, SHA256_DIGEST_SIZE, key_info, key_info_size, quic_key, QUIC_KEY_SIZE); + if (ret) { + lgerr("hkdfExpand quic_key: %d", ret); + ret = -EINVAL; + goto error; + } + + ret = hkdfExpand(SHA256_HASH_ALGO, client_initial_secret, SHA256_DIGEST_SIZE, iv_info, iv_info_size, quic_iv, QUIC_IV_SIZE); + if (ret) { + lgerr("hkdfExpand quic_iv: %d", ret); + ret = -EINVAL; + goto error; + } + + ret = hkdfExpand(SHA256_HASH_ALGO, client_initial_secret, SHA256_DIGEST_SIZE, hp_info, hp_info_size, quic_hp, QUIC_HP_SIZE); + if (ret) { + lgerr("hkdfExpand quic_hp: %d", ret); + ret = -EINVAL; + goto error; + } + + // Decrypt packet number length and packet number + ret = aesInit(&actx, quic_hp, QUIC_HP_SIZE); + if (ret) { + lgerr("aesInit with quic_hp: %d", ret); + ret = -EINVAL; + goto error; + } + ret = ecbEncrypt(&aesCipherAlgo, &actx, + qich.sample, mask, qich.sample_length); + if (ret) { + lgerr("ecbEncrypt for mask: %d", ret); + ret = -EINVAL; + goto error; + } + + // Update decrypted payload header with decrypted packet_number_length + decrypted_payload[0] ^= mask[0] & 0x0f; + + qich_ltspc = (struct quici_lhdr_typespec){decrypted_payload[0]}; + + packet_number_length = qich_ltspc.number_length + 1; + if (qich.length < packet_number_length) { + ret = -EINVAL; + goto error; + } + + packet_number = qich.protected_payload; + protected_payload = qich.protected_payload + packet_number_length; + protected_payload_length = qich.length - packet_number_length; + + decrypted_packet_number = dcptr; + + for (int i = 0; i < packet_number_length; i++) { + decrypted_packet_number[i] = packet_number[i] ^ mask[i + 1]; + } + dcptr += packet_number_length; + + for (int i = QUIC_IV_SIZE - packet_number_length, j = 0; + i < QUIC_IV_SIZE; i++, j++) { + + quic_iv[i] ^= decrypted_packet_number[j]; + } + + ret = aesInit(&actx, quic_key, QUIC_KEY_SIZE); + if (ret) { + lgerr("aesInit for quic_key: %d", ret); + ret = -EINVAL; + goto error; + } + ret = gcmInit(&gctx, &aesCipherAlgo, &actx); + if (ret) { + lgerr("gcmInit: %d", ret); + ret = -EINVAL; + goto error; + } + + decrypted_message = dcptr; + + ret = gcmDecrypt( + &gctx, quic_iv, QUIC_IV_SIZE, + NULL, 0, + protected_payload, decrypted_message, protected_payload_length, + quic_key, QUIC_KEY_SIZE + ); + if (ret != 0 && ret != ERROR_FAILURE) { + lgerr("gcmInit: %d", ret); + ret = -EINVAL; + goto error; + } + // TAG is padded in the end of decrypted message + decrypted_message_len = protected_payload_length - QUIC_TAG_SIZE; + + if (!udecrypted_payload) { + lgerr("decrypted_payload cannot be NULL!"); + ret = -EINVAL; + goto error; + } + + *udecrypted_payload = decrypted_payload; + if (udecrypted_payload_len) + *udecrypted_payload_len = decrypted_payload_len; + if (udecrypted_message) + *udecrypted_message = decrypted_message; + if (udecrypted_message_len) + *udecrypted_message_len = decrypted_message_len; + + return 0; +error: + free(decrypted_payload); +error_nfr: + return ret; +} diff --git a/raw_replacements.h b/src/raw_replacements.h similarity index 100% rename from raw_replacements.h rename to src/raw_replacements.h diff --git a/src/tls.c b/src/tls.c new file mode 100644 index 00000000..ac12b7e3 --- /dev/null +++ b/src/tls.c @@ -0,0 +1,400 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + +#include "types.h" +#include "tls.h" +#include "config.h" +#include "logging.h" +#include "utils.h" + +#ifndef KERNEL_SPACE +#include +#include +#endif + +int bruteforce_analyze_sni_str( + const struct section_config_t *section, + const uint8_t *data, size_t dlen, + struct tls_verdict *vrd +) { + *vrd = (struct tls_verdict){0}; + + if (section->all_domains) { + vrd->target_sni = 1; + vrd->sni_len = 0; + vrd->sni_ptr = data + dlen / 2; + return 0; + } + + for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) { + const char *domain_startp = sne->domain_name; + int domain_len = sne->domain_len; + + if (sne->domain_len + dlen + 1 > MAX_PACKET_SIZE) { + continue; + } + + NETBUF_ALLOC(buf, MAX_PACKET_SIZE); + if (!NETBUF_CHECK(buf)) { + lgerror(-ENOMEM, "Allocation error"); + return -ENOMEM; + } + NETBUF_ALLOC(nzbuf, MAX_PACKET_SIZE * sizeof(int)); + if (!NETBUF_CHECK(nzbuf)) { + lgerror(-ENOMEM, "Allocation error"); + NETBUF_FREE(buf); + return -ENOMEM; + } + + int *zbuf = (void *)nzbuf; + + memcpy(buf, domain_startp, domain_len); + memcpy(buf + domain_len, "#", 1); + memcpy(buf + domain_len + 1, data, dlen); + + z_function((char *)buf, zbuf, domain_len + 1 + dlen); + + for (unsigned int k = 0; k < dlen; k++) { + if (zbuf[k] == domain_len) { + vrd->target_sni = 1; + vrd->sni_len = domain_len; + vrd->sni_ptr = data + (k - domain_len - 1); + vrd->target_sni_ptr = vrd->sni_ptr; + vrd->target_sni_len = vrd->sni_len; + NETBUF_FREE(buf); + NETBUF_FREE(nzbuf); + return 0; + } + } + + + NETBUF_FREE(buf); + NETBUF_FREE(nzbuf); + } + + return 0; +} +static int analyze_sni_str( + const struct section_config_t *section, + const char *sni_name, int sni_len, + struct tls_verdict *vrd +) { + if (section->all_domains) { + vrd->target_sni = 1; + goto check_domain; + } + + for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) { + const char *sni_startp = sni_name + sni_len - sne->domain_len; + const char *domain_startp = sne->domain_name; + + if (sni_len >= sne->domain_len && + sni_len < 128 && + !strncmp(sni_startp, + domain_startp, + sne->domain_len)) { + vrd->target_sni = 1; + vrd->target_sni_ptr = (const uint8_t *)sni_startp; + vrd->target_sni_len = sne->domain_len; + break; + } + } + +check_domain: + if (vrd->target_sni == 1) { + for (struct domains_list *sne = section->exclude_sni_domains; sne != NULL; sne = sne->next) { + const char *sni_startp = sni_name + sni_len - sne->domain_len; + const char *domain_startp = sne->domain_name; + + if (sni_len >= sne->domain_len && + sni_len < 128 && + !strncmp(sni_startp, + domain_startp, + sne->domain_len)) { + vrd->target_sni = 0; + lgdebugmsg("Excluded SNI: %.*s", + vrd->sni_len, vrd->sni_ptr); + } + } + } + + return 0; +} + +int analyze_tls_message( + const struct section_config_t *section, + const uint8_t *message_data, + size_t message_length, + struct tls_verdict *tlsv +) { + *tlsv = (struct tls_verdict){0}; + const uint8_t *handshakeProto = message_data; + const uint8_t *data_end = message_data + message_length; + + if (handshakeProto + 1 >= data_end) + goto invalid; + + uint8_t handshakeType = *handshakeProto; + + if (handshakeType != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) + goto next; + + const uint8_t *msgPtr = handshakeProto; + msgPtr += 1; + msgPtr += 3 + 2 + 32; + + if (msgPtr + 1 >= data_end) + goto invalid; + uint8_t sessionIdLength = *msgPtr; + msgPtr++; + msgPtr += sessionIdLength; + + if (msgPtr + 2 >= data_end) + goto invalid; + uint16_t ciphersLength = ntohs(*(uint16_t *)msgPtr); + msgPtr += 2; + msgPtr += ciphersLength; + + if (msgPtr + 1 >= data_end) + goto invalid; + uint8_t compMethodsLen = *msgPtr; + msgPtr++; + msgPtr += compMethodsLen; + + if (msgPtr + 2 >= data_end) + goto invalid; + uint16_t extensionsLen = ntohs(*(uint16_t *)msgPtr); + msgPtr += 2; + + const uint8_t *extensionsPtr = msgPtr; + const uint8_t *extensions_end = extensionsPtr + extensionsLen; + if (extensions_end > data_end) extensions_end = data_end; + + while (extensionsPtr < extensions_end) { + const uint8_t *extensionPtr = extensionsPtr; + if (extensionPtr + 4 >= extensions_end) + goto invalid; + + uint16_t extensionType = + ntohs(*(uint16_t *)extensionPtr); + extensionPtr += 2; + + uint16_t extensionLen = + ntohs(*(uint16_t *)extensionPtr); + extensionPtr += 2; + + + if (extensionPtr + extensionLen > extensions_end) + goto invalid; + + if (extensionType != TLS_EXTENSION_SNI) + goto nextExtension; + + const uint8_t *sni_ext_ptr = extensionPtr; + + if (sni_ext_ptr + 2 >= extensions_end) + goto invalid; + uint16_t sni_ext_dlen = ntohs(*(uint16_t *)sni_ext_ptr); + + sni_ext_ptr += 2; + + const uint8_t *sni_ext_end = sni_ext_ptr + sni_ext_dlen; + if (sni_ext_end > extensions_end) + goto invalid; + + if (sni_ext_ptr + 3 >= sni_ext_end) + goto invalid; + sni_ext_ptr++; + uint16_t sni_len = ntohs(*(uint16_t *)sni_ext_ptr); + sni_ext_ptr += 2; + + if (sni_ext_ptr + sni_len > sni_ext_end) + goto invalid; + + const char *sni_name = (char *)sni_ext_ptr; + + tlsv->sni_ptr = (const uint8_t *)sni_name; + tlsv->sni_len = sni_len; + tlsv->target_sni_ptr = tlsv->sni_ptr; + tlsv->target_sni_len = tlsv->sni_len; + + analyze_sni_str(section, sni_name, sni_len, tlsv); + return TLS_MESSAGE_ANALYZE_FOUND; + +nextExtension: + extensionsPtr += 2 + 2 + extensionLen; + } + +next: + return TLS_MESSAGE_ANALYZE_GOTO_NEXT; +invalid: + return TLS_MESSAGE_ANALYZE_INVALID; +} + +/** + * Processes tls payload of the tcp request. + * + * data Payload data of TCP. + * dlen Length of `data`. + */ +struct tls_verdict analyze_tls_data( + const struct section_config_t *section, + const uint8_t *data, + size_t dlen) +{ + struct tls_verdict vrd = {0}; + + const uint8_t *data_end = data + dlen; + const uint8_t *message_ptr = data; + int ret; + + if (section->sni_detection == SNI_DETECTION_BRUTE) { + bruteforce_analyze_sni_str(section, data, dlen, &vrd); + goto out; + } + + while (message_ptr + 5 < data_end) { + uint8_t tls_content_type = *message_ptr; + message_ptr++; + + uint8_t tls_vmajor = *message_ptr; + if (tls_vmajor != 0x03) break; + message_ptr++; + + uint8_t tls_vminor = *message_ptr; + message_ptr++; + + uint16_t message_length = ntohs(*(const uint16_t *)message_ptr); + message_ptr += 2; + + + const uint8_t *tls_message_data = message_ptr; + // Since real length may be truncated use minimum of two + size_t tls_message_length = min(message_length, data_end - message_ptr); + + if (tls_content_type != TLS_CONTENT_TYPE_HANDSHAKE) + goto nextMessage; + + ret = analyze_tls_message( + section, + tls_message_data, + tls_message_length, + &vrd + ); + + switch (ret) { + case TLS_MESSAGE_ANALYZE_GOTO_NEXT: + goto nextMessage; + case TLS_MESSAGE_ANALYZE_FOUND: + case TLS_MESSAGE_ANALYZE_INVALID: + default: + goto out; + + } + +nextMessage: + message_ptr += tls_message_length; + } + +out: + return vrd; +} + +int gen_fake_sni(struct fake_type type, + const void *ipxh, size_t iph_len, + const struct tcphdr *tcph, size_t tcph_len, + uint8_t *buf, size_t *buflen) { + size_t data_len = type.fake_len; + + if (type.type == FAKE_PAYLOAD_RANDOM && data_len == 0) { + data_len = (size_t)randint() % 1200; + } + + if (!ipxh || !tcph || !buf || !buflen) + return -EINVAL; + + int ipxv = netproto_version(ipxh, iph_len); + + if (ipxv == IP4VERSION) { + const struct iphdr *iph = ipxh; + + memcpy(buf, iph, iph_len); + struct iphdr *niph = (struct iphdr *)buf; + + niph->protocol = IPPROTO_TCP; + } else if (ipxv == IP6VERSION) { + const struct ip6_hdr *iph = ipxh; + + iph_len = sizeof(struct ip6_hdr); + memcpy(buf, iph, iph_len); + struct ip6_hdr *niph = (struct ip6_hdr *)buf; + + niph->ip6_nxt = IPPROTO_TCP; + } else { + return -EINVAL; + } + + size_t dlen = iph_len + tcph_len + data_len; + + if (*buflen < dlen) + return -ENOMEM; + + memcpy(buf + iph_len, tcph, tcph_len); + uint8_t *bfdptr = buf + iph_len + tcph_len; + + switch (type.type) { + case FAKE_PAYLOAD_DATA: + memcpy(bfdptr, type.fake_data, data_len); + break; + default: // FAKE_PAYLOAD_RANDOM +#ifdef KERNEL_SPACE + get_random_bytes(bfdptr, data_len); +#else /* KERNEL_SPACE */ +#if _NO_GETRANDOM + { + int ret = open("/dev/urandom", O_RDONLY); + if (ret < 0) { + lgerror(ret, "Unable to open /dev/urandom"); + return ret; + } + + read(ret, bfdptr, data_len); + close(ret); + } +#else /* _NO_GETRANDOM */ + getrandom(bfdptr, data_len, 0); +#endif /* _NO_GETRANDOM */ +#endif /* KERNEL_SPACE */ + } + + if (ipxv == IP4VERSION) { + struct iphdr *niph = (struct iphdr *)buf; + niph->tot_len = htons(dlen); + } else if (ipxv == IP6VERSION) { + struct ip6_hdr *niph = (struct ip6_hdr *)buf; + niph->ip6_plen = htons(dlen - iph_len); + } + + fail_packet(type.strategy, buf, &dlen, *buflen); + + *buflen = dlen; + + return 0; +} + diff --git a/src/tls.h b/src/tls.h new file mode 100644 index 00000000..6f96fcc5 --- /dev/null +++ b/src/tls.h @@ -0,0 +1,85 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + +#ifndef TLS_H +#define TLS_H + +#include "types.h" +#include "utils.h" + + +/** + * Result of analyze_tls_data function + */ +struct tls_verdict { + const uint8_t *sni_ptr; + int sni_len; + + int target_sni; /* boolean, 1 if target found */ + const uint8_t *target_sni_ptr; /* pointer to target domain instead of entire sni */ + int target_sni_len; /* length of target domain instead of entire sni */ +}; + +#define TLS_CONTENT_TYPE_HANDSHAKE 0x16 +#define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 0x01 +#define TLS_EXTENSION_SNI 0x0000 +#define TLS_EXTENSION_CLIENT_HELLO_ENCRYPTED 0xfe0d + +#define TLS_MESSAGE_ANALYZE_INVALID -1 +#define TLS_MESSAGE_ANALYZE_FOUND 0 +#define TLS_MESSAGE_ANALYZE_GOTO_NEXT 1 + +/** + * Analyzes each TLS Client Hello message (inside TLS Record or QUIC CRYPTO FRAME) + */ +int analyze_tls_message( + const struct section_config_t *section, + const uint8_t *message_data, + size_t message_length, + struct tls_verdict *tlsv +); + +/** + * Tries to bruteforce over the packet and match domains as plain text + */ +int bruteforce_analyze_sni_str( + const struct section_config_t *section, + const uint8_t *data, size_t dlen, + struct tls_verdict *vrd +); + + +/** + * Processes the packet and finds TLS Client Hello information inside it. + * data pointer points to start of TLS Message (TCP Payload) + * + * Note that all the constant pointers of tls_verdict will be relative to data pointer + */ +struct tls_verdict analyze_tls_data(const struct section_config_t *section, const uint8_t *data, size_t dlen); + + +/** + * Generates the fake client hello message + */ +int gen_fake_sni(struct fake_type type, + const void *iph, size_t iph_len, + const struct tcphdr *tcph, size_t tcph_len, + uint8_t *buf, size_t *buflen); + +#endif /* TLS_H */ diff --git a/types.h b/src/types.h similarity index 74% rename from types.h rename to src/types.h index e35733b8..0f2b7fa5 100644 --- a/types.h +++ b/src/types.h @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #define _GNU_SOURCE #ifndef TYPES_H #define TYPES_H @@ -8,6 +27,18 @@ #include // IWYU pragma: export #include + +typedef __u8 uint8_t; +typedef __u16 uint16_t; +typedef __u32 uint32_t; +typedef __u64 uint64_t; +typedef __s8 int8_t; +typedef __s16 int16_t; +typedef __s32 int32_t; +typedef __s64 int64_t; + +typedef __s32 int_least32_t; /* integer of >= 32 bits */ +typedef __s16 int_least16_t; /* integer of >= 16 bits */ #else /* USER_SPACE */ #include // IWYU pragma: export @@ -36,6 +67,7 @@ #define free kfree #define malloc(size) kmalloc((size), GFP_KERNEL) +#define calloc(n, size) kcalloc((n), (size), GFP_KERNEL) #define ip6_hdr ipv6hdr diff --git a/utils.c b/src/utils.c similarity index 79% rename from utils.c rename to src/utils.c index ecb6af57..5bb7a3ce 100644 --- a/utils.c +++ b/src/utils.c @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #include "utils.h" #include "logging.h" #include "types.h" @@ -21,7 +40,7 @@ void tcp4_set_checksum(struct tcphdr *tcph, struct iphdr *iph) { #ifdef KERNEL_SPACE - uint32_t tcp_packet_len = ntohs(iph->tot_len) - (iph->ihl << 2); + size_t tcp_packet_len = ntohs(iph->tot_len) - (iph->ihl << 2); tcph->check = 0; tcph->check = csum_tcpudp_magic( iph->saddr, iph->daddr, tcp_packet_len, @@ -35,7 +54,7 @@ void tcp4_set_checksum(struct tcphdr *tcph, struct iphdr *iph) void udp4_set_checksum(struct udphdr *udph, struct iphdr *iph) { #ifdef KERNEL_SPACE - uint32_t udp_packet_len = ntohs(iph->tot_len) - (iph->ihl << 2); + size_t udp_packet_len = ntohs(iph->tot_len) - (iph->ihl << 2); udph->check = 0; udph->check = csum_tcpudp_magic( iph->saddr, iph->daddr, udp_packet_len, @@ -78,7 +97,7 @@ void udp6_set_checksum(struct udphdr *udph, struct ip6_hdr *iph) { #endif } -int set_ip_checksum(void *iph, uint32_t iphb_len) { +int set_ip_checksum(void *iph, size_t iphb_len) { int ipvx = netproto_version(iph, iphb_len); if (ipvx == IP4VERSION) { @@ -90,7 +109,7 @@ int set_ip_checksum(void *iph, uint32_t iphb_len) { return 0; } -int set_tcp_checksum(struct tcphdr *tcph, void *iph, uint32_t iphb_len) { +int set_tcp_checksum(struct tcphdr *tcph, void *iph, size_t iphb_len) { int ipvx = netproto_version(iph, iphb_len); if (ipvx == IP4VERSION) { @@ -103,7 +122,7 @@ int set_tcp_checksum(struct tcphdr *tcph, void *iph, uint32_t iphb_len) { return 0; } -int set_udp_checksum(struct udphdr *udph, void *iph, uint32_t iphb_len) { +int set_udp_checksum(struct udphdr *udph, void *iph, size_t iphb_len) { int ipvx = netproto_version(iph, iphb_len); if (ipvx == IP4VERSION) { @@ -118,9 +137,9 @@ int set_udp_checksum(struct udphdr *udph, void *iph, uint32_t iphb_len) { } -int ip4_payload_split(uint8_t *pkt, uint32_t buflen, - struct iphdr **iph, uint32_t *iph_len, - uint8_t **payload, uint32_t *plen) { +int ip4_payload_split(uint8_t *pkt, size_t buflen, + struct iphdr **iph, size_t *iph_len, + uint8_t **payload, size_t *plen) { if (pkt == NULL || buflen < sizeof(struct iphdr)) { lgerror(-EINVAL, "ip4_payload_split: pkt|buflen"); return -EINVAL; @@ -132,8 +151,8 @@ int ip4_payload_split(uint8_t *pkt, uint32_t buflen, return -EINVAL; } - uint32_t hdr_len = hdr->ihl * 4; - uint32_t pktlen = ntohs(hdr->tot_len); + size_t hdr_len = hdr->ihl * 4; + size_t pktlen = ntohs(hdr->tot_len); if (buflen < pktlen || hdr_len > pktlen) { lgerror(-EINVAL, "ip4_payload_split: buflen cmp pktlen"); return -EINVAL; @@ -151,17 +170,17 @@ int ip4_payload_split(uint8_t *pkt, uint32_t buflen, return 0; } -int tcp4_payload_split(uint8_t *pkt, uint32_t buflen, - struct iphdr **iph, uint32_t *iph_len, - struct tcphdr **tcph, uint32_t *tcph_len, - uint8_t **payload, uint32_t *plen) { +int tcp4_payload_split(uint8_t *pkt, size_t buflen, + struct iphdr **iph, size_t *iph_len, + struct tcphdr **tcph, size_t *tcph_len, + uint8_t **payload, size_t *plen) { struct iphdr *hdr; - uint32_t hdr_len; + size_t hdr_len; struct tcphdr *thdr; - uint32_t thdr_len; + size_t thdr_len; uint8_t *tcph_pl; - uint32_t tcph_plen; + size_t tcph_plen; if (ip4_payload_split(pkt, buflen, &hdr, &hdr_len, &tcph_pl, &tcph_plen)){ @@ -193,9 +212,9 @@ int tcp4_payload_split(uint8_t *pkt, uint32_t buflen, return 0; } -int ip6_payload_split(uint8_t *pkt, uint32_t buflen, - struct ip6_hdr **iph, uint32_t *iph_len, - uint8_t **payload, uint32_t *plen) { +int ip6_payload_split(uint8_t *pkt, size_t buflen, + struct ip6_hdr **iph, size_t *iph_len, + uint8_t **payload, size_t *plen) { if (pkt == NULL || buflen < sizeof(struct ip6_hdr)) { lgerror(-EINVAL, "ip6_payload_split: pkt|buflen"); return -EINVAL; @@ -207,10 +226,10 @@ int ip6_payload_split(uint8_t *pkt, uint32_t buflen, return -EINVAL; } - uint32_t hdr_len = sizeof(struct ip6_hdr); - uint32_t pktlen = ntohs(hdr->ip6_plen); + size_t hdr_len = sizeof(struct ip6_hdr); + size_t pktlen = ntohs(hdr->ip6_plen); if (buflen < pktlen) { - lgerror(-EINVAL, "ip6_payload_split: buflen cmp pktlen: %d %d", buflen, pktlen); + lgerror(-EINVAL, "ip6_payload_split: buflen cmp pktlen: %zu %zu", buflen, pktlen); return -EINVAL; } @@ -226,17 +245,17 @@ int ip6_payload_split(uint8_t *pkt, uint32_t buflen, return 0; } -int tcp6_payload_split(uint8_t *pkt, uint32_t buflen, - struct ip6_hdr **iph, uint32_t *iph_len, - struct tcphdr **tcph, uint32_t *tcph_len, - uint8_t **payload, uint32_t *plen) { +int tcp6_payload_split(uint8_t *pkt, size_t buflen, + struct ip6_hdr **iph, size_t *iph_len, + struct tcphdr **tcph, size_t *tcph_len, + uint8_t **payload, size_t *plen) { struct ip6_hdr *hdr; - uint32_t hdr_len; + size_t hdr_len; struct tcphdr *thdr; - uint32_t thdr_len; + size_t thdr_len; uint8_t *tcph_pl; - uint32_t tcph_plen; + size_t tcph_plen; if (ip6_payload_split(pkt, buflen, &hdr, &hdr_len, &tcph_pl, &tcph_plen)){ @@ -268,10 +287,10 @@ int tcp6_payload_split(uint8_t *pkt, uint32_t buflen, return 0; } -int tcp_payload_split(uint8_t *pkt, uint32_t buflen, - void **iph, uint32_t *iph_len, - struct tcphdr **tcph, uint32_t *tcph_len, - uint8_t **payload, uint32_t *plen) { +int tcp_payload_split(uint8_t *pkt, size_t buflen, + void **iph, size_t *iph_len, + struct tcphdr **tcph, size_t *tcph_len, + uint8_t **payload, size_t *plen) { int netvers = netproto_version(pkt, buflen); if (netvers == IP4VERSION) { return tcp4_payload_split(pkt, buflen, (struct iphdr **)iph, iph_len, tcph, tcph_len, payload, plen); @@ -284,16 +303,16 @@ int tcp_payload_split(uint8_t *pkt, uint32_t buflen, } -int udp4_payload_split(uint8_t *pkt, uint32_t buflen, - struct iphdr **iph, uint32_t *iph_len, +int udp4_payload_split(uint8_t *pkt, size_t buflen, + struct iphdr **iph, size_t *iph_len, struct udphdr **udph, - uint8_t **payload, uint32_t *plen) { + uint8_t **payload, size_t *plen) { struct iphdr *hdr; - uint32_t hdr_len; + size_t hdr_len; struct udphdr *uhdr; uint8_t *ip_ph; - uint32_t ip_phlen; + size_t ip_phlen; if (ip4_payload_split(pkt, buflen, &hdr, &hdr_len, &ip_ph, &ip_phlen)){ @@ -322,16 +341,16 @@ int udp4_payload_split(uint8_t *pkt, uint32_t buflen, return 0; } -int udp6_payload_split(uint8_t *pkt, uint32_t buflen, - struct ip6_hdr **iph, uint32_t *iph_len, +int udp6_payload_split(uint8_t *pkt, size_t buflen, + struct ip6_hdr **iph, size_t *iph_len, struct udphdr **udph, - uint8_t **payload, uint32_t *plen) { + uint8_t **payload, size_t *plen) { struct ip6_hdr *hdr; - uint32_t hdr_len; + size_t hdr_len; struct udphdr *uhdr; uint8_t *ip_ph; - uint32_t ip_phlen; + size_t ip_phlen; if (ip6_payload_split(pkt, buflen, &hdr, &hdr_len, &ip_ph, &ip_phlen)){ @@ -360,10 +379,10 @@ int udp6_payload_split(uint8_t *pkt, uint32_t buflen, return 0; } -int udp_payload_split(uint8_t *pkt, uint32_t buflen, - void **iph, uint32_t *iph_len, +int udp_payload_split(uint8_t *pkt, size_t buflen, + void **iph, size_t *iph_len, struct udphdr **udph, - uint8_t **payload, uint32_t *plen) { + uint8_t **payload, size_t *plen) { int netvers = netproto_version(pkt, buflen); if (netvers == IP4VERSION) { return udp4_payload_split(pkt, buflen, (struct iphdr **)iph, iph_len, udph, payload, plen); @@ -376,14 +395,14 @@ int udp_payload_split(uint8_t *pkt, uint32_t buflen, } // split packet to two ipv4 fragments. -int ip4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset, - uint8_t *frag1, uint32_t *f1len, - uint8_t *frag2, uint32_t *f2len) { +int ip4_frag(const uint8_t *pkt, size_t buflen, size_t payload_offset, + uint8_t *frag1, size_t *f1len, + uint8_t *frag2, size_t *f2len) { struct iphdr *hdr; const uint8_t *payload; - uint32_t plen; - uint32_t hdr_len; + size_t plen; + size_t hdr_len; int ret; if (!frag1 || !f1len || !frag2 || !f2len) @@ -406,11 +425,11 @@ int ip4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset, return -EINVAL; } - uint32_t f1_plen = payload_offset; - uint32_t f1_dlen = f1_plen + hdr_len; + size_t f1_plen = payload_offset; + size_t f1_dlen = f1_plen + hdr_len; - uint32_t f2_plen = plen - payload_offset; - uint32_t f2_dlen = f2_plen + hdr_len; + size_t f2_plen = plen - payload_offset; + size_t f2_dlen = f2_plen + hdr_len; if (*f1len < f1_dlen || *f2len < f2_dlen) { return -ENOMEM; @@ -455,15 +474,15 @@ int ip4_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset, } // split packet to two tcp-on-ipv4 segments. -int tcp_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset, - uint8_t *seg1, uint32_t *s1len, - uint8_t *seg2, uint32_t *s2len) { +int tcp_frag(const uint8_t *pkt, size_t buflen, size_t payload_offset, + uint8_t *seg1, size_t *s1len, + uint8_t *seg2, size_t *s2len) { void *hdr; - uint32_t hdr_len; + size_t hdr_len; struct tcphdr *tcph; - uint32_t tcph_len; - uint32_t plen; + size_t tcph_len; + size_t plen; const uint8_t *payload; int ret; @@ -499,11 +518,11 @@ int tcp_frag(const uint8_t *pkt, uint32_t buflen, uint32_t payload_offset, return -EINVAL; } - uint32_t s1_plen = payload_offset; - uint32_t s1_dlen = s1_plen + hdr_len + tcph_len; + size_t s1_plen = payload_offset; + size_t s1_dlen = s1_plen + hdr_len + tcph_len; - uint32_t s2_plen = plen - payload_offset; - uint32_t s2_dlen = s2_plen + hdr_len + tcph_len; + size_t s2_plen = plen - payload_offset; + size_t s2_dlen = s2_plen + hdr_len + tcph_len; if (*s1len < s1_dlen || *s2len < s2_dlen) return -ENOMEM; @@ -570,7 +589,7 @@ void z_function(const char *str, int *zbuf, size_t len) { } } -void shift_data(uint8_t *data, uint32_t dlen, uint32_t delta) { +void shift_data(uint8_t *data, size_t dlen, size_t delta) { uint8_t *ndptr = data + delta + dlen; uint8_t *dptr = data + dlen; uint8_t *ndlptr = data; @@ -594,20 +613,20 @@ struct tcp_md5sig_opt { // Real length of the option, with NOOP fillers #define TCP_MD5SIG_OPT_RLEN 20 -int fail_packet(struct failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen) { +int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen, size_t avail_buflen) { void *iph; - uint32_t iph_len; + size_t iph_len; struct tcphdr *tcph; - uint32_t tcph_len; + size_t tcph_len; uint8_t *data; - uint32_t dlen; + size_t dlen; int ret; ret = tcp_payload_split(payload, *plen, &iph, &iph_len, &tcph, &tcph_len, &data, &dlen); - uint32_t ipxv = netproto_version(payload, *plen); + int ipxv = netproto_version(payload, *plen); if (ret < 0) { return ret; @@ -691,15 +710,15 @@ int fail_packet(struct failing_strategy strategy, uint8_t *payload, uint32_t *pl return 0; } -int seqovl_packet(uint8_t *payload, uint32_t *plen, uint32_t seq_delta) { +int seqovl_packet(uint8_t *payload, size_t *plen, size_t seq_delta) { int ipxv = netproto_version(payload, *plen); void *iph; - uint32_t iph_len; + size_t iph_len; struct tcphdr *tcph; - uint32_t tcph_len; + size_t tcph_len; uint8_t *data; - uint32_t dlen; + size_t dlen; int ret = tcp_payload_split(payload, *plen, diff --git a/utils.h b/src/utils.h similarity index 56% rename from utils.h rename to src/utils.h index 439dbcd4..6c025a2b 100644 --- a/utils.h +++ b/src/utils.h @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #ifndef UTILS_H #define UTILS_H @@ -12,33 +31,33 @@ * payload_offset indicates the position relatively to start of IP payload * (start of transport header) */ -int ip4_frag(const uint8_t *pkt, uint32_t pktlen, - uint32_t payload_offset, - uint8_t *frag1, uint32_t *f1len, - uint8_t *frag2, uint32_t *f2len); +int ip4_frag(const uint8_t *pkt, size_t pktlen, + size_t payload_offset, + uint8_t *frag1, size_t *f1len, + uint8_t *frag2, size_t *f2len); /** * Splits the packet to two TCP segments on position payload_offset * payload_offset indicates the position relatively to start of TCP payload. */ -// int tcp4_frag(const uint8_t *pkt, uint32_t pktlen, -// uint32_t payload_offset, -// uint8_t *seg1, uint32_t *s1len, -// uint8_t *seg2, uint32_t *s2len); -int tcp_frag(const uint8_t *pkt, uint32_t pktlen, - uint32_t payload_offset, - uint8_t *seg1, uint32_t *s1len, - uint8_t *seg2, uint32_t *s2len); +// int tcp4_frag(const uint8_t *pkt, size_t pktlen, +// size_t payload_offset, +// uint8_t *seg1, size_t *s1len, +// uint8_t *seg2, size_t *s2len); +int tcp_frag(const uint8_t *pkt, size_t pktlen, + size_t payload_offset, + uint8_t *seg1, size_t *s1len, + uint8_t *seg2, size_t *s2len); /** * Splits the raw packet payload to ip header and ip payload. */ -int ip4_payload_split(uint8_t *pkt, uint32_t buflen, - struct iphdr **iph, uint32_t *iph_len, - uint8_t **payload, uint32_t *plen); +int ip4_payload_split(uint8_t *pkt, size_t buflen, + struct iphdr **iph, size_t *iph_len, + uint8_t **payload, size_t *plen); -static inline int netproto_version(const uint8_t *pkt, uint32_t buflen) { +static inline int netproto_version(const uint8_t *pkt, size_t buflen) { if (pkt == NULL || buflen == 0) return -1; @@ -49,48 +68,48 @@ static inline int netproto_version(const uint8_t *pkt, uint32_t buflen) { /** * Splits the raw packet payload to ip header, tcp header and tcp payload. */ -int tcp4_payload_split(uint8_t *pkt, uint32_t buflen, - struct iphdr **iph, uint32_t *iph_len, - struct tcphdr **tcph, uint32_t *tcph_len, - uint8_t **payload, uint32_t *plen); +int tcp4_payload_split(uint8_t *pkt, size_t buflen, + struct iphdr **iph, size_t *iph_len, + struct tcphdr **tcph, size_t *tcph_len, + uint8_t **payload, size_t *plen); /** * Splits the raw packet payload to ip header and ip payload. */ -int ip6_payload_split(uint8_t *pkt, uint32_t buflen, - struct ip6_hdr **iph, uint32_t *iph_len, - uint8_t **payload, uint32_t *plen); +int ip6_payload_split(uint8_t *pkt, size_t buflen, + struct ip6_hdr **iph, size_t *iph_len, + uint8_t **payload, size_t *plen); /** * Splits the raw packet payload to ip header, tcp header and tcp payload. */ -int tcp6_payload_split(uint8_t *pkt, uint32_t buflen, - struct ip6_hdr **iph, uint32_t *iph_len, - struct tcphdr **tcph, uint32_t *tcph_len, - uint8_t **payload, uint32_t *plen); +int tcp6_payload_split(uint8_t *pkt, size_t buflen, + struct ip6_hdr **iph, size_t *iph_len, + struct tcphdr **tcph, size_t *tcph_len, + uint8_t **payload, size_t *plen); -int tcp_payload_split(uint8_t *pkt, uint32_t buflen, - void **iph, uint32_t *iph_len, - struct tcphdr **tcph, uint32_t *tcph_len, - uint8_t **payload, uint32_t *plen); +int tcp_payload_split(uint8_t *pkt, size_t buflen, + void **iph, size_t *iph_len, + struct tcphdr **tcph, size_t *tcph_len, + uint8_t **payload, size_t *plen); /** * Splits the raw packet payload to ip header, udp header and udp payload. */ -int udp4_payload_split(uint8_t *pkt, uint32_t buflen, - struct iphdr **iph, uint32_t *iph_len, +int udp4_payload_split(uint8_t *pkt, size_t buflen, + struct iphdr **iph, size_t *iph_len, struct udphdr **udph, - uint8_t **payload, uint32_t *plen); + uint8_t **payload, size_t *plen); -int udp6_payload_split(uint8_t *pkt, uint32_t buflen, - struct ip6_hdr **iph, uint32_t *iph_len, +int udp6_payload_split(uint8_t *pkt, size_t buflen, + struct ip6_hdr **iph, size_t *iph_len, struct udphdr **udph, - uint8_t **payload, uint32_t *plen); + uint8_t **payload, size_t *plen); -int udp_payload_split(uint8_t *pkt, uint32_t buflen, - void **iph, uint32_t *iph_len, +int udp_payload_split(uint8_t *pkt, size_t buflen, + void **iph, size_t *iph_len, struct udphdr **udph, - uint8_t **payload, uint32_t *plen); + uint8_t **payload, size_t *plen); void tcp4_set_checksum(struct tcphdr *tcph, struct iphdr *iph); void ip4_set_checksum(struct iphdr *iph); @@ -99,22 +118,22 @@ void tcp6_set_checksum(struct tcphdr *tcph, struct ip6_hdr *iph); void udp4_set_checksum(struct udphdr *udph, struct iphdr *iph); void udp6_set_checksum(struct udphdr *udph, struct ip6_hdr *iph); -int set_ip_checksum(void *iph, uint32_t iphb_len); -int set_tcp_checksum(struct tcphdr *tcph, void *iph, uint32_t iphb_len); -int set_udp_checksum(struct udphdr *udph, void *iph, uint32_t iphb_len); +int set_ip_checksum(void *iph, size_t iphb_len); +int set_tcp_checksum(struct tcphdr *tcph, void *iph, size_t iphb_len); +int set_udp_checksum(struct udphdr *udph, void *iph, size_t iphb_len); void z_function(const char *str, int *zbuf, size_t len); /** * Shifts data left delta bytes. Fills delta buffer with zeroes. */ -void shift_data(uint8_t *data, uint32_t dlen, uint32_t delta); +void shift_data(uint8_t *data, size_t dlen, size_t delta); struct failing_strategy { unsigned int strategy; uint8_t faking_ttl; - uint32_t randseq_offset; + size_t randseq_offset; }; @@ -165,12 +184,12 @@ struct udp_fake_type { * * Does not support bitmask, pass standalone strategy. */ -int fail_packet(struct failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen); +int fail_packet(struct failing_strategy strategy, uint8_t *payload, size_t *plen, size_t avail_buflen); /** * Shifts the payload right and pushes zeroes before it. Useful for TCP TLS faking. */ -int seqovl_packet(uint8_t *payload, uint32_t *plen, uint32_t seq_delta); +int seqovl_packet(uint8_t *payload, size_t *plen, size_t seq_delta); @@ -178,7 +197,7 @@ static inline struct failing_strategy args_default_failing_strategy(const struct struct failing_strategy fl_strat = { .strategy = (unsigned int)section->faking_strategy, .faking_ttl = section->faking_ttl, - .randseq_offset = (uint32_t)section->fakeseq_offset + .randseq_offset = (size_t)section->fakeseq_offset }; return fl_strat; } diff --git a/youtubeUnblock.c b/src/youtubeUnblock.c similarity index 91% rename from youtubeUnblock.c rename to src/youtubeUnblock.c index 0d7d662a..8daad462 100644 --- a/youtubeUnblock.c +++ b/src/youtubeUnblock.c @@ -1,3 +1,22 @@ +/* + youtubeUnblock - https://github.com/Waujito/youtubeUnblock + + Copyright (C) 2024-2025 Vadim Vetrov + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 + along with this program. If not, see . +*/ + #define _GNU_SOURCE #ifndef __linux__ #error "The package is linux only!" @@ -177,7 +196,7 @@ static int close_raw6_socket(void) { return 0; } -static int send_raw_ipv4(const uint8_t *pkt, uint32_t pktlen) { +static int send_raw_ipv4(const uint8_t *pkt, size_t pktlen) { int ret; if (pktlen > AVAILABLE_MTU) return -ENOMEM; @@ -214,7 +233,7 @@ static int send_raw_ipv4(const uint8_t *pkt, uint32_t pktlen) { return sent; } -static int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen) { +static int send_raw_ipv6(const uint8_t *pkt, size_t pktlen) { int ret; if (pktlen > AVAILABLE_MTU) return -ENOMEM; @@ -251,7 +270,7 @@ static int send_raw_ipv6(const uint8_t *pkt, uint32_t pktlen) { return sent; } -static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) { +static int send_raw_socket(const uint8_t *pkt, size_t pktlen) { int ret; if (pktlen > AVAILABLE_MTU) { @@ -270,8 +289,8 @@ static int send_raw_socket(const uint8_t *pkt, uint32_t pktlen) { return -ENOMEM; } - uint32_t buff1_size = MNL_SOCKET_BUFFER_SIZE; - uint32_t buff2_size = MNL_SOCKET_BUFFER_SIZE; + size_t buff1_size = MNL_SOCKET_BUFFER_SIZE; + size_t buff2_size = MNL_SOCKET_BUFFER_SIZE; if ((ret = tcp_frag(pkt, pktlen, AVAILABLE_MTU-128, buff1, &buff1_size, buff2, &buff2_size)) < 0) { @@ -354,7 +373,7 @@ static int fallback_accept_packet(uint32_t id, struct queue_data qdata) { struct dps_t { uint8_t *pkt; - uint32_t pktlen; + size_t pktlen; // Time for the packet in milliseconds uint32_t timer; }; @@ -363,7 +382,7 @@ void *delay_packet_send_fn(void *data) { struct dps_t *dpdt = data; uint8_t *pkt = dpdt->pkt; - uint32_t pktlen = dpdt->pktlen; + size_t pktlen = dpdt->pktlen; usleep(dpdt->timer * 1000); int ret = send_raw_socket(pkt, pktlen); @@ -377,7 +396,7 @@ void *delay_packet_send_fn(void *data) { return NULL; } -int delay_packet_send(const unsigned char *data, unsigned int data_len, unsigned int delay_ms) { +int delay_packet_send(const unsigned char *data, size_t data_len, unsigned int delay_ms) { struct dps_t *dpdt = malloc(sizeof(struct dps_t)); dpdt->pkt = malloc(data_len); memcpy(dpdt->pkt, data, data_len); @@ -559,11 +578,11 @@ int init_queue(int queue_num) { ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, &qdata); if (ret < 0) { - lgerror(-EPERM, "mnl_cb_run"); - if (errno == EPERM) { - lgerror(-errno, "Probably another instance of youtubeUnblock with the same queue number is running\n"); + lgerror(ret, "mnl_cb_run"); + if (ret == -EPERM) { + lgerr("Probably another instance of youtubeUnblock with the same queue number is running\n"); } else { - lgerror(-errno, "Make sure the nfnetlink_queue kernel module is loaded\n"); + lgerr("Make sure the nfnetlink_queue kernel module is loaded\n"); } goto die; } diff --git a/test/main_fn.c b/test/main_fn.c new file mode 100644 index 00000000..d068a952 --- /dev/null +++ b/test/main_fn.c @@ -0,0 +1,18 @@ +#include "config.h" +#include "unity_fixture.h" + +struct instance_config_t instance_config = { + .send_raw_packet = NULL, + .send_delayed_packet = NULL, +}; + +static void RunAllTests(void) +{ + RUN_TEST_GROUP(TLSTest) + RUN_TEST_GROUP(QuicTest); +} + +int main(int argc, const char * argv[]) +{ + return UnityMain(argc, argv, RunAllTests); +} diff --git a/test/quic.c b/test/quic.c new file mode 100644 index 00000000..ebe29c43 --- /dev/null +++ b/test/quic.c @@ -0,0 +1,255 @@ +// RFC 9001 Appendix A. +static const char quic_testing_payload[] = "\xc0\x00\x00\x00\x01\x08\x83\x94\xc8\xf0\x3e\x51\x57\x08\x00\x00\x44\x9e\x7b\x9a\xec\x34\xd1\xb1\xc9\x8d\xd7\x68\x9f\xb8\xec\x11\xd2\x42\xb1\x23\xdc\x9b\xd8\xba\xb9\x36\xb4\x7d\x92\xec\x35\x6c\x0b\xab\x7d\xf5\x97\x6d\x27\xcd\x44\x9f\x63\x30\x00\x99\xf3\x99\x1c\x26\x0e\xc4\xc6\x0d\x17\xb3\x1f\x84\x29\x15\x7b\xb3\x5a\x12\x82\xa6\x43\xa8\xd2\x26\x2c\xad\x67\x50\x0c\xad\xb8\xe7\x37\x8c\x8e\xb7\x53\x9e\xc4\xd4\x90\x5f\xed\x1b\xee\x1f\xc8\xaa\xfb\xa1\x7c\x75\x0e\x2c\x7a\xce\x01\xe6\x00\x5f\x80\xfc\xb7\xdf\x62\x12\x30\xc8\x37\x11\xb3\x93\x43\xfa\x02\x8c\xea\x7f\x7f\xb5\xff\x89\xea\xc2\x30\x82\x49\xa0\x22\x52\x15\x5e\x23\x47\xb6\x3d\x58\xc5\x45\x7a\xfd\x84\xd0\x5d\xff\xfd\xb2\x03\x92\x84\x4a\xe8\x12\x15\x46\x82\xe9\xcf\x01\x2f\x90\x21\xa6\xf0\xbe\x17\xdd\xd0\xc2\x08\x4d\xce\x25\xff\x9b\x06\xcd\xe5\x35\xd0\xf9\x20\xa2\xdb\x1b\xf3\x62\xc2\x3e\x59\x6d\x11\xa4\xf5\xa6\xcf\x39\x48\x83\x8a\x3a\xec\x4e\x15\xda\xf8\x50\x0a\x6e\xf6\x9e\xc4\xe3\xfe\xb6\xb1\xd9\x8e\x61\x0a\xc8\xb7\xec\x3f\xaf\x6a\xd7\x60\xb7\xba\xd1\xdb\x4b\xa3\x48\x5e\x8a\x94\xdc\x25\x0a\xe3\xfd\xb4\x1e\xd1\x5f\xb6\xa8\xe5\xeb\xa0\xfc\x3d\xd6\x0b\xc8\xe3\x0c\x5c\x42\x87\xe5\x38\x05\xdb\x05\x9a\xe0\x64\x8d\xb2\xf6\x42\x64\xed\x5e\x39\xbe\x2e\x20\xd8\x2d\xf5\x66\xda\x8d\xd5\x99\x8c\xca\xbd\xae\x05\x30\x60\xae\x6c\x7b\x43\x78\xe8\x46\xd2\x9f\x37\xed\x7b\x4e\xa9\xec\x5d\x82\xe7\x96\x1b\x7f\x25\xa9\x32\x38\x51\xf6\x81\xd5\x82\x36\x3a\xa5\xf8\x99\x37\xf5\xa6\x72\x58\xbf\x63\xad\x6f\x1a\x0b\x1d\x96\xdb\xd4\xfa\xdd\xfc\xef\xc5\x26\x6b\xa6\x61\x17\x22\x39\x5c\x90\x65\x56\xbe\x52\xaf\xe3\xf5\x65\x63\x6a\xd1\xb1\x7d\x50\x8b\x73\xd8\x74\x3e\xeb\x52\x4b\xe2\x2b\x3d\xcb\xc2\xc7\x46\x8d\x54\x11\x9c\x74\x68\x44\x9a\x13\xd8\xe3\xb9\x58\x11\xa1\x98\xf3\x49\x1d\xe3\xe7\xfe\x94\x2b\x33\x04\x07\xab\xf8\x2a\x4e\xd7\xc1\xb3\x11\x66\x3a\xc6\x98\x90\xf4\x15\x70\x15\x85\x3d\x91\xe9\x23\x03\x7c\x22\x7a\x33\xcd\xd5\xec\x28\x1c\xa3\xf7\x9c\x44\x54\x6b\x9d\x90\xca\x00\xf0\x64\xc9\x9e\x3d\xd9\x79\x11\xd3\x9f\xe9\xc5\xd0\xb2\x3a\x22\x9a\x23\x4c\xb3\x61\x86\xc4\x81\x9e\x8b\x9c\x59\x27\x72\x66\x32\x29\x1d\x6a\x41\x82\x11\xcc\x29\x62\xe2\x0f\xe4\x7f\xeb\x3e\xdf\x33\x0f\x2c\x60\x3a\x9d\x48\xc0\xfc\xb5\x69\x9d\xbf\xe5\x89\x64\x25\xc5\xba\xc4\xae\xe8\x2e\x57\xa8\x5a\xaf\x4e\x25\x13\xe4\xf0\x57\x96\xb0\x7b\xa2\xee\x47\xd8\x05\x06\xf8\xd2\xc2\x5e\x50\xfd\x14\xde\x71\xe6\xc4\x18\x55\x93\x02\xf9\x39\xb0\xe1\xab\xd5\x76\xf2\x79\xc4\xb2\xe0\xfe\xb8\x5c\x1f\x28\xff\x18\xf5\x88\x91\xff\xef\x13\x2e\xef\x2f\xa0\x93\x46\xae\xe3\x3c\x28\xeb\x13\x0f\xf2\x8f\x5b\x76\x69\x53\x33\x41\x13\x21\x19\x96\xd2\x00\x11\xa1\x98\xe3\xfc\x43\x3f\x9f\x25\x41\x01\x0a\xe1\x7c\x1b\xf2\x02\x58\x0f\x60\x47\x47\x2f\xb3\x68\x57\xfe\x84\x3b\x19\xf5\x98\x40\x09\xdd\xc3\x24\x04\x4e\x84\x7a\x4f\x4a\x0a\xb3\x4f\x71\x95\x95\xde\x37\x25\x2d\x62\x35\x36\x5e\x9b\x84\x39\x2b\x06\x10\x85\x34\x9d\x73\x20\x3a\x4a\x13\xe9\x6f\x54\x32\xec\x0f\xd4\xa1\xee\x65\xac\xcd\xd5\xe3\x90\x4d\xf5\x4c\x1d\xa5\x10\xb0\xff\x20\xdc\xc0\xc7\x7f\xcb\x2c\x0e\x0e\xb6\x05\xcb\x05\x04\xdb\x87\x63\x2c\xf3\xd8\xb4\xda\xe6\xe7\x05\x76\x9d\x1d\xe3\x54\x27\x01\x23\xcb\x11\x45\x0e\xfc\x60\xac\x47\x68\x3d\x7b\x8d\x0f\x81\x13\x65\x56\x5f\xd9\x8c\x4c\x8e\xb9\x36\xbc\xab\x8d\x06\x9f\xc3\x3b\xd8\x01\xb0\x3a\xde\xa2\xe1\xfb\xc5\xaa\x46\x3d\x08\xca\x19\x89\x6d\x2b\xf5\x9a\x07\x1b\x85\x1e\x6c\x23\x90\x52\x17\x2f\x29\x6b\xfb\x5e\x72\x40\x47\x90\xa2\x18\x10\x14\xf3\xb9\x4a\x4e\x97\xd1\x17\xb4\x38\x13\x03\x68\xcc\x39\xdb\xb2\xd1\x98\x06\x5a\xe3\x98\x65\x47\x92\x6c\xd2\x16\x2f\x40\xa2\x9f\x0c\x3c\x87\x45\xc0\xf5\x0f\xba\x38\x52\xe5\x66\xd4\x45\x75\xc2\x9d\x39\xa0\x3f\x0c\xda\x72\x19\x84\xb6\xf4\x40\x59\x1f\x35\x5e\x12\xd4\x39\xff\x15\x0a\xab\x76\x13\x49\x9d\xbd\x49\xad\xab\xc8\x67\x6e\xef\x02\x3b\x15\xb6\x5b\xfc\x5c\xa0\x69\x48\x10\x9f\x23\xf3\x50\xdb\x82\x12\x35\x35\xeb\x8a\x74\x33\xbd\xab\xcb\x90\x92\x71\xa6\xec\xbc\xb5\x8b\x93\x6a\x88\xcd\x4e\x8f\x2e\x6f\xf5\x80\x01\x75\xf1\x13\x25\x3d\x8f\xa9\xca\x88\x85\xc2\xf5\x52\xe6\x57\xdc\x60\x3f\x25\x2e\x1a\x8e\x30\x8f\x76\xf0\xbe\x79\xe2\xfb\x8f\x5d\x5f\xbb\xe2\xe3\x0e\xca\xdd\x22\x07\x23\xc8\xc0\xae\xa8\x07\x8c\xdf\xcb\x38\x68\x26\x3f\xf8\xf0\x94\x00\x54\xda\x48\x78\x18\x93\xa7\xe4\x9a\xd5\xaf\xf4\xaf\x30\x0c\xd8\x04\xa6\xb6\x27\x9a\xb3\xff\x3a\xfb\x64\x49\x1c\x85\x19\x4a\xab\x76\x0d\x58\xa6\x06\x65\x4f\x9f\x44\x00\xe8\xb3\x85\x91\x35\x6f\xbf\x64\x25\xac\xa2\x6d\xc8\x52\x44\x25\x9f\xf2\xb1\x9c\x41\xb9\xf9\x6f\x3c\xa9\xec\x1d\xde\x43\x4d\xa7\xd2\xd3\x92\xb9\x05\xdd\xf3\xd1\xf9\xaf\x93\xd1\xaf\x59\x50\xbd\x49\x3f\x5a\xa7\x31\xb4\x05\x6d\xf3\x1b\xd2\x67\xb6\xb9\x0a\x07\x98\x31\xaa\xf5\x79\xbe\x0a\x39\x01\x31\x37\xaa\xc6\xd4\x04\xf5\x18\xcf\xd4\x68\x40\x64\x7e\x78\xbf\xe7\x06\xca\x4c\xf5\xe9\xc5\x45\x3e\x9f\x7c\xfd\x2b\x8b\x4c\x8d\x16\x9a\x44\xe5\x5c\x88\xd4\xa9\xa7\xf9\x47\x42\x41\xe2\x21\xaf\x44\x86\x00\x18\xab\x08\x56\x97\x2e\x19\x4c\xd9\x34"; +static const char quic_decrypted_header[] = "\xc3\x00\x00\x00\x01\x08\x83\x94\xc8\xf0\x3e\x51\x57\x08\x00\x00\x44\x9e\x00\x00\x00\x02"; +static const char quic_decrypted_crypto[] = "\x06\x00\x40\xf1\x01\x00\x00\xed\x03\x03\xeb\xf8\xfa\x56\xf1\x29\x39\xb9\x58\x4a\x38\x96\x47\x2e\xc4\x0b\xb8\x63\xcf\xd3\xe8\x68\x04\xfe\x3a\x47\xf0\x6a\x2b\x69\x48\x4c\x00\x00\x04\x13\x01\x13\x02\x01\x00\x00\xc0\x00\x00\x00\x10\x00\x0e\x00\x00\x0b\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\xff\x01\x00\x01\x00\x00\x0a\x00\x08\x00\x06\x00\x1d\x00\x17\x00\x18\x00\x10\x00\x07\x00\x05\x04\x61\x6c\x70\x6e\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x33\x00\x26\x00\x24\x00\x1d\x00\x20\x93\x70\xb2\xc9\xca\xa4\x7f\xba\xba\xf4\x55\x9f\xed\xba\x75\x3d\xe1\x71\xfa\x71\xf5\x0f\x1c\xe1\x5d\x43\xe9\x94\xec\x74\xd7\x48\x00\x2b\x00\x03\x02\x03\x04\x00\x0d\x00\x10\x00\x0e\x04\x03\x05\x03\x06\x03\x02\x03\x08\x04\x08\x05\x08\x06\x00\x2d\x00\x02\x01\x01\x00\x1c\x00\x02\x40\x01\x00\x39\x00\x32\x04\x08\xff\xff\xff\xff\xff\xff\xff\xff\x05\x04\x80\x00\xff\xff\x07\x04\x80\x00\xff\xff\x08\x01\x10\x01\x04\x80\x00\x75\x30\x09\x01\x10\x0f\x08\x83\x94\xc8\xf0\x3e\x51\x57\x08\x06\x04\x80\x00\xff\xff"; +static const int quic_padding_len = 917; + +// Just a QUIC payload but with sparse frames (like ping, padding, ping, crypto 0, padding, ping, ping, padding, ping, crypto 425, padding) +static const char quic_sparse_payload[] = "\306\000\000\000\001\bB\302\246\317\237]S\226\000\000D\320\372/\3503Ac\222\312\360\355\030\223\231\340\360\022\222e\177$@\270\312\006\205-\267\304\207\036Zq?\246\2072zza\272\337\365'\335_\246\255\2502\347\245r\217>\2556\t\033\347\234w*Q4\003\330\270\037\271\004\346\254B(G\022\356\232\221P\357\305>\301T\331J xv.<\224\344Q\267\v\017b\254\260f\313\232\2213D:F\371\214\177\342C\234\022\301\316\277\342/\027\337X\317\250\200N< 6y\313\r\224\310i\263-\212\372\030\264Z\003#D4\234\315\205H\373\227\026yx\245d\375\211U\223\235\204\236\"T\255i\001\3308)ca%\243\376.mMc\225\b&\276\245n\233V\300\334\261\261\247\266(\334kA\314\250\261\271\353\nC\034\273\276\324\361J\341\017\361N\212\3128\261\233z\267|\344\260d\376\344\342\357\336\255X\366w\313\225C\022\022s\256\202\3568k!\177\025\375K~\224y\216\022\341\376\230\024\346\212l\025\253\300\256\031\360O\200|\331\342\315=I\306dS\030\306\320\212\177\356\350\207\360D7\177\agQ\"\031o6\202\352k\206]\210\370k5k\252\221\254\245\364\333\247\310\207\024\202Q#\314\214\264\341R?UL\340\271\313\213nj\217;\rU\304C\274\361[\327\002\321\372\212LO\325\324\237<\336\361<\205\331w\177`\210\\\276\304\314\220\235\3437\206g\323\275\036\a\033A!\254\217\341\277y6\211\304\031`-d\207wj\037\334MjY'!\327\245\002\255;\b\251\215\tY\310/\366N\224\206\027\037*\311\235\302\236=\377C\264\343o\255\264f\235%\036\026y\353\271(\3160\343*\300>\214&}\177-\363jj\336\204'\266\310\210\312\347\211h)\351\031\325\231\332\177\332#\3552bC\2775)\336\353\271gY\305\315`\212\342\325\376\250\2235y\a\315b\200R\361S\022\333\f\023\r\313\370\267\n\205\314\374\257\376\211\304Y?}.u\244b\315\221\264\211\371\256\224\332C\333@\025\027nb)G\360S\326_\277\362\201\365]\2745\376\253#\251\240\224=\316Y_\233\260\302\260\227.}\260\226\244\241r\320\347_\2273V\237\0262\375^\374F\266!\036k\346\352\204\222\300VuN\027\216\"\2531j\330\222\335\354Uz\367,\376\201\272O\177\376\026\220:?\n\202S\220\373\343\333'+%*rW\n\177Y{\347\211\357+\364(\270\034\207\371\221>\200Ua\026\034\235e\246D\036\352X\202\350\036\303\231\210\351j+\227e\352il\362\273`\360\361\304e\356\206\321\2232\327]\246\325\273\361\233G\336n\212.\335\250\t\177\233$\243\334<\304%\332\000\346\2777\343c\026`|\222\3666\207\021\034\001~\206\221I\f\316\f\006\000\036~\313kH\243L\343B\261Yg\031\362\324\370-\260B\330?e>fd\r\3544\\\312E\231\000\210oZ\033s\207\220\36379f=\017\032\256~\222\377!q\270w\305!\312o\343\035_\003U\313P\356\363^\016o\203,Yf \354\321\0038:\363I\300\215+h\316\305\257\305\002\t\232c\333'~\341\352\3170\362\244A\211\360\272\371\321\371Q\b\237\3076s.\032\322k\202,\345\374\266\233b OS\035\b*\242J\265\215\357\317\325\356\322\031g\2610G]\272i\265\\,\226\237\323\355\351\237\345\032b\364\347\250\227\217\323\353Y\002q[\335\365\034\363$*\312\231\317\302}\2600~\261O\336\265(d\240\323\214zr\371=\027\203\376\330\032w\002,90~{\3677\230\363\250b\320\202I\221\213?\272\227\ncc\343\031Ow\0347s\313\356\037\312t\206\002\006\336\270\203\277\020j\210g\372MU\2758\333\326:\312\262\r\022\210\275[}\314\377\035\241\267s\326\211\300\236;\217\001/\354k\365+?n\230e\350\002z\\K\035\227j\331\031\rj\230\306\306\236\367\021p#\001\203\262\206+kg\313u\205a\004\t2>\322\224\327\001.c\t\225\244=\243M\006\311\347z\262\021Hl\027\202\271\033\345~\334\214\034\202\024m@\372\361Kk@~\374\340Z\260D\245\272'M\232\001$\242wJ:\r\r-\244\363\217\t\261WgS7\272\213\357\314\240\371\374\313\233r\235\017\235\031\230%}Z\345\""; + +unsigned char filebr[] = { + 0x06, 0x16, 0xea, 0x20, 0xf5, 0xb6, 0x09, 0x0e, 0x90, 0x54, 0x17, 0x78, + 0xaa, 0x9a, 0xd9, 0xe1, 0xb8, 0xdf, 0xdc, 0x8e, 0xf8, 0x3a, 0xdb, 0x59, + 0xbb, 0x84, 0x60, 0x2b +}; + + +#include "unity.h" +#include "unity_fixture.h" + +#include "quic.h" +#include "types.h" +#include +#include "tls.h" +#include "config.h" +#include "logging.h" + +static struct section_config_t sconf = default_section_config; + +TEST_GROUP(QuicTest); + +TEST_SETUP(QuicTest) +{ +} + +TEST_TEAR_DOWN(QuicTest) +{ +} + +TEST(QuicTest, Test_decrypts) +{ + int ret; + uint8_t *decrypted_payload; + size_t decrypted_payload_len; + const uint8_t *decrypted_message; + size_t decrypted_message_len; + + ret = quic_parse_initial_message( + (const uint8_t *)quic_testing_payload, sizeof(quic_testing_payload) - 1, + &decrypted_payload, &decrypted_payload_len, + &decrypted_message, &decrypted_message_len + ); + + TEST_ASSERT_EQUAL(ret, 0); + + TEST_ASSERT_EQUAL(sizeof(quic_testing_payload) - 1, decrypted_payload_len); + TEST_ASSERT_EQUAL_MEMORY(quic_decrypted_header, decrypted_payload, sizeof(quic_decrypted_header) - 1); + TEST_ASSERT_EQUAL(decrypted_message, decrypted_payload + sizeof(quic_decrypted_header) - 1); + TEST_ASSERT_EQUAL_MEMORY(quic_decrypted_crypto, decrypted_message, sizeof(quic_decrypted_crypto) - 1); + + const uint8_t *curptr = decrypted_message + (sizeof(quic_decrypted_crypto) - 1); + ssize_t curptr_len = decrypted_message_len - (sizeof(quic_decrypted_crypto) - 1); + TEST_ASSERT_EQUAL(quic_padding_len, curptr_len); + + while (curptr_len-- > 0) { + TEST_ASSERT_EQUAL(0x00, *curptr++); + } + TEST_ASSERT_EQUAL(decrypted_message + decrypted_message_len, curptr); + + // tag is left + TEST_ASSERT_EQUAL(16, decrypted_payload + decrypted_payload_len - curptr); + +#undef free + free(decrypted_payload); +#define free unity_free +} + +TEST(QuicTest, Test_crypto_parser_valid) +{ + ssize_t fret; + struct quic_frame_crypto fr_cr; + + fret = quic_parse_crypto(&fr_cr, (const uint8_t *)quic_decrypted_crypto, sizeof(quic_decrypted_crypto)); + TEST_ASSERT_EQUAL(sizeof(quic_decrypted_crypto) - 1, fret); + TEST_ASSERT_EQUAL(0, fr_cr.offset); + TEST_ASSERT_EQUAL(241, fr_cr.payload_length); + // one for type, one for offset, two for length + TEST_ASSERT_EQUAL(quic_decrypted_crypto + 4, fr_cr.payload); +} + +TEST(QuicTest, Test_crypto_parser_tls) +{ + ssize_t fret; + int ret; + struct quic_frame_crypto fr_cr; + struct tls_verdict tlsv; + + fret = quic_parse_crypto(&fr_cr, (const uint8_t *)quic_decrypted_crypto, sizeof(quic_decrypted_crypto)); + TEST_ASSERT_GREATER_OR_EQUAL(0, fret); + ret = analyze_tls_message(&sconf, fr_cr.payload, fr_cr.payload_length, &tlsv); + TEST_ASSERT_GREATER_OR_EQUAL(0, ret); + TEST_ASSERT_EQUAL_STRING_LEN("example.com", tlsv.sni_ptr, 11); +} + +TEST(QuicTest, Test_crypto_parser_invalid) +{ + ssize_t fret; + struct quic_frame_crypto fr_cr; + + fret = quic_parse_crypto(&fr_cr, NULL, 0); + TEST_ASSERT_EQUAL(-EINVAL, fret); +} + +TEST(QuicTest, Test_varlength_parser) +{ + uint8_t varlv[4]; + uint64_t mlen, var; + + varlv[0] = 0x00; + varlv[1] = 0x00; + varlv[2] = 0x00; + varlv[3] = 0x00; + mlen = 4; + var = quic_parse_varlength(varlv, &mlen); + TEST_ASSERT_EQUAL(0, var); + TEST_ASSERT_EQUAL(1, mlen); + + varlv[0] = 0x40; + varlv[1] = 0xf1; + varlv[2] = 0x00; + varlv[3] = 0x00; + mlen = 4; + var = quic_parse_varlength(varlv, &mlen); + TEST_ASSERT_EQUAL(241, var); + TEST_ASSERT_EQUAL(2, mlen); + + mlen = 2; + var = quic_parse_varlength(varlv, &mlen); + TEST_ASSERT_EQUAL(241, var); + TEST_ASSERT_EQUAL(2, mlen); + + // overflow + mlen = 1; + var = quic_parse_varlength(varlv, &mlen); + TEST_ASSERT_EQUAL(0, var); + TEST_ASSERT_EQUAL(0, mlen); +} + +TEST(QuicTest, Test_parse_quic_decrypted) +{ +#undef free + + int ret; + uint8_t *decrypted_payload; + size_t decrypted_payload_len; + const uint8_t *decrypted_message; + size_t decrypted_message_len; + uint8_t *crypto_message; + size_t crypto_message_len; + struct tls_verdict tlsv = {0}; + + ret = quic_parse_initial_message( + (const uint8_t *)quic_testing_payload, sizeof(quic_testing_payload) - 1, + &decrypted_payload, &decrypted_payload_len, + &decrypted_message, &decrypted_message_len + ); + TEST_ASSERT_EQUAL(0, ret); + + ret = parse_quic_decrypted( + &sconf, decrypted_message, decrypted_message_len, + &crypto_message, &crypto_message_len); + TEST_ASSERT_EQUAL(0, ret); + free(decrypted_payload); + decrypted_payload = NULL; + + ret = analyze_tls_message( + &sconf, crypto_message, crypto_message_len, &tlsv + ); + TEST_ASSERT_EQUAL(11, tlsv.sni_len); + TEST_ASSERT_EQUAL_STRING_LEN("example.com", tlsv.sni_ptr, 11); + free(crypto_message); + +#define free unity_free +} + +TEST(QuicTest, Test_parse_quic_decrypted_on_sparse) +{ +#undef free + + int ret; + uint8_t *decrypted_payload; + size_t decrypted_payload_len; + const uint8_t *decrypted_message; + size_t decrypted_message_len; + uint8_t *crypto_message; + size_t crypto_message_len; + struct tls_verdict tlsv = {0}; + + ret = quic_parse_initial_message( + (const uint8_t *)quic_sparse_payload, sizeof(quic_sparse_payload) - 1, + &decrypted_payload, &decrypted_payload_len, + &decrypted_message, &decrypted_message_len + ); + TEST_ASSERT_EQUAL(0, ret); + + ret = parse_quic_decrypted( + &sconf, decrypted_message, decrypted_message_len, + &crypto_message, &crypto_message_len); + TEST_ASSERT_EQUAL(0, ret); + free(decrypted_payload); + decrypted_payload = NULL; + + ret = analyze_tls_message( + &sconf, crypto_message, crypto_message_len, &tlsv + ); + TEST_ASSERT_EQUAL(19, tlsv.sni_len); + TEST_ASSERT_EQUAL_STRING_LEN("ipm.adblockplus.dev", tlsv.sni_ptr, 19); + free(crypto_message); + +#define free unity_free +} + +TEST(QuicTest, Test_parse_quic_decrypted_on_fail) +{ +#undef free + + int ret; + uint8_t *crypto_message; + size_t crypto_message_len; + struct tls_verdict tlsv = {0}; + + ret = parse_quic_decrypted( + &sconf, filebr, sizeof(filebr) - 1, + &crypto_message, &crypto_message_len); + TEST_ASSERT_EQUAL(0, ret); + + ret = analyze_tls_message( + &sconf, crypto_message, crypto_message_len, &tlsv + ); + TEST_ASSERT_EQUAL(0, tlsv.sni_len); + free(crypto_message); + +#define free unity_free +} + +TEST_GROUP_RUNNER(QuicTest) +{ + RUN_TEST_CASE(QuicTest, Test_decrypts); + RUN_TEST_CASE(QuicTest, Test_crypto_parser_valid); + RUN_TEST_CASE(QuicTest, Test_crypto_parser_tls); + RUN_TEST_CASE(QuicTest, Test_crypto_parser_invalid); + RUN_TEST_CASE(QuicTest, Test_varlength_parser); + RUN_TEST_CASE(QuicTest, Test_parse_quic_decrypted) + RUN_TEST_CASE(QuicTest, Test_parse_quic_decrypted_on_sparse) + RUN_TEST_CASE(QuicTest, Test_parse_quic_decrypted_on_fail) +} diff --git a/test/tls.c b/test/tls.c new file mode 100644 index 00000000..d31caecb --- /dev/null +++ b/test/tls.c @@ -0,0 +1,38 @@ +static const char tls_chlo_message[] = "\001\000\002\000\003\003*{D\360FDTZ\305\231\272\006\240\246oa\365}ut\321\033\354\361}\334\227\342\215\257]\332\000\000\006\023\001\023\002\023\003\001\000\001\321\0009\000_\t\002@g\017\000\005\004\200`\000\000q'\004\200\001\026\210\a\004\200`\000\000\001\004\200\000u0\003\002E\300\006\004\200`\000\000\316E,\310\0160;\306\003g\201k\004\004\200\360\000\000\200\000GR\004\000\000\000\001 \004\200\001\000\000\200\377s\333\f\000\000\000\001\n\212\nJ\000\000\000\001\b\002@d\000\020\000\005\000\003\002h3\000+\000\003\002\003\004\000\n\000\b\000\006\000\035\000\027\000\030\000\033\000\003\002\000\002Di\000\005\000\003\002h3\000\r\000\024\000\022\004\003\b\004\004\001\005\003\b\005\005\001\b\006\006\001\002\001\000-\000\002\001\001\376\r\000\332\000\000\001\000\001|\000 \004\256\340\330}\337lC3\304gv\325}\rT\370O,i^\001\357\323\373?\205@3\023\354{\000\260\247cf\207\3276\312\205G\017\213Y\231\b\301~\225r\v\001X\026\335\254H\231\237\237\263\027b\b\327\0351W\000\177tc\213:^\f\362\340\225_\272\331\351\002\026rds\326\034\345*5!\221\265\206\270\240\375\nw\v\340 \003\340\307\230H\203#\212\371\364\257H\220\230L\230{\243\355\v'\325@\240EZ\306\230a\233;\033|=(\372P\232\216\215\203\374\234\222\375\004\3058l\275+?\f\306\335\342Q\313\"F\377G<2Jqb\033\033,|\302w\337bO\032\276\374\312X\364}\255xq\274\2348\247K\345t\327\345\322M\004\220\376*\344\365\0003\000&\000$\000\035\000 W\356I\271\201\350\263[cn\\H?\376s``\v\230\306?E=2\017u\306\027\nc{c\000\000\000\030\000\026\000\000\023abc.defghijklm.ndev"; + +#include "unity.h" +#include "unity_fixture.h" + +#include "types.h" +#include +#include "tls.h" +#include "config.h" +#include "logging.h" + +static struct section_config_t sconf = default_section_config; + +TEST_GROUP(TLSTest); + +TEST_SETUP(TLSTest) +{ +} + +TEST_TEAR_DOWN(TLSTest) +{ +} + +TEST(TLSTest, Test_CHLO_message_detect) +{ + struct tls_verdict tlsv; + int ret; + ret = analyze_tls_message(&sconf, (const uint8_t *)tls_chlo_message, sizeof(tls_chlo_message) - 1, &tlsv); + TEST_ASSERT_EQUAL(0, ret); + TEST_ASSERT_GREATER_OR_EQUAL(19, tlsv.sni_len); + TEST_ASSERT_EQUAL_STRING_LEN("abc.defghijklm.ndev", tlsv.sni_ptr, 19); +} + + +TEST_GROUP_RUNNER(TLSTest) +{ + RUN_TEST_CASE(TLSTest, Test_CHLO_message_detect); +} diff --git a/test/unity/unity.c b/test/unity/unity.c new file mode 100644 index 00000000..7fa2dc63 --- /dev/null +++ b/test/unity/unity.c @@ -0,0 +1,2501 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" + +#ifndef UNITY_PROGMEM +#define UNITY_PROGMEM +#endif + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +void UNITY_OUTPUT_CHAR(int); +#endif + +/* Helpful macros for us to use here in Assert functions */ +#define UNITY_FAIL_AND_BAIL do { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define UNITY_IGNORE_AND_BAIL do { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define RETURN_IF_FAIL_OR_IGNORE do { if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) { TEST_ABORT(); } } while (0) + +struct UNITY_STORAGE_T Unity; + +#ifdef UNITY_OUTPUT_COLOR +const char UNITY_PROGMEM UnityStrOk[] = "\033[42mOK\033[0m"; +const char UNITY_PROGMEM UnityStrPass[] = "\033[42mPASS\033[0m"; +const char UNITY_PROGMEM UnityStrFail[] = "\033[41mFAIL\033[0m"; +const char UNITY_PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[0m"; +#else +const char UNITY_PROGMEM UnityStrOk[] = "OK"; +const char UNITY_PROGMEM UnityStrPass[] = "PASS"; +const char UNITY_PROGMEM UnityStrFail[] = "FAIL"; +const char UNITY_PROGMEM UnityStrIgnore[] = "IGNORE"; +#endif +static const char UNITY_PROGMEM UnityStrNull[] = "NULL"; +static const char UNITY_PROGMEM UnityStrSpacer[] = ". "; +static const char UNITY_PROGMEM UnityStrExpected[] = " Expected "; +static const char UNITY_PROGMEM UnityStrWas[] = " Was "; +static const char UNITY_PROGMEM UnityStrGt[] = " to be greater than "; +static const char UNITY_PROGMEM UnityStrLt[] = " to be less than "; +static const char UNITY_PROGMEM UnityStrOrEqual[] = "or equal to "; +static const char UNITY_PROGMEM UnityStrNotEqual[] = " to be not equal to "; +static const char UNITY_PROGMEM UnityStrElement[] = " Element "; +static const char UNITY_PROGMEM UnityStrByte[] = " Byte "; +static const char UNITY_PROGMEM UnityStrMemory[] = " Memory Mismatch."; +static const char UNITY_PROGMEM UnityStrDelta[] = " Values Not Within Delta "; +static const char UNITY_PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UNITY_PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UNITY_PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char UNITY_PROGMEM UnityStrNot[] = "Not "; +static const char UNITY_PROGMEM UnityStrInf[] = "Infinity"; +static const char UNITY_PROGMEM UnityStrNegInf[] = "Negative Infinity"; +static const char UNITY_PROGMEM UnityStrNaN[] = "NaN"; +static const char UNITY_PROGMEM UnityStrDet[] = "Determinate"; +static const char UNITY_PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +#endif +const char UNITY_PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; +const char UNITY_PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UNITY_PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UNITY_PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char UNITY_PROGMEM UnityStrBreaker[] = "-----------------------"; +static const char UNITY_PROGMEM UnityStrResultsTests[] = " Tests "; +static const char UNITY_PROGMEM UnityStrResultsFailures[] = " Failures "; +static const char UNITY_PROGMEM UnityStrResultsIgnored[] = " Ignored "; +#ifndef UNITY_EXCLUDE_DETAILS +static const char UNITY_PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; +#endif +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +/* Local helper function to print characters. */ +static void UnityPrintChar(const char* pch) +{ + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } +} + +/*-----------------------------------------------*/ +/* Local helper function to print ANSI escape strings e.g. "\033[42m". */ +#ifdef UNITY_OUTPUT_COLOR +static UNITY_UINT UnityPrintAnsiEscapeString(const char* string) +{ + const char* pch = string; + UNITY_UINT count = 0; + + while (*pch && (*pch != 'm')) + { + UNITY_OUTPUT_CHAR(*pch); + pch++; + count++; + } + UNITY_OUTPUT_CHAR('m'); + count++; + + return count; +} +#endif + +/*-----------------------------------------------*/ +void UnityPrint(const char* string) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch) + { +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + UnityPrintChar(pch); + pch++; + } + } +} +/*-----------------------------------------------*/ +void UnityPrintLen(const char* string, const UNITY_UINT32 length) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch && ((UNITY_UINT32)(pch - string) < length)) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } + pch++; + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (style == UNITY_DISPLAY_STYLE_CHAR) + { + /* printable characters plus CR & LF are printed */ + UNITY_OUTPUT_CHAR('\''); + if ((number <= 126) && (number >= 32)) + { + UNITY_OUTPUT_CHAR((int)number); + } + /* write escaped carriage returns */ + else if (number == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (number == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 2); + } + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrintNumber(number); + } + } + else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) + { + UnityPrintNumberUnsigned((UNITY_UINT)number); + } + else + { + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const UNITY_INT number_to_print) +{ + UNITY_UINT number = (UNITY_UINT)number_to_print; + + if (number_to_print < 0) + { + /* A negative number, including MIN negative */ + UNITY_OUTPUT_CHAR('-'); + number = (~number) + 1; + } + UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const UNITY_UINT number) +{ + UNITY_UINT divisor = 1; + + /* figure out initial divisor */ + while (number / divisor > 9) + { + divisor *= 10; + } + + /* now mod and print, then divide divisor */ + do + { + UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); + divisor /= 10; + } while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) +{ + int nibble; + char nibbles = nibbles_to_print; + + if ((unsigned)nibbles > UNITY_MAX_NIBBLES) + { + nibbles = UNITY_MAX_NIBBLES; + } + + while (nibbles > 0) + { + nibbles--; + nibble = (int)(number >> (nibbles * 4)) & 0x0F; + if (nibble <= 9) + { + UNITY_OUTPUT_CHAR((char)('0' + nibble)); + } + else + { + UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) +{ + UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); + UNITY_INT32 i; + + for (i = 0; i < UNITY_INT_WIDTH; i++) + { + if (current_bit & mask) + { + if (current_bit & number) + { + UNITY_OUTPUT_CHAR('1'); + } + else + { + UNITY_OUTPUT_CHAR('0'); + } + } + else + { + UNITY_OUTPUT_CHAR('X'); + } + current_bit = current_bit >> 1; + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine. The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ +#ifdef UNITY_INCLUDE_DOUBLE + static const int sig_digits = 9; + static const UNITY_INT32 min_scaled = 100000000; + static const UNITY_INT32 max_scaled = 1000000000; +#else + static const int sig_digits = 7; + static const UNITY_INT32 min_scaled = 1000000; + static const UNITY_INT32 max_scaled = 10000000; +#endif + + UNITY_DOUBLE number = input_number; + + /* print minus sign (does not handle negative zero) */ + if (number < 0.0f) + { + UNITY_OUTPUT_CHAR('-'); + number = -number; + } + + /* handle zero, NaN, and +/- infinity */ + if (number == 0.0f) + { + UnityPrint("0"); + } + else if (UNITY_IS_NAN(number)) + { + UnityPrint("nan"); + } + else if (UNITY_IS_INF(number)) + { + UnityPrint("inf"); + } + else + { + UNITY_INT32 n_int = 0; + UNITY_INT32 n; + int exponent = 0; + int decimals; + int digits; + char buf[16] = {0}; + + /* + * Scale up or down by powers of 10. To minimize rounding error, + * start with a factor/divisor of 10^10, which is the largest + * power of 10 that can be represented exactly. Finally, compute + * (exactly) the remaining power of 10 and perform one more + * multiplication or division. + */ + if (number < 1.0f) + { + UNITY_DOUBLE factor = 1.0f; + + while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; } + while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; } + + number *= factor; + } + else if (number > (UNITY_DOUBLE)max_scaled) + { + UNITY_DOUBLE divisor = 1.0f; + + while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; } + while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; } + + number /= divisor; + } + else + { + /* + * In this range, we can split off the integer part before + * doing any multiplications. This reduces rounding error by + * freeing up significant bits in the fractional part. + */ + UNITY_DOUBLE factor = 1.0f; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; + + while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; } + + number *= factor; + } + + /* round to nearest integer */ + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO + /* round to even if exactly between two integers */ + if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f)) + n--; +#endif + + n += n_int; + + if (n >= max_scaled) + { + n = min_scaled; + exponent++; + } + + /* determine where to place decimal point */ + decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1); + exponent += decimals; + + /* truncate trailing zeroes after decimal point */ + while ((decimals > 0) && ((n % 10) == 0)) + { + n /= 10; + decimals--; + } + + /* build up buffer in reverse order */ + digits = 0; + while ((n != 0) || (digits <= decimals)) + { + buf[digits++] = (char)('0' + n % 10); + n /= 10; + } + + /* print out buffer (backwards) */ + while (digits > 0) + { + if (digits == decimals) + { + UNITY_OUTPUT_CHAR('.'); + } + UNITY_OUTPUT_CHAR(buf[--digits]); + } + + /* print exponent if needed */ + if (exponent != 0) + { + UNITY_OUTPUT_CHAR('e'); + + if (exponent < 0) + { + UNITY_OUTPUT_CHAR('-'); + exponent = -exponent; + } + else + { + UNITY_OUTPUT_CHAR('+'); + } + + digits = 0; + while ((exponent != 0) || (digits < 2)) + { + buf[digits++] = (char)('0' + exponent % 10); + exponent /= 10; + } + while (digits > 0) + { + UNITY_OUTPUT_CHAR(buf[--digits]); + } + } + } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ +#ifdef UNITY_OUTPUT_FOR_ECLIPSE + UNITY_OUTPUT_CHAR('('); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(')'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else +#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH + UnityPrint("'); + UnityPrint(Unity.CurrentTestName); + UnityPrint(" "); +#else +#ifdef UNITY_OUTPUT_FOR_QT_CREATOR + UnityPrint("file://"); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#endif +#endif +#endif +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + } + else if (!Unity.CurrentTestFailed) + { + UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); + UnityPrint(UnityStrPass); + } + else + { + Unity.TestFailures++; + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char* msg) +{ +#ifdef UNITY_PRINT_TEST_CONTEXT + UnityPrint(UnityStrSpacer); + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrSpacer); + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + } +#endif + if (msg) + { + UnityPrint(UnityStrSpacer); + UnityPrint(msg); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(expected); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(actual); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char* expected, + const char* actual, + const UNITY_UINT32 length) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(expected, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(actual, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_LINE_TYPE lineNumber, + const char* msg) +{ + /* Both are NULL or same pointer */ + if (expected == actual) { return 0; } + + /* print and return true if just expected is NULL */ + if (expected == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForExpected); + UnityAddMsgIfSpecified(msg); + return 1; + } + + /* print and return true if just actual is NULL */ + if (actual == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForActual); + UnityAddMsgIfSpecified(msg); + return 1; + } + + return 0; /* return false if neither is NULL */ +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((mask & expected) != (mask & actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); + UnityPrint(UnityStrWas); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + int failed = 0; + RETURN_IF_FAIL_OR_IGNORE; + + if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) { return; } + if ((threshold == actual)) { failed = 1; } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + else /* UINT or HEX */ + { + if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(actual, style); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + if (compare == UNITY_NOT_EQUAL) { UnityPrint(UnityStrNotEqual); } + UnityPrintNumberByStyle(threshold, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#define UnityPrintPointlessAndBail() \ +do { \ + UnityTestResultsFailBegin(lineNumber); \ + UnityPrint(UnityStrPointless); \ + UnityAddMsgIfSpecified(msg); \ + UNITY_FAIL_AND_BAIL; \ +} while (0) + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x000000FF; + actual_val &= 0x000000FF; + } + increment = sizeof(UNITY_INT8); + break; + + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x0000FFFF; + actual_val &= 0x0000FFFF; + } + increment = sizeof(UNITY_INT16); + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; +#ifdef UNITY_SUPPORT_64 + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x00000000FFFFFFFF; + actual_val &= 0x00000000FFFFFFFF; + } +#endif + increment = sizeof(UNITY_INT32); + length = 4; + break; + } + + if (expect_val != actual_val) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ + if (UNITY_IS_INF(expected) && UNITY_IS_INF(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \ + if (UNITY_NAN_CHECK) return 1; \ + (diff) = (actual) - (expected); \ + if ((diff) < 0) (diff) = -(diff); \ + if ((delta) < 0) (delta) = -(delta); \ + return !(UNITY_IS_NAN(diff) || UNITY_IS_INF(diff) || ((diff) > (delta))) + /* This first part of this condition will catch any NaN or Infinite values */ +#ifndef UNITY_NAN_NOT_EQUAL_NAN + #define UNITY_NAN_CHECK UNITY_IS_NAN(expected) && UNITY_IS_NAN(actual) +#else + #define UNITY_NAN_CHECK 0 +#endif + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + do { \ + UnityPrint(UnityStrExpected); \ + UnityPrintFloat(expected); \ + UnityPrint(UnityStrWas); \ + UnityPrintFloat(actual); \ + } while (0) +#else + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) +{ + UNITY_FLOAT diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; + UNITY_FLOAT in_delta = delta; + UNITY_FLOAT current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_FLOAT_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityFloatsWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + + if (!UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityFloatsWithin(threshold * UNITY_FLOAT_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat((UNITY_DOUBLE)actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) +{ + UNITY_DOUBLE diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; + UNITY_DOUBLE in_delta = delta; + UNITY_DOUBLE current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_DOUBLE_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityDoublesWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (!UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityDoublesWithin(threshold * UNITY_DOUBLE_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat(actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual > expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + else + { + if ((UNITY_UINT)actual > (UNITY_UINT)expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + increment = sizeof(UNITY_INT8); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)actual; + increment = sizeof(UNITY_UINT8); + } + break; + + case 2: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + increment = sizeof(UNITY_INT16); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)actual; + increment = sizeof(UNITY_UINT16); + } + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)actual; + increment = sizeof(UNITY_UINT64); + } + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + increment = sizeof(UNITY_INT32); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)actual; + increment = sizeof(UNITY_UINT32); + } + length = 4; + break; + } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual_val > expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + else + { + if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; expected[i] || actual[i]; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStrings(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; (i < length) && (expected[i] || actual[i]); i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStringsLen(expected, actual, length); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 i = 0; + UNITY_UINT32 j = 0; + const char* expd = NULL; + const char* act = NULL; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if no elements, it's an error */ + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if ((const void*)expected == (const void*)actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + if (flags != UNITY_ARRAY_TO_ARRAY) + { + expd = (const char*)expected; + } + + do + { + act = actual[j]; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expd = ((const char* const*)expected)[j]; + } + + /* if both pointers not null compare the strings */ + if (expd && act) + { + for (i = 0; expd[i] || act[i]; i++) + { + if (expd[i] != act[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expd != act) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings(expd, act); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; + UNITY_UINT32 elements = num_elements; + UNITY_UINT32 bytes; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + if (length == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + bytes = length; + while (bytes--) + { + if (*ptr_exp != *ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrMemory); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + } + UnityPrint(UnityStrByte); + UnityPrintNumberUnsigned(length - bytes - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp++; + ptr_act++; + } + if (flags == UNITY_ARRAY_TO_VAL) + { + ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + } + } +} + +/*-----------------------------------------------*/ + +static union +{ + UNITY_INT8 i8; + UNITY_INT16 i16; + UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 + UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT + float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE + double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ + switch(size) + { + case 1: + UnityQuickCompare.i8 = (UNITY_INT8)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + + case 2: + UnityQuickCompare.i16 = (UNITY_INT16)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 + case 8: + UnityQuickCompare.i64 = (UNITY_INT64)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + + default: /* 4 bytes */ + UnityQuickCompare.i32 = (UNITY_INT32)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); + } +} + +#ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ + UnityQuickCompare.f = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ + UnityQuickCompare.d = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED + +/*----------------------------------------------- + * printf length modifier helpers + *-----------------------------------------------*/ + +enum UnityLengthModifier { + UNITY_LENGTH_MODIFIER_NONE, + UNITY_LENGTH_MODIFIER_LONG_LONG, + UNITY_LENGTH_MODIFIER_LONG, +}; + +#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \ +do { \ + switch (LENGTH_MOD) \ + { \ + case UNITY_LENGTH_MODIFIER_LONG_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_NONE: \ + default: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \ + break; \ + } \ + } \ +} while (0) + +static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length) +{ + enum UnityLengthModifier length_mod; + switch (pch[0]) + { + case 'l': + { + if (pch[1] == 'l') + { + *length = 2; + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + } + else + { + *length = 1; + length_mod = UNITY_LENGTH_MODIFIER_LONG; + } + break; + } + case 'h': + { + // short and char are converted to int + length_mod = UNITY_LENGTH_MODIFIER_NONE; + if (pch[1] == 'h') + { + *length = 2; + } + else + { + *length = 1; + } + break; + } + case 'j': + case 'z': + case 't': + case 'L': + { + // Not supported, but should gobble up the length specifier anyway + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 1; + break; + } + default: + { + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 0; + } + } + return length_mod; +} + +/*----------------------------------------------- + * printf helper function + *-----------------------------------------------*/ +static void UnityPrintFVA(const char* format, va_list va) +{ + const char* pch = format; + if (pch != NULL) + { + while (*pch) + { + /* format identification character */ + if (*pch == '%') + { + pch++; + + if (pch != NULL) + { + int length_mod_size; + enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size); + pch += length_mod_size; + + switch (*pch) + { + case 'd': + case 'i': + { + UNITY_INT number; + UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int); + UnityPrintNumber((UNITY_INT)number); + break; + } +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + case 'f': + case 'g': + { + const double number = va_arg(va, double); + UnityPrintFloat((UNITY_DOUBLE)number); + break; + } +#endif + case 'u': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UnityPrintNumberUnsigned(number); + break; + } + case 'b': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('b'); + UnityPrintMask(mask, number); + break; + } + case 'x': + case 'X': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex(number, UNITY_MAX_NIBBLES); + break; + } + case 'p': + { + UNITY_UINT number; + char nibbles_to_print = 8; + if (UNITY_POINTER_WIDTH == 64) + { + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + nibbles_to_print = 16; + } + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, nibbles_to_print); + break; + } + case 'c': + { + const int ch = va_arg(va, int); + UnityPrintChar((const char *)&ch); + break; + } + case 's': + { + const char * string = va_arg(va, const char *); + UnityPrint(string); + break; + } + case '%': + { + UnityPrintChar(pch); + break; + } + default: + { + /* print the unknown format character */ + UNITY_OUTPUT_CHAR('%'); + UnityPrintChar(pch); + break; + } + } + } + } +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + else if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + else if (*pch == '\n') + { + UNITY_PRINT_EOL(); + } + else + { + UnityPrintChar(pch); + } + + pch++; + } + } +} + +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if(format != NULL) + { + UnityPrint(": "); + va_list va; + va_start(va, format); + UnityPrintFVA(format, va); + va_end(va); + } + UNITY_PRINT_EOL(); +} +#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */ + + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityFail(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + +#ifdef UNITY_PRINT_TEST_CONTEXT + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + if (msg[0] != ' ') + { + UNITY_OUTPUT_CHAR(' '); + } + UnityPrint(msg); + } + + UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrIgnore); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityMessage(const char* msg, const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_PRINT_EOL(); +} + +/*-----------------------------------------------*/ +/* If we have not defined our own test runner, then include our default test runner to make life easier */ +#ifndef UNITY_SKIP_DEFAULT_RUNNER +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + UNITY_EXEC_TIME_START(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT()) + { + tearDown(); + } + UNITY_EXEC_TIME_STOP(); + UnityConcludeTest(); +} +#endif + +/*-----------------------------------------------*/ +void UnitySetTestFile(const char* filename) +{ + Unity.TestFile = filename; +} + +/*-----------------------------------------------*/ +void UnityBegin(const char* filename) +{ + Unity.TestFile = filename; + Unity.CurrentTestName = NULL; + Unity.CurrentTestLineNumber = 0; + Unity.NumberOfTests = 0; + Unity.TestFailures = 0; + Unity.TestIgnores = 0; + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + + UNITY_CLR_DETAILS(); + UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ + UNITY_PRINT_EOL(); + UnityPrint(UnityStrBreaker); + UNITY_PRINT_EOL(); + UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); + UnityPrint(UnityStrResultsTests); + UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); + UnityPrint(UnityStrResultsFailures); + UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); + UnityPrint(UnityStrResultsIgnored); + UNITY_PRINT_EOL(); + if (Unity.TestFailures == 0U) + { + UnityPrint(UnityStrOk); + } + else + { + UnityPrint(UnityStrFail); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL + UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); +#endif + } + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); + UNITY_OUTPUT_COMPLETE(); + return (int)(Unity.TestFailures); +} + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_USE_COMMAND_LINE_ARGS + +char* UnityOptionIncludeNamed = NULL; +char* UnityOptionExcludeNamed = NULL; +int UnityVerbosity = 1; +int UnityStrictMatch = 0; + +/*-----------------------------------------------*/ +int UnityParseOptions(int argc, char** argv) +{ + int i; + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + UnityStrictMatch = 0; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'l': /* list tests */ + return -1; + case 'n': /* include tests with name including this string */ + case 'f': /* an alias for -n */ + UnityStrictMatch = (argv[i][1] == 'n'); /* strictly match this string if -n */ + if (argv[i][2] == '=') + { + UnityOptionIncludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionIncludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Include Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + case 'q': /* quiet */ + UnityVerbosity = 0; + break; + case 'v': /* verbose */ + UnityVerbosity = 2; + break; + case 'x': /* exclude tests with name including this string */ + if (argv[i][2] == '=') + { + UnityOptionExcludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionExcludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Exclude Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + default: + UnityPrint("ERROR: Unknown Option "); + UNITY_OUTPUT_CHAR(argv[i][1]); + UNITY_PRINT_EOL(); + /* Now display help */ + /* FALLTHRU */ + case 'h': + UnityPrint("Options: "); UNITY_PRINT_EOL(); + UnityPrint("-l List all tests and exit"); UNITY_PRINT_EOL(); + UnityPrint("-f NAME Filter to run only tests whose name includes NAME"); UNITY_PRINT_EOL(); + UnityPrint("-n NAME Run only the test named NAME"); UNITY_PRINT_EOL(); + UnityPrint("-h show this Help menu"); UNITY_PRINT_EOL(); + UnityPrint("-q Quiet/decrease verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-v increase Verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-x NAME eXclude tests whose name includes NAME"); UNITY_PRINT_EOL(); + UNITY_OUTPUT_FLUSH(); + return 1; + } + } + } + + return 0; +} + +/*-----------------------------------------------*/ +static int IsStringInBiggerString(const char* longstring, const char* shortstring) +{ + const char* lptr = longstring; + const char* sptr = shortstring; + const char* lnext = lptr; + + if (*sptr == '*') + { + return UnityStrictMatch ? 0 : 1; + } + + while (*lptr) + { + lnext = lptr + 1; + + /* If they current bytes match, go on to the next bytes */ + while (*lptr && *sptr && (*lptr == *sptr)) + { + lptr++; + sptr++; + + switch (*sptr) + { + case '*': /* we encountered a wild-card */ + return UnityStrictMatch ? 0 : 1; + + case ',': /* we encountered the end of match string */ + case '"': + case '\'': + case 0: + return (!UnityStrictMatch || (*lptr == 0)) ? 1 : 0; + + case ':': /* we encountered the end of a partial match */ + return 2; + + default: + break; + } + } + + // If we didn't match and we're on strict matching, we already know we failed + if (UnityStrictMatch) + { + return 0; + } + + /* Otherwise we start in the long pointer 1 character further and try again */ + lptr = lnext; + sptr = shortstring; + } + + return 0; +} + +/*-----------------------------------------------*/ +static int UnityStringArgumentMatches(const char* str) +{ + int retval; + const char* ptr1; + const char* ptr2; + const char* ptrf; + + /* Go through the options and get the substrings for matching one at a time */ + ptr1 = str; + while (ptr1[0] != 0) + { + if ((ptr1[0] == '"') || (ptr1[0] == '\'')) + { + ptr1++; + } + + /* look for the start of the next partial */ + ptr2 = ptr1; + ptrf = 0; + do + { + ptr2++; + if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) + { + ptrf = &ptr2[1]; + } + } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + + while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) + { + ptr2++; + } + + /* done if complete filename match */ + retval = IsStringInBiggerString(Unity.TestFile, ptr1); + if (retval == 1) + { + return retval; + } + + /* done if testname match after filename partial match */ + if ((retval == 2) && (ptrf != 0)) + { + if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) + { + return 1; + } + } + + /* done if complete testname match */ + if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) + { + return 1; + } + + ptr1 = ptr2; + } + + /* we couldn't find a match for any substrings */ + return 0; +} + +/*-----------------------------------------------*/ +int UnityTestMatches(void) +{ + /* Check if this test name matches the included test pattern */ + int retval; + if (UnityOptionIncludeNamed) + { + retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); + } + else + { + retval = 1; + } + + /* Check if this test name matches the excluded test pattern */ + if (UnityOptionExcludeNamed) + { + if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) + { + retval = 0; + } + } + + return retval; +} + +#endif /* UNITY_USE_COMMAND_LINE_ARGS */ +/*-----------------------------------------------*/ diff --git a/test/unity/unity.h b/test/unity/unity.h new file mode 100644 index 00000000..9e2a97b7 --- /dev/null +++ b/test/unity/unity.h @@ -0,0 +1,698 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR 2 +#define UNITY_VERSION_MINOR 6 +#define UNITY_VERSION_BUILD 1 +#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__) +#endif + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) + +/*------------------------------------------------------- + * Build Directives + *------------------------------------------------------- + + * These macros do nothing, but they are useful for additional build context. + * Tools (like Ceedling) can scan for these directives and make use of them for + * per-test-executable #include search paths and linking. */ + +/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */ +#define TEST_SOURCE_FILE(a) + +/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */ +#define TEST_INCLUDE_PATH(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") +#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty") +#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) +#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/test/unity/unity_fixture.c b/test/unity/unity_fixture.c new file mode 100644 index 00000000..9b3fce27 --- /dev/null +++ b/test/unity/unity_fixture.c @@ -0,0 +1,310 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity_fixture.h" +#include "unity_internals.h" +#include + +struct UNITY_FIXTURE_T UnityFixture; + +/* If you decide to use the function pointer approach. + * Build with -D UNITY_OUTPUT_CHAR=outputChar and include + * int (*outputChar)(int) = putchar; */ + +void setUp(void) { /*does nothing*/ } +void tearDown(void) { /*does nothing*/ } + +static void announceTestRun(unsigned int runNumber) +{ + UnityPrint("Unity test run "); + UnityPrintNumberUnsigned(runNumber+1); + UnityPrint(" of "); + UnityPrintNumberUnsigned(UnityFixture.RepeatCount); + UNITY_PRINT_EOL(); +} + +int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)) +{ + int result = UnityGetCommandLineOptions(argc, argv); + unsigned int r; + if (result != 0) + return result; + + for (r = 0; r < UnityFixture.RepeatCount; r++) + { + UnityBegin(argv[0]); + announceTestRun(r); + runAllTests(); + if (!UnityFixture.Verbose) UNITY_PRINT_EOL(); + UnityEnd(); + } + + return (int)Unity.TestFailures; +} + +static int selected(const char* filter, const char* name) +{ + if (filter == 0) + return 1; + return strstr(name, filter) ? 1 : 0; +} + +static int testSelected(const char* test) +{ + return selected(UnityFixture.NameFilter, test); +} + +static int groupSelected(const char* group) +{ + return selected(UnityFixture.GroupFilter, group); +} + +void UnityTestRunner(unityfunction* setup, + unityfunction* testBody, + unityfunction* teardown, + const char* printableName, + const char* group, + const char* name, + const char* file, + unsigned int line) +{ + if (testSelected(name) && groupSelected(group)) + { + Unity.TestFile = file; + Unity.CurrentTestName = printableName; + Unity.CurrentTestLineNumber = line; + if (UnityFixture.Verbose) + { + UnityPrint(printableName); + #ifndef UNITY_REPEAT_TEST_NAME + Unity.CurrentTestName = NULL; + #endif + } + else if (UnityFixture.Silent) + { + /* Do Nothing */ + } + else + { + UNITY_OUTPUT_CHAR('.'); + } + + Unity.NumberOfTests++; + UnityPointer_Init(); + + UNITY_EXEC_TIME_START(); + + if (TEST_PROTECT()) + { + setup(); + testBody(); + } + if (TEST_PROTECT()) + { + teardown(); + } + if (TEST_PROTECT()) + { + UnityPointer_UndoAllSets(); + } + UnityConcludeFixtureTest(); + } +} + +void UnityIgnoreTest(const char* printableName, const char* group, const char* name) +{ + if (testSelected(name) && groupSelected(group)) + { + Unity.NumberOfTests++; + Unity.TestIgnores++; + if (UnityFixture.Verbose) + { + UnityPrint(printableName); + UNITY_PRINT_EOL(); + } + else if (UnityFixture.Silent) + { + /* Do Nothing */ + } + else + { + UNITY_OUTPUT_CHAR('!'); + } + } +} + +/*-------------------------------------------------------- */ +/*Automatic pointer restoration functions */ +struct PointerPair +{ + void** pointer; + void* old_value; +}; + +static struct PointerPair pointer_store[UNITY_MAX_POINTERS]; +static int pointer_index = 0; + +void UnityPointer_Init(void) +{ + pointer_index = 0; +} + +void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line) +{ + if (pointer_index >= UNITY_MAX_POINTERS) + { + UNITY_TEST_FAIL(line, "Too many pointers set"); + } + else + { + pointer_store[pointer_index].pointer = pointer; + pointer_store[pointer_index].old_value = *pointer; + *pointer = newValue; + pointer_index++; + } +} + +void UnityPointer_UndoAllSets(void) +{ + while (pointer_index > 0) + { + pointer_index--; + *(pointer_store[pointer_index].pointer) = + pointer_store[pointer_index].old_value; + } +} + +int UnityGetCommandLineOptions(int argc, const char* argv[]) +{ + int i; + UnityFixture.Verbose = 0; + UnityFixture.Silent = 0; + UnityFixture.GroupFilter = 0; + UnityFixture.NameFilter = 0; + UnityFixture.RepeatCount = 1; + + if (argc == 1) + return 0; + + for (i = 1; i < argc; ) + { + if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) + { + /* Usage */ + UnityPrint("Runs a series of unit tests."); + UNITY_PRINT_EOL(); + UNITY_PRINT_EOL(); + UnityPrint("When no flag is specified, all tests are run."); + UNITY_PRINT_EOL(); + UNITY_PRINT_EOL(); + UnityPrint("Optional flags:"); + UNITY_PRINT_EOL(); + UnityPrint(" -v Verbose output: show all tests executed even if they pass"); + UNITY_PRINT_EOL(); + UnityPrint(" -s Silent mode: minimal output showing only test failures"); + UNITY_PRINT_EOL(); + UnityPrint(" -g NAME Only run tests in groups that contain the string NAME"); + UNITY_PRINT_EOL(); + UnityPrint(" -n NAME Only run tests whose name contains the string NAME"); + UNITY_PRINT_EOL(); + UnityPrint(" -r NUMBER Repeatedly run all tests NUMBER times"); + UNITY_PRINT_EOL(); + UnityPrint(" -h, --help Display this help message"); + UNITY_PRINT_EOL(); + UNITY_PRINT_EOL(); +#ifdef UNITY_CUSTOM_HELP_MSG + /* User-defined help message, e.g. to point to project-specific documentation */ + UnityPrint(UNITY_CUSTOM_HELP_MSG); + UNITY_PRINT_EOL(); +#else + /* Default help suffix if a custom one is not defined */ + UnityPrint("More information about Unity: https://www.throwtheswitch.org/unity"); + UNITY_PRINT_EOL(); +#endif + return 1; /* Exit without running the tests */ + } + else if (strcmp(argv[i], "-v") == 0) + { + UnityFixture.Verbose = 1; + i++; + } + else if (strcmp(argv[i], "-s") == 0) + { + UnityFixture.Silent = 1; + i++; + } + else if (strcmp(argv[i], "-g") == 0) + { + i++; + if (i >= argc) + return 1; + UnityFixture.GroupFilter = argv[i]; + i++; + } + else if (strcmp(argv[i], "-n") == 0) + { + i++; + if (i >= argc) + return 1; + UnityFixture.NameFilter = argv[i]; + i++; + } + else if (strcmp(argv[i], "-r") == 0) + { + UnityFixture.RepeatCount = 2; + i++; + if (i < argc) + { + if (*(argv[i]) >= '0' && *(argv[i]) <= '9') + { + unsigned int digit = 0; + UnityFixture.RepeatCount = 0; + while (argv[i][digit] >= '0' && argv[i][digit] <= '9') + { + UnityFixture.RepeatCount *= 10; + UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0'; + } + i++; + } + } + } + else + { + /* ignore unknown parameter */ + i++; + } + } + return 0; +} + +void UnityConcludeFixtureTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + UNITY_PRINT_EOL(); + } + else if (!Unity.CurrentTestFailed) + { + if (UnityFixture.Verbose) + { + UnityPrint(" "); + UnityPrint(UnityStrPass); + UNITY_EXEC_TIME_STOP(); + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + } + } + else /* Unity.CurrentTestFailed */ + { + Unity.TestFailures++; + UNITY_PRINT_EOL(); + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; +} diff --git a/test/unity/unity_fixture.h b/test/unity/unity_fixture.h new file mode 100644 index 00000000..ed6ff482 --- /dev/null +++ b/test/unity/unity_fixture.h @@ -0,0 +1,94 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FIXTURE_H_ +#define UNITY_FIXTURE_H_ + +#include "unity.h" +#include "unity_fixture_internals.h" + +#ifndef UNITY_FIXTURE_NO_EXTRAS +#include "unity_memory.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + + +int UnityMain(int argc, const char* argv[], void (*runAllTests)(void)); + + +#define TEST_GROUP(group)\ + static const char* TEST_GROUP_##group = #group + +#define TEST_SETUP(group) void TEST_##group##_SETUP(void);\ + void TEST_##group##_SETUP(void) + +#define TEST_TEAR_DOWN(group) void TEST_##group##_TEAR_DOWN(void);\ + void TEST_##group##_TEAR_DOWN(void) + + +#define TEST(group, name) \ + void TEST_##group##_##name##_(void);\ + void TEST_##group##_##name##_run(void);\ + void TEST_##group##_##name##_run(void)\ + {\ + UnityTestRunner(TEST_##group##_SETUP,\ + TEST_##group##_##name##_,\ + TEST_##group##_TEAR_DOWN,\ + "TEST(" #group ", " #name ")",\ + TEST_GROUP_##group, #name,\ + __FILE__, __LINE__);\ + }\ + void TEST_##group##_##name##_(void) + +#define IGNORE_TEST(group, name) \ + void TEST_##group##_##name##_(void);\ + void TEST_##group##_##name##_run(void);\ + void TEST_##group##_##name##_run(void)\ + {\ + UnityIgnoreTest("IGNORE_TEST(" #group ", " #name ")", TEST_GROUP_##group, #name);\ + }\ + void TEST_##group##_##name##_(void) + +/* Call this for each test, insider the group runner */ +#define RUN_TEST_CASE(group, name) \ + { void TEST_##group##_##name##_run(void);\ + TEST_##group##_##name##_run(); } + +/* This goes at the bottom of each test file or in a separate c file */ +#define TEST_GROUP_RUNNER(group)\ + void TEST_##group##_GROUP_RUNNER(void);\ + void TEST_##group##_GROUP_RUNNER(void) + +/* Call this from main */ +#define RUN_TEST_GROUP(group)\ + { void TEST_##group##_GROUP_RUNNER(void);\ + TEST_##group##_GROUP_RUNNER(); } + +/* CppUTest Compatibility Macros */ +#ifndef UNITY_EXCLUDE_CPPUTEST_ASSERTS +/* Sets a pointer and automatically restores it to its old value after teardown */ +#define UT_PTR_SET(ptr, newPointerValue) UnityPointer_Set((void**)&(ptr), (void*)(newPointerValue), __LINE__) +#define TEST_ASSERT_POINTERS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_PTR((expected), (actual)) +#define TEST_ASSERT_BYTES_EQUAL(expected, actual) TEST_ASSERT_EQUAL_HEX8(0xff & (expected), 0xff & (actual)) +#define FAIL(message) TEST_FAIL_MESSAGE((message)) +#define CHECK(condition) TEST_ASSERT_TRUE((condition)) +#define LONGS_EQUAL(expected, actual) TEST_ASSERT_EQUAL_INT((expected), (actual)) +#define STRCMP_EQUAL(expected, actual) TEST_ASSERT_EQUAL_STRING((expected), (actual)) +#define DOUBLES_EQUAL(expected, actual, delta) TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* UNITY_FIXTURE_H_ */ diff --git a/test/unity/unity_fixture_internals.h b/test/unity/unity_fixture_internals.h new file mode 100644 index 00000000..f8f83d2d --- /dev/null +++ b/test/unity/unity_fixture_internals.h @@ -0,0 +1,50 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_FIXTURE_INTERNALS_H_ +#define UNITY_FIXTURE_INTERNALS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct UNITY_FIXTURE_T +{ + int Verbose; + int Silent; + unsigned int RepeatCount; + const char* NameFilter; + const char* GroupFilter; +}; +extern struct UNITY_FIXTURE_T UnityFixture; + +typedef void unityfunction(void); +void UnityTestRunner(unityfunction* setup, + unityfunction* testBody, + unityfunction* teardown, + const char* printableName, + const char* group, + const char* name, + const char* file, unsigned int line); + +void UnityIgnoreTest(const char* printableName, const char* group, const char* name); +int UnityGetCommandLineOptions(int argc, const char* argv[]); +void UnityConcludeFixtureTest(void); + +void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line); +void UnityPointer_UndoAllSets(void); +void UnityPointer_Init(void); +#ifndef UNITY_MAX_POINTERS +#define UNITY_MAX_POINTERS 5 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* UNITY_FIXTURE_INTERNALS_H_ */ diff --git a/test/unity/unity_internals.h b/test/unity/unity_internals.h new file mode 100644 index 00000000..562f5b6d --- /dev/null +++ b/test/unity/unity_internals.h @@ -0,0 +1,1183 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define UNITY_FUNCTION_ATTR(a) __attribute__((a)) +#else + #define UNITY_FUNCTION_ATTR(a) /* ignore */ +#endif + +/* UNITY_NORETURN is only required if we have setjmp.h. */ +#ifndef UNITY_EXCLUDE_SETJMP_H + #ifndef UNITY_NORETURN + #if defined(__cplusplus) + #if __cplusplus >= 201103L + #define UNITY_NORETURN [[ noreturn ]] + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L + /* _Noreturn keyword is used from C11 but deprecated in C23. */ + #if defined(_WIN32) && defined(_MSC_VER) + /* We are using MSVC compiler on Windows platform. */ + /* Not all Windows SDKs supports , but compiler can support C11: */ + /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ + /* Not sure, that Mingw compilers has Windows SDK headers at all. */ + #include + #endif + + /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ + /* Mingw GCC should work without that fixes. */ + /* Based on: */ + /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ + /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ + #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) + /* Based on tests and: */ + /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ + /* https://en.cppreference.com/w/c/language/_Noreturn */ + #define UNITY_NORETURN _Noreturn + #else /* Using newer Windows SDK or not MSVC compiler */ + #if defined(__GNUC__) + /* The header collides with __attribute(noreturn)__ from GCC. */ + #define UNITY_NORETURN _Noreturn + #else + #include + #define UNITY_NORETURN noreturn + #endif + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L + /* Since C23, the keyword _Noreturn has been replaced by the attribute noreturn, based on: */ + /* https://en.cppreference.com/w/c/language/attributes/noreturn */ + #define UNITY_NORETURN [[ noreturn ]] + #endif + #endif + #ifndef UNITY_NORETURN + #define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__) + #endif +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_INT_WIDTH (32) + #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_LONG_WIDTH (32) + #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH + #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char UNITY_UINT8; + typedef unsigned short UNITY_UINT16; + typedef unsigned int UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed short UNITY_INT16; + typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char UNITY_UINT8; + typedef unsigned int UNITY_UINT16; + typedef unsigned long UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed int UNITY_INT16; + typedef signed long UNITY_INT32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_INT; + #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else + /* 64-bit Support */ + #if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long UNITY_UINT64; + typedef signed long long UNITY_INT64; + #elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long UNITY_UINT64; + typedef signed long UNITY_INT64; + #else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) + #endif + typedef UNITY_UINT64 UNITY_UINT; + typedef UNITY_INT64 UNITY_INT; + #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + #define UNITY_PTR_TO_INT UNITY_INT32 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + #define UNITY_PTR_TO_INT UNITY_INT64 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + #define UNITY_PTR_TO_INT UNITY_INT16 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE + #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR + #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isnan macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_NAN +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define UNITY_IS_NAN(n) ((n != n) ? 1 : 0) +#else +#define UNITY_IS_NAN(n) isnan(n) +#endif +#endif + +/* isinf macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_INF +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define UNITY_IS_INF(n) (UNITY_IS_NAN((n) - (n)) && !UNITY_IS_NAN(n)) +#else +#define UNITY_IS_INF(n) isinf(n) +#endif +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + + /* No Floating Point Support */ + #ifndef UNITY_EXCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #else + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifndef UNITY_EXCLUDE_FLOAT + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ + #endif + +#else + + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR + /* Default to using putchar, which is defined in stdio.h */ + #include + #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION + extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH + #ifdef UNITY_USE_FLUSH_STDOUT + /* We want to use the stdout flush utility */ + #include + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #else + /* We've specified nothing, therefore flush should just be ignored */ + #define UNITY_OUTPUT_FLUSH() (void)0 + #endif +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION + extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME + #if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) + /* If none any of these macros are defined then try to provide a default implementation */ + + #if defined(UNITY_CLOCK_MS) + /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ + #define UNITY_TIME_TYPE UNITY_UINT + #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() + #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(_WIN32) + #include + #define UNITY_TIME_TYPE clock_t + #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(__unix__) || defined(__APPLE__) + #include + #define UNITY_TIME_TYPE struct timespec + #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #endif + #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_WITHIN = 0x0, + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_NOT_EQUAL = 0x0, + UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnitySetTestFile(const char* filename); +void UnityConcludeTest(void); + +#ifndef RUN_TEST +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); +#else +#define UNITY_SKIP_DEFAULT_RUNNER +#endif + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0) + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +#ifdef UNITY_PRINT_TEST_CONTEXT +void UNITY_PRINT_TEST_CONTEXT(void); +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +#ifndef UNITY_EXCLUDE_SETJMP_H +UNITY_NORETURN void UnityFail(const char* message, const UNITY_LINE_TYPE line); +UNITY_NORETURN void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#else +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#endif + +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifdef UNITY_TEST_PROTECT +#define TEST_PROTECT() UNITY_TEST_PROTECT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#else +#define TEST_PROTECT() 1 +#endif +#endif + +#ifdef UNITY_TEST_ABORT +#define TEST_ABORT() UNITY_TEST_ABORT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_ABORT() return +#endif +#endif + +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS + #ifdef __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #define UNITY_SUPPORT_VARIADIC_MACROS + #endif + #endif +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) +#endif +#endif + +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES + #ifdef UNITY_SUPPORT_VARIADIC_MACROS + #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) + #define TEST_CASE(...) + #endif + #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) + #define TEST_RANGE(...) + #endif + #if !defined(TEST_MATRIX) && !defined(UNITY_EXCLUDE_TEST_MATRIX) + #define TEST_MATRIX(...) + #endif + #endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((line), (message)); } } while (0) +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (line), (message)) +#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (line), (message)) +#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/test/unity/unity_memory.c b/test/unity/unity_memory.c new file mode 100644 index 00000000..e9eaae35 --- /dev/null +++ b/test/unity/unity_memory.c @@ -0,0 +1,203 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#include "unity.h" +#include "unity_memory.h" +#include + +#define MALLOC_DONT_FAIL -1 +static int malloc_count; +static int malloc_fail_countdown = MALLOC_DONT_FAIL; + +void UnityMalloc_StartTest(void) +{ + malloc_count = 0; + malloc_fail_countdown = MALLOC_DONT_FAIL; +} + +void UnityMalloc_EndTest(void) +{ + malloc_fail_countdown = MALLOC_DONT_FAIL; + if (malloc_count != 0) + { + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!"); + } +} + +void UnityMalloc_MakeMallocFailAfterCount(int countdown) +{ + malloc_fail_countdown = countdown; +} + +/* These definitions are always included from unity_fixture_malloc_overrides.h */ +/* We undef to use them or avoid conflict with per the C standard */ +#undef malloc +#undef free +#undef calloc +#undef realloc + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC +static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES]; +static size_t heap_index; +#else +#include +#endif + +typedef struct GuardBytes +{ + size_t size; + size_t guard_space; +} Guard; + +#define UNITY_MALLOC_ALIGNMENT (UNITY_POINTER_WIDTH / 8) +static const char end[] = "END"; + +static size_t unity_size_round_up(size_t size) +{ + size_t rounded_size; + + rounded_size = ((size + UNITY_MALLOC_ALIGNMENT - 1) / UNITY_MALLOC_ALIGNMENT) * UNITY_MALLOC_ALIGNMENT; + + return rounded_size; +} + +void* unity_malloc(size_t size) +{ + char* mem; + Guard* guard; + size_t total_size; + + total_size = sizeof(Guard) + unity_size_round_up(size + sizeof(end)); + + if (malloc_fail_countdown != MALLOC_DONT_FAIL) + { + if (malloc_fail_countdown == 0) + return NULL; + malloc_fail_countdown--; + } + + if (size == 0) return NULL; +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES) + { + guard = NULL; + } + else + { + /* We know we can get away with this cast because we aligned memory already */ + guard = (Guard*)(void*)(&unity_heap[heap_index]); + heap_index += total_size; + } +#else + guard = (Guard*)UNITY_MALLOC(total_size); +#endif + if (guard == NULL) return NULL; + malloc_count++; + guard->size = size; + guard->guard_space = 0; + mem = (char*)&(guard[1]); + memcpy(&mem[size], end, sizeof(end)); + + return (void*)mem; +} + +static int isOverrun(void* mem) +{ + Guard* guard = (Guard*)mem; + char* memAsChar = (char*)mem; + guard--; + + return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0; +} + +static void release_memory(void* mem) +{ + Guard* guard = (Guard*)mem; + guard--; + + malloc_count--; +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC + { + size_t block_size; + + block_size = unity_size_round_up(guard->size + sizeof(end)); + + if (mem == unity_heap + heap_index - block_size) + { + heap_index -= (sizeof(Guard) + block_size); + } + } +#else + UNITY_FREE(guard); +#endif +} + +void unity_free(void* mem) +{ + int overrun; + + if (mem == NULL) + { + return; + } + + overrun = isOverrun(mem); + release_memory(mem); + if (overrun) + { + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()"); + } +} + +void* unity_calloc(size_t num, size_t size) +{ + void* mem = unity_malloc(num * size); + if (mem == NULL) return NULL; + memset(mem, 0, num * size); + return mem; +} + +void* unity_realloc(void* oldMem, size_t size) +{ + Guard* guard = (Guard*)oldMem; + void* newMem; + + if (oldMem == NULL) return unity_malloc(size); + + guard--; + if (isOverrun(oldMem)) + { + release_memory(oldMem); + UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()"); + } + + if (size == 0) + { + release_memory(oldMem); + return NULL; + } + + if (guard->size >= size) return oldMem; + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC /* Optimization if memory is expandable */ + { + size_t old_total_size = unity_size_round_up(guard->size + sizeof(end)); + + if ((oldMem == unity_heap + heap_index - old_total_size) && + ((heap_index - old_total_size + unity_size_round_up(size + sizeof(end))) <= UNITY_INTERNAL_HEAP_SIZE_BYTES)) + { + release_memory(oldMem); /* Not thread-safe, like unity_heap generally */ + return unity_malloc(size); /* No memcpy since data is in place */ + } + } +#endif + newMem = unity_malloc(size); + if (newMem == NULL) return NULL; /* Do not release old memory */ + memcpy(newMem, oldMem, guard->size); + release_memory(oldMem); + return newMem; +} diff --git a/test/unity/unity_memory.h b/test/unity/unity_memory.h new file mode 100644 index 00000000..70a7f25f --- /dev/null +++ b/test/unity/unity_memory.h @@ -0,0 +1,61 @@ +/* ========================================================================= + Unity - A Test Framework for C + ThrowTheSwitch.org + Copyright (c) 2007-25 Mike Karlesky, Mark VanderVoord, & Greg Williams + SPDX-License-Identifier: MIT +========================================================================= */ + +#ifndef UNITY_MEMORY_OVERRIDES_H_ +#define UNITY_MEMORY_OVERRIDES_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#ifdef UNITY_EXCLUDE_STDLIB_MALLOC +/* Define this macro to remove the use of stdlib.h, malloc, and free. + * Many embedded systems do not have a heap or malloc/free by default. + * This internal unity_malloc() provides allocated memory deterministically from + * the end of an array only, unity_free() only releases from end-of-array, + * blocks are not coalesced, and memory not freed in LIFO order is stranded. */ + #ifndef UNITY_INTERNAL_HEAP_SIZE_BYTES + #define UNITY_INTERNAL_HEAP_SIZE_BYTES 256 + #endif +#endif + +/* These functions are used by Unity to allocate and release memory + * on the heap and can be overridden with platform-specific implementations. + * For example, when using FreeRTOS UNITY_MALLOC becomes pvPortMalloc() + * and UNITY_FREE becomes vPortFree(). */ +#if !defined(UNITY_MALLOC) || !defined(UNITY_FREE) + #include + #define UNITY_MALLOC(size) malloc(size) + #define UNITY_FREE(ptr) free(ptr) +#else + extern void* UNITY_MALLOC(size_t size); + extern void UNITY_FREE(void* ptr); +#endif + +#define malloc unity_malloc +#define calloc unity_calloc +#define realloc unity_realloc +#define free unity_free + +void* unity_malloc(size_t size); +void* unity_calloc(size_t num, size_t size); +void* unity_realloc(void * oldMem, size_t size); +void unity_free(void * mem); + +/* You must compile with malloc replacement, as defined in unity_fixture_malloc_overrides.h */ +void UnityMalloc_StartTest(void); +void UnityMalloc_EndTest(void); +void UnityMalloc_MakeMallocFailAfterCount(int countdown); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tls.c b/tls.c deleted file mode 100644 index a32bb862..00000000 --- a/tls.c +++ /dev/null @@ -1,334 +0,0 @@ -#include "types.h" -#include "tls.h" -#include "config.h" -#include "logging.h" -#include "utils.h" - -#ifndef KERNEL_SPACE -#include -#include -#endif - -static int bruteforce_analyze_sni_str( - const struct section_config_t *section, - const uint8_t *data, size_t dlen, - struct tls_verdict *vrd -) { - if (section->all_domains) { - vrd->target_sni = 1; - vrd->sni_len = 0; - vrd->sni_offset = dlen / 2; - return 0; - } - - for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) { - const char *domain_startp = sne->domain_name; - int domain_len = sne->domain_len; - - if (sne->domain_len + dlen + 1 > MAX_PACKET_SIZE) { - continue; - } - - NETBUF_ALLOC(buf, MAX_PACKET_SIZE); - if (!NETBUF_CHECK(buf)) { - lgerror(-ENOMEM, "Allocation error"); - return -ENOMEM; - } - NETBUF_ALLOC(nzbuf, MAX_PACKET_SIZE * sizeof(int)); - if (!NETBUF_CHECK(nzbuf)) { - lgerror(-ENOMEM, "Allocation error"); - NETBUF_FREE(buf); - return -ENOMEM; - } - - int *zbuf = (void *)nzbuf; - - memcpy(buf, domain_startp, domain_len); - memcpy(buf + domain_len, "#", 1); - memcpy(buf + domain_len + 1, data, dlen); - - z_function((char *)buf, zbuf, domain_len + 1 + dlen); - - for (unsigned int k = 0; k < dlen; k++) { - if (zbuf[k] == domain_len) { - vrd->target_sni = 1; - vrd->sni_len = domain_len; - vrd->sni_offset = (k - domain_len - 1); - vrd->sni_target_offset = vrd->sni_offset; - vrd->sni_target_len = vrd->sni_len; - NETBUF_FREE(buf); - NETBUF_FREE(nzbuf); - return 0; - } - } - - - NETBUF_FREE(buf); - NETBUF_FREE(nzbuf); - } - - return 0; -} -static int analyze_sni_str( - const struct section_config_t *section, - const char *sni_name, int sni_len, const uint8_t *data, - struct tls_verdict *vrd -) { - if (section->all_domains) { - vrd->target_sni = 1; - goto check_domain; - } - - for (struct domains_list *sne = section->sni_domains; sne != NULL; sne = sne->next) { - const char *sni_startp = sni_name + sni_len - sne->domain_len; - const char *domain_startp = sne->domain_name; - - if (sni_len >= sne->domain_len && - sni_len < 128 && - !strncmp(sni_startp, - domain_startp, - sne->domain_len)) { - vrd->target_sni = 1; - vrd->sni_target_offset = (const uint8_t *)sni_startp - data; - vrd->sni_target_len = sne->domain_len; - break; - } - } - -check_domain: - if (vrd->target_sni == 1) { - for (struct domains_list *sne = section->exclude_sni_domains; sne != NULL; sne = sne->next) { - const char *sni_startp = sni_name + sni_len - sne->domain_len; - const char *domain_startp = sne->domain_name; - - if (sni_len >= sne->domain_len && - sni_len < 128 && - !strncmp(sni_startp, - domain_startp, - sne->domain_len)) { - vrd->target_sni = 0; - lgdebugmsg("Excluded SNI: %.*s", - vrd->sni_len, data + vrd->sni_offset); - } - } - } - - return 0; -} - - -#define TLS_CONTENT_TYPE_HANDSHAKE 0x16 -#define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 0x01 -#define TLS_EXTENSION_SNI 0x0000 -#define TLS_EXTENSION_CLIENT_HELLO_ENCRYPTED 0xfe0d - -/** - * Processes tls payload of the tcp request. - * - * data Payload data of TCP. - * dlen Length of `data`. - */ -struct tls_verdict analyze_tls_data( - const struct section_config_t *section, - const uint8_t *data, - uint32_t dlen) -{ - struct tls_verdict vrd = {0}; - - size_t i = 0; - const uint8_t *data_end = data + dlen; - - if (section->sni_detection == SNI_DETECTION_BRUTE) { - bruteforce_analyze_sni_str(section, data, dlen, &vrd); - goto out; - } - - while (i + 4 < dlen) { - const uint8_t *msgData = data + i; - - uint8_t tls_content_type = *msgData; - uint8_t tls_vmajor = *(msgData + 1); - uint16_t message_length = ntohs(*(uint16_t *)(msgData + 3)); - - if (tls_vmajor != 0x03) goto nextMessage; - - if (i + 5 > dlen) break; - - if (tls_content_type != TLS_CONTENT_TYPE_HANDSHAKE) - goto nextMessage; - - const uint8_t *handshakeProto = msgData + 5; - - if (handshakeProto + 1 >= data_end) break; - - uint8_t handshakeType = *handshakeProto; - - if (handshakeType != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) - goto nextMessage; - - const uint8_t *msgPtr = handshakeProto; - msgPtr += 1; - msgPtr += 3 + 2 + 32; - - if (msgPtr + 1 >= data_end) break; - uint8_t sessionIdLength = *msgPtr; - msgPtr++; - msgPtr += sessionIdLength; - - if (msgPtr + 2 >= data_end) break; - uint16_t ciphersLength = ntohs(*(uint16_t *)msgPtr); - msgPtr += 2; - msgPtr += ciphersLength; - - if (msgPtr + 1 >= data_end) break; - uint8_t compMethodsLen = *msgPtr; - msgPtr++; - msgPtr += compMethodsLen; - - if (msgPtr + 2 >= data_end) break; - uint16_t extensionsLen = ntohs(*(uint16_t *)msgPtr); - msgPtr += 2; - - const uint8_t *extensionsPtr = msgPtr; - const uint8_t *extensions_end = extensionsPtr + extensionsLen; - if (extensions_end > data_end) extensions_end = data_end; - - while (extensionsPtr < extensions_end) { - const uint8_t *extensionPtr = extensionsPtr; - if (extensionPtr + 4 >= extensions_end) break; - - uint16_t extensionType = - ntohs(*(uint16_t *)extensionPtr); - extensionPtr += 2; - - uint16_t extensionLen = - ntohs(*(uint16_t *)extensionPtr); - extensionPtr += 2; - - - if (extensionPtr + extensionLen > extensions_end) - break; - - if (extensionType != TLS_EXTENSION_SNI) - goto nextExtension; - - const uint8_t *sni_ext_ptr = extensionPtr; - - if (sni_ext_ptr + 2 >= extensions_end) break; - uint16_t sni_ext_dlen = ntohs(*(uint16_t *)sni_ext_ptr); - - sni_ext_ptr += 2; - - const uint8_t *sni_ext_end = sni_ext_ptr + sni_ext_dlen; - if (sni_ext_end >= extensions_end) break; - - if (sni_ext_ptr + 3 >= sni_ext_end) break; - sni_ext_ptr++; - uint16_t sni_len = ntohs(*(uint16_t *)sni_ext_ptr); - sni_ext_ptr += 2; - - if (sni_ext_ptr + sni_len > sni_ext_end) break; - - const char *sni_name = (char *)sni_ext_ptr; - - vrd.sni_offset = (uint8_t *)sni_name - data; - vrd.sni_target_offset = vrd.sni_offset; - vrd.sni_len = sni_len; - vrd.sni_target_len = vrd.sni_len; - - analyze_sni_str(section, sni_name, sni_len, data, &vrd); - goto out; - -nextExtension: - extensionsPtr += 2 + 2 + extensionLen; - } -nextMessage: - i += 5 + message_length; - } - -out: - return vrd; -} - -int gen_fake_sni(struct fake_type type, - const void *ipxh, uint32_t iph_len, - const struct tcphdr *tcph, uint32_t tcph_len, - uint8_t *buf, uint32_t *buflen) { - uint32_t data_len = type.fake_len; - - if (type.type == FAKE_PAYLOAD_RANDOM && data_len == 0) { - data_len = (uint32_t)randint() % 1200; - } - - if (!ipxh || !tcph || !buf || !buflen) - return -EINVAL; - - int ipxv = netproto_version(ipxh, iph_len); - - if (ipxv == IP4VERSION) { - const struct iphdr *iph = ipxh; - - memcpy(buf, iph, iph_len); - struct iphdr *niph = (struct iphdr *)buf; - - niph->protocol = IPPROTO_TCP; - } else if (ipxv == IP6VERSION) { - const struct ip6_hdr *iph = ipxh; - - iph_len = sizeof(struct ip6_hdr); - memcpy(buf, iph, iph_len); - struct ip6_hdr *niph = (struct ip6_hdr *)buf; - - niph->ip6_nxt = IPPROTO_TCP; - } else { - return -EINVAL; - } - - uint32_t dlen = iph_len + tcph_len + data_len; - - if (*buflen < dlen) - return -ENOMEM; - - memcpy(buf + iph_len, tcph, tcph_len); - uint8_t *bfdptr = buf + iph_len + tcph_len; - - switch (type.type) { - case FAKE_PAYLOAD_DATA: - memcpy(bfdptr, type.fake_data, data_len); - break; - default: // FAKE_PAYLOAD_RANDOM -#ifdef KERNEL_SPACE - get_random_bytes(bfdptr, data_len); -#else /* KERNEL_SPACE */ -#if _NO_GETRANDOM - { - int ret = open("/dev/urandom", O_RDONLY); - if (ret < 0) { - lgerror(ret, "Unable to open /dev/urandom"); - return ret; - } - - read(ret, bfdptr, data_len); - close(ret); - } -#else /* _NO_GETRANDOM */ - getrandom(bfdptr, data_len, 0); -#endif /* _NO_GETRANDOM */ -#endif /* KERNEL_SPACE */ - } - - if (ipxv == IP4VERSION) { - struct iphdr *niph = (struct iphdr *)buf; - niph->tot_len = htons(dlen); - } else if (ipxv == IP6VERSION) { - struct ip6_hdr *niph = (struct ip6_hdr *)buf; - niph->ip6_plen = htons(dlen - iph_len); - } - - fail_packet(type.strategy, buf, &dlen, *buflen); - - *buflen = dlen; - - return 0; -} - diff --git a/tls.h b/tls.h deleted file mode 100644 index 024a1ccb..00000000 --- a/tls.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TLS_H -#define TLS_H - -#include "types.h" -#include "utils.h" - - -/** - * Result of analyze_tls_data function - */ -struct tls_verdict { - int target_sni; /* google video hello packet */ - int sni_offset; /* offset from start of tcp _payload_ */ - int sni_target_offset; /* offset of target domain instead of entire sni */ - int sni_target_len; /* offset of target domain instead of entire sni */ - int sni_len; -}; - -/** - * Processes the packet and finds TLS Client Hello information inside it. - * data pointer points to start of TLS Message (TCP Payload) - */ -struct tls_verdict analyze_tls_data(const struct section_config_t *section, const uint8_t *data, uint32_t dlen); - - -/** - * Generates the fake client hello message - */ -int gen_fake_sni(struct fake_type type, - const void *iph, uint32_t iph_len, - const struct tcphdr *tcph, uint32_t tcph_len, - uint8_t *buf, uint32_t *buflen); - -#endif /* TLS_H */ diff --git a/uspace.mk b/uspace.mk index 0e618a08..c1d2756c 100644 --- a/uspace.mk +++ b/uspace.mk @@ -4,6 +4,8 @@ USE_SYS_LIBS := no #Userspace app makes here BUILD_DIR := $(CURDIR)/build DEPSDIR := $(BUILD_DIR)/deps +INCLUDE_DIR := $(CURDIR)/src +SRC_DIR := $(CURDIR)/src CC:=gcc CCLD:=$(CC) @@ -15,7 +17,7 @@ ifeq ($(USE_SYS_LIBS), no) REQ = $(LIBNETFILTER_QUEUE) $(LIBMNL) $(LIBCRYPTO) endif -override CFLAGS += -DPKG_VERSION=\"$(PKG_FULLVERSION)\" -Wall -Wpedantic -Wno-unused-variable -std=gnu99 +override CFLAGS += -DPKG_VERSION=\"$(PKG_FULLVERSION)\" -I$(INCLUDE_DIR) -Wall -Wpedantic -Wno-unused-variable -std=gnu99 -Ideps/cyclone/include LIBNFNETLINK_CFLAGS := -I$(DEPSDIR)/include LIBNFNETLINK_LIBS := -L$(DEPSDIR)/lib @@ -30,16 +32,24 @@ endif export CC CCLD LD CFLAGS LDFLAGS LIBNFNETLINK_CFLAGS LIBNFNETLINK_LIBS LIBMNL_CFLAGS LIBMNL_LIBS APP:=$(BUILD_DIR)/youtubeUnblock +TEST_APP:=$(BUILD_DIR)/testYoutubeUnblock -SRCS := youtubeUnblock.c mangle.c args.c utils.c quic.c tls.c getopt.c +SRCS := mangle.c args.c utils.c quic.c tls.c getopt.c quic_crypto.c OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o) +APP_EXEC := youtubeUnblock.c +APP_OBJ := $(APP_EXEC:%.c=$(BUILD_DIR)/%.o) + + +TEST_SRCS := $(shell find test -name "*.c") +TEST_OBJS := $(TEST_SRCS:%.c=$(BUILD_DIR)/%.o) +TEST_CFLAGS := -Itest/unity -Itest LIBNFNETLINK := $(DEPSDIR)/lib/libnfnetlink.la LIBMNL := $(DEPSDIR)/lib/libmnl.la LIBNETFILTER_QUEUE := $(DEPSDIR)/lib/libnetfilter_queue.la -#LIBCRYPTO := $(DEPSDIR)/lib64/libcrypto.a +LIBCYCLONE := $(DEPSDIR)/lib/libcyclone.a -.PHONY: default all dev dev_attrs prepare_dirs +.PHONY: default all test build_test dev dev_attrs prepare_dirs default: all run_dev: dev @@ -52,14 +62,21 @@ dev_attrs: all: prepare_dirs $(APP) +build_test: prepare_dirs $(TEST_APP) +test: build_test + $(TEST_APP) + prepare_dirs: mkdir -p $(BUILD_DIR) + mkdir -p $(BUILD_DIR)/crypto + mkdir -p $(BUILD_DIR)/test + mkdir -p $(BUILD_DIR)/test/unity mkdir -p $(DEPSDIR) -$(LIBCRYPTO): - cd deps/openssl && ./Configure --prefix=$(DEPSDIR) $(if $(CROSS_COMPILE_PLATFORM),--cross-compile-prefix=$(CROSS_COMPILE_PLATFORM)-,) --no-shared - $(MAKE) -C deps/openssl - $(MAKE) install_sw -C deps/openssl +$(LIBCYCLONE): + $(MAKE) -C deps/cyclone CFLAGS="$(CFLAGS)" + mkdir -p $(DEPSDIR)/lib + cp deps/cyclone/libcyclone.a $(DEPSDIR)/lib/libcyclone.a $(LIBNFNETLINK): cd deps/libnfnetlink && ./autogen.sh && ./configure --prefix=$(DEPSDIR) $(if $(CROSS_COMPILE_PLATFORM),--host=$(CROSS_COMPILE_PLATFORM),) --enable-static --disable-shared @@ -76,14 +93,22 @@ $(LIBNETFILTER_QUEUE): $(LIBNFNETLINK) $(LIBMNL) $(MAKE) -C deps/libnetfilter_queue $(MAKE) install -C deps/libnetfilter_queue -$(APP): $(OBJS) $(REQ) +$(APP): $(OBJS) $(APP_OBJ) $(REQ) $(LIBCYCLONE) @echo 'CCLD $(APP)' - $(CCLD) $(OBJS) -o $(APP) $(LDFLAGS) -lmnl -lnetfilter_queue -lpthread + $(CCLD) $(OBJS) $(APP_OBJ) -o $(APP) $(LDFLAGS) -lmnl -lnetfilter_queue -lpthread -lcyclone -$(BUILD_DIR)/%.o: %.c $(REQ) config.h +$(TEST_APP): $(APP) $(TEST_OBJS) $(REQ) $(LIBCYCLONE) + @echo 'CCLD $(TEST_APP)' + $(CCLD) $(OBJS) $(TEST_OBJS) -o $(TEST_APP) $(LDFLAGS) -lmnl -lnetfilter_queue -lpthread -lcyclone + +$(BUILD_DIR)/%.o: src/%.c $(REQ) $(INCLUDE_DIR)/config.h @echo 'CC $@' $(CC) -c $(CFLAGS) $(LDFLAGS) $< -o $@ +$(BUILD_DIR)/test/%.o: test/%.c $(REQ) $(INCLUDE_DIR)/config.h + @echo 'CC $@' + $(CC) -c $(CFLAGS) $(LDFLAGS) $(TEST_CFLAGS) $< -o $@ + install: all install -d $(DESTDIR)$(PREFIX)/bin/ install -m 755 $(APP) $(DESTDIR)$(PREFIX)/bin/ @@ -106,5 +131,5 @@ ifeq ($(USE_SYS_LIBS), no) $(MAKE) distclean -C deps/libnetfilter_queue || true $(MAKE) distclean -C deps/libmnl || true $(MAKE) distclean -C deps/libnfnetlink || true - #$(MAKE) distclean -C deps/openssl || true endif + $(MAKE) clean -C deps/cyclone || true