From 5c84f2e9b5b758e5b827b229d1c48c5f84b0e64a Mon Sep 17 00:00:00 2001 From: Vadim Vetrov Date: Sat, 21 Sep 2024 22:13:32 +0300 Subject: [PATCH] Add crypto files --- Kbuild | 4 +- deps/cyclone/Makefile | 24 + deps/cyclone/aes.c | 577 +++++++++ deps/cyclone/cpu_endian.c | 151 +++ deps/cyclone/ecb.c | 116 ++ deps/cyclone/gcm.c | 629 ++++++++++ deps/cyclone/hkdf.c | 226 ++++ deps/cyclone/hmac.c | 303 +++++ deps/cyclone/include/aead/gcm.h | 92 ++ deps/cyclone/include/cipher/aes.h | 103 ++ deps/cyclone/include/cipher_modes/ecb.h | 54 + deps/cyclone/include/compiler_port.h | 283 +++++ deps/cyclone/include/core/crypto.h | 1119 ++++++++++++++++++ deps/cyclone/include/core/crypto_legacy.h | 68 ++ deps/cyclone/include/cpu_endian.h | 481 ++++++++ deps/cyclone/include/crypto_config.h | 7 + deps/cyclone/include/error.h | 320 +++++ deps/cyclone/include/hash/hash_algorithms.h | 62 + deps/cyclone/include/hash/sha256.h | 96 ++ deps/cyclone/include/kdf/hkdf.h | 58 + deps/cyclone/include/mac/hmac.h | 102 ++ deps/cyclone/include/os_port.h | 110 ++ deps/cyclone/libcyclone.a | Bin 0 -> 39842 bytes deps/cyclone/sha256.c | 361 ++++++ args.c => src/args.c | 0 args.h => src/args.h | 0 config.h => src/config.h | 0 getopt.c => src/getopt.c | 0 getopt.h => src/getopt.h | 0 kargs.c => src/kargs.c | 0 kytunblock.c => src/kytunblock.c | 0 logging.h => src/logging.h | 0 mangle.c => src/mangle.c | 0 mangle.h => src/mangle.h | 0 quic.c => src/quic.c | 93 +- quic.h => src/quic.h | 93 +- src/quic_crypto.c | 247 ++++ raw_replacements.h => src/raw_replacements.h | 0 tls.c => src/tls.c | 0 tls.h => src/tls.h | 0 types.h => src/types.h | 12 + utils.c => src/utils.c | 0 utils.h => src/utils.h | 0 youtubeUnblock.c => src/youtubeUnblock.c | 0 uspace.mk | 25 +- 45 files changed, 5751 insertions(+), 65 deletions(-) create mode 100644 deps/cyclone/Makefile create mode 100644 deps/cyclone/aes.c create mode 100644 deps/cyclone/cpu_endian.c create mode 100644 deps/cyclone/ecb.c create mode 100644 deps/cyclone/gcm.c create mode 100644 deps/cyclone/hkdf.c create mode 100644 deps/cyclone/hmac.c create mode 100644 deps/cyclone/include/aead/gcm.h create mode 100644 deps/cyclone/include/cipher/aes.h create mode 100644 deps/cyclone/include/cipher_modes/ecb.h create mode 100644 deps/cyclone/include/compiler_port.h create mode 100644 deps/cyclone/include/core/crypto.h create mode 100644 deps/cyclone/include/core/crypto_legacy.h create mode 100644 deps/cyclone/include/cpu_endian.h create mode 100644 deps/cyclone/include/crypto_config.h create mode 100644 deps/cyclone/include/error.h create mode 100644 deps/cyclone/include/hash/hash_algorithms.h create mode 100644 deps/cyclone/include/hash/sha256.h create mode 100644 deps/cyclone/include/kdf/hkdf.h create mode 100644 deps/cyclone/include/mac/hmac.h create mode 100644 deps/cyclone/include/os_port.h create mode 100644 deps/cyclone/libcyclone.a create mode 100644 deps/cyclone/sha256.c rename args.c => src/args.c (100%) rename args.h => src/args.h (100%) rename config.h => src/config.h (100%) rename getopt.c => src/getopt.c (100%) rename getopt.h => src/getopt.h (100%) rename kargs.c => src/kargs.c (100%) rename kytunblock.c => src/kytunblock.c (100%) rename logging.h => src/logging.h (100%) rename mangle.c => src/mangle.c (100%) rename mangle.h => src/mangle.h (100%) rename quic.c => src/quic.c (78%) rename quic.h => src/quic.h (55%) create mode 100644 src/quic_crypto.c rename raw_replacements.h => src/raw_replacements.h (100%) rename tls.c => src/tls.c (100%) rename tls.h => src/tls.h (100%) rename types.h => src/types.h (91%) rename utils.c => src/utils.c (100%) rename utils.h => src/utils.h (100%) rename youtubeUnblock.c => src/youtubeUnblock.c (100%) diff --git a/Kbuild b/Kbuild index 3dbbfe3..380a4b9 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/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/deps/cyclone/Makefile b/deps/cyclone/Makefile new file mode 100644 index 0000000..ec5bbd5 --- /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 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 0000000..78a3cdf --- /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 0000000..fd49899 --- /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 0000000..83cd580 --- /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 0000000..22cadbd --- /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 0000000..0c8c912 --- /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 0000000..6bfb582 --- /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 0000000..3d355e1 --- /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 0000000..e06aa3c --- /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 0000000..08ab5fd --- /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 0000000..d89d1e1 --- /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 0000000..7485eda --- /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 0000000..a7c3c8d --- /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 0000000000000000000000000000000000000000..ca3fc903a28785e29750af543ecc7a9c11ccbc4d GIT binary patch literal 39842 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 literal 0 HcmV?d00001 diff --git a/deps/cyclone/sha256.c b/deps/cyclone/sha256.c new file mode 100644 index 0000000..9b7f095 --- /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/args.c b/src/args.c similarity index 100% rename from args.c rename to src/args.c diff --git a/args.h b/src/args.h similarity index 100% rename from args.h rename to src/args.h diff --git a/config.h b/src/config.h similarity index 100% rename from config.h rename to src/config.h diff --git a/getopt.c b/src/getopt.c similarity index 100% rename from getopt.c rename to src/getopt.c 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 100% rename from kargs.c rename to src/kargs.c diff --git a/kytunblock.c b/src/kytunblock.c similarity index 100% rename from kytunblock.c rename to src/kytunblock.c diff --git a/logging.h b/src/logging.h similarity index 100% rename from logging.h rename to src/logging.h diff --git a/mangle.c b/src/mangle.c similarity index 100% rename from mangle.c rename to src/mangle.c diff --git a/mangle.h b/src/mangle.h similarity index 100% rename from mangle.h rename to src/mangle.h diff --git a/quic.c b/src/quic.c similarity index 78% rename from quic.c rename to src/quic.c index 339616b..4f9f7dc 100644 --- a/quic.c +++ b/src/quic.c @@ -12,7 +12,7 @@ struct quic_pnumber { uint8_t d4; }; -uint64_t quic_parse_varlength(uint8_t *variable, uint64_t *mlen) { +uint64_t quic_parse_varlength(const uint8_t *variable, uint64_t *mlen) { if (mlen && *mlen == 0) return 0; uint64_t vr = (*variable & 0x3F); uint8_t len = 1 << (*variable >> 6); @@ -31,35 +31,66 @@ uint64_t quic_parse_varlength(uint8_t *variable, uint64_t *mlen) { return vr; } -int quic_parse_data(uint8_t *raw_payload, uint32_t raw_payload_len, - struct quic_lhdr **qch, uint32_t *qch_len, +int64_t quic_get_version(const struct quic_lhdr *qch) { + int64_t qversion = ntohl(qch->version); + + switch (qversion) { + case QUIC_V1: + case QUIC_V2: + return qversion; + default: + return -qversion; + } +} + +int quic_check_is_initial(const struct quic_lhdr *qch) { + int64_t qversion = quic_get_version(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, uint32_t raw_payload_len, + const struct quic_lhdr **qch, uint32_t *qch_len, struct quic_cids *qci, - uint8_t **payload, uint32_t *plen) { + const 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; + const struct quic_lhdr *nqch = (const 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); + const 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; - } - } + int64_t qversion = quic_get_version(nqch); - if (!found) { - lgtrace_addp("quic version undefined %d", ntohl(nqch->version)); + if (qversion < 0) { + lgtrace_addp("quic version undefined %ld", -qversion); return -EPROTO; } - lgtrace_addp("quic version valid %d", ntohl(nqch->version)); + lgtrace_addp("quic version valid %ld", qversion); if (left_len < 2) goto invalid_packet; struct quic_cids nqci = {0}; @@ -93,14 +124,12 @@ 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) { +int quic_parse_initial_header(const uint8_t *inpayload, uint32_t inplen, + struct quici_hdr *qhdr) { if (inplen < 3) goto invalid_packet; struct quici_hdr nqhdr; - uint8_t *cur_ptr = inpayload; + const uint8_t *cur_ptr = inpayload; uint32_t left_len = inplen; uint64_t tlen = left_len; @@ -115,22 +144,18 @@ int quic_parse_initial_message(uint8_t *inpayload, uint32_t inplen, tlen = left_len; nqhdr.length = quic_parse_varlength(cur_ptr, &tlen); - if (left_len != nqhdr.length + tlen && - left_len <= qch->number_length + 1) + if (left_len < nqhdr.length + tlen || + nqhdr.length < QUIC_SAMPLE_SIZE + + QUIC_SAMPLE_OFFSET + ) goto invalid_packet; + cur_ptr += tlen; - 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; + nqhdr.protected_payload = cur_ptr; + nqhdr.sample = cur_ptr + QUIC_SAMPLE_OFFSET; + nqhdr.sample_length = QUIC_SAMPLE_SIZE; if (qhdr) *qhdr = nqhdr; - if (payload) *payload = cur_ptr; - if (plen) *plen = left_len; return 0; @@ -272,13 +297,13 @@ int detect_udp_filtered(const struct section_config_t *section, const struct quic_lhdr *qch; uint32_t qch_len; struct quic_cids qci; - uint8_t *quic_raw_payload; + const 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, + &qch, &qch_len, &qci, &quic_raw_payload, &quic_raw_plen); if (ret < 0) { diff --git a/quic.h b/src/quic.h similarity index 55% rename from quic.h rename to src/quic.h index 0422941..1626d5a 100644 --- a/quic.h +++ b/src/quic.h @@ -49,13 +49,42 @@ static const uint32_t supported_versions[] = { 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 number_length:2; - uint8_t reserved:2; + uint8_t type_specific:4;// protected uint8_t type:2; uint8_t fixed:1; uint8_t form:1; @@ -63,8 +92,7 @@ struct quic_lhdr { uint8_t form:1; uint8_t fixed:1; uint8_t type:2; - uint8_t reserved:2; - uint8_t number_length:2; + uint8_t type_specific:4;// protected #else #error "Undefined endian" #endif @@ -77,9 +105,9 @@ struct quic_lhdr { */ struct quic_cids { uint8_t dst_len; - uint8_t *dst_id; + const uint8_t *dst_id; uint8_t src_len; - uint8_t *src_id; + const uint8_t *src_id; }; /** @@ -89,10 +117,10 @@ struct quic_cids { * \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, +int quic_parse_data(const uint8_t *raw_payload, uint32_t raw_payload_len, + const struct quic_lhdr **qch, uint32_t *qch_len, struct quic_cids *qci, - uint8_t **payload, uint32_t *plen); + const uint8_t **payload, uint32_t *plen); /** @@ -103,7 +131,7 @@ int quic_parse_data(uint8_t *raw_payload, uint32_t raw_payload_len, * \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); +uint64_t quic_parse_varlength(const uint8_t *variable, uint64_t *mlen); // quici stands for QUIC Initial @@ -112,19 +140,48 @@ uint64_t quic_parse_varlength(uint8_t *variable, uint64_t *mlen); */ struct quici_hdr { uint64_t token_len; - uint8_t *token; + const uint8_t *token; uint64_t length; - uint32_t packet_number; + + const uint8_t *protected_payload; // with packet number + + // RFC 9001 5.4.2 + uint64_t sample_length; + const uint8_t *sample; }; /** - * Parses QUIC initial payload. - * \inpayload is a raw QUIC payload (payload after quic large header) + * Checks for quic version and checks if it is supported */ -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); +int64_t quic_get_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); + + +/** + * 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, uint32_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, uint32_t quic_plen, + uint8_t **udecrypted_payload, uint32_t *udecrypted_payload_len, + const uint8_t **udecrypted_message, uint32_t *udecrypted_message_len +); // Like fail_packet for TCP int udp_fail_packet(struct udp_failing_strategy strategy, uint8_t *payload, uint32_t *plen, uint32_t avail_buflen); diff --git a/src/quic_crypto.c b/src/quic_crypto.c new file mode 100644 index 0000000..adb0900 --- /dev/null +++ b/src/quic_crypto.c @@ -0,0 +1,247 @@ +#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, uint32_t quic_plen, + uint8_t **udecrypted_payload, uint32_t *udecrypted_payload_len, + const uint8_t **udecrypted_message, uint32_t *udecrypted_message_len +) { + int ret; + const struct quic_lhdr *qch; + uint32_t qch_len; + struct quic_cids qci; + const uint8_t *inpayload; + uint32_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; + uint32_t decrypted_payload_len; + uint8_t *decrypted_packet_number = NULL; + uint8_t *dcptr = NULL; + // Decrypted plain message without header + uint8_t *decrypted_message = NULL; + uint32_t decrypted_message_len; + AesContext actx; + GcmContext gctx; + int64_t qversion; + const uint8_t *iv_info; + uint32_t iv_info_size; + const uint8_t *key_info; + uint32_t key_info_size; + const uint8_t *hp_info; + uint32_t hp_info_size; + + ret = quic_parse_data(quic_payload, quic_plen, + &qch, &qch_len, &qci, &inpayload, &inplen + ); + + qversion = quic_get_version(qch); + 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; + 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; + 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, (const unsigned char *)QUIC_INITIAL_SALT_V1, sizeof(QUIC_INITIAL_SALT_V1) - 1, 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/tls.c b/src/tls.c similarity index 100% rename from tls.c rename to src/tls.c diff --git a/tls.h b/src/tls.h similarity index 100% rename from tls.h rename to src/tls.h diff --git a/types.h b/src/types.h similarity index 91% rename from types.h rename to src/types.h index e35733b..a8f8112 100644 --- a/types.h +++ b/src/types.h @@ -8,6 +8,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 diff --git a/utils.c b/src/utils.c similarity index 100% rename from utils.c rename to src/utils.c diff --git a/utils.h b/src/utils.h similarity index 100% rename from utils.h rename to src/utils.h diff --git a/youtubeUnblock.c b/src/youtubeUnblock.c similarity index 100% rename from youtubeUnblock.c rename to src/youtubeUnblock.c diff --git a/uspace.mk b/uspace.mk index 0e618a0..35244b0 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 @@ -31,13 +33,13 @@ export CC CCLD LD CFLAGS LDFLAGS LIBNFNETLINK_CFLAGS LIBNFNETLINK_LIBS LIBMNL_CF APP:=$(BUILD_DIR)/youtubeUnblock -SRCS := youtubeUnblock.c mangle.c args.c utils.c quic.c tls.c getopt.c +SRCS := youtubeUnblock.c mangle.c args.c utils.c quic.c tls.c getopt.c quic_crypto.c OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o) 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 default: all @@ -54,12 +56,13 @@ all: prepare_dirs $(APP) prepare_dirs: mkdir -p $(BUILD_DIR) + mkdir -p $(BUILD_DIR)/crypto 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 + 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,11 +79,11 @@ $(LIBNETFILTER_QUEUE): $(LIBNFNETLINK) $(LIBMNL) $(MAKE) -C deps/libnetfilter_queue $(MAKE) install -C deps/libnetfilter_queue -$(APP): $(OBJS) $(REQ) +$(APP): $(OBJS) $(REQ) $(LIBCYCLONE) @echo 'CCLD $(APP)' - $(CCLD) $(OBJS) -o $(APP) $(LDFLAGS) -lmnl -lnetfilter_queue -lpthread + $(CCLD) $(OBJS) -o $(APP) $(LDFLAGS) -lmnl -lnetfilter_queue -lpthread -lcyclone -$(BUILD_DIR)/%.o: %.c $(REQ) config.h +$(BUILD_DIR)/%.o: src/%.c $(REQ) $(INCLUDE_DIR)/config.h @echo 'CC $@' $(CC) -c $(CFLAGS) $(LDFLAGS) $< -o $@ @@ -106,5 +109,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