From 70d714cac3ee7689c25695ff9edf679a4a3a244f Mon Sep 17 00:00:00 2001 From: "Peter S. Bornerup" Date: Thu, 11 Apr 2024 10:07:30 +0200 Subject: [PATCH] feat: add option to link against custom crypto implementations We seek the option to link against custom crypto implementations to be used for key storage and crypto computational tasks. This is introduced as an configurable option. In the work, common crypto part of the codespace has been moved public include file folder. Add feature that ensured that the externally loaded keys are memzero'ed after their use. Add automated build processes with multiple different compiler types and CMake flag combinations. More might be added in the future. Update the repository documentation for external key loading. --------- Co-authored-by: Benjamin Bruun --- .github/workflows/cmake-build.yml | 24 +++++++- CMakeLists.txt | 17 +++++- include/onomondo/softsim/config.h | 35 ++++++++--- include/onomondo/softsim/crypto.h | 64 ++++++++++++++++++++ include/onomondo/utils/ss_crypto_extension.h | 44 ++++++++++++++ src/softsim/CMakeLists.txt | 3 +- src/softsim/crypto/aes-encblock.c | 19 +++--- src/softsim/uicc/uicc_remote_cmd.c | 6 +- src/softsim/uicc/utils_3des.c | 3 + src/softsim/uicc/utils_3des.h | 15 ++--- src/softsim/uicc/utils_aes.c | 40 +++++++++++- src/softsim/uicc/utils_aes.h | 15 ++--- src/softsim/uicc/utils_ota.c | 38 +++++++++--- src/softsim/uicc/utils_ota.h | 16 +---- tests/aes/CMakeLists.txt | 3 +- tests/app_transact/CMakeLists.txt | 3 +- tests/ota/CMakeLists.txt | 2 +- tests/ota/ota_test.c | 8 +-- utils/CMakeLists.txt | 10 ++- utils/ss_crypto_extension.c | 17 ++++++ 20 files changed, 306 insertions(+), 76 deletions(-) create mode 100644 include/onomondo/softsim/crypto.h create mode 100644 include/onomondo/utils/ss_crypto_extension.h create mode 100644 utils/ss_crypto_extension.c diff --git a/.github/workflows/cmake-build.yml b/.github/workflows/cmake-build.yml index 28c3c8e..c343a3f 100644 --- a/.github/workflows/cmake-build.yml +++ b/.github/workflows/cmake-build.yml @@ -11,6 +11,11 @@ concurrency: jobs: cmake-build-and-test: + strategy: + matrix: + flags: ["", "-DCONFIG_EXTERNAL_KEY_LOAD=y"] + compiler: [gcc, clang] + runs-on: ubuntu-20.04 timeout-minutes: 15 @@ -26,11 +31,28 @@ jobs: - name: Install Embedded Toolchain uses: carlosperate/arm-none-eabi-gcc-action@v1.8.1 + if: matrix.compiler == 'gcc' + + - name: Install CLANG + run: | + sudo apt-get update + sudo apt-get install -y clang + if: matrix.compiler == 'clang' + + - name: Add key loaders to tests + run: | + echo "void ss_load_key_external(const uint8_t *key_id, size_t in_len, uint8_t *key, size_t *key_len){memcpy(key, key_id, in_len);*key_len = in_len;}" >> src/softsim/main.c + echo "void ss_load_key_external(const uint8_t *key_id, size_t in_len, uint8_t *key, size_t *key_len){memcpy(key, key_id, in_len);*key_len = in_len;}" >> tests/ota/ota_test.c + echo "void ss_load_key_external(const uint8_t *key_id, size_t in_len, uint8_t *key, size_t *key_len){memcpy(key, key_id, in_len);*key_len = in_len;}" >> tests/aes/aes_test.c + if: matrix.flags == '-DCONFIG_EXTERNAL_KEY_LOAD=y' - name: Configure and Build Project run: | - cmake -S . -B build -DBUILD_TESTING=y -DCONFIG_USE_SYSTEM_HEAP=y -DCONFIG_ENABLE_SANITIZE=y + cmake -S . -B build -DBUILD_TESTING=y -DCONFIG_USE_SYSTEM_HEAP=y -DCONFIG_ENABLE_SANITIZE=y ${{ matrix.flags }} cmake --build build + env: + CC: ${{ matrix.compiler }} + CXX: ${{ matrix.compiler }}++ - name: Test Project run: cd build && ctest --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index 8976ee9..ae3322b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,9 @@ option(CONFIG_ENABLE_SANITIZE "Build with -fsanitize=address -fsanitize=undefine option(CONFIG_USE_SYSTEM_HEAP "Use free/malloc instead of port_free/port_malloc") option(CONFIG_USE_LOGS "Set SS_LOGP macro to link against ss_logp") option(CONFIG_USE_EXPERIMENTAL_SUSPEND_COMMAND "Building with experimental support for suspend") -option(CONFIG_USE_UTILS "Use the extra functionality found in the collective utils folder" ON) +option(CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION "Use external crypto implementations") +option(CONFIG_EXTERNAL_KEY_LOAD "Use crypto exstension for loading keys") +option(CONFIG_USE_UTILS "Use the extra functionality found in the collective utils folder") if(CONFIG_USE_SYSTEM_HEAP) add_compile_definitions(CONFIG_USE_SYSTEM_HEAP) @@ -26,6 +28,19 @@ if(CONFIG_USE_EXPERIMENTAL_SUSPEND_COMMAND) add_compile_definitions(CONFIG_USE_EXPERIMENTAL_SUSPEND_COMMAND) endif() +if(CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION AND CONFIG_EXTERNAL_KEY_LOAD) + message(FATAL_ERROR "CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION and CONFIG_EXTERNAL_KEY_LOAD should not be used together") +endif() + +if(CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION) + message(STATUS "Using external crypto implementation") + add_compile_definitions(-DCONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION) +endif() + +if(CONFIG_EXTERNAL_KEY_LOAD) + add_compile_definitions(-DCONFIG_EXTERNAL_KEY_LOAD) +endif() + if(CONFIG_ENABLE_SANITIZE) add_compile_options(-fsanitize=address -fsanitize=undefined) add_link_options(-fsanitize=address -fsanitize=undefined) diff --git a/include/onomondo/softsim/config.h b/include/onomondo/softsim/config.h index bd94c79..a641994 100644 --- a/include/onomondo/softsim/config.h +++ b/include/onomondo/softsim/config.h @@ -1,14 +1,33 @@ -#ifndef INCLUDE_ONOMONDO_SOFTSIM_CONFIG_H_ -#define INCLUDE_ONOMONDO_SOFTSIM_CONFIG_H_ +/* + * Copyright (c) 2024 Onomondo ApS. All rights reserved. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +/* + * This file solely exist to print config opitons at compile time + */ +#pragma once #ifdef CONFIG_USE_SYSTEM_HEAP - #pragma message "Using CONFIG_USE_SYSTEM_HEAP" -#else // DEFAULT - #pragma message "Using port_malloc and port_free instead of system default" -#endif // CONFIG_USE_SYSTEM_HEAP +#pragma message "Using CONFIG_USE_SYSTEM_HEAP" +#else +#pragma message "Using port_malloc and port_free instead of system default" +#endif // CONFIG_USE_SYSTEM_HEAP #ifdef CONFIG_USE_EXPERIMENTAL_SUSPEND_COMMAND - #pragma message "Building with experimental support for suspend" +#pragma message "Building with experimental support for suspend" #endif // CONFIG_USE_EXPERIMENTAL_SUSPEND_COMMAND -#endif // INCLUDE_ONOMONDO_SOFTSIM_CONFIG_H_ + +#if defined(CONFIG_EXTERNAL_KEY_LOAD) && defined(CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION) +#error "External CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION implementation and CONFIG_EXTERNAL_KEY_LOAD should not be enabled at the same time." +#endif // CONFIG_EXTERNAL_KEY_LOAD && EXTERNAL_CRYPTO_IMPLEMENTATION + +#ifdef CONFIG_EXTERNAL_KEY_LOAD +#pragma message "Enabling CONFIG_EXTERNAL_KEY_LOAD" +#endif // CONFIG_EXTERNAL_KEY_LOAD + +#ifdef CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION +#pragma message "Enabling CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION" +#endif // CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION diff --git a/include/onomondo/softsim/crypto.h b/include/onomondo/softsim/crypto.h new file mode 100644 index 0000000..4521b87 --- /dev/null +++ b/include/onomondo/softsim/crypto.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Onomondo ApS. All rights reserved. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include +#include +#include + +#define AES_BLOCKSIZE 16 + +/* See also ETSI TS 102 225, section 5.1.1 and 5.1.2 */ +enum enc_algorithm { + NONE, + TRIPLE_DES_CBC2, + AES_CBC, + AES_CMAC, +}; + +/*! Perform an in-place AES decryption with the common settings of OTA + * (CBC mode, zero IV). + * \param[inout] buffer user provided memory with plaintext to decrypt. + * \param[in] buffer_len length of the plaintext data to decrypt (multiple of 16). + * \param[in] key AES key. + * \param[in] key_len length of the AES key. */ +void ss_utils_aes_decrypt(uint8_t *buffer, size_t buffer_len, const uint8_t *key, size_t key_len); + +/*! Perform an in-place AES encryption with the common settings of OTA + * (CBC mode, zero IV). + * \param[inout] buffer user provided memory with plaintext to encrypt. + * \param[in] buffer_len length of the plaintext data to encrypt (multiple of 16). + * \param[in] key 16 byte AES key. + * \param[in] key_len length of the AES key. */ +void ss_utils_aes_encrypt(uint8_t *buffer, size_t buffer_len, const uint8_t *key, size_t key_len); + +/*! Perform an in-place 3DES decryption with the common settings of OTA + * (CBC mode, 16-byte key, zero IV). + * \param[inout] buffer user provided memory with plaintext to decrypt. + * \param[in] buffer_len length of the plaintext data to decrypt (multiple of 8). + * \param[in] key 16 byte DES key. */ +void ss_utils_3des_decrypt(uint8_t *buffer, size_t buffer_len, const uint8_t *key); + +/*! Perform an in-place 3DES encryption with the common settings of OTA + * (CBC mode, 16-byte key, zero IV). + * \param[inout] buffer user provided memory with plaintext to encrypt. + * \param[in] buffer_len length of the plaintext data to encrypt (multiple of 8). + * \param[in] key 16 byte DES key. */ +void ss_utils_3des_encrypt(uint8_t *buffer, size_t buffer_len, const uint8_t *key); + +/*! Calculate cryptographic checksum (CC) using a specified algorithm. + * \param[out] cc user provided memory for resulting cryptographic checksum. + * \param[out] cc_len length of user provided memory for resulting cryptographic checksum. + * \param[in] key cryptographic key. + * \param[in] key_len cryptographic key length. + * \param[in] data1 user buffer containing part 1 of the data. + * \param[in] data1_len length of data part 1 (must be multiple of blocksize) + * \param[in] data2 user buffer containing part 2 of the data. + * \param[in] data2_len length of data part 2 (unpadded). + * \returns 0 on success, -EINVAL on error. */ +int ss_utils_ota_calc_cc(uint8_t *cc, size_t cc_len, uint8_t *key, size_t key_len, enum enc_algorithm alg, + uint8_t *data1, size_t data1_len, uint8_t *data2, size_t data2_len); diff --git a/include/onomondo/utils/ss_crypto_extension.h b/include/onomondo/utils/ss_crypto_extension.h new file mode 100644 index 0000000..76623e3 --- /dev/null +++ b/include/onomondo/utils/ss_crypto_extension.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Onomondo ApS. All rights reserved. + * + * SPDX-License-Identifier: GPL-3.0-only + */ +#pragma once + +/* + * Motivation here is to provide a simple mechanism for importing keys from + * different locations than the file-system. Some platforms are very limited + * w.r.t. security and crypto engines. + * + * By doing this we can with relative ease enable the use of + * dedicated secure zones. Those zones however aren't suitable for storing all + * SoftSIM internal data. This is _a_ compromise that allows some sense of secure key storage. + * + * This mechanism is completely optional. By storing the key identifiers instead of keys in the + * A00X files we can use the key ID to fetch the correct key from secure storage. The keys will still + * live in potential non-secure RAM while in use. Immediately after use the keys are zeroed out. + * + * At all times where a dedicated crypto engine or other secure implementations exist (i.e. ARM TrustZone) + * the CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION should be used. + * + * This function is called immediately before the block encryption/decryption is carried out. + */ + +#ifdef CONFIG_EXTERNAL_KEY_LOAD + +#include +#include +#include +/*! + * \brief Load a key from an external source + * + * This function is called when the SoftSIM needs to load a key from an external + * source. The key is loaded into the buffer provided. + * + * \param key_id buffer with the key ID. + * \param key buffer with the resolved key. The key is loaded into this buffer. + * \param in_len Length of the key_id buffer + * \param key_len Length of the key_buffer. After loading the key this should hold the length of the key. + */ +void ss_load_key_external(const uint8_t *key_id, size_t in_len, uint8_t *key, size_t *key_len) __attribute__((weak)); +#endif /* ifdef CONFIG_EXTERNAL_KEY_LOAD */ diff --git a/src/softsim/CMakeLists.txt b/src/softsim/CMakeLists.txt index dd336f1..0a1f9ec 100644 --- a/src/softsim/CMakeLists.txt +++ b/src/softsim/CMakeLists.txt @@ -9,4 +9,5 @@ add_library(storage STATIC storage.c fs.c) target_include_directories(storage PUBLIC ${CMAKE_SOURCE_DIR}/include) add_executable(softsim main.c) -target_link_libraries(softsim uicc milenage crypto storage) +target_link_libraries(softsim uicc milenage crypto storage $<$:utils>) + diff --git a/src/softsim/crypto/aes-encblock.c b/src/softsim/crypto/aes-encblock.c index a521621..d1b9a2c 100644 --- a/src/softsim/crypto/aes-encblock.c +++ b/src/softsim/crypto/aes-encblock.c @@ -7,8 +7,8 @@ * See README for more details. */ +#include #include "includes.h" - #include "common.h" #include "aes.h" #include "aes_wrap.h" @@ -18,15 +18,18 @@ * @key: Key for AES * @in: Input data (16 bytes) * @out: Output of the AES block operation (16 bytes) - * Returns: 0 on success, -1 on failure + * Returns: 0 */ + +/* adjusted from Jouni Malinen impl */ int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) { - void *ctx; - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - aes_encrypt(ctx, in, out); - aes_encrypt_deinit(ctx); + // ss_utils_aes_encrypt will overwrite input buffer + uint8_t buf[AES_BLOCK_SIZE]; + memcpy(buf, in, AES_BLOCK_SIZE); + + ss_utils_aes_encrypt(buf, AES_BLOCK_SIZE, key, AES_BLOCK_SIZE); + memcpy(out, buf, AES_BLOCK_SIZE); + return 0; } diff --git a/src/softsim/uicc/uicc_remote_cmd.c b/src/softsim/uicc/uicc_remote_cmd.c index 2947cb7..5978b00 100644 --- a/src/softsim/uicc/uicc_remote_cmd.c +++ b/src/softsim/uicc/uicc_remote_cmd.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2024 Onomondo ApS. All rights reserved. - * - * SPDX-License-Identifier: GPL-3.0-only + * + * SPDX-License-Identifier: GPL-3.0-only */ #include "uicc_remote_cmd.h" @@ -14,6 +14,7 @@ #include #include #include +#include #include "context.h" #include "fcp.h" @@ -22,7 +23,6 @@ #include "uicc_pin.h" #include "utils.h" #include "utils_3des.h" -#include "utils_aes.h" #include "utils_ota.h" /* Information element identifier for command packets, as used in TS 23.048 diff --git a/src/softsim/uicc/utils_3des.c b/src/softsim/uicc/utils_3des.c index 5bd6d87..f123149 100644 --- a/src/softsim/uicc/utils_3des.c +++ b/src/softsim/uicc/utils_3des.c @@ -8,7 +8,9 @@ #include "utils.h" #include "utils_3des.h" #include "crypto/des_i.h" +#include +#ifndef CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION void setup_key(const uint8_t *src, struct des3_key_s *dest) { /* The library wants keys in 24byte form, but we have the 16byte form */ @@ -137,3 +139,4 @@ void ss_utils_3des_cc_cleanup(struct utils_3des_cc_ctx *cc) ss_memzero(cc->key, sizeof(cc->key)); SS_FREE(cc->key); } +#endif // CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION diff --git a/src/softsim/uicc/utils_3des.h b/src/softsim/uicc/utils_3des.h index 586e3dd..007b343 100644 --- a/src/softsim/uicc/utils_3des.h +++ b/src/softsim/uicc/utils_3des.h @@ -1,19 +1,17 @@ /* * Copyright (c) 2024 Onomondo ApS. All rights reserved. - * - * SPDX-License-Identifier: GPL-3.0-only + * + * SPDX-License-Identifier: GPL-3.0-only */ #pragma once +#include +#include + #define DES_BLOCKSIZE 8 #define TRIPLE_DES_KEYLEN 16 -void ss_utils_3des_decrypt(uint8_t *buffer, size_t buffer_len, - const uint8_t *key); -void ss_utils_3des_encrypt(uint8_t *buffer, size_t buffer_len, - const uint8_t *key); - struct des3_key_s; struct utils_3des_cc_ctx { struct des3_key_s *key; @@ -23,6 +21,5 @@ struct utils_3des_cc_ctx { }; void ss_utils_3des_cc_setup(struct utils_3des_cc_ctx *cc, const uint8_t *key); -void ss_utils_3des_cc_feed(struct utils_3des_cc_ctx *cc, const uint8_t *data, - size_t data_len); +void ss_utils_3des_cc_feed(struct utils_3des_cc_ctx *cc, const uint8_t *data, size_t data_len); void ss_utils_3des_cc_cleanup(struct utils_3des_cc_ctx *cc); diff --git a/src/softsim/uicc/utils_aes.c b/src/softsim/uicc/utils_aes.c index 58ab0dd..d566f99 100644 --- a/src/softsim/uicc/utils_aes.c +++ b/src/softsim/uicc/utils_aes.c @@ -1,18 +1,35 @@ /* * Copyright (c) 2024 Onomondo ApS. All rights reserved. - * - * SPDX-License-Identifier: GPL-3.0-only + * + * SPDX-License-Identifier: GPL-3.0-only */ #include #include #include +#include +#include #include "utils.h" #include "utils_aes.h" #include "crypto/common.h" - #include "crypto/aes.h" +/* This allows users to fetch keys from more custom locations. + * Very useful for devices where the filesystem isn't trusted. + * I.e. The key is preferably loaded from a secure zone or from encrypted + * representation etc. */ + +#define COPY_EXTERNAL_KEY_TO_LOCAL_VAR() \ + uint8_t modified_key[AES_BLOCKSIZE]; \ + size_t modified_key_len = AES_BLOCKSIZE; \ + ss_load_key_external(key, key_len, modified_key, &modified_key_len); \ + key = modified_key; \ + key_len = modified_key_len; + +#define MEMZERO_EXTERNAL_KEY() ss_memzero(modified_key, sizeof(modified_key)); + +#ifndef CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION + /*! Perform an in-place AES decryption with the common settings of OTA * (CBC mode, zero IV). * \param[inout] buffer user provided memory with plaintext to decrypt. @@ -27,6 +44,10 @@ void ss_utils_aes_decrypt(uint8_t *buffer, size_t buffer_len, const uint8_t *key int i; int j; +#ifdef CONFIG_EXTERNAL_KEY_LOAD + COPY_EXTERNAL_KEY_TO_LOCAL_VAR() +#endif // CONFIG_EXTERNAL_KEY_LOAD + aes_ctx = aes_decrypt_init(key, key_len); /* Adjusted from hostap's crypto_internal-cipher.c */ @@ -41,6 +62,10 @@ void ss_utils_aes_decrypt(uint8_t *buffer, size_t buffer_len, const uint8_t *key } aes_decrypt_deinit(aes_ctx); + +#ifdef CONFIG_EXTERNAL_KEY_LOAD + MEMZERO_EXTERNAL_KEY() +#endif // CONFIG_EXTERNAL_KEY_LOAD } /*! Perform an in-place AES encryption with the common settings of OTA @@ -56,6 +81,10 @@ void ss_utils_aes_encrypt(uint8_t *buffer, size_t buffer_len, const uint8_t *key int i; int j; +#ifdef CONFIG_EXTERNAL_KEY_LOAD + COPY_EXTERNAL_KEY_TO_LOCAL_VAR() +#endif // CONFIG_EXTERNAL_KEY_LOAD + aes_ctx = aes_encrypt_init(key, key_len); /* Adjusted from hostap's crypto_internal-cipher.c */ @@ -68,7 +97,12 @@ void ss_utils_aes_encrypt(uint8_t *buffer, size_t buffer_len, const uint8_t *key } aes_encrypt_deinit(aes_ctx); + +#ifdef CONFIG_EXTERNAL_KEY_LOAD + MEMZERO_EXTERNAL_KEY() +#endif // CONFIG_EXTERNAL_KEY_LOAD } +#endif // CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION /* Shift a whole block to the left by one bit position. * (See also RFC 4493, appendix A) */ diff --git a/src/softsim/uicc/utils_aes.h b/src/softsim/uicc/utils_aes.h index 3a3dab7..2f79232 100644 --- a/src/softsim/uicc/utils_aes.h +++ b/src/softsim/uicc/utils_aes.h @@ -1,18 +1,13 @@ /* * Copyright (c) 2024 Onomondo ApS. All rights reserved. - * - * SPDX-License-Identifier: GPL-3.0-only + * + * SPDX-License-Identifier: GPL-3.0-only */ #pragma once #define AES_BLOCKSIZE 16 -void ss_utils_aes_decrypt(uint8_t *buffer, size_t buffer_len, - const uint8_t *key, size_t key_len); -void ss_utils_aes_encrypt(uint8_t *buffer, size_t buffer_len, - const uint8_t *key, size_t key_len); - struct utils_aes_cc_ctx { void *aes_ctx; @@ -30,8 +25,6 @@ struct utils_aes_cc_ctx { bool inert_padding; }; -void ss_utils_aes_cc_setup(struct utils_aes_cc_ctx *cc, const uint8_t *key, - size_t key_len, bool inert_padding); -void ss_utils_aes_cc_feed(struct utils_aes_cc_ctx *cc, const uint8_t *data, - size_t data_len, bool last); +void ss_utils_aes_cc_setup(struct utils_aes_cc_ctx *cc, const uint8_t *key, size_t key_len, bool inert_padding); +void ss_utils_aes_cc_feed(struct utils_aes_cc_ctx *cc, const uint8_t *data, size_t data_len, bool last); void ss_utils_aes_cc_cleanup(struct utils_aes_cc_ctx *cc); diff --git a/src/softsim/uicc/utils_ota.c b/src/softsim/uicc/utils_ota.c index a8e07b6..31cd2da 100644 --- a/src/softsim/uicc/utils_ota.c +++ b/src/softsim/uicc/utils_ota.c @@ -1,18 +1,20 @@ /* * Copyright (c) 2024 Onomondo ApS. All rights reserved. - * - * SPDX-License-Identifier: GPL-3.0-only + * + * SPDX-License-Identifier: GPL-3.0-only */ #include #include #include #include +#include +#include +#include +#include "utils_ota.h" #include "utils.h" #include "utils_3des.h" #include "utils_aes.h" -#include "utils_ota.h" -#include /*! Calculate the number of padding bytes (pcnt) for a given length. * \param[in] algorithm algorithm to use. @@ -36,11 +38,13 @@ uint8_t ss_utils_ota_calc_pcnt(enum enc_algorithm algorithm, size_t data_len) return (-(blocksize + data_len)) % blocksize; } +#ifndef CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION + /*! Calculate cryptographic checksum (CC) using a specified algorithm. - * \param[out] cc user provided memory for resulting cryptpgraphic checksum. - * \param[out] cc_len length of user provided memory for resulting cryptpgraphic checksum. - * \param[in] key cryptpgraphic key. - * \param[in] key_len cryptpgraphic key length. + * \param[out] cc user provided memory for resulting cryptographic checksum. + * \param[out] cc_len length of user provided memory for resulting cryptographic checksum. + * \param[in] key cryptographic key. + * \param[in] key_len cryptographic key length. * \param[in] data1 user buffer containing part 1 of the data. * \param[in] data1_len length of data part 1 (must be multiple of blocksize) * \param[in] data2 user buffer containing part 2 of the data. @@ -52,6 +56,18 @@ int ss_utils_ota_calc_cc(uint8_t *cc, size_t cc_len, uint8_t *key, size_t key_le struct utils_3des_cc_ctx cc_des; struct utils_aes_cc_ctx cc_aes; + /* This allows users to fetch keys from more custom locations. + * Very useful for devices where the filesystem isn't trusted. + * I.e. The key is preferably loaded from a secure zone or from encrypted + * representation etc.*/ +#ifdef CONFIG_EXTERNAL_KEY_LOAD + uint8_t modified_key[AES_BLOCKSIZE]; + size_t modified_key_len = AES_BLOCKSIZE; + ss_load_key_external(key, key_len, modified_key, &modified_key_len); + key = modified_key; + key_len = modified_key_len; +#endif // CONFIG_EXTERNAL_KEY_LOAD + /* NOTE: This function accepts two separate buffers (data1 and data2). * The reason for this is that the data we are going to sign is in two * separate buffers and to avoid copying the two buffers into a single @@ -88,4 +104,10 @@ int ss_utils_ota_calc_cc(uint8_t *cc, size_t cc_len, uint8_t *key, size_t key_le SS_LOGP(SREMOTECMD, LERROR, "unable to calculate cc, improper crypto algorithm selected\n"); return -EINVAL; } + +#ifdef CONFIG_EXTERNAL_KEY_LOAD + ss_memzero(modified_key, sizeof(modified_key)); +#endif // CONFIG_EXTERNAL_KEY_LOAD } + +#endif // CONFIG_EXTERNAL_CRYPTO_IMPLEMENTATION diff --git a/src/softsim/uicc/utils_ota.h b/src/softsim/uicc/utils_ota.h index e1615bc..441b5b8 100644 --- a/src/softsim/uicc/utils_ota.h +++ b/src/softsim/uicc/utils_ota.h @@ -1,24 +1,14 @@ /* * Copyright (c) 2024 Onomondo ApS. All rights reserved. - * - * SPDX-License-Identifier: GPL-3.0-only + * + * SPDX-License-Identifier: GPL-3.0-only */ #pragma once -/* See also ETSI TS 102 225, section 5.1.1 and 5.1.2 */ -enum enc_algorithm { - NONE, - TRIPLE_DES_CBC2, - AES_CBC, - AES_CMAC, -}; +#include #define OTA_KEY_LEN 16 #define OTA_INTEGRITY_LEN 8 uint8_t ss_utils_ota_calc_pcnt(enum enc_algorithm algorithm, size_t data_len); -int ss_utils_ota_calc_cc(uint8_t *cc, size_t cc_len, - uint8_t *key, size_t key_len, enum enc_algorithm alg, - uint8_t *data1, size_t data1_len, - uint8_t *data2, size_t data2_len); diff --git a/tests/aes/CMakeLists.txt b/tests/aes/CMakeLists.txt index 3bb7adf..5f9d044 100644 --- a/tests/aes/CMakeLists.txt +++ b/tests/aes/CMakeLists.txt @@ -5,8 +5,7 @@ add_executable(aes_test aes_test.c) include_directories(${PROJECT_SOURCE_DIR}) include_directories(${PROJECT_SOURCE_DIR}/include) - -target_link_libraries(aes_test uicc crypto) +target_link_libraries(aes_test uicc crypto $<$:utils>) add_test(NAME aes_test COMMAND sh -c "$ > aes_test.out") diff --git a/tests/app_transact/CMakeLists.txt b/tests/app_transact/CMakeLists.txt index f2ac40f..3a84561 100644 --- a/tests/app_transact/CMakeLists.txt +++ b/tests/app_transact/CMakeLists.txt @@ -5,6 +5,5 @@ add_executable(app_apdu_test app_transact_test.c) include_directories(${PROJECT_SOURCE_DIR}/include) -target_link_libraries(app_apdu_test uicc milenage crypto storage) - +target_link_libraries(app_apdu_test uicc milenage crypto storage $<$:utils>) diff --git a/tests/ota/CMakeLists.txt b/tests/ota/CMakeLists.txt index 9c61b83..5d15c1d 100644 --- a/tests/ota/CMakeLists.txt +++ b/tests/ota/CMakeLists.txt @@ -6,7 +6,7 @@ add_executable(ota_test ota_test.c) include_directories(${PROJECT_SOURCE_DIR}) include_directories(${PROJECT_SOURCE_DIR}/include) -target_link_libraries(ota_test uicc crypto) +target_link_libraries(ota_test uicc crypto $<$:utils>) add_test(NAME ota_test COMMAND sh -c "$ > ota_test.out") diff --git a/tests/ota/ota_test.c b/tests/ota/ota_test.c index 4bb6344..d044f85 100644 --- a/tests/ota/ota_test.c +++ b/tests/ota/ota_test.c @@ -16,7 +16,7 @@ static void calc_and_print_pcnt(enum enc_algorithm algorithm, size_t data_len, u { char *algorithm_str; uint8_t pcnt; - + switch (algorithm) { case TRIPLE_DES_CBC2: algorithm_str = "DES_CBC2"; @@ -32,7 +32,7 @@ static void calc_and_print_pcnt(enum enc_algorithm algorithm, size_t data_len, u } pcnt = ss_utils_ota_calc_pcnt(algorithm, data_len); - + printf("algorithm=%s data_len=%zu, pcnt=%u, pcnt_expected=%u\n", algorithm_str, data_len, ss_utils_ota_calc_pcnt(algorithm, data_len), pcnt_expected); @@ -53,7 +53,7 @@ static void ss_utils_ota_calc_pcnt_test(void) calc_and_print_pcnt(TRIPLE_DES_CBC2, 9, 7); calc_and_print_pcnt(TRIPLE_DES_CBC2, 17, 7); calc_and_print_pcnt(TRIPLE_DES_CBC2, 25, 7); - + /* DES Off by -1 */ calc_and_print_pcnt(TRIPLE_DES_CBC2, 7, 1); calc_and_print_pcnt(TRIPLE_DES_CBC2, 15, 1); @@ -70,7 +70,7 @@ static void ss_utils_ota_calc_pcnt_test(void) calc_and_print_pcnt(AES_CBC, 17, 15); calc_and_print_pcnt(AES_CBC, 33, 15); calc_and_print_pcnt(AES_CBC, 49, 15); - + /* AES Off by -1 */ calc_and_print_pcnt(AES_CBC, 15, 1); calc_and_print_pcnt(AES_CBC, 31, 1); diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 519dc0d..cab00b9 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -1,7 +1,15 @@ # Copyright (c) 2024 Onomondo ApS. All rights reserved. # SPDX-License-Identifier: GPL-3.0-only -add_library(utils STATIC ss_profile.c) +set(utils_collection + ss_profile.c +) + +if(CONFIG_EXTERNAL_KEY_LOAD) + set(utils_collection ${utils_collection} ss_crypto_extension.c) +endif() + +add_library(utils STATIC ${utils_collection}) target_include_directories(utils PUBLIC diff --git a/utils/ss_crypto_extension.c b/utils/ss_crypto_extension.c new file mode 100644 index 0000000..647d558 --- /dev/null +++ b/utils/ss_crypto_extension.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 Onomondo ApS. All rights reserved. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include +#include +#include + +/* IMPL some sensible default */ + +void ss_load_key_external(const uint8_t *key_id, size_t in_len, uint8_t *key, size_t *key_len) +{ + memcpy(key, key_id, in_len); + *key_len = in_len; +}