diff --git a/docs/api/00-mainpage.md b/docs/api/00-mainpage.md
index 5212f41b..73be9674 100644
--- a/docs/api/00-mainpage.md
+++ b/docs/api/00-mainpage.md
@@ -34,33 +34,47 @@ The BSL as a whole is separated into two primary layers of implementation: an AP
The Frontend library provides the service API for the BSL to be called by its associated [BPA integration](@ref bpa-integrators) and for stable public APIs used by [Policy Provider implementations](@ref policy-providers) and [Security Context implementations](@ref security-contexts).
The Backend library implements forward-declared structs and functions from the Frontend using specific concrete data containers, algorithms, _etc._
-The BSL source repository also contains @ref example-pps and @ref example-default-scs to actually exercise the BSL during testing, and a @ref mock-bpa which allows as-built integration testing of the BSL using a pseudo-daemon process.
+The following diagram shows the relationships between major BSL components, where solid lines indicate direct API calls and dashed lines indicate registered callback uses.
@dot
digraph example {
- node [shape=record, fontname=Helvetica, fontsize=10];
+ graph [fontname=Helvetica];
+ node [shape=box, fontname=Helvetica, fontsize=10];
+ newrank=true;
- frontend [ label="Frontend" ];
- backend [ label=<Backend> ];
- frontend -> backend [ dir=back ];
+ subgraph cluster_bsl {
+ label="BSL";
+ frontend [ label="Frontend" ];
+ backend [ label=<Backend> ];
+ }
+ frontend -> backend [ style=solid ];
host [ label="Host" ];
bpa [ label="BPA" ];
- crypto [ label="Crypto\nFunctions" ];
- reg_pol [ label="Policy\nRegistry" ];
- reg_sc [ label="Security Context\nRegistry" ];
- backend -> host [ arrowhead="open", style="dashed" ];
- backend -> bpa [ arrowhead="open", style="dashed" ];
- backend -> crypto [ arrowhead="open", style="dashed" ];
- backend -> reg_pol [ arrowhead="open", style="dashed" ];
- backend -> reg_sc [ arrowhead="open", style="dashed" ];
+ reg_pp [ label=<Policy Providers> ];
+ reg_sc [ label=<Security Contexts> ];
+ backend -> host [ arrowhead="open", style=dashed ];
+ backend -> bpa [ arrowhead="open", style=dashed ];
+ backend -> reg_pp [ arrowhead="open", style=dashed ];
+ backend -> reg_sc [ arrowhead="open", style=dashed ];
+ { rank=same; host; bpa; reg_sc; reg_pp; }
+
+ subgraph cluster_crypto {
+ label="BSL crypto";
+ rank=same;
+ crypto [ label="Crypto\nFunctions" ];
+ keystore [ label="Key Store" ];
+ }
+ reg_sc -> crypto [ arrowhead="open", style=solid ];
+ crypto -> keystore [ arrowhead="open", style=solid ];
+ keystore -> bpa [ arrowhead="open", style=dashed ];
}
@enddot
The BSL comes with a @ref frontend and a @ref backend_dyn implementation which uses heap-allocated, dynamically-sized data structures and run-time registration capabilities.
For a more constrained (_e.g._, flight software) environment an alternative backend could be implemented with fixed-size data containers and constant-time registry lookup algorithms.
-Along with these libraries are also two integration extensions: an _Example Policy_ module and a _Default Security Contexts_ module.
+The BSL source repository also contains @ref example-pps and @ref example-scs to actually exercise the BSL during testing, and a @ref mock-bpa which allows as-built integration testing of the BSL using a pseudo-daemon process.
Together these use the abstract Frontend and populate the otherwise empty Dynamic Backend registries to create an out-of-the-box usable BPSec implementation.
# Dependencies
@@ -88,8 +102,8 @@ This is the concrete implementation of a backend using dynamic heap-allocated co
It uses POSIX APIs to provide necessary Host functions for the BSL, and OpenSSL APIs to provide crypto functions for the BSL.
-@defgroup example_pp Example Policy Provider
-@brief Implementation of a simple rule-based policy provider.
+@defgroup example_pp Sample Policy Provider
+@brief Implementation of a simple rule-based policy provider configured with JSON input.
This group contains files used by the Example Policy Provider library included with the BSL.
@@ -100,12 +114,26 @@ This group contains files used by the Example Policy Provider library included w
This group contains files used by the Default Security Contexts (RFC 9173 @cite rfc9173) library included with the BSL.
+@defgroup cose_sc COSE Context
+@brief Implementation of the COSE Context using the BSL crypto API.
+
+This group contains files used by the COSE Context (draft @cite draft-ietf-dtn-bpsec-cose) library included with the BSL.
+
+
+@defgroup crypto Cryptographic Processing and Key Store API
+@brief Implementation of the BSL crypto API by a software backend and user of the BSL key store interface.
+
+This group contains files used by the Default Security Contexts (RFC 9173 @cite rfc9173) library included with the BSL.
+
+
@defgroup mock_bpa Example/Mock BP Agent
@brief Files used in the Mock BPA used for testing.
The Mock BPA performs whole-bundle encoding and decoding (CODEC) functions, but no other stateful bundle processing.
This allows end-to-end bundle testing with real policy configurations.
+The Mock BPA also implements an in-memory key store registered with the BSL crypto library.
+
@defgroup unit_test Unit Testing
@brief Files used for unit testing of BSL behaviors.
diff --git a/docs/api/02-bpa-integrators.md b/docs/api/02-bpa-integrators.md
index a4fc96ae..2f3a2e72 100644
--- a/docs/api/02-bpa-integrators.md
+++ b/docs/api/02-bpa-integrators.md
@@ -77,9 +77,13 @@ digraph bpa_interaction {
}
@enddot
-# BPA Callback API {#bpa-callback-api}
+# BPA Callback APIs {#bpa-callback-api}
Separate from the API used to call into the BSL to initiate security processing, the BSL relies on specific functions provided by the BPA to do its normal processing.
-Some of these functions are for introspecting and manipulating specific bundle or block contents, others are for encoding and decoding EID and EID Pattern values.
+Some of these functions are for introspecting and manipulating specific bundle or block contents, others are for encoding and decoding EID and EID Pattern values, and a separate set are used by the internal BSL crypto library for key store access.
-The BSL dynamic backend declares a set of functions which are delegated to the BPA, which are registered in the dynamic backend using the ::BSL_HostDescriptors_t struct and the BSL_HostDescriptors_Set() function.
+The BSL dynamic backend declares a set of functions which are delegated to the BPA.
+These are registered in the dynamic backend using the ::BSL_HostDescriptors_t struct and the BSL_HostDescriptors_Set() function.
+
+The BSL crypto library declares a set of functions which are delegated to the BPA.
+These are registered in the crypto library using the ::BSL_KeyStore_Descriptors_t struct and the BSL_KeyStore_Init() function.
diff --git a/docs/api/04-examples-and-mocks.md b/docs/api/04-examples-and-mocks.md
index 8610876d..0e3557ff 100644
--- a/docs/api/04-examples-and-mocks.md
+++ b/docs/api/04-examples-and-mocks.md
@@ -39,11 +39,13 @@ This PP is registered and used by the @ref mock-bpa for many BSL testing cases.
Sources related to these example PPs are associated with the @ref example_pp group.
-# Example Default Security Contexts {#example-default-scs}
+# Example Security Contexts {#example-scs}
The two Default Security Contexts defined in RFC 9173 @cite rfc9173 offer minimal, interoperable, and pre-shared-key-focused integrity and confidentiality operations.
-An implementation of these two SCs is maintained as part of the BSL source and uses the BSL crypto library as an interface to the OpenSSL library @cite lib:openssl from the host OS.
+The COSE Context defined in an internet draft @cite draft-ietf-dtn-bpsec-cose offers more full-featured, layered symmetric key options including key wrapping and key derivation.
+
+An implementation of each of these SCs is maintained as part of the BSL source and uses the BSL crypto library as an wrapper for the OpenSSL library @cite lib:openssl from the host OS and a key store registered with the crypto library (part of the @ref bpa-callback-api).
These SCs are registered and used by the @ref mock-bpa for BSL testing.
Sources related to these example SCs are associated with the @ref default_sc group.
@@ -55,7 +57,7 @@ The Mock BPA uses an un-framed UDPCL-like interface for its underlayer and also
The Mock BPA is limited to a single registered endpoint, and does no other handling normally required by RFC 9171 @cite rfc9171. So for this reason it is not a true BPA and must not be treated as one.
-Upon startup, the Mock BPA registers a single [ION-based Example Policy Provider](@ref example-pps) and the two [example Default Security Contexts](@ref example-default-scs).
+Upon startup, the Mock BPA registers a single [ION-based Example Policy Provider](@ref example-pps) and all of the [example Security Contexts](@ref example-scs).
Sources related to the Mock BPA are associated with the @ref mock_bpa group.
@@ -75,7 +77,7 @@ The path to the JSON file should be passed to the Mock BPA with the `-j` command
## Key Management
-The keys used by the example SCs registered in the Mock BPA's Cryptographic Library instance are obtained from a file using the JSON Web Key (JWK) format of RFC 7517 @cite rfc7517.
+The keys used by the example SCs registered in the Mock BPA's key store are obtained from a file using either the JSON Web Key (JWK) Set format of RFC 7517 @cite rfc7517 or the COSE Key Set format of RFC 9052 @cite rfc9052.
The implementation to support these SCs only handles symmetric keys and only the minimal header parameters needed for key ID ("kid") and symmetric key material itself ("k").
@@ -94,4 +96,4 @@ The table below contains the Mock BPA executable command line options. See the M
| `-s` | The endpoint ID of the local security source used to handle BPSec. |
| `-p` | The comma-separated bit fields representing policies to initialize Mock BPA with. |
| `-j` | The path to a ION-Like Policy JSON-encoded policy structure file containing policies to initialize Mock BPA with. |
-| `-k` | The path to a JSON Web Key (JWK) formatted file containing keys to register with the BPA's Cryptographic Library instance. |
+| `-k` | The path to a JSON Web Key (JWK) file (named ".json") or COSE Key Set (named ".cbor") containing keys to register with the BPA's key store. |
diff --git a/docs/api/dictionary.txt b/docs/api/dictionary.txt
index f91cc4d6..5fca1d8a 100644
--- a/docs/api/dictionary.txt
+++ b/docs/api/dictionary.txt
@@ -51,6 +51,7 @@ callee's
calloc
CALLOC
Carsten
+cbor
CBOR
CCSDS
cek
@@ -127,6 +128,7 @@ isspace
JHU
Josefsson
JPL
+json
JSON
JWK
JWKs
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cd3b0472..3e7f5325 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -54,9 +54,11 @@ target_include_directories(bsl_front PUBLIC
add_library(bsl_crypto)
target_sources(bsl_crypto PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/bsl/crypto/CryptoInterface.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/bsl/crypto/KeyStore.h
)
target_sources(bsl_crypto PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/bsl/crypto/CryptoInterface.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/bsl/crypto/KeyStore.c
)
set_target_properties(bsl_crypto
PROPERTIES
@@ -180,7 +182,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/eidpat.h
${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/encode.h
${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/decode.h
- ${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/key_registry.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/KeyStore.h
${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/ctr.h
${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/MockBPA.h
)
@@ -194,7 +196,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/eidpat.c
${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/encode.c
${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/decode.c
- ${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/key_registry.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/KeyStore.c
${CMAKE_CURRENT_SOURCE_DIR}/bsl/mock_bpa/ctr.c
)
set_target_properties(bsl_mock_bpa
diff --git a/src/bsl/crypto/CryptoInterface.c b/src/bsl/crypto/CryptoInterface.c
index 24e75108..6a6ae1fc 100644
--- a/src/bsl/crypto/CryptoInterface.c
+++ b/src/bsl/crypto/CryptoInterface.c
@@ -20,8 +20,8 @@
* subcontract 1700763.
*/
/** @file
+ * @ingroup crypto
* Backend cryptography implementation
- * @ingroup backend_dyn
*/
#include "CryptoInterface.h"
@@ -29,9 +29,6 @@
#include "bsl/front/TextUtil.h"
#include "bsl/dynamic/IdValPair.h"
-#include
-#include
-#include
#include
#include
#include
@@ -42,133 +39,32 @@
#include
#endif /* defined(HAVE_VALGRIND) */
-/**
- * Struct to hold private key information
- */
-typedef struct BSL_CryptoKey_s
-{
- /// Pointer to raw key information
- BSL_Data_t raw;
- /// Additional parameter dictionary
- BSLB_IdValPairPtrMap_t params;
- /// Statistics related to this key
- BSL_Crypto_KeyStats_t stats;
- /// Mutex for #stats
- pthread_mutex_t stats_mutex;
-} BSL_CryptoKey_t;
-
-static void BSL_CryptoKey_Init(BSL_CryptoKey_t *key)
-{
- ASSERT_ARG_NONNULL(key);
-
- BSL_Data_Init(&(key->raw));
- BSLB_IdValPairPtrMap_init(key->params);
-
- for (uint64_t i = 0; i < BSL_CRYPTO_KEYSTATS_MAX_INDEX; i++)
- {
- key->stats.stats[i] = 0;
- }
- pthread_mutex_init(&key->stats_mutex, NULL);
-}
-
-static void BSL_CryptoKey_Deinit(BSL_CryptoKey_t *key)
-{
- ASSERT_ARG_NONNULL(key);
-
- BSL_Data_Deinit(&(key->raw));
- BSLB_IdValPairPtrMap_clear(key->params);
-
- pthread_mutex_destroy(&key->stats_mutex);
- for (uint64_t i = 0; i < BSL_CRYPTO_KEYSTATS_MAX_INDEX; i++)
- {
- key->stats.stats[i] = 0;
- }
-}
-
-/** M*LIB OPLIST for ::BSL_CryptoKey_t
- */
-#define M_OPL_BSL_CryptoKey_t() \
- M_OPEXTEND(M_POD_OPLIST, INIT(API_2(BSL_CryptoKey_Init)), INIT_SET(0), SET(0), CLEAR(API_2(BSL_CryptoKey_Deinit)))
-
-/** @struct BSL_CryptoKeyPtr_t
- * Thread-safe shared pointer to memory-stable ::BSL_CryptoKey_t struct.
- */
-/** @struct BSL_CryptoKeyDict_t
- * Stable dict of crypto keys (key: key ID | value: BSL_CryptoKeyPtr_t)
- */
-/// @cond Doxygen_Suppress
-// NOLINTBEGIN
-// GCOV_EXCL_START
-M_SHARED_PTR_DEF(BSL_CryptoKeyPtr, BSL_CryptoKey_t, M_OPL_BSL_CryptoKey_t())
-#define M_OPL_BSL_CryptoKeyPtr() M_SHARED_PTR_OPLIST(BSL_CryptoKeyPtr, M_OPL_BSL_CryptoKey_t())
-M_DICT_DEF2(BSL_CryptoKeyDict, m_bstring_t, M_BSTRING_OPLIST, BSL_CryptoKeyPtr_t *, M_OPL_BSL_CryptoKeyPtr())
-// GCOV_EXCL_STOP
-// NOLINTEND
-/// @endcond
+extern BSL_KeyStore_Descriptors_t BSL_KeyStore_State;
/// Random bytes generator
-static BSL_Crypto_RandBytesFn rand_bytes_generator;
-
-/// Crypto key registry
-static BSL_CryptoKeyDict_t StaticKeyRegistry;
-static pthread_mutex_t StaticCryptoMutex = PTHREAD_MUTEX_INITIALIZER;
-
-void BSL_CryptoInit(void)
-{
- pthread_mutex_lock(&StaticCryptoMutex);
- BSL_CryptoKeyDict_init(StaticKeyRegistry);
- pthread_mutex_unlock(&StaticCryptoMutex);
- rand_bytes_generator = RAND_bytes;
-}
-
-void BSL_CryptoDeinit(void)
-{
- pthread_mutex_lock(&StaticCryptoMutex);
- BSL_CryptoKeyDict_clear(StaticKeyRegistry);
- pthread_mutex_unlock(&StaticCryptoMutex);
-}
+static BSL_Crypto_RandBytesFn rand_bytes_generator = RAND_bytes;
void BSL_Crypto_SetRngGenerator(BSL_Crypto_RandBytesFn rand_gen_fn)
{
rand_bytes_generator = rand_gen_fn;
}
-void BSL_Crypto_ReleaseKeyHandle(BSL_Crypto_KeyHandle_t keyhandle)
-{
- if (!keyhandle)
- {
- return;
- }
-
- BSL_CryptoKeyPtr_t *ptr = keyhandle;
- BSL_CryptoKeyPtr_release(ptr);
-}
-
-bool BSL_Crypto_CompareKeys(BSL_Crypto_KeyHandle_t hdl1, BSL_Crypto_KeyHandle_t hdl2)
-{
- if (!hdl1 || !hdl2)
- {
- return false;
- }
- const BSL_CryptoKey_t *key1 = BSL_CryptoKeyPtr_ref(hdl1);
- const BSL_CryptoKey_t *key2 = BSL_CryptoKeyPtr_ref(hdl2);
-
- return BSL_Crypto_Compare(key1->raw.ptr, key1->raw.len, key2->raw.ptr, key2->raw.len);
-}
-
int BSL_Crypto_UnwrapKey(BSL_Crypto_KeyHandle_t kek_handle, const BSL_Data_t *wrapped_key,
BSL_Crypto_KeyHandle_t *cek_handle)
{
ASSERT_ARG_NONNULL(kek_handle);
ASSERT_ARG_NONNULL(wrapped_key);
ASSERT_ARG_NONNULL(cek_handle);
+ *cek_handle = NULL;
- BSL_CryptoKey_t *kek = BSL_CryptoKeyPtr_ref(kek_handle);
+ int retval = BSL_SUCCESS;
+ int res;
- *cek_handle = NULL;
+ BSL_Data_t kek_view;
+ CHK_PRECONDITION(BSL_SUCCESS == BSL_KeyStore_State.get_keymat(kek_handle, &kek_view));
const EVP_CIPHER *cipher;
- switch (kek->raw.len)
+ switch (kek_view.len)
{
case 16:
{
@@ -193,64 +89,85 @@ int BSL_Crypto_UnwrapKey(BSL_Crypto_KeyHandle_t kek_handle, const BSL_Data_t *wr
}
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
- CHK_PROPERTY(ctx != NULL);
-
- BSL_CryptoKeyPtr_t *cek_ptr = BSL_CryptoKeyPtr_new();
- // managed struct
- BSL_CryptoKey_t *cek = BSL_CryptoKeyPtr_ref(cek_ptr);
- CHK_PROPERTY(cek != NULL);
-
- // wrapped key always 8 bytes greater than CEK @cite rfc3394 (2.2.1)
- BSL_Data_Resize(&cek->raw, wrapped_key->len - 8);
-
- BSL_LOG_PLAINTEXT_PTR("using KEK", cek_handle, kek->raw.ptr, kek->raw.len);
- int dec_result = EVP_DecryptInit_ex(ctx, cipher, NULL, kek->raw.ptr, NULL);
- if (dec_result != 1)
+ // GCOV_EXCL_START
+ if (ctx == NULL)
{
- BSL_LOG_ERR("EVP_DecryptInit_ex: %s", ERR_error_string(ERR_get_error(), NULL));
- BSL_CryptoKeyPtr_release(cek_ptr);
+ BSL_LOG_ERR("Could not create cipher context");
return BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
}
- EVP_CIPHER_CTX_set_padding(ctx, 0);
+ // GCOV_EXCL_STOP
- pthread_mutex_lock(&kek->stats_mutex);
- kek->stats.stats[BSL_CRYPTO_KEYSTATS_TIMES_USED]++;
- kek->stats.stats[BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED] += cek->raw.len;
- pthread_mutex_unlock(&kek->stats_mutex);
+ BSL_Data_t cek_keymat;
+ // wrapped key always 8 bytes greater than CEK @cite rfc3394 (2.2.1)
+ res = BSL_Data_InitBuffer(&cek_keymat, wrapped_key->len - 8);
+ if (BSL_SUCCESS != res)
+ {
+ retval = res;
+ }
- int out_len = (int)cek->raw.len;
- BSL_LOG_PLAINTEXT_PTR("wrapped key", cek_handle, wrapped_key->ptr, wrapped_key->len);
- int decrypt_res = EVP_DecryptUpdate(ctx, cek->raw.ptr, &out_len, wrapped_key->ptr, wrapped_key->len);
- if (decrypt_res != 1)
+ if (BSL_SUCCESS == retval)
{
- BSL_LOG_ERR("EVP_DecryptUpdate: %s", ERR_error_string(ERR_get_error(), NULL));
- EVP_CIPHER_CTX_free(ctx);
- BSL_CryptoKeyPtr_release(cek_ptr);
- return BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ BSL_LOG_PLAINTEXT_PTR("using KEK", cek_handle, kek_view.ptr, kek_view.len);
+ res = EVP_DecryptInit_ex(ctx, cipher, NULL, kek_view.ptr, NULL);
+ // GCOV_EXCL_START
+ if (res != 1)
+ {
+ BSL_LOG_ERR("EVP_DecryptInit_ex: %s", ERR_error_string(ERR_get_error(), NULL));
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+ // GCOV_EXCL_STOP
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
}
- cek->raw.len = (size_t)out_len;
- uint8_t buf[EVP_CIPHER_CTX_block_size(ctx)];
- int final_len = 0;
- int res = EVP_DecryptFinal_ex(ctx, buf, &final_len);
- if (res != 1)
+ BSL_KeyStore_State.update_stats(kek_handle, 1, cek_keymat.len);
+
+ int out_len;
+ if (BSL_SUCCESS == retval)
{
- BSL_LOG_ERR("Failed DecryptFinal: %s", ERR_error_string(ERR_get_error(), NULL));
- EVP_CIPHER_CTX_free(ctx);
- BSL_CryptoKeyPtr_release(cek_ptr);
- return BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ out_len = (int)cek_keymat.len;
+ BSL_LOG_PLAINTEXT_PTR("wrapped key", cek_handle, wrapped_key->ptr, wrapped_key->len);
+ res = EVP_DecryptUpdate(ctx, cek_keymat.ptr, &out_len, wrapped_key->ptr, (int)wrapped_key->len);
+ // GCOV_EXCL_START
+ if (res != 1)
+ {
+ BSL_LOG_ERR("EVP_DecryptUpdate: %s", ERR_error_string(ERR_get_error(), NULL));
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+ // GCOV_EXCL_STOP
+ else
+ {
+ cek_keymat.len = (size_t)out_len;
+ }
}
- if (final_len > 0)
+ if (BSL_SUCCESS == retval)
{
- BSL_Data_AppendFrom(&cek->raw, (size_t)final_len, buf);
+ out_len = 0;
+ res = EVP_DecryptFinal_ex(ctx, NULL, &out_len);
+ // GCOV_EXCL_START
+ if (res != 1)
+ {
+ BSL_LOG_ERR("Failed DecryptFinal: %s", ERR_error_string(ERR_get_error(), NULL));
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+ else if (out_len > 0)
+ {
+ BSL_LOG_ERR("Key wrap without padding should not have any final data");
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+ // GCOV_EXCL_STOP
+ BSL_LOG_PLAINTEXT_PTR("unwrapped key", cek_handle, cek_keymat.ptr, cek_keymat.len);
}
EVP_CIPHER_CTX_free(ctx);
- BSL_LOG_PLAINTEXT_PTR("unwrapped key", cek, cek->raw.ptr, cek->raw.len);
- *cek_handle = cek_ptr;
- return 0;
+ if (BSL_SUCCESS == retval)
+ {
+ retval = BSL_Crypto_LoadKey(cek_keymat.ptr, cek_keymat.len, cek_handle);
+ }
+ BSL_Data_Deinit(&cek_keymat);
+
+ return retval;
}
int BSL_Crypto_WrapKey(BSL_Crypto_KeyHandle_t kek_handle, BSL_Crypto_KeyHandle_t cek_handle, BSL_Data_t *wrapped_key)
@@ -259,11 +176,17 @@ int BSL_Crypto_WrapKey(BSL_Crypto_KeyHandle_t kek_handle, BSL_Crypto_KeyHandle_t
CHK_ARG_NONNULL(cek_handle);
CHK_ARG_NONNULL(wrapped_key);
- BSL_CryptoKey_t *kek = BSL_CryptoKeyPtr_ref(kek_handle);
- BSL_CryptoKey_t *cek = BSL_CryptoKeyPtr_ref(cek_handle);
+ int retval = BSL_SUCCESS;
+ int res;
+
+ BSL_Data_t kek_view;
+ CHK_PRECONDITION(BSL_SUCCESS == BSL_KeyStore_State.get_keymat(kek_handle, &kek_view));
+
+ BSL_Data_t cek_view;
+ CHK_PRECONDITION(BSL_SUCCESS == BSL_KeyStore_State.get_keymat(cek_handle, &cek_view));
const EVP_CIPHER *cipher;
- switch (kek->raw.len)
+ switch (kek_view.len)
{
case 16:
{
@@ -288,54 +211,69 @@ int BSL_Crypto_WrapKey(BSL_Crypto_KeyHandle_t kek_handle, BSL_Crypto_KeyHandle_t
}
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ // GCOV_EXCL_START
if (ctx == NULL)
{
BSL_LOG_ERR("Could not create cipher context");
- return -1;
+ return BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
}
+ // GCOV_EXCL_STOP
- BSL_LOG_PLAINTEXT_PTR("using KEK", cek_handle, kek->raw.ptr, kek->raw.len);
- int enc_result = EVP_EncryptInit_ex(ctx, cipher, NULL, kek->raw.ptr, NULL);
- if (!enc_result)
+ // wrapped key always 8 bytes greater than CEK @cite rfc3394 (2.2.1)
+ res = BSL_Data_Resize(wrapped_key, cek_view.len + 8);
+ if (BSL_SUCCESS != res)
{
- EVP_CIPHER_CTX_free(ctx);
- return -1;
+ retval = res;
}
- pthread_mutex_lock(&kek->stats_mutex);
- kek->stats.stats[BSL_CRYPTO_KEYSTATS_TIMES_USED]++;
- kek->stats.stats[BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED] += cek->raw.len;
- pthread_mutex_unlock(&kek->stats_mutex);
-
- // wrapped key always 8 bytes greater than CEK @cite rfc3394 (2.2.1)
- BSL_Data_Resize(wrapped_key, cek->raw.len + 8);
-
- int out_len = (int)wrapped_key->len;
- BSL_LOG_PLAINTEXT_PTR("unwrapped key", cek_handle, cek->raw.ptr, cek->raw.len);
- if (!EVP_EncryptUpdate(ctx, (unsigned char *)wrapped_key->ptr, &out_len, cek->raw.ptr, cek->raw.len))
+ if (BSL_SUCCESS == retval)
{
- EVP_CIPHER_CTX_free(ctx);
- return -2;
+ BSL_LOG_PLAINTEXT_PTR("using KEK", cek_handle, kek_view.ptr, kek_view.len);
+ // GCOV_EXCL_START
+ res = EVP_EncryptInit_ex(ctx, cipher, NULL, kek_view.ptr, NULL);
+ if (res != 1)
+ {
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+ // GCOV_EXCL_STOP
}
- wrapped_key->len = (size_t)out_len;
- uint8_t buf[EVP_CIPHER_CTX_block_size(ctx)];
- int final_len = 0;
- if (!EVP_EncryptFinal_ex(ctx, buf, &final_len))
+ BSL_KeyStore_State.update_stats(kek_handle, 1, cek_view.len);
+
+ int out_len;
+ if (BSL_SUCCESS == retval)
{
- EVP_CIPHER_CTX_free(ctx);
- return -1;
+ out_len = (int)wrapped_key->len;
+ BSL_LOG_PLAINTEXT_PTR("unwrapped key", cek_handle, cek_view.ptr, cek_view.len);
+ res = EVP_EncryptUpdate(ctx, (unsigned char *)wrapped_key->ptr, &out_len, cek_view.ptr, (int)cek_view.len);
+ if (res != 1)
+ {
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+ wrapped_key->len = (size_t)out_len;
}
- if (final_len > 0)
+ if (BSL_SUCCESS == retval)
{
- BSL_Data_AppendFrom(&cek->raw, final_len, buf);
+ out_len = 0;
+ res = EVP_EncryptFinal_ex(ctx, NULL, &out_len);
+ // GCOV_EXCL_START
+ if (res != 1)
+ {
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+ else if (out_len > 0)
+ {
+ BSL_LOG_ERR("Key wrap without padding should not have any final data");
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+ // GCOV_EXCL_STOP
+ BSL_LOG_PLAINTEXT_PTR("wrapped key", cek_handle, wrapped_key->ptr, wrapped_key->len);
}
EVP_CIPHER_CTX_free(ctx);
- BSL_LOG_PLAINTEXT_PTR("wrapped key", cek_handle, wrapped_key->ptr, wrapped_key->len);
- return 0;
+ return retval;
}
// work-around allowance for empty salt and info
@@ -346,10 +284,11 @@ static const uint8_t BSL_Crypto_zero = 0;
int BSL_Crypto_KDF(BSL_Crypto_KeyHandle_t kdk_handle, BSL_Crypto_KDFVariant_t func, const BSL_Data_t *salt,
const BSL_Data_t *info, size_t keylen, BSL_Crypto_KeyHandle_t *cek_handle)
{
+ CHK_ARG_NONNULL(cek_handle);
+ *cek_handle = NULL;
CHK_ARG_NONNULL(kdk_handle);
CHK_ARG_NONNULL(salt);
CHK_ARG_NONNULL(info);
- CHK_ARG_NONNULL(cek_handle);
CHK_PRECONDITION(keylen > 0);
char *digest_name;
@@ -366,38 +305,42 @@ int BSL_Crypto_KDF(BSL_Crypto_KeyHandle_t kdk_handle, BSL_Crypto_KDFVariant_t fu
return BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
}
- BSL_CryptoKey_t *kdk = BSL_CryptoKeyPtr_ref(kdk_handle);
- CHK_PRECONDITION(kdk->raw.len > 0);
+ int retval = BSL_SUCCESS;
+ int res;
- BSL_CryptoKeyPtr_t *cek_ptr = BSL_CryptoKeyPtr_new();
- // managed struct
- BSL_CryptoKey_t *cek = BSL_CryptoKeyPtr_ref(cek_ptr);
- CHK_PROPERTY(cek != NULL);
+ BSL_Data_t kdk_view;
+ CHK_PRECONDITION(BSL_SUCCESS == BSL_KeyStore_State.get_keymat(kdk_handle, &kdk_view));
- if (BSL_SUCCESS != BSL_Data_Resize(&cek->raw, keylen))
+ BSL_Data_t cek_keymat;
+ if (BSL_SUCCESS != BSL_Data_InitBuffer(&cek_keymat, keylen))
{
- BSL_CryptoKeyPtr_release(cek_ptr);
- return BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
}
- int retval = BSL_SUCCESS;
-
- EVP_KDF *kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
- if (!kdf)
+ EVP_KDF *kdf = NULL;
+ if (BSL_SUCCESS == retval)
{
- BSL_LOG_ERR("EVP_KDF_fetch: %s", ERR_error_string(ERR_get_error(), NULL));
- retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
+ // GCOV_EXCL_START
+ if (!kdf)
+ {
+ BSL_LOG_ERR("EVP_KDF_fetch: %s", ERR_error_string(ERR_get_error(), NULL));
+ retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+ // GCOV_EXCL_STOP
}
EVP_KDF_CTX *kctx = NULL;
if (BSL_SUCCESS == retval)
{
kctx = EVP_KDF_CTX_new(kdf);
+ // GCOV_EXCL_START
if (!kctx)
{
BSL_LOG_ERR("EVP_KDF_CTX_new: %s", ERR_error_string(ERR_get_error(), NULL));
retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
}
+ // GCOV_EXCL_STOP
}
if (kdf)
{
@@ -410,27 +353,26 @@ int BSL_Crypto_KDF(BSL_Crypto_KeyHandle_t kdk_handle, BSL_Crypto_KDFVariant_t fu
OSSL_PARAM *par = params;
*par++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, digest_name, strlen(digest_name));
- BSL_LOG_PLAINTEXT_PTR("using key", kctx, kdk->raw.ptr, kdk->raw.len);
- *par++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, kdk->raw.ptr, kdk->raw.len);
+ BSL_LOG_PLAINTEXT_PTR("using key", kctx, kdk_view.ptr, kdk_view.len);
+ *par++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, kdk_view.ptr, kdk_view.len);
BSL_LOG_PLAINTEXT_PTR("using salt", kctx, salt->ptr, salt->len);
*par++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, BSL_Crypto_PtrOrZero(salt->ptr), salt->len);
BSL_LOG_PLAINTEXT_PTR("using info", kctx, info->ptr, info->len);
*par++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, BSL_Crypto_PtrOrZero(info->ptr), info->len);
*par = OSSL_PARAM_construct_end();
- pthread_mutex_lock(&kdk->stats_mutex);
- kdk->stats.stats[BSL_CRYPTO_KEYSTATS_TIMES_USED]++;
- kdk->stats.stats[BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED] += cek->raw.len;
- pthread_mutex_unlock(&kdk->stats_mutex);
+ BSL_KeyStore_State.update_stats(kdk_handle, 1, cek_keymat.len);
- int res = EVP_KDF_derive(kctx, cek->raw.ptr, cek->raw.len, params);
- BSL_LOG_DEBUG("EVP_KDF_derive gave %zu bytes, return %d", cek->raw.len, res);
- BSL_LOG_PLAINTEXT_PTR("KDF out", kctx, cek->raw.ptr, cek->raw.len);
+ res = EVP_KDF_derive(kctx, cek_keymat.ptr, cek_keymat.len, params);
+ BSL_LOG_DEBUG("EVP_KDF_derive gave %zu bytes, return %d", cek_keymat.len, res);
+ BSL_LOG_PLAINTEXT_PTR("KDF out", kctx, cek_keymat.ptr, cek_keymat.len);
+ // GCOV_EXCL_START
if (res <= 0)
{
BSL_LOG_ERR("EVP_KDF_derive: %s", ERR_error_string(ERR_get_error(), NULL));
retval = BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
}
+ // GCOV_EXCL_STOP
}
if (kctx)
{
@@ -439,13 +381,10 @@ int BSL_Crypto_KDF(BSL_Crypto_KeyHandle_t kdk_handle, BSL_Crypto_KDFVariant_t fu
if (BSL_SUCCESS == retval)
{
- *cek_handle = cek_ptr;
- }
- else
- {
- *cek_handle = NULL;
- BSL_CryptoKeyPtr_release(cek_ptr);
+ retval = BSL_Crypto_LoadKey(cek_keymat.ptr, cek_keymat.len, cek_handle);
}
+
+ BSL_Data_Deinit(&cek_keymat);
return retval;
}
@@ -471,10 +410,11 @@ int BSL_AuthCtx_Init(BSL_AuthCtx_t *hmac_ctx, BSL_Crypto_KeyHandle_t keyhandle,
return BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
}
- hmac_ctx->keyhandle = BSL_CryptoKeyPtr_acquire(keyhandle);
+ hmac_ctx->keyhandle = BSL_KeyStore_State.acquire_key(keyhandle);
+ CHK_PRECONDITION(hmac_ctx->keyhandle);
- BSL_CryptoKey_t *key_info = BSL_CryptoKeyPtr_ref(hmac_ctx->keyhandle);
- CHK_PRECONDITION(key_info->raw.len > 0);
+ BSL_Data_t key_view;
+ CHK_PRECONDITION(BSL_SUCCESS == BSL_KeyStore_State.get_keymat(hmac_ctx->keyhandle, &key_view));
EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
CHK_PRECONDITION(mac != NULL);
@@ -486,27 +426,29 @@ int BSL_AuthCtx_Init(BSL_AuthCtx_t *hmac_ctx, BSL_Crypto_KeyHandle_t keyhandle,
OSSL_PARAM params[2];
{
OSSL_PARAM *par = params;
- *par++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, digest_name, strlen(digest_name));
- *par++ = OSSL_PARAM_construct_end();
+
+ *par++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, digest_name, strlen(digest_name));
+ *par++ = OSSL_PARAM_construct_end();
}
- BSL_LOG_PLAINTEXT_PTR("using key", hmac_ctx, key_info->raw.ptr, key_info->raw.len);
- int res = EVP_MAC_init(hmac_ctx->libhandle, key_info->raw.ptr, key_info->raw.len, params);
+ BSL_LOG_PLAINTEXT_PTR("using key", hmac_ctx, key_view.ptr, key_view.len);
+ int res = EVP_MAC_init(hmac_ctx->libhandle, key_view.ptr, key_view.len, params);
CHK_PROPERTY(res == 1);
hmac_ctx->block_size = EVP_MAC_CTX_get_block_size(hmac_ctx->libhandle);
+ BSL_LOG_DEBUG("MAC block size %zu", hmac_ctx->block_size);
+ // GCOV_EXCL_START
if (hmac_ctx->block_size == 0)
{
hmac_ctx->block_size = 1024;
BSL_LOG_ERR("invalid block size zero, assuming %zu", hmac_ctx->block_size);
}
+ // GCOV_EXCL_STOP
res = BSL_Data_InitBuffer(&hmac_ctx->in_buf, hmac_ctx->block_size);
CHK_PROPERTY(!res);
- pthread_mutex_lock(&key_info->stats_mutex);
- key_info->stats.stats[BSL_CRYPTO_KEYSTATS_TIMES_USED]++;
- pthread_mutex_unlock(&key_info->stats_mutex);
+ BSL_KeyStore_State.update_stats(keyhandle, 1, 0);
return 0;
}
@@ -523,10 +465,7 @@ int BSL_AuthCtx_DigestBuffer(BSL_AuthCtx_t *hmac_ctx, const void *data, size_t d
BSL_LOG_DEBUG("EVP_MAC_update took %zu bytes, return %d", data_len, res);
CHK_PROPERTY(res == 1);
- BSL_CryptoKey_t *key_info = BSL_CryptoKeyPtr_ref(hmac_ctx->keyhandle);
- pthread_mutex_lock(&key_info->stats_mutex);
- key_info->stats.stats[BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED] += data_len;
- pthread_mutex_unlock(&key_info->stats_mutex);
+ BSL_KeyStore_State.update_stats(hmac_ctx->keyhandle, 0, data_len);
return 0;
}
@@ -536,8 +475,6 @@ int BSL_AuthCtx_DigestSeq(BSL_AuthCtx_t *hmac_ctx, BSL_SeqReader_t *reader)
ASSERT_ARG_NONNULL(hmac_ctx);
ASSERT_ARG_NONNULL(reader);
- BSL_CryptoKey_t *key_info = BSL_CryptoKeyPtr_ref(hmac_ctx->keyhandle);
-
while (true)
{
// read until there is no more
@@ -553,9 +490,7 @@ int BSL_AuthCtx_DigestSeq(BSL_AuthCtx_t *hmac_ctx, BSL_SeqReader_t *reader)
BSL_LOG_DEBUG("EVP_MAC_update took %zu bytes, return %d", block_size, res);
CHK_PROPERTY(res == 1);
- pthread_mutex_lock(&key_info->stats_mutex);
- key_info->stats.stats[BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED] += block_size;
- pthread_mutex_unlock(&key_info->stats_mutex);
+ BSL_KeyStore_State.update_stats(hmac_ctx->keyhandle, 0, block_size);
}
return 0;
@@ -586,7 +521,8 @@ void BSL_AuthCtx_Deinit(BSL_AuthCtx_t *hmac_ctx)
BSL_Data_Deinit(&hmac_ctx->in_buf);
EVP_MAC_CTX_free(hmac_ctx->libhandle);
- BSL_CryptoKeyPtr_release(hmac_ctx->keyhandle);
+ BSL_KeyStore_State.release_key(hmac_ctx->keyhandle);
+
memset(hmac_ctx, 0, sizeof(BSL_AuthCtx_t));
}
@@ -610,9 +546,11 @@ int BSL_Cipher_Init(BSL_Cipher_t *cipher_ctx, BSL_CipherMode_e enc, BSL_Crypto_A
memset(cipher_ctx, 0, sizeof(*cipher_ctx));
- cipher_ctx->keyhandle = BSL_CryptoKeyPtr_acquire(keyhandle);
+ cipher_ctx->keyhandle = BSL_KeyStore_State.acquire_key(keyhandle);
+ CHK_PRECONDITION(cipher_ctx->keyhandle);
- BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(cipher_ctx->keyhandle);
+ BSL_Data_t key_view;
+ CHK_PRECONDITION(BSL_SUCCESS == BSL_KeyStore_State.get_keymat(cipher_ctx->keyhandle, &key_view));
cipher_ctx->libhandle = EVP_CIPHER_CTX_new();
cipher_ctx->enc = enc;
@@ -633,23 +571,37 @@ int BSL_Cipher_Init(BSL_Cipher_t *cipher_ctx, BSL_CipherMode_e enc, BSL_Crypto_A
return BSL_ERR_FAILURE;
}
- int res =
- EVP_CipherInit_ex(cipher_ctx->libhandle, cipher, NULL, NULL, NULL, (cipher_ctx->enc == BSL_CRYPTO_ENCRYPT));
+ const int do_encrypt = (cipher_ctx->enc == BSL_CRYPTO_ENCRYPT);
+
+ int res = EVP_CipherInit_ex(cipher_ctx->libhandle, cipher, NULL, NULL, NULL, do_encrypt);
CHK_PROPERTY(res == 1);
- cipher_ctx->block_size = (size_t)EVP_CIPHER_get_block_size(cipher_ctx->libhandle);
+ {
+ const size_t need_len = (size_t)EVP_CIPHER_CTX_get_key_length(cipher_ctx->libhandle);
+ CHK_PROPERTY(key_view.len == need_len);
+ }
+
+ cipher_ctx->block_size = (size_t)EVP_CIPHER_CTX_get_block_size(cipher_ctx->libhandle);
+ if (cipher_ctx->block_size == 1)
+ {
+ // Choose a reasonable chunk size
+ cipher_ctx->block_size = 1024;
+ }
+ BSL_LOG_DEBUG("Cipher block size %zu", cipher_ctx->block_size);
+ // GCOV_EXCL_START
if (cipher_ctx->block_size == 0)
{
cipher_ctx->block_size = 1024;
BSL_LOG_ERR("invalid block size zero, assuming %zu", cipher_ctx->block_size);
}
+ // GCOV_EXCL_STOP
res = EVP_CIPHER_CTX_ctrl(cipher_ctx->libhandle, EVP_CTRL_GCM_SET_IVLEN, (int)iv_val->len, NULL);
CHK_PROPERTY(res == 1);
- BSL_LOG_PLAINTEXT_PTR("using key", cipher_ctx, key->raw.ptr, key->raw.len);
+ BSL_LOG_PLAINTEXT_PTR("using key", cipher_ctx, key_view.ptr, key_view.len);
BSL_LOG_PLAINTEXT_PTR("using IV", cipher_ctx, iv_val->ptr, iv_val->len);
- res = EVP_CipherInit_ex(cipher_ctx->libhandle, NULL, NULL, key->raw.ptr, iv_val->ptr, -1);
+ res = EVP_CipherInit_ex(cipher_ctx->libhandle, NULL, NULL, key_view.ptr, iv_val->ptr, -1);
CHK_PROPERTY(res == 1);
res = BSL_Data_InitBuffer(&cipher_ctx->in_buf, cipher_ctx->block_size);
@@ -658,9 +610,7 @@ int BSL_Cipher_Init(BSL_Cipher_t *cipher_ctx, BSL_CipherMode_e enc, BSL_Crypto_A
res = BSL_Data_InitBuffer(&cipher_ctx->out_buf, cipher_ctx->block_size);
CHK_PROPERTY(!res);
- pthread_mutex_lock(&key->stats_mutex);
- key->stats.stats[BSL_CRYPTO_KEYSTATS_TIMES_USED]++;
- pthread_mutex_unlock(&key->stats_mutex);
+ BSL_KeyStore_State.update_stats(cipher_ctx->keyhandle, 1, 0);
return 0;
}
@@ -679,10 +629,7 @@ int BSL_Cipher_AddAadBuffer(BSL_Cipher_t *cipher_ctx, const void *aad, size_t aa
BSL_LOG_DEBUG("EVP_CipherUpdate took %zu bytes, return %d", aad_len, res);
CHK_PROPERTY(res == 1);
- BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(cipher_ctx->keyhandle);
- pthread_mutex_lock(&key->stats_mutex);
- key->stats.stats[BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED] += aad_len;
- pthread_mutex_unlock(&key->stats_mutex);
+ BSL_KeyStore_State.update_stats(cipher_ctx->keyhandle, 0, aad_len);
return 0;
}
@@ -692,8 +639,6 @@ int BSL_Cipher_AddAadSeq(BSL_Cipher_t *cipher_ctx, BSL_SeqReader_t *reader)
ASSERT_ARG_NONNULL(cipher_ctx);
ASSERT_ARG_NONNULL(reader);
- BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(cipher_ctx->keyhandle);
-
while (true)
{
// read until there is no more
@@ -711,9 +656,7 @@ int BSL_Cipher_AddAadSeq(BSL_Cipher_t *cipher_ctx, BSL_SeqReader_t *reader)
EVP_CipherUpdate(cipher_ctx->libhandle, NULL, &block_size_int, cipher_ctx->in_buf.ptr, block_size_int);
CHK_PROPERTY(res == 1);
- pthread_mutex_lock(&key->stats_mutex);
- key->stats.stats[BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED] += block_size_int;
- pthread_mutex_unlock(&key->stats_mutex);
+ BSL_KeyStore_State.update_stats(cipher_ctx->keyhandle, 0, block_size_int);
}
return 0;
@@ -723,9 +666,6 @@ int BSL_Cipher_AddSeq(BSL_Cipher_t *cipher_ctx, BSL_SeqReader_t *reader, BSL_Seq
{
ASSERT_ARG_NONNULL(cipher_ctx);
ASSERT_ARG_NONNULL(reader);
- BSL_LOG_DEBUG("block size %zu bytes", cipher_ctx->block_size);
-
- BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(cipher_ctx->keyhandle);
while (limit)
{
@@ -747,9 +687,7 @@ int BSL_Cipher_AddSeq(BSL_Cipher_t *cipher_ctx, BSL_SeqReader_t *reader, BSL_Seq
BSL_LOG_PLAINTEXT_PTR("cipher out", cipher_ctx, cipher_ctx->out_buf.ptr, block_size_int);
CHK_PROPERTY(res == 1);
- pthread_mutex_lock(&key->stats_mutex);
- key->stats.stats[BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED] += block_size_int;
- pthread_mutex_unlock(&key->stats_mutex);
+ BSL_KeyStore_State.update_stats(cipher_ctx->keyhandle, 0, block_size_int);
if ((block_size_int > 0) && writer)
{
@@ -807,11 +745,13 @@ int BSL_Cipher_FinalizeSeq(BSL_Cipher_t *cipher_ctx, BSL_SeqWriter_t *writer)
int res = EVP_CipherFinal_ex(cipher_ctx->libhandle, cipher_ctx->out_buf.ptr, &block_size_int);
BSL_LOG_DEBUG("EVP_CipherFinal_ex gave %d bytes, return %d", block_size_int, res);
+ // GCOV_EXCL_START
if (res != 1)
{
BSL_LOG_ERR("EVP_CipherFinal_ex error %s", ERR_error_string(ERR_get_error(), NULL));
return BSL_ERR_FAILURE;
}
+ // GCOV_EXCL_STOP
if ((block_size_int > 0) && writer)
{
@@ -822,189 +762,24 @@ int BSL_Cipher_FinalizeSeq(BSL_Cipher_t *cipher_ctx, BSL_SeqWriter_t *writer)
return BSL_SUCCESS;
}
-int BSL_Cipher_Deinit(BSL_Cipher_t *cipher_ctx)
+void BSL_Cipher_Deinit(BSL_Cipher_t *cipher_ctx)
{
- CHK_ARG_NONNULL(cipher_ctx);
+ ASSERT_ARG_NONNULL(cipher_ctx);
+
BSL_Data_Deinit(&cipher_ctx->out_buf);
BSL_Data_Deinit(&cipher_ctx->in_buf);
EVP_CIPHER_CTX_free(cipher_ctx->libhandle);
- BSL_CryptoKeyPtr_release(cipher_ctx->keyhandle);
- memset(cipher_ctx, 0, sizeof(*cipher_ctx));
- return BSL_SUCCESS;
-}
-
-int BSL_Crypto_GenKey(size_t key_length, BSL_Crypto_KeyHandle_t *key_out)
-{
- CHK_ARG_NONNULL(key_out);
- *key_out = NULL;
- CHK_ARG_EXPR(key_length > 0);
-
- BSL_CryptoKeyPtr_t *key_ptr = BSL_CryptoKeyPtr_new();
- // managed struct
- BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(key_ptr);
- CHK_PROPERTY(key != NULL);
-
- BSL_Data_Resize(&key->raw, key_length);
- if (rand_bytes_generator(key->raw.ptr, (int)key->raw.len) != 1)
- {
- BSL_CryptoKeyPtr_release(key_ptr);
- return BSL_ERR_FAILURE;
- }
+ BSL_KeyStore_State.release_key(cipher_ctx->keyhandle);
- *key_out = key_ptr;
- return BSL_SUCCESS;
-}
-
-int BSL_Crypto_LoadKey(const uint8_t *secret, size_t secret_len, BSL_Crypto_KeyHandle_t *key_out)
-{
- CHK_ARG_NONNULL(key_out);
- *key_out = NULL;
- CHK_ARG_EXPR(secret_len > 0);
-
- BSL_CryptoKeyPtr_t *key_ptr = BSL_CryptoKeyPtr_new();
- // managed struct
- BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(key_ptr);
- CHK_PROPERTY(key != NULL);
-
- int ecode = 0;
- if ((ecode = BSL_Data_CopyFrom(&key->raw, secret_len, secret)) != 0)
- {
- BSL_LOG_ERR("Failed to copy key");
- BSL_CryptoKeyPtr_release(key_ptr);
- return ecode;
- }
-
- *key_out = key_ptr;
- return BSL_SUCCESS;
+ memset(cipher_ctx, 0, sizeof(*cipher_ctx));
}
int BSL_Crypto_GenIV(BSL_Data_t *buf)
{
+ ASSERT_PRECONDITION(rand_bytes_generator);
CHK_ARG_NONNULL(buf);
memset(buf->ptr, 0, buf->len);
CHK_PROPERTY(rand_bytes_generator((unsigned char *)(buf->ptr), buf->len) == 1);
return BSL_SUCCESS;
}
-
-int BSL_Crypto_AddRegistryKey(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t handle)
-{
- ASSERT_ARG_NONNULL(keyid);
- CHK_ARG_NONNULL(handle);
-
- BSL_CryptoKeyPtr_t *key_ptr = handle;
-
- m_bstring_t keyid_str;
- m_bstring_init(keyid_str);
- m_bstring_push_back_bytes(keyid_str, keyid->len, keyid->ptr);
-
- pthread_mutex_lock(&StaticCryptoMutex);
- BSL_CryptoKeyDict_set_at(StaticKeyRegistry, keyid_str, key_ptr);
- pthread_mutex_unlock(&StaticCryptoMutex);
-
- m_bstring_clear(keyid_str);
- return 0;
-}
-
-BSL_IdValPair_t *BSL_Crypto_SetKeyParameter(BSL_Crypto_KeyHandle_t handle, int64_t param_id)
-{
- ASSERT_ARG_NONNULL(handle);
- BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(handle);
-
- BSL_IdValPair_t *retval = NULL;
- if (key)
- {
- BSLB_IdValPairPtr_t *param_ptr;
-
- BSLB_IdValPairPtr_t **found = BSLB_IdValPairPtrMap_get(key->params, param_id);
- if (found)
- {
- param_ptr = *found;
- retval = BSLB_IdValPairPtr_ref(param_ptr);
- }
- else
- {
- param_ptr = BSLB_IdValPairPtr_new();
- BSLB_IdValPairPtrMap_set_at(key->params, param_id, param_ptr);
- retval = BSLB_IdValPairPtr_ref(param_ptr);
- // map keeps a reference so this is safe
- BSLB_IdValPairPtr_release(param_ptr);
- }
- }
- return retval;
-}
-
-const BSL_IdValPair_t *BSL_Crypto_GetKeyParameter(BSL_Crypto_KeyHandle_t handle, int64_t param_id)
-{
- ASSERT_ARG_NONNULL(handle);
- BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(handle);
-
- const BSL_IdValPair_t *retval = NULL;
- if (key)
- {
- BSLB_IdValPairPtr_t **found = BSLB_IdValPairPtrMap_get(key->params, param_id);
- if (found)
- {
- retval = BSLB_IdValPairPtr_ref(*found);
- }
- }
- return retval;
-}
-
-int BSL_Crypto_GetRegistryKey(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t *key_handle)
-{
- ASSERT_ARG_NONNULL(keyid);
- CHK_ARG_NONNULL(key_handle);
-
- m_bstring_t keyid_str;
- m_bstring_init(keyid_str);
- m_bstring_push_back_bytes(keyid_str, keyid->len, keyid->ptr);
-
- int retval = BSL_SUCCESS;
- pthread_mutex_lock(&StaticCryptoMutex);
- BSL_CryptoKeyPtr_t **found = BSL_CryptoKeyDict_get(StaticKeyRegistry, keyid_str);
- if (!found)
- {
- *key_handle = NULL;
- retval = BSL_ERR_NOT_FOUND;
- }
- else
- {
- *key_handle = BSL_CryptoKeyPtr_acquire(*found);
- }
- pthread_mutex_unlock(&StaticCryptoMutex);
-
- m_bstring_clear(keyid_str);
- return retval;
-}
-
-int BSL_Crypto_RemoveRegistryKey(const BSL_Data_t *keyid)
-{
- ASSERT_ARG_NONNULL(keyid);
-
- m_bstring_t keyid_str;
- m_bstring_init(keyid_str);
- m_bstring_push_back_bytes(keyid_str, keyid->len, keyid->ptr);
-
- pthread_mutex_lock(&StaticCryptoMutex);
- int res = BSL_CryptoKeyDict_erase(StaticKeyRegistry, keyid_str);
- pthread_mutex_unlock(&StaticCryptoMutex);
-
- m_bstring_clear(keyid_str);
- return res ? BSL_SUCCESS : -1;
-}
-
-int BSL_Crypto_GetKeyStatistics(BSL_Crypto_KeyHandle_t handle, BSL_Crypto_KeyStats_t *stats)
-{
- ASSERT_ARG_NONNULL(handle);
- CHK_ARG_NONNULL(stats);
-
- BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(handle);
-
- pthread_mutex_lock(&key->stats_mutex);
- // copy as POD
- *stats = key->stats;
- pthread_mutex_unlock(&key->stats_mutex);
-
- return BSL_SUCCESS;
-}
diff --git a/src/bsl/crypto/CryptoInterface.h b/src/bsl/crypto/CryptoInterface.h
index 510ebb14..3001f947 100644
--- a/src/bsl/crypto/CryptoInterface.h
+++ b/src/bsl/crypto/CryptoInterface.h
@@ -20,13 +20,15 @@
* subcontract 1700763.
*/
/** @file
- * @ingroup frontend
+ * @ingroup crypto
* Abstract interface for crypto processing.
* This file is organized into groups based on topic: key registry, HMAC, cipher, etc.
*/
#ifndef BSL_FRONTEND_CRYPTO_INTERFACE_H_
#define BSL_FRONTEND_CRYPTO_INTERFACE_H_
+#include "KeyStore.h"
+
#include "bsl/BPSecLib_Private.h" // TODO replace with Variant.h
#include "bsl/BSLConfig.h"
#include "bsl/front/Data.h"
@@ -39,16 +41,6 @@
extern "C" {
#endif
-/** Initialize the crypto subsystem.
- * This must be called once per process.
- */
-void BSL_CryptoInit(void);
-
-/** Deinitialize the crypto subsystem.
- * This should be called at the end of the process.
- */
-void BSL_CryptoDeinit(void);
-
/**
* Function pointer def for random bytestring generator
* @param buf buffer to fill with random bytes
@@ -87,121 +79,6 @@ bool BSL_Crypto_Compare(const void *data1, size_t size1, const void *data2, size
*/
typedef void *BSL_Crypto_LibHandle_t;
-/** @name Key registry interface
- *
- * There are two forms of managed crypto keys in this interface:
- * 1. Identified keys persisted in a long-term, thread-safe registry.
- * These keys have byte string names (which can contain UTF8 text) and can
- * have additional parameters to restrict their use.
- * 2. Anonymous ephemeral keys used for individual operations and then discarded.
- * These keys do not have names and are typically key-wrapped or the result of a
- * key derivation function (KDF).
- */
-///@{
-
-typedef enum
-{
- BSL_CRYPTO_KEYSTATS_TIMES_USED = 0,
- BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED,
- /// Not a real index, used to size arrays
- BSL_CRYPTO_KEYSTATS_MAX_INDEX
-} BSL_Crypto_KeyStatCounterIndex_t;
-
-/**
- * Structure containing statistics for individual keys
- */
-typedef struct BSL_Crypto_KeyStats_s
-{
- /// Counters for each ::BSL_Crypto_KeyStatCounterIndex_t value
- uint64_t stats[BSL_CRYPTO_KEYSTATS_MAX_INDEX];
-} BSL_Crypto_KeyStats_t;
-
-/** Opaque handle for key objects in the key store.
- */
-typedef struct BSL_CryptoKeyPtr_s *BSL_Crypto_KeyHandle_t;
-
-/**
- * Generate a new cryptographic key.
- * @param[in] key_length length of new key in bytes.
- * @param[out] key_out pointer to pointer for new key handle.
- * The handle must be released with BSL_Crypto_ReleaseKeyHandle() when it is done being used.
- */
-int BSL_Crypto_GenKey(size_t key_length, BSL_Crypto_KeyHandle_t *key_out);
-
-/**
- * Load a new cryptographic key.
- * @param[in] secret raw symmetric key.
- * @param secret_len length of @c secret data.
- * @param[out] key_out pointer to pointer for new key handle.
- * The handle must be released with BSL_Crypto_ReleaseKeyHandle() when it is done being used.
- */
-int BSL_Crypto_LoadKey(const uint8_t *secret, size_t secret_len, BSL_Crypto_KeyHandle_t *key_out);
-
-/** Release a key handle after it is done being used.
- *
- * @param[in] keyhandle key handle to release.
- * If the handle is null this does nothing.
- * @post If this is the last use of the handle (including the key registry) the key will be destroyed.
- */
-void BSL_Crypto_ReleaseKeyHandle(BSL_Crypto_KeyHandle_t keyhandle);
-
-/** Compare two keys in a time-invariant way.
- * This avoids side channel attacks which depend on comparison time.
- *
- * @param[in] hdl1 The first key handle.
- * @param[in] hdl2 The second key handle.
- * @return True if they compare equal.
- */
-bool BSL_Crypto_CompareKeys(BSL_Crypto_KeyHandle_t hdl1, BSL_Crypto_KeyHandle_t hdl2);
-
-/** Get pointers to an existing key, if present.
- *
- * @param keyid The key to search for.
- * @param[in, out] key_handle pointer to pointer for new key handle.
- * The handle must be released with BSL_Crypto_ReleaseKeyHandle() when it is done being used.
- * @return Zero if the key was present.
- */
-int BSL_Crypto_GetRegistryKey(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t *key_handle);
-
-/** Erase key entry from crypto library registry, if present.
- * @param[in] keyid key ID of key to remove.
- * @return Zero if the key was present.
- */
-int BSL_Crypto_RemoveRegistryKey(const BSL_Data_t *keyid);
-
-/**
- * Add a new key to the crypto key registry
- * @param[in] keyid key ID that crypto functions will use to access key
- * @param[out] handle Key handle to add to the registry.
- * Once the key is added it should be treated as read-only for thread-safety purposes.
- * When handle is output, the handle must be released with BSL_Crypto_ReleaseKeyHandle() when it is done being used.
- * @return Zero upon success.
- */
-int BSL_Crypto_AddRegistryKey(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t handle);
-
-/** Add a context-specific parameter to a known key.
- *
- * @param[in] handle The key ID to update.
- * @param[in] param_id The parameter to access.
- * If the parameter does not already exist it will be created.
- * @return Non-NULL pointer if successful.
- */
-BSL_IdValPair_t *BSL_Crypto_SetKeyParameter(BSL_Crypto_KeyHandle_t handle, int64_t param_id);
-
-/** Get key parameter for read-only access.
- * @overload
- */
-const BSL_IdValPair_t *BSL_Crypto_GetKeyParameter(BSL_Crypto_KeyHandle_t handle, int64_t param_id);
-
-/**
- * Retrieve statistics related to a crypto key
- * @param[in] handle The handle of a key in the crypto registry to retrieve the stats of.
- * @param[out] stats struct containing statistics related to the key id
- */
-int BSL_Crypto_GetKeyStatistics(BSL_Crypto_KeyHandle_t handle, BSL_Crypto_KeyStats_t *stats);
-
-///@} key registry
-
/** @name AES Key Wrap interface */
///@{
@@ -394,9 +271,8 @@ int BSL_Cipher_FinalizeSeq(BSL_Cipher_t *cipher_ctx, BSL_SeqWriter_t *writer);
/**
* De-initialize crypto context resources
* @param cipher_ctx pointer to context to deinitialize
- * @return 0 if successful
*/
-int BSL_Cipher_Deinit(BSL_Cipher_t *cipher_ctx);
+void BSL_Cipher_Deinit(BSL_Cipher_t *cipher_ctx);
///@} cipher
diff --git a/src/bsl/crypto/KeyStore.c b/src/bsl/crypto/KeyStore.c
new file mode 100644
index 00000000..00b790b4
--- /dev/null
+++ b/src/bsl/crypto/KeyStore.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2025-2026 The Johns Hopkins University Applied Physics
+ * Laboratory LLC.
+ *
+ * This file is part of the Bundle Protocol Security Library (BSL).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work was performed for the Jet Propulsion Laboratory, California
+ * Institute of Technology, sponsored by the United States Government under
+ * the prime contract 80NM0018D0004 between the Caltech and NASA under
+ * subcontract 1700763.
+ */
+
+/** @file
+ * @ingroup crypto
+ * Backend implementation of the crypto API using ::BSL_KeyStore_Descriptors_t callbacks.
+ */
+#include "KeyStore.h"
+
+#include "CryptoInterface.h"
+
+#include
+#include
+
+#define BSL_KeyStore_Descriptors_EMPTY \
+ { \
+ .new_key = NULL \
+ }
+
+/// Initialized to library default
+BSL_KeyStore_Descriptors_t BSL_KeyStore_State = BSL_KeyStore_Descriptors_EMPTY;
+
+int BSL_KeyStore_Init(BSL_KeyStore_Descriptors_t desc)
+{
+ // GCOV_EXCL_START
+ CHK_PRECONDITION(desc.new_key);
+ CHK_PRECONDITION(desc.acquire_key);
+ CHK_PRECONDITION(desc.release_key);
+ CHK_PRECONDITION(desc.find_key);
+ CHK_PRECONDITION(desc.set_keymat);
+ CHK_PRECONDITION(desc.get_keymat);
+ CHK_PRECONDITION(desc.get_parameter);
+ CHK_PRECONDITION(desc.update_stats);
+ CHK_PRECONDITION(desc.get_stats);
+ // GCOV_EXCL_STOP
+
+ BSL_KeyStore_State = desc;
+ return BSL_SUCCESS;
+}
+
+void BSL_KeyStore_Deinit(void)
+{
+ BSL_KeyStore_State = (BSL_KeyStore_Descriptors_t)BSL_KeyStore_Descriptors_EMPTY;
+}
+
+void BSL_Crypto_ReleaseKeyHandle(BSL_Crypto_KeyHandle_t keyhandle)
+{
+ ASSERT_PRECONDITION(BSL_KeyStore_State.release_key);
+ BSL_KeyStore_State.release_key(keyhandle);
+}
+
+bool BSL_Crypto_CompareKeys(BSL_Crypto_KeyHandle_t hdl1, BSL_Crypto_KeyHandle_t hdl2)
+{
+ ASSERT_PRECONDITION(BSL_KeyStore_State.get_keymat);
+ if (!hdl1 || !hdl2)
+ {
+ return false;
+ }
+
+ BSL_Data_t key1_view;
+ CHK_PRECONDITION(BSL_SUCCESS == BSL_KeyStore_State.get_keymat(hdl1, &key1_view));
+ BSL_Data_t key2_view;
+ CHK_PRECONDITION(BSL_SUCCESS == BSL_KeyStore_State.get_keymat(hdl2, &key2_view));
+
+ return BSL_Crypto_Compare(key1_view.ptr, key1_view.len, key2_view.ptr, key2_view.len);
+}
+
+int BSL_Crypto_GenKey(size_t key_length, BSL_Crypto_KeyHandle_t *key_out)
+{
+ CHK_ARG_NONNULL(key_out);
+ *key_out = NULL;
+ CHK_ARG_EXPR(key_length > 0);
+ int retval = BSL_SUCCESS;
+
+ BSL_Data_t keymat;
+ BSL_Data_InitBuffer(&keymat, key_length);
+ if (BSL_SUCCESS != BSL_Crypto_GenIV(&keymat)) // FIXME rename for clarity
+ {
+ BSL_Data_Deinit(&keymat);
+ return BSL_ERR_FAILURE;
+ }
+
+ retval = BSL_Crypto_LoadKey(keymat.ptr, keymat.len, key_out);
+ BSL_Data_Deinit(&keymat);
+ return retval;
+}
+
+int BSL_Crypto_LoadKey(const uint8_t *secret, size_t secret_len, BSL_Crypto_KeyHandle_t *key_out)
+{
+ ASSERT_PRECONDITION(BSL_KeyStore_State.new_key);
+ ASSERT_PRECONDITION(BSL_KeyStore_State.set_keymat);
+ CHK_ARG_NONNULL(key_out);
+ *key_out = NULL;
+ CHK_ARG_EXPR(secret_len > 0);
+
+ int res = BSL_KeyStore_State.new_key(key_out);
+ if (BSL_SUCCESS != res)
+ {
+ BSL_LOG_ERR("Failed to create new key");
+ return BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+
+ BSL_Data_t keymat = BSL_DATA_INIT_VIEW(secret, secret_len);
+
+ res = BSL_KeyStore_State.set_keymat(*key_out, &keymat);
+ if (BSL_SUCCESS != res)
+ {
+ BSL_LOG_ERR("Failed to set new key material");
+ return BSL_ERR_SECURITY_CONTEXT_CRYPTO_FAILED;
+ }
+
+ return BSL_SUCCESS;
+}
+
+const BSL_IdValPair_t *BSL_Crypto_GetKeyParameter(BSL_Crypto_KeyHandle_t handle, int64_t param_id)
+{
+ ASSERT_PRECONDITION(BSL_KeyStore_State.get_parameter);
+ return BSL_KeyStore_State.get_parameter(handle, param_id);
+}
+
+int BSL_Crypto_GetRegistryKey(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t *handle)
+{
+ CHK_ARG_NONNULL(keyid);
+ CHK_ARG_NONNULL(handle);
+ ASSERT_PRECONDITION(BSL_KeyStore_State.find_key);
+ return BSL_KeyStore_State.find_key(keyid, handle);
+}
+
+int BSL_Crypto_GetKeyStatistics(BSL_Crypto_KeyHandle_t handle, BSL_Crypto_KeyStats_t *stats)
+{
+ CHK_ARG_NONNULL(handle);
+ CHK_ARG_NONNULL(stats);
+ ASSERT_PRECONDITION(BSL_KeyStore_State.find_key);
+ return BSL_KeyStore_State.get_stats(handle, stats);
+}
diff --git a/src/bsl/crypto/KeyStore.h b/src/bsl/crypto/KeyStore.h
new file mode 100644
index 00000000..4d6ab9d4
--- /dev/null
+++ b/src/bsl/crypto/KeyStore.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2025-2026 The Johns Hopkins University Applied Physics
+ * Laboratory LLC.
+ *
+ * This file is part of the Bundle Protocol Security Library (BSL).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work was performed for the Jet Propulsion Laboratory, California
+ * Institute of Technology, sponsored by the United States Government under
+ * the prime contract 80NM0018D0004 between the Caltech and NASA under
+ * subcontract 1700763.
+ */
+/** @file
+ * @ingroup crypto
+ *
+ * There are two forms of managed crypto keys in this interface:
+ * 1. Identified keys persisted in a long-term, thread-safe registry.
+ * These keys have byte string names (which can contain UTF8 text) and can
+ * have additional parameters to restrict their use.
+ * 2. Anonymous ephemeral keys used for individual operations and then discarded.
+ * These keys do not have names and are typically key-wrapped or the result of a
+ * key derivation function (KDF).
+ */
+#ifndef BSL_CRYPTO_KEYSTORE_H_
+#define BSL_CRYPTO_KEYSTORE_H_
+
+#include "bsl/BPSecLib_Private.h" // TODO replace with Variant.h
+#include "bsl/front/Data.h"
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Opaque handle for key objects in the key store.
+ */
+typedef void *BSL_Crypto_KeyHandle_t;
+
+/// Indices of telemetry counters in ::BSL_Crypto_KeyStats_t
+typedef enum
+{
+ /// Incremented once per use.
+ BSL_CRYPTO_KEYSTATS_TIMES_USED = 0,
+ /** Incremented for each byte processed.
+ * The specific meaning depends on the algorithm associated with the key.
+ */
+ BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED,
+ /// Not a real index, used to size arrays
+ BSL_CRYPTO_KEYSTATS_MAX_INDEX
+} BSL_Crypto_KeyStats_CounterIndex_t;
+
+/**
+ * Structure containing statistics for individual keys
+ */
+typedef struct
+{
+ /// Counters for each ::BSL_Crypto_KeyStats_CounterIndex_t value
+ uint64_t stats[BSL_CRYPTO_KEYSTATS_MAX_INDEX];
+} BSL_Crypto_KeyStats_t;
+
+/** The set of callback function pointers which actually implement
+ * a key store.
+ * When registering, all of the functions need to be non-NULL.
+ */
+typedef struct
+{
+ /** Construct a new default empty key, outside of a key store.
+ * @param[out] key_out The non-null pointer to set.
+ * The handle must be released with #release_key when it is done being used.
+ * @return BSL_SUCCESS if successful.
+ */
+ int (*new_key)(BSL_Crypto_KeyHandle_t *key_out);
+
+ /** Acquire a new copy of a handle.
+ * @param[in] handle The handle to acquire.
+ * If NULL handle this is a do-nothing.
+ * @return The copy, or NULL if failure.
+ */
+ BSL_Crypto_KeyHandle_t (*acquire_key)(BSL_Crypto_KeyHandle_t handle);
+
+ /** Release the use of a handle.
+ * When all active handles are released the key should be destroyed.
+ * @param[in] handle The handle to release.
+ * If NULL handle this is a do-nothing.
+ */
+ void (*release_key)(BSL_Crypto_KeyHandle_t handle);
+
+ /** Find an identified key in the key store.
+ * Some keys are ephemeral and not registered in the store.
+ * @param[in] keyid A unique-to-the-store identifier for a key.
+ * @param[out] handle If found, will be set non-null handle.
+ * @return BSL_SUCCESS if found.
+ */
+ int (*find_key)(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t *handle);
+
+ /** Set the (plaintext) key material for a key.
+ * @param[in] handle The handle to the key.
+ * @param[in] data Non-null pointer to key bytes, which will be copied.
+ * @return BSL_SUCCESS if valid.
+ */
+ int (*set_keymat)(BSL_Crypto_KeyHandle_t handle, const BSL_Data_t *data);
+
+ /** Get the (plaintext) key material for a key.
+ * @param[in] handle The handle to the key.
+ * @param[out] data Non-null pointer to output struct, which will be set
+ * to a view on the data.
+ * @return BSL_SUCCESS if valid.
+ */
+ int (*get_keymat)(BSL_Crypto_KeyHandle_t handle, BSL_Data_t *view);
+
+ /** Get a specific parameter which may be attached to a key.
+ * @param[in] handle The handle to the key.
+ * @param param_id The unique identifier for the parameter.
+ * The available parameters will be determined by the key source
+ * (e.g. COSE_Key parameters).
+ * @return A non-null pointer if the parameter exists.
+ */
+ const BSL_IdValPair_t *(*get_parameter)(BSL_Crypto_KeyHandle_t handle, int64_t param_id);
+
+ /** Update telemetry counters for a key.
+ */
+ void (*update_stats)(BSL_Crypto_KeyHandle_t handle, uint64_t use, uint64_t bytes);
+
+ /** Get full counters for a key.
+ */
+ int (*get_stats)(BSL_Crypto_KeyHandle_t handle, BSL_Crypto_KeyStats_t *stats);
+
+} BSL_KeyStore_Descriptors_t;
+
+/** Initialize the key store subsystem.
+ * This must be called once per process.
+ *
+ * @warning This function is not thread safe and should be used before any
+ * ::BSL_LibCtx_s is initialized or other BSL interfaces used.
+ *
+ * @param desc The descriptor to use for future key store access.
+ * @return Zero if successful, negative on error.
+ */
+int BSL_KeyStore_Init(BSL_KeyStore_Descriptors_t desc);
+
+/** Deinitialize the key store subsystem.
+ * This should be called at the end of the process.
+ *
+ * @warning This function is not thread safe and should be used after any
+ * ::BSL_LibCtx_s is deinitialized.
+ */
+void BSL_KeyStore_Deinit(void);
+
+/**
+ * Generate a new cryptographic key.
+ * @param[in] key_length length of new key in bytes.
+ * @param[out] key_out pointer to pointer for new key handle.
+ * The handle must be released with BSL_Crypto_ReleaseKeyHandle() when it is done being used.
+ */
+int BSL_Crypto_GenKey(size_t key_length, BSL_Crypto_KeyHandle_t *key_out);
+
+/**
+ * Load a new cryptographic key.
+ * @param[in] secret raw symmetric key.
+ * @param secret_len length of @c secret data.
+ * @param[out] key_out pointer to pointer for new key handle.
+ * The handle must be released with BSL_Crypto_ReleaseKeyHandle() when it is done being used.
+ */
+int BSL_Crypto_LoadKey(const uint8_t *secret, size_t secret_len, BSL_Crypto_KeyHandle_t *key_out);
+
+/** Release a key handle after it is done being used.
+ *
+ * @param[in] keyhandle key handle to release.
+ * If the handle is null this does nothing.
+ * @post If this is the last use of the handle (including the key registry) the key will be destroyed.
+ */
+void BSL_Crypto_ReleaseKeyHandle(BSL_Crypto_KeyHandle_t keyhandle);
+
+/** Compare two keys in a time-invariant way.
+ * This avoids side channel attacks which depend on comparison time.
+ *
+ * @param[in] hdl1 The first key handle.
+ * @param[in] hdl2 The second key handle.
+ * @return True if they compare equal.
+ */
+bool BSL_Crypto_CompareKeys(BSL_Crypto_KeyHandle_t hdl1, BSL_Crypto_KeyHandle_t hdl2);
+
+/** Get pointers to an existing key, if present.
+ *
+ * @param keyid The key to search for.
+ * @param[in, out] handle pointer to pointer for new key handle.
+ * The handle must be released with BSL_Crypto_ReleaseKeyHandle() when it is done being used.
+ * @return Zero if the key was present.
+ */
+int BSL_Crypto_GetRegistryKey(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t *handle);
+
+/** Get key parameter for read-only access.
+ * @param[in] handle The handle to the key.
+ * @param param_id The unique identifier for the parameter.
+ * The available parameters will be determined by the key source
+ * (e.g. COSE_Key parameters).
+ * @return A non-null pointer if the parameter exists.
+ */
+const BSL_IdValPair_t *BSL_Crypto_GetKeyParameter(BSL_Crypto_KeyHandle_t handle, int64_t param_id);
+
+/**
+ * Retrieve statistics related to a crypto key
+ * @param[in] handle The handle of a key in the crypto registry to retrieve the stats of.
+ * @param[out] stats struct containing statistics related to the key id
+ */
+int BSL_Crypto_GetKeyStatistics(BSL_Crypto_KeyHandle_t handle, BSL_Crypto_KeyStats_t *stats);
+
+#ifdef __cplusplus
+} // extern C
+#endif
+
+#endif /* BSL_CRYPTO_KEYSTORE_H_ */
diff --git a/src/bsl/mock_bpa/KeyStore.c b/src/bsl/mock_bpa/KeyStore.c
new file mode 100644
index 00000000..1ad3abbf
--- /dev/null
+++ b/src/bsl/mock_bpa/KeyStore.c
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 2025-2026 The Johns Hopkins University Applied Physics
+ * Laboratory LLC.
+ *
+ * This file is part of the Bundle Protocol Security Library (BSL).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work was performed for the Jet Propulsion Laboratory, California
+ * Institute of Technology, sponsored by the United States Government under
+ * the prime contract 80NM0018D0004 between the Caltech and NASA under
+ * subcontract 1700763.
+ */
+
+/** @file
+ * @ingroup mock_bpa
+ * Provider of a key store via the crypto API ::BSL_KeyStore_Descriptors_t.
+ */
+
+#include "KeyStore.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+/**
+ * Struct to hold private key information
+ */
+typedef struct BSL_CryptoKey_s
+{
+ /// Pointer to raw key information
+ BSL_Data_t raw;
+ /// Additional parameter dictionary
+ BSLB_IdValPairPtrMap_t params;
+ /// Statistics related to this key
+ BSL_Crypto_KeyStats_t stats;
+ /// Mutex for #stats
+ pthread_mutex_t stats_mutex;
+} BSL_CryptoKey_t;
+
+static void BSL_CryptoKey_Init(BSL_CryptoKey_t *key)
+{
+ ASSERT_ARG_NONNULL(key);
+
+ BSL_Data_Init(&(key->raw));
+ BSLB_IdValPairPtrMap_init(key->params);
+
+ for (uint64_t i = 0; i < BSL_CRYPTO_KEYSTATS_MAX_INDEX; i++)
+ {
+ key->stats.stats[i] = 0;
+ }
+ pthread_mutex_init(&key->stats_mutex, NULL);
+}
+
+static void BSL_CryptoKey_Deinit(BSL_CryptoKey_t *key)
+{
+ ASSERT_ARG_NONNULL(key);
+
+ BSL_Data_Deinit(&(key->raw));
+ BSLB_IdValPairPtrMap_clear(key->params);
+
+ pthread_mutex_destroy(&key->stats_mutex);
+ for (uint64_t i = 0; i < BSL_CRYPTO_KEYSTATS_MAX_INDEX; i++)
+ {
+ key->stats.stats[i] = 0;
+ }
+}
+
+/** M*LIB OPLIST for ::BSL_CryptoKey_t
+ */
+#define M_OPL_BSL_CryptoKey_t() \
+ M_OPEXTEND(M_POD_OPLIST, INIT(API_2(BSL_CryptoKey_Init)), INIT_SET(0), SET(0), CLEAR(API_2(BSL_CryptoKey_Deinit)))
+
+/** @struct BSL_CryptoKeyPtr_t
+ * Thread-safe shared pointer to memory-stable ::BSL_CryptoKey_t struct.
+ */
+/** @struct BSL_CryptoKeyDict_t
+ * Stable dict of crypto keys (key: key ID | value: BSL_CryptoKeyPtr_t)
+ */
+/// @cond Doxygen_Suppress
+// NOLINTBEGIN
+// GCOV_EXCL_START
+M_SHARED_PTR_DEF(BSL_CryptoKeyPtr, BSL_CryptoKey_t, M_OPL_BSL_CryptoKey_t())
+#define M_OPL_BSL_CryptoKeyPtr() M_SHARED_PTR_OPLIST(BSL_CryptoKeyPtr, M_OPL_BSL_CryptoKey_t())
+M_DICT_DEF2(BSL_CryptoKeyDict, m_bstring_t, M_BSTRING_OPLIST, BSL_CryptoKeyPtr_t *, M_OPL_BSL_CryptoKeyPtr())
+// GCOV_EXCL_STOP
+// NOLINTEND
+/// @endcond
+
+/// Crypto key registry
+static BSL_CryptoKeyDict_t StaticKeyRegistry;
+static pthread_mutex_t StaticCryptoMutex = PTHREAD_MUTEX_INITIALIZER;
+
+void MockBPA_KeyStore_Init(void)
+{
+ pthread_mutex_lock(&StaticCryptoMutex);
+ BSL_CryptoKeyDict_init(StaticKeyRegistry);
+ pthread_mutex_unlock(&StaticCryptoMutex);
+
+ BSL_KeyStore_Init(MockBPA_KeyStore_Descriptors());
+}
+
+void MockBPA_KeyStore_Deinit(void)
+{
+ BSL_KeyStore_Deinit();
+
+ pthread_mutex_lock(&StaticCryptoMutex);
+ BSL_CryptoKeyDict_clear(StaticKeyRegistry);
+ pthread_mutex_unlock(&StaticCryptoMutex);
+}
+
+int MockBPA_KeyStore_AddKey(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t handle)
+{
+ ASSERT_ARG_NONNULL(keyid);
+ CHK_ARG_NONNULL(handle);
+
+ BSL_CryptoKeyPtr_t *key_ptr = handle;
+
+ m_bstring_t keyid_str;
+ m_bstring_init(keyid_str);
+ m_bstring_push_back_bytes(keyid_str, keyid->len, keyid->ptr);
+
+ pthread_mutex_lock(&StaticCryptoMutex);
+ BSL_CryptoKeyDict_set_at(StaticKeyRegistry, keyid_str, key_ptr);
+ pthread_mutex_unlock(&StaticCryptoMutex);
+
+ m_bstring_clear(keyid_str);
+ return 0;
+}
+
+int MockBPA_KeyStore_RemoveKey(const BSL_Data_t *keyid)
+{
+ ASSERT_ARG_NONNULL(keyid);
+
+ m_bstring_t keyid_str;
+ m_bstring_init(keyid_str);
+ m_bstring_push_back_bytes(keyid_str, keyid->len, keyid->ptr);
+
+ pthread_mutex_lock(&StaticCryptoMutex);
+ int res = BSL_CryptoKeyDict_erase(StaticKeyRegistry, keyid_str);
+ pthread_mutex_unlock(&StaticCryptoMutex);
+
+ m_bstring_clear(keyid_str);
+ return res ? BSL_SUCCESS : -1;
+}
+
+BSL_IdValPair_t *MockBPA_KeyStore_SetKeyParameter(BSL_Crypto_KeyHandle_t handle, int64_t param_id)
+{
+ ASSERT_ARG_NONNULL(handle);
+ BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(handle);
+
+ BSL_IdValPair_t *retval = NULL;
+ if (key)
+ {
+ BSLB_IdValPairPtr_t *param_ptr;
+
+ BSLB_IdValPairPtr_t **found = BSLB_IdValPairPtrMap_get(key->params, param_id);
+ if (found)
+ {
+ param_ptr = *found;
+ retval = BSLB_IdValPairPtr_ref(param_ptr);
+ }
+ else
+ {
+ param_ptr = BSLB_IdValPairPtr_new();
+ BSLB_IdValPairPtrMap_set_at(key->params, param_id, param_ptr);
+ retval = BSLB_IdValPairPtr_ref(param_ptr);
+ // map keeps a reference so this is safe
+ BSLB_IdValPairPtr_release(param_ptr);
+ }
+ }
+ return retval;
+}
+
+static int MockBPA_KeyStore_FindKey(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t *handle)
+{
+ CHK_ARG_NONNULL(keyid);
+ CHK_ARG_NONNULL(handle);
+
+ m_bstring_t keyid_str;
+ m_bstring_init(keyid_str);
+ m_bstring_push_back_bytes(keyid_str, keyid->len, keyid->ptr);
+
+ int retval = BSL_SUCCESS;
+ pthread_mutex_lock(&StaticCryptoMutex);
+ BSL_CryptoKeyPtr_t **found = BSL_CryptoKeyDict_get(StaticKeyRegistry, keyid_str);
+ if (!found)
+ {
+ *handle = NULL;
+ retval = BSL_ERR_NOT_FOUND;
+ }
+ else
+ {
+ *handle = BSL_CryptoKeyPtr_acquire(*found);
+ }
+ pthread_mutex_unlock(&StaticCryptoMutex);
+
+ m_bstring_clear(keyid_str);
+ return retval;
+}
+
+static const BSL_IdValPair_t *MockBPA_KeyStore_GetKeyParameter(BSL_Crypto_KeyHandle_t handle, int64_t param_id)
+{
+ if (!handle)
+ {
+ return NULL;
+ }
+ BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(handle);
+
+ const BSL_IdValPair_t *retval = NULL;
+ if (key)
+ {
+ BSLB_IdValPairPtr_t **found = BSLB_IdValPairPtrMap_get(key->params, param_id);
+ if (found)
+ {
+ retval = BSLB_IdValPairPtr_ref(*found);
+ }
+ }
+ return retval;
+}
+
+static int MockBPA_KeyStore_New(BSL_Crypto_KeyHandle_t *handle)
+{
+ ASSERT_ARG_NONNULL(handle);
+ *handle = BSL_CryptoKeyPtr_new();
+ return BSL_SUCCESS;
+}
+
+static int MockBPA_KeyStore_SetKeymat(BSL_Crypto_KeyHandle_t handle, const BSL_Data_t *data)
+{
+ ASSERT_ARG_NONNULL(handle);
+ ASSERT_ARG_NONNULL(data);
+ BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(handle);
+ return BSL_Data_CopyFrom(&key->raw, data->len, data->ptr);
+}
+
+static int MockBPA_KeyStore_GetKeymat(BSL_Crypto_KeyHandle_t handle, BSL_Data_t *data)
+{
+ ASSERT_ARG_NONNULL(handle);
+ ASSERT_ARG_NONNULL(data);
+ const BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(handle);
+ BSL_Data_InitView(data, key->raw.len, key->raw.ptr);
+ return BSL_SUCCESS;
+}
+
+static BSL_Crypto_KeyHandle_t MockBPA_KeyStore_Acquire(BSL_Crypto_KeyHandle_t handle)
+{
+ if (!handle)
+ {
+ return NULL;
+ }
+
+ BSL_CryptoKeyPtr_t *ptr = handle;
+ return BSL_CryptoKeyPtr_acquire(ptr);
+}
+
+static void MockBPA_KeyStore_Release(BSL_Crypto_KeyHandle_t handle)
+{
+ if (!handle)
+ {
+ return;
+ }
+
+ BSL_CryptoKeyPtr_t *ptr = handle;
+ BSL_CryptoKeyPtr_release(ptr);
+}
+
+static void MockBPA_KeyStore_UpdateStats(BSL_Crypto_KeyHandle_t handle, uint64_t use, uint64_t bytes)
+{
+ if (!handle)
+ {
+ return;
+ }
+ BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(handle);
+
+ pthread_mutex_lock(&key->stats_mutex);
+ key->stats.stats[BSL_CRYPTO_KEYSTATS_TIMES_USED] += use;
+ key->stats.stats[BSL_CRYPTO_KEYSTATS_BYTES_PROCESSED] += bytes;
+ pthread_mutex_unlock(&key->stats_mutex);
+}
+
+static int MockBPA_KeyStore_GetStats(BSL_Crypto_KeyHandle_t handle, BSL_Crypto_KeyStats_t *stats)
+{
+ CHK_ARG_NONNULL(handle);
+ CHK_ARG_NONNULL(stats);
+
+ BSL_CryptoKey_t *key = BSL_CryptoKeyPtr_ref(handle);
+
+ pthread_mutex_lock(&key->stats_mutex);
+ // copy as POD
+ *stats = key->stats;
+ pthread_mutex_unlock(&key->stats_mutex);
+
+ return BSL_SUCCESS;
+}
+
+BSL_KeyStore_Descriptors_t MockBPA_KeyStore_Descriptors(void)
+{
+ BSL_KeyStore_Descriptors_t desc = {
+ .new_key = &MockBPA_KeyStore_New,
+ .set_keymat = &MockBPA_KeyStore_SetKeymat,
+ .get_keymat = &MockBPA_KeyStore_GetKeymat,
+ .acquire_key = &MockBPA_KeyStore_Acquire,
+ .release_key = &MockBPA_KeyStore_Release,
+ .find_key = &MockBPA_KeyStore_FindKey,
+ .get_parameter = &MockBPA_KeyStore_GetKeyParameter,
+ .update_stats = &MockBPA_KeyStore_UpdateStats,
+ .get_stats = &MockBPA_KeyStore_GetStats,
+ };
+ return desc;
+}
+
+int MockBPA_KeyStore_LoadJwk(int fd)
+{
+ int retval = BSL_SUCCESS;
+
+ json_error_t err;
+
+ json_t *root = json_loadfd(fd, 0, &err);
+ if (!root)
+ {
+ BSL_LOG_ERR("JSON error: line %d: %s", err.line, err.text);
+ json_decref(root);
+ return 1;
+ }
+
+ const json_t *keys = json_object_get(root, "keys");
+ if (!keys || !json_is_array(keys))
+ {
+ BSL_LOG_ERR("Missing \"keys\" ");
+ json_decref(root);
+ return 1;
+ }
+
+ const size_t n = json_array_size(keys);
+ BSL_LOG_INFO("Found %zu key objects", n);
+
+ for (size_t i = 0; i < n; ++i)
+ {
+ const json_t *key_obj = json_array_get(keys, i);
+ if (!json_is_object(key_obj))
+ {
+ continue;
+ }
+
+ const json_t *kty = json_object_get(key_obj, "kty");
+ if (!kty)
+ {
+ BSL_LOG_ERR("Missing \"kty\" ");
+ continue;
+ }
+
+ if (0 != strcmp("oct", json_string_value(kty)))
+ {
+ BSL_LOG_ERR("Not a symmetric key set");
+ continue;
+ }
+
+ const json_t *kid = json_object_get(key_obj, "kid");
+ if (!kid || !json_is_string(kid))
+ {
+ BSL_LOG_ERR("Missing \"kid\" ");
+ continue;
+ }
+ const char *kid_str = json_string_value(kid);
+ BSL_LOG_DEBUG("kid: %s", kid_str);
+
+ const json_t *k = json_object_get(key_obj, "k");
+ if (!k || !json_is_string(k))
+ {
+ BSL_LOG_ERR("Missing \"k\" ");
+ continue;
+ }
+
+ BSL_Data_t k_data;
+ BSL_Data_Init(&k_data);
+ retval = BSL_TextUtil_Base64_Decode(&k_data, json_string_value(k), json_string_length(k));
+
+ if (!retval)
+ {
+ BSL_Data_t kid_view = BSL_DATA_INIT_VIEW_CSTR(kid_str);
+
+ BSL_Crypto_KeyHandle_t keyhandle;
+ BSL_Crypto_LoadKey(k_data.ptr, k_data.len, &keyhandle);
+ retval = MockBPA_KeyStore_AddKey(&kid_view, keyhandle);
+ BSL_Crypto_ReleaseKeyHandle(keyhandle);
+ }
+ BSL_Data_Deinit(&k_data);
+
+ if (retval)
+ {
+ BSL_LOG_ERR("JKW register failure");
+ break;
+ }
+ }
+
+ json_decref(root);
+ return retval;
+}
+
+/** Decode a @c COSE_KeySet array.
+ * Matches ::BSL_CBOR_Decode_f signature.
+ */
+static int mock_bpa_key_registry_cosekey_decode(QCBORDecodeContext *dec, const void *obj _U_)
+{
+ int retval = BSL_SUCCESS;
+
+ QCBORItem item;
+ QCBORDecode_EnterArray(dec, NULL);
+
+ // array-of-key-maps
+ while (QCBOR_SUCCESS == QCBORDecode_PeekNext(dec, &item))
+ {
+ bool has_kty = false;
+ int64_t kty = 0;
+ bool has_alg = false;
+ int64_t alg = 0;
+ UsefulBufC kid = NULLUsefulBufC;
+ UsefulBufC baseiv = NULLUsefulBufC;
+ UsefulBufC k_data = NULLUsefulBufC;
+
+ QCBORDecode_EnterArray(dec, NULL); // using QCBOR_DECODE_MODE_MAP_AS_ARRAY
+
+ while (QCBOR_SUCCESS == QCBORDecode_PeekNext(dec, &item))
+ {
+ int64_t label;
+ QCBORDecode_GetInt64(dec, &label);
+ if (QCBOR_SUCCESS != QCBORDecode_GetError(dec))
+ {
+ BSL_LOG_ERR("Unable to get key label");
+ break;
+ }
+ BSL_LOG_DEBUG("got label %" PRId64, label);
+
+ switch (label)
+ {
+ case BSLX_COSEMSG_KEY_PARAM_KTY:
+ QCBORDecode_GetInt64(dec, &kty);
+ has_kty = true;
+ break;
+ case BSLX_COSEMSG_KEY_PARAM_KID:
+ QCBORDecode_GetByteString(dec, &kid);
+ break;
+ case BSLX_COSEMSG_KEY_PARAM_ALG:
+ QCBORDecode_GetInt64(dec, &alg);
+ has_alg = true;
+ break;
+ case BSLX_COSEMSG_KEY_PARAM_BASEIV:
+ QCBORDecode_GetByteString(dec, &baseiv);
+ break;
+ case -1:
+ if (has_kty && (kty == 4))
+ {
+ QCBORDecode_GetByteString(dec, &k_data);
+ }
+ break;
+ default:
+ // consume but ignore
+ QCBORDecode_VGetNextConsume(dec, &item);
+ break;
+ }
+ if (QCBOR_SUCCESS != QCBORDecode_GetError(dec))
+ {
+ BSL_LOG_ERR("Unable to get key value");
+ break;
+ }
+
+ if (has_kty && (kty != 4))
+ {
+ BSL_LOG_WARNING("Ignoring non-symmetric key type %" PRId64, kty);
+ break;
+ }
+ }
+ QCBORDecode_ExitArray(dec);
+
+ // If valid enough to store
+ if (has_kty && kid.ptr && k_data.ptr)
+ {
+ BSL_Data_t kid_view;
+ BSL_Data_InitView(&kid_view, kid.len, (BSL_DataPtr_t)kid.ptr);
+
+ BSL_Crypto_KeyHandle_t keyhandle;
+ BSL_Crypto_LoadKey(k_data.ptr, k_data.len, &keyhandle);
+
+ if (has_alg)
+ {
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSLX_COSEMSG_KEY_PARAM_ALG, alg);
+ }
+ else
+ {
+ BSL_LOG_WARNING("COSE Key without an alg parameter");
+ }
+
+ if (baseiv.len > 0)
+ {
+ BSL_Data_t view;
+ BSL_Data_InitView(&view, baseiv.len, (BSL_DataPtr_t)baseiv.ptr);
+ BSL_IdValPair_SetBytestr(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_BASEIV),
+ BSLX_COSEMSG_KEY_PARAM_BASEIV, view);
+ }
+
+ retval = MockBPA_KeyStore_AddKey(&kid_view, keyhandle);
+ BSL_Crypto_ReleaseKeyHandle(keyhandle);
+ BSL_LOG_DEBUG("Adding key result %d", retval);
+ if (BSL_SUCCESS != retval)
+ {
+ BSL_LOG_ERR("Unable to store key");
+ break;
+ }
+ }
+ }
+ QCBORDecode_ExitArray(dec);
+ return retval;
+}
+
+int MockBPA_KeyStore_LoadCoseKeySet(int infd)
+{
+ struct stat sb;
+ if ((fstat(infd, &sb) < 0) || (sb.st_size == 0))
+ {
+ BSL_LOG_ERR("Error getting file size");
+ close(infd);
+ return BSL_ERR_DECODING;
+ }
+
+ void *data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, infd, 0);
+ if (!data)
+ {
+ BSL_LOG_ERR("Error in mmap");
+ close(infd);
+ return BSL_ERR_DECODING;
+ }
+
+ BSL_Data_t view;
+ BSL_Data_InitView(&view, sb.st_size, (BSL_DataPtr_t)data);
+
+ int retval = BSL_CBOR_Decode(&view, &mock_bpa_key_registry_cosekey_decode, NULL);
+
+ if (munmap(data, sb.st_size) < 0)
+ {
+ BSL_LOG_ERR("Error in munmap");
+ }
+ close(infd);
+ return retval;
+}
+
+int MockBPA_KeyStore_LoadFile(const char *file_path)
+{
+ int retval = BSL_SUCCESS;
+
+ int infd = open(file_path, O_RDONLY);
+ if (infd < 0)
+ {
+ BSL_LOG_ERR("Failed to open input file %s", file_path);
+ return BSL_ERR_DECODING;
+ }
+
+ BSL_LOG_INFO("Reading keys from %s", file_path);
+ m_string_t path;
+ m_string_init_set_cstr(path, file_path);
+ bool is_json = m_string_end_with_str_p(path, ".json");
+ bool is_cbor = m_string_end_with_str_p(path, ".cbor");
+ m_string_clear(path);
+
+ if (is_json)
+ {
+ retval = MockBPA_KeyStore_LoadJwk(infd);
+ }
+ else if (is_cbor)
+ {
+ retval = MockBPA_KeyStore_LoadCoseKeySet(infd);
+ }
+ else
+ {
+ BSL_LOG_ERR("Unhandled key file extension for %s", file_path);
+ retval = BSL_ERR_ARG_INVALID;
+ }
+
+ return retval;
+}
diff --git a/src/bsl/mock_bpa/KeyStore.h b/src/bsl/mock_bpa/KeyStore.h
new file mode 100644
index 00000000..f25a3c0e
--- /dev/null
+++ b/src/bsl/mock_bpa/KeyStore.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2025-2026 The Johns Hopkins University Applied Physics
+ * Laboratory LLC.
+ *
+ * This file is part of the Bundle Protocol Security Library (BSL).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work was performed for the Jet Propulsion Laboratory, California
+ * Institute of Technology, sponsored by the United States Government under
+ * the prime contract 80NM0018D0004 between the Caltech and NASA under
+ * subcontract 1700763.
+ */
+
+/** @file
+ * @ingroup mock_bpa
+ * Declaration of functions to load and manipulate the Mock BPA key store
+ * separate from the API used by the crypto library.
+ */
+
+#ifndef BSL_MOCKBPA_KEYSTORE_H_
+#define BSL_MOCKBPA_KEYSTORE_H_
+
+#include
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Get key store descriptors for the process.
+ *
+ * @return Populated descriptor struct.
+ */
+BSL_KeyStore_Descriptors_t MockBPA_KeyStore_Descriptors(void);
+
+/** Initialize the key storage and register it with BSL_KeyStore_Init().
+ */
+void MockBPA_KeyStore_Init(void);
+
+/** De-register with BSL_KeyStore_Deinit() and clear all key storage.
+ */
+void MockBPA_KeyStore_Deinit(void);
+
+/** Erase key entry from crypto library registry, if present.
+ * @param[in] keyid key ID of key to remove.
+ * @return Zero if the key was present.
+ */
+int MockBPA_KeyStore_RemoveKey(const BSL_Data_t *keyid);
+
+/**
+ * Add a new key to the crypto key registry
+ * @param[in] keyid key ID that crypto functions will use to access key
+ * @param[out] handle Key handle to add to the registry.
+ * Once the key is added it should be treated as read-only for thread-safety purposes.
+ * When handle is output, the handle must be released with BSL_Crypto_ReleaseKeyHandle() when it is done being used.
+ * @return Zero upon success.
+ */
+int MockBPA_KeyStore_AddKey(const BSL_Data_t *keyid, BSL_Crypto_KeyHandle_t handle);
+
+/** Add a context-specific parameter to a known key.
+ *
+ * @param[in] handle The key ID to update.
+ * @param[in] param_id The parameter to access.
+ * If the parameter does not already exist it will be created.
+ * @return Non-NULL pointer if successful.
+ */
+BSL_IdValPair_t *MockBPA_KeyStore_SetKeyParameter(BSL_Crypto_KeyHandle_t handle, int64_t param_id);
+
+/** @brief Initialize keys
+ * @param[in] file_path path to JSON file with JWK Set or CBOR file with @c COSE_KeySet
+ * @return 0 if successful.
+ */
+int MockBPA_KeyStore_LoadFile(const char *file_path);
+
+/** @warning Exposed only for testing.
+ * @param infd The file descriptor to read from.
+ */
+int MockBPA_KeyStore_LoadJwk(int infd);
+
+/** @warning Exposed only for testing.
+ * @param infd The file descriptor to read from.
+ */
+int MockBPA_KeyStore_LoadCoseKeySet(int infd);
+
+#ifdef __cplusplus
+} // extern C
+#endif
+
+#endif /* BSL_MOCKBPA_KEYSTORE_H_ */
diff --git a/src/bsl/mock_bpa/MockBPA.h b/src/bsl/mock_bpa/MockBPA.h
index 25abad36..fe8b2ae4 100644
--- a/src/bsl/mock_bpa/MockBPA.h
+++ b/src/bsl/mock_bpa/MockBPA.h
@@ -27,6 +27,7 @@
#include "decode.h"
#include "eidpat.h"
#include "encode.h"
+#include "KeyStore.h"
#include "log.h"
#endif //_BSL_MockBPA_MockBPA_H_
diff --git a/src/bsl/mock_bpa/agent.c b/src/bsl/mock_bpa/agent.c
index 4b59f6a1..ba5771c4 100644
--- a/src/bsl/mock_bpa/agent.c
+++ b/src/bsl/mock_bpa/agent.c
@@ -21,8 +21,9 @@
*/
/** @file
- * Definitions for Agent initialization.
* @ingroup mock_bpa
+ * Definitions for Agent initialization and
+ * provider of host functions via the API ::BSL_HostDescriptors_t.
*/
#include "agent.h"
diff --git a/src/bsl/mock_bpa/agent.h b/src/bsl/mock_bpa/agent.h
index e537a0af..bb7bc296 100644
--- a/src/bsl/mock_bpa/agent.h
+++ b/src/bsl/mock_bpa/agent.h
@@ -144,9 +144,10 @@ typedef struct MockBPA_Agent_s
} MockBPA_Agent_t;
-/** Get host descriptors without a specific agent.
+/** Get host descriptors for a specific agent.
*
* @param[in] agent The agent to associate as user data.
+ * @return Populated descriptor struct.
*/
BSL_HostDescriptors_t MockBPA_Agent_Descriptors(MockBPA_Agent_t *agent);
diff --git a/src/bsl/mock_bpa/key_registry.c b/src/bsl/mock_bpa/key_registry.c
deleted file mode 100644
index ba5a33c9..00000000
--- a/src/bsl/mock_bpa/key_registry.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (c) 2025-2026 The Johns Hopkins University Applied Physics
- * Laboratory LLC.
- *
- * This file is part of the Bundle Protocol Security Library (BSL).
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * This work was performed for the Jet Propulsion Laboratory, California
- * Institute of Technology, sponsored by the United States Government under
- * the prime contract 80NM0018D0004 between the Caltech and NASA under
- * subcontract 1700763.
- */
-
-/** @file
- * @ingroup mock_bpa
- */
-
-#include "key_registry.h"
-
-#include "bsl/front/TextUtil.h"
-#include "bsl/dynamic/CBOR.h"
-#include "bsl/cose_sc/CoseMsg.h"
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-int mock_bpa_key_registry_init_jwk(int fd)
-{
- int retval = BSL_SUCCESS;
-
- json_error_t err;
-
- json_t *root = json_loadfd(fd, 0, &err);
- if (!root)
- {
- BSL_LOG_ERR("JSON error: line %d: %s", err.line, err.text);
- json_decref(root);
- return 1;
- }
-
- const json_t *keys = json_object_get(root, "keys");
- if (!keys || !json_is_array(keys))
- {
- BSL_LOG_ERR("Missing \"keys\" ");
- json_decref(root);
- return 1;
- }
-
- const size_t n = json_array_size(keys);
- BSL_LOG_INFO("Found %zu key objects", n);
-
- for (size_t i = 0; i < n; ++i)
- {
- const json_t *key_obj = json_array_get(keys, i);
- if (!json_is_object(key_obj))
- {
- continue;
- }
-
- const json_t *kty = json_object_get(key_obj, "kty");
- if (!kty)
- {
- BSL_LOG_ERR("Missing \"kty\" ");
- continue;
- }
-
- if (0 != strcmp("oct", json_string_value(kty)))
- {
- BSL_LOG_ERR("Not a symmetric key set");
- continue;
- }
-
- const json_t *kid = json_object_get(key_obj, "kid");
- if (!kid || !json_is_string(kid))
- {
- BSL_LOG_ERR("Missing \"kid\" ");
- continue;
- }
- const char *kid_str = json_string_value(kid);
- BSL_LOG_DEBUG("kid: %s", kid_str);
-
- const json_t *k = json_object_get(key_obj, "k");
- if (!k || !json_is_string(k))
- {
- BSL_LOG_ERR("Missing \"k\" ");
- continue;
- }
-
- BSL_Data_t k_data;
- BSL_Data_Init(&k_data);
- retval = BSL_TextUtil_Base64_Decode(&k_data, json_string_value(k), json_string_length(k));
-
- if (!retval)
- {
- BSL_Data_t kid_view = BSL_DATA_INIT_VIEW_CSTR(kid_str);
-
- BSL_Crypto_KeyHandle_t keyhandle;
- BSL_Crypto_LoadKey(k_data.ptr, k_data.len, &keyhandle);
- retval = BSL_Crypto_AddRegistryKey(&kid_view, keyhandle);
- BSL_Crypto_ReleaseKeyHandle(keyhandle);
- }
- BSL_Data_Deinit(&k_data);
-
- if (retval)
- {
- BSL_LOG_ERR("JKW register failure");
- break;
- }
- }
-
- json_decref(root);
- return retval;
-}
-
-/** Decode a @c COSE_KeySet array.
- * Matches ::BSL_CBOR_Decode_f signature.
- */
-static int mock_bpa_key_registry_cosekey_decode(QCBORDecodeContext *dec, const void *obj _U_)
-{
- int retval = BSL_SUCCESS;
-
- QCBORItem item;
- QCBORDecode_EnterArray(dec, NULL);
-
- // array-of-key-maps
- while (QCBOR_SUCCESS == QCBORDecode_PeekNext(dec, &item))
- {
- bool has_kty = false;
- int64_t kty = 0;
- bool has_alg = false;
- int64_t alg = 0;
- UsefulBufC kid = NULLUsefulBufC;
- UsefulBufC baseiv = NULLUsefulBufC;
- UsefulBufC k_data = NULLUsefulBufC;
-
- QCBORDecode_EnterArray(dec, NULL); // using QCBOR_DECODE_MODE_MAP_AS_ARRAY
-
- while (QCBOR_SUCCESS == QCBORDecode_PeekNext(dec, &item))
- {
- int64_t label;
- QCBORDecode_GetInt64(dec, &label);
- if (QCBOR_SUCCESS != QCBORDecode_GetError(dec))
- {
- BSL_LOG_ERR("Unable to get key label");
- break;
- }
- BSL_LOG_DEBUG("got label %" PRId64, label);
-
- switch (label)
- {
- case BSLX_COSEMSG_KEY_PARAM_KTY:
- QCBORDecode_GetInt64(dec, &kty);
- has_kty = true;
- break;
- case BSLX_COSEMSG_KEY_PARAM_KID:
- QCBORDecode_GetByteString(dec, &kid);
- break;
- case BSLX_COSEMSG_KEY_PARAM_ALG:
- QCBORDecode_GetInt64(dec, &alg);
- has_alg = true;
- break;
- case BSLX_COSEMSG_KEY_PARAM_BASEIV:
- QCBORDecode_GetByteString(dec, &baseiv);
- break;
- case -1:
- if (has_kty && (kty == 4))
- {
- QCBORDecode_GetByteString(dec, &k_data);
- }
- break;
- default:
- // consume but ignore
- QCBORDecode_VGetNextConsume(dec, &item);
- break;
- }
- if (QCBOR_SUCCESS != QCBORDecode_GetError(dec))
- {
- BSL_LOG_ERR("Unable to get key value");
- break;
- }
-
- if (has_kty && (kty != 4))
- {
- BSL_LOG_WARNING("Ignoring non-symmetric key type %" PRId64, kty);
- break;
- }
- }
- QCBORDecode_ExitArray(dec);
-
- // If valid enough to store
- if (has_kty && kid.ptr && k_data.ptr)
- {
- BSL_Data_t kid_view;
- BSL_Data_InitView(&kid_view, kid.len, (BSL_DataPtr_t)kid.ptr);
-
- BSL_Crypto_KeyHandle_t keyhandle;
- BSL_Crypto_LoadKey(k_data.ptr, k_data.len, &keyhandle);
-
- if (has_alg)
- {
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
- BSLX_COSEMSG_KEY_PARAM_ALG, alg);
- }
- else
- {
- BSL_LOG_WARNING("COSE Key without an alg parameter");
- }
-
- if (baseiv.len > 0)
- {
- BSL_Data_t view;
- BSL_Data_InitView(&view, baseiv.len, (BSL_DataPtr_t)baseiv.ptr);
- BSL_IdValPair_SetBytestr(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_BASEIV),
- BSLX_COSEMSG_KEY_PARAM_BASEIV, view);
- }
-
- retval = BSL_Crypto_AddRegistryKey(&kid_view, keyhandle);
- BSL_Crypto_ReleaseKeyHandle(keyhandle);
- BSL_LOG_DEBUG("Adding key result %d", retval);
- if (BSL_SUCCESS != retval)
- {
- BSL_LOG_ERR("Unable to store key");
- break;
- }
- }
- }
- QCBORDecode_ExitArray(dec);
- return retval;
-}
-
-int mock_bpa_key_registry_init_cosekey(int infd)
-{
- struct stat sb;
- if ((fstat(infd, &sb) < 0) || (sb.st_size == 0))
- {
- BSL_LOG_ERR("Error getting file size");
- close(infd);
- return BSL_ERR_DECODING;
- }
-
- void *data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, infd, 0);
- if (!data)
- {
- BSL_LOG_ERR("Error in mmap");
- close(infd);
- return BSL_ERR_DECODING;
- }
-
- BSL_Data_t view;
- BSL_Data_InitView(&view, sb.st_size, (BSL_DataPtr_t)data);
-
- int retval = BSL_CBOR_Decode(&view, &mock_bpa_key_registry_cosekey_decode, NULL);
-
- if (munmap(data, sb.st_size) < 0)
- {
- BSL_LOG_ERR("Error in munmap");
- }
- close(infd);
- return retval;
-}
-
-int mock_bpa_key_registry_init(const char *file_path)
-{
- int retval = BSL_SUCCESS;
-
- int infd = open(file_path, O_RDONLY);
- if (infd < 0)
- {
- BSL_LOG_ERR("Failed to open input file %s", file_path);
- return BSL_ERR_DECODING;
- }
-
- BSL_LOG_INFO("Reading keys from %s", file_path);
- m_string_t path;
- m_string_init_set_cstr(path, file_path);
- bool is_json = m_string_end_with_str_p(path, ".json");
- bool is_cbor = m_string_end_with_str_p(path, ".cbor");
- m_string_clear(path);
-
- if (is_json)
- {
- retval = mock_bpa_key_registry_init_jwk(infd);
- }
- else if (is_cbor)
- {
- retval = mock_bpa_key_registry_init_cosekey(infd);
- }
- else
- {
- BSL_LOG_ERR("Unhandled key file extension for %s", file_path);
- retval = BSL_ERR_ARG_INVALID;
- }
-
- return retval;
-}
-
-int mock_bpa_rfc9173_bcb_cek(unsigned char *buf, int len)
-{
- if (len == 12) // IV
- {
- uint8_t iv[] = { 0x54, 0x77, 0x65, 0x6c, 0x76, 0x65, 0x31, 0x32, 0x31, 0x32, 0x31, 0x32 };
- memcpy(buf, iv, 12);
- }
- else // A3 KEY
- {
- uint8_t rfc9173A3_key[] = { 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69,
- 0x6f, 0x70, 0x61, 0x73, 0x64, 0x66, 0x67, 0x68 };
- memcpy(buf, rfc9173A3_key, len);
- }
- return 1;
-}
diff --git a/src/bsl/mock_bpa/key_registry.h b/src/bsl/mock_bpa/key_registry.h
deleted file mode 100644
index 2c80375f..00000000
--- a/src/bsl/mock_bpa/key_registry.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2025-2026 The Johns Hopkins University Applied Physics
- * Laboratory LLC.
- *
- * This file is part of the Bundle Protocol Security Library (BSL).
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * This work was performed for the Jet Propulsion Laboratory, California
- * Institute of Technology, sponsored by the United States Government under
- * the prime contract 80NM0018D0004 between the Caltech and NASA under
- * subcontract 1700763.
- */
-
-/** @file
- * @ingroup mock_bpa
- */
-
-#ifndef BSL_MOCK_BPA_KEY_REGISTRY_H_
-#define BSL_MOCK_BPA_KEY_REGISTRY_H_
-
-#include "bsl/crypto/CryptoInterface.h"
-
-#include
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** @brief Initialize keys
- * @param[in] file_path path to JSON file with JWKs or CBOR file with @c COSE_KeySet
- * @return 0 if successful.
- */
-int mock_bpa_key_registry_init(const char *file_path);
-
-/** @warning Exposed only for testing.
- * @param infd The file descriptor to read from.
- */
-int mock_bpa_key_registry_init_jwk(int infd);
-
-/** @warning Exposed only for testing.
- * @param infd The file descriptor to read from.
- */
-int mock_bpa_key_registry_init_cosekey(int infd);
-
-/**
- * Custom RNG function for BCB testing
- */
-int mock_bpa_rfc9173_bcb_cek(unsigned char *buf, int len);
-
-#ifdef __cplusplus
-} // extern C
-#endif
-
-#endif
diff --git a/src/bsl/mock_bpa/mock_bpa.c b/src/bsl/mock_bpa/mock_bpa.c
index c761d53d..5aec854b 100644
--- a/src/bsl/mock_bpa/mock_bpa.c
+++ b/src/bsl/mock_bpa/mock_bpa.c
@@ -25,7 +25,7 @@
* unix domain sockets.
*/
#include "agent.h"
-#include "key_registry.h"
+#include "KeyStore.h"
#include "log.h"
#include "bsl/BPSecLib_Private.h"
@@ -118,6 +118,25 @@ static void show_usage(const char *argv0)
BSL_VERSION, argv0);
}
+/**
+ * Custom RNG function for BCB testing
+ */
+static int mock_bpa_rfc9173_bcb_cek(unsigned char *buf, int len)
+{
+ if (len == 12) // IV
+ {
+ uint8_t iv[] = { 0x54, 0x77, 0x65, 0x6c, 0x76, 0x65, 0x31, 0x32, 0x31, 0x32, 0x31, 0x32 };
+ memcpy(buf, iv, 12);
+ }
+ else // A3 KEY
+ {
+ uint8_t rfc9173A3_key[] = { 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69,
+ 0x6f, 0x70, 0x61, 0x73, 0x64, 0x66, 0x67, 0x68 };
+ memcpy(buf, rfc9173A3_key, len);
+ }
+ return 1;
+}
+
int main(int argc, char **argv)
{
int retval = 0;
@@ -128,7 +147,7 @@ int main(int argc, char **argv)
return 2;
}
mock_bpa_LogOpen();
- BSL_CryptoInit();
+ MockBPA_KeyStore_Init();
if ((res = MockBPA_Agent_Init(&agent, &policy)))
{
BSL_LOG_ERR("Failed to initialize mock BPA, error %d", res);
@@ -191,7 +210,7 @@ int main(int argc, char **argv)
break;
}
case 'k':
- if (mock_bpa_key_registry_init(optarg))
+ if (MockBPA_KeyStore_LoadFile(optarg))
{
retval = 1;
}
@@ -252,7 +271,7 @@ int main(int argc, char **argv)
BSL_HostEID_Deinit(&sec_eid);
BSL_HostEID_Deinit(&app_eid);
- BSL_CryptoDeinit();
+ MockBPA_KeyStore_Deinit();
mock_bpa_LogClose();
BSL_HostDescriptors_Clear();
return retval;
diff --git a/test/DefaultScUtils.h b/test/DefaultScUtils.h
index 48306bf9..2a5abd71 100644
--- a/test/DefaultScUtils.h
+++ b/test/DefaultScUtils.h
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include
@@ -55,7 +56,7 @@ static inline int BSL_Crypto_AddRegistryKeyName(const char *name, const uint8_t
BSL_Crypto_KeyHandle_t keyhandle;
BSL_Crypto_LoadKey(ptr, len, &keyhandle);
BSL_Data_t key_id = BSL_DATA_INIT_VIEW_CSTR(name);
- int res = BSL_Crypto_AddRegistryKey(&key_id, keyhandle);
+ int res = MockBPA_KeyStore_AddKey(&key_id, keyhandle);
BSL_Crypto_ReleaseKeyHandle(keyhandle);
return res;
}
@@ -68,10 +69,10 @@ static inline int BSL_Crypto_GetRegistryKeyName(const char *name, BSL_Crypto_Key
}
/// Test helper function
-static inline int BSL_Crypto_RemoveRegistryKeyName(const char *name)
+static inline int MockBPA_KeyStore_RemoveKeyName(const char *name)
{
BSL_Data_t key_id = BSL_DATA_INIT_VIEW_CSTR(name);
- return BSL_Crypto_RemoveRegistryKey(&key_id);
+ return MockBPA_KeyStore_RemoveKey(&key_id);
}
/// @brief Sample policy provider ID
diff --git a/test/fuzz_mock_bpa_keyregistry_cosekey.cpp b/test/fuzz_mock_bpa_keyregistry_cosekey.cpp
index e5ff486d..73b2238a 100644
--- a/test/fuzz_mock_bpa_keyregistry_cosekey.cpp
+++ b/test/fuzz_mock_bpa_keyregistry_cosekey.cpp
@@ -26,7 +26,7 @@
#include "TestUtils.h"
#include
-#include
+#include
#include
#include
@@ -51,7 +51,7 @@ extern "C" int LLVMFuzzerInitialize(int *argc _U_, char ***argv _U_)
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
int retval = 0;
- BSL_CryptoInit();
+ MockBPA_KeyStore_Init();
FILE *tmp = tmpfile();
size_t got = fwrite(data, size, 1, tmp);
@@ -65,13 +65,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
if (!retval)
{
int infd = fileno(tmp);
- if (mock_bpa_key_registry_init_cosekey(infd))
+ if (MockBPA_KeyStore_LoadCoseKeySet(infd))
{
retval = -1;
}
}
fclose(tmp);
- BSL_CryptoDeinit();
+ MockBPA_KeyStore_Deinit();
return retval;
}
diff --git a/test/fuzz_mock_bpa_keyregistry_jwk.cpp b/test/fuzz_mock_bpa_keyregistry_jwk.cpp
index 8fb5d6e5..46d9549a 100644
--- a/test/fuzz_mock_bpa_keyregistry_jwk.cpp
+++ b/test/fuzz_mock_bpa_keyregistry_jwk.cpp
@@ -26,7 +26,7 @@
#include "TestUtils.h"
#include
-#include
+#include
#include
#include
@@ -51,7 +51,7 @@ extern "C" int LLVMFuzzerInitialize(int *argc _U_, char ***argv _U_)
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
int retval = 0;
- BSL_CryptoInit();
+ MockBPA_KeyStore_Init();
FILE *tmp = tmpfile();
size_t got = fwrite(data, size, 1, tmp);
@@ -65,13 +65,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
if (!retval)
{
int infd = fileno(tmp);
- if (mock_bpa_key_registry_init_jwk(infd))
+ if (MockBPA_KeyStore_LoadJwk(infd))
{
retval = -1;
}
}
fclose(tmp);
- BSL_CryptoDeinit();
+ MockBPA_KeyStore_Deinit();
return retval;
}
diff --git a/test/test_BackendSecurityContext.c b/test/test_BackendSecurityContext.c
index 21ea2bc1..591ac0b8 100644
--- a/test/test_BackendSecurityContext.c
+++ b/test/test_BackendSecurityContext.c
@@ -82,7 +82,7 @@ int suiteTearDown(int failures)
void setUp(void)
{
- BSL_CryptoInit();
+ MockBPA_KeyStore_Init();
setenv("BSL_TEST_LOCAL_IPN_EID", "ipn:2.1", 1);
TEST_ASSERT_EQUAL(0, BSL_TestContext_Init(&LocalTestCtx));
BSL_TestUtils_SetupDefaultSecurityContext(&LocalTestCtx.bsl);
@@ -90,7 +90,7 @@ void setUp(void)
void tearDown(void)
{
- BSL_CryptoDeinit();
+ MockBPA_KeyStore_Deinit();
TEST_ASSERT_EQUAL(0, BSL_TestContext_Deinit(&LocalTestCtx));
}
diff --git a/test/test_CoseContext.c b/test/test_CoseContext.c
index e452b18c..aaad40f7 100644
--- a/test/test_CoseContext.c
+++ b/test/test_CoseContext.c
@@ -60,13 +60,13 @@ int suiteTearDown(int failures)
void setUp(void)
{
- BSL_CryptoInit();
+ MockBPA_KeyStore_Init();
TEST_ASSERT_EQUAL(0, BSL_TestContext_Init(&LocalTestCtx));
}
void tearDown(void)
{
- BSL_CryptoDeinit();
+ MockBPA_KeyStore_Deinit();
TEST_ASSERT_EQUAL(0, BSL_TestContext_Deinit(&LocalTestCtx));
}
@@ -284,11 +284,11 @@ void test_AppendixA_Example1_BIB_Source(void)
TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_LoadKey(keymat.ptr, keymat.len, &keyhandle));
BSL_Data_Deinit(&keymat);
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
BSLX_COSEMSG_KEY_PARAM_ALG, BSLX_COSEMSG_ALG_HMAC_SHA_384_384);
BSL_Data_t keyid = BSL_DATA_INIT_VIEW_CSTR(exA_1_kid);
- TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_AddRegistryKey(&keyid, keyhandle));
+ TEST_ASSERT_EQUAL_INT(0, MockBPA_KeyStore_AddKey(&keyid, keyhandle));
}
TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, exA_nosec));
@@ -402,11 +402,11 @@ void test_AppendixA_Example1_BIB_VerifyAccept(BSL_SecRole_e role, int mismatch)
TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_LoadKey(keymat.ptr, keymat.len, &keyhandle));
BSL_Data_Deinit(&keymat);
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
BSLX_COSEMSG_KEY_PARAM_ALG, BSLX_COSEMSG_ALG_HMAC_SHA_384_384);
BSL_Data_t keyid = BSL_DATA_INIT_VIEW_CSTR(exA_1_kid);
- TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_AddRegistryKey(&keyid, keyhandle));
+ TEST_ASSERT_EQUAL_INT(0, MockBPA_KeyStore_AddKey(&keyid, keyhandle));
}
TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, exA_1_mac0));
@@ -568,11 +568,11 @@ void test_CCSDS_Example_Mac_Source(void)
TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_LoadKey(keymat.ptr, keymat.len, &keyhandle));
BSL_Data_Deinit(&keymat);
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
BSLX_COSEMSG_KEY_PARAM_ALG, BSLX_COSEMSG_ALG_AES_KW_256);
BSL_Data_t keyid = BSL_DATA_INIT_VIEW_CSTR(ccsds_mac_kid);
- TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_AddRegistryKey(&keyid, keyhandle));
+ TEST_ASSERT_EQUAL_INT(0, MockBPA_KeyStore_AddKey(&keyid, keyhandle));
}
TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, ccsds_mac_nosec));
@@ -675,11 +675,11 @@ void test_CCSDS_Example_Mac_VerifyAccept(BSL_SecRole_e role, int mismatch)
TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_LoadKey(keymat.ptr, keymat.len, &keyhandle));
BSL_Data_Deinit(&keymat);
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
BSLX_COSEMSG_KEY_PARAM_ALG, BSLX_COSEMSG_ALG_AES_KW_256);
BSL_Data_t keyid = BSL_DATA_INIT_VIEW_CSTR(ccsds_mac_kid);
- TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_AddRegistryKey(&keyid, keyhandle));
+ TEST_ASSERT_EQUAL_INT(0, MockBPA_KeyStore_AddKey(&keyid, keyhandle));
}
TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, ccsds_mac_bib));
@@ -822,19 +822,19 @@ void test_AppendixA_Example4_BCB_Source(void)
TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_LoadKey(keymat.ptr, keymat.len, &keyhandle));
BSL_Data_Deinit(&keymat);
}
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
BSLX_COSEMSG_KEY_PARAM_ALG, BSLX_COSEMSG_ALG_AES_GCM_256);
{
BSL_Data_t buf;
BSL_Data_Init(&buf);
TEST_ASSERT_EQUAL(0, BSL_TestUtils_DecodeBase16_cstr(&buf, exA_4_biv));
- BSL_IdValPair_SetBytestr(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_BASEIV),
+ BSL_IdValPair_SetBytestr(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_BASEIV),
BSLX_COSEMSG_KEY_PARAM_BASEIV, buf);
BSL_Data_Deinit(&buf);
}
BSL_Data_t keyid = BSL_DATA_INIT_VIEW_CSTR(exA_4_kid);
- TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_AddRegistryKey(&keyid, keyhandle));
+ TEST_ASSERT_EQUAL_INT(0, MockBPA_KeyStore_AddKey(&keyid, keyhandle));
}
TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, exA_nosec));
@@ -946,19 +946,19 @@ void test_AppendixA_Example4_BCB_VerifyAccept(BSL_SecRole_e role, int mismatch)
TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_LoadKey(keymat.ptr, keymat.len, &keyhandle));
BSL_Data_Deinit(&keymat);
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
BSLX_COSEMSG_KEY_PARAM_ALG, BSLX_COSEMSG_ALG_AES_GCM_256);
{
BSL_Data_t buf;
BSL_Data_Init(&buf);
TEST_ASSERT_EQUAL(0, BSL_TestUtils_DecodeBase16_cstr(&buf, exA_4_biv));
- BSL_IdValPair_SetBytestr(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_BASEIV),
+ BSL_IdValPair_SetBytestr(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_BASEIV),
BSLX_COSEMSG_KEY_PARAM_BASEIV, buf);
BSL_Data_Deinit(&buf);
}
BSL_Data_t keyid = BSL_DATA_INIT_VIEW_CSTR(exA_4_kid);
- TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_AddRegistryKey(&keyid, keyhandle));
+ TEST_ASSERT_EQUAL_INT(0, MockBPA_KeyStore_AddKey(&keyid, keyhandle));
}
TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, exA_4_enc0));
@@ -1125,11 +1125,11 @@ void test_AppendixA_Example5_BCB_Source(void)
TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_LoadKey(keymat.ptr, keymat.len, &keyhandle));
BSL_Data_Deinit(&keymat);
}
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
BSLX_COSEMSG_KEY_PARAM_ALG, BSLX_COSEMSG_ALG_AES_KW_256);
BSL_Data_t keyid = BSL_DATA_INIT_VIEW_CSTR(exA_5_kid);
- TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_AddRegistryKey(&keyid, keyhandle));
+ TEST_ASSERT_EQUAL_INT(0, MockBPA_KeyStore_AddKey(&keyid, keyhandle));
}
TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, exA_nosec));
@@ -1232,11 +1232,11 @@ void test_AppendixA_Example5_BCB_VerifyAccept(BSL_SecRole_e role, int mismatch)
TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_LoadKey(keymat.ptr, keymat.len, &keyhandle));
BSL_Data_Deinit(&keymat);
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
BSLX_COSEMSG_KEY_PARAM_ALG, BSLX_COSEMSG_ALG_AES_KW_256);
BSL_Data_t keyid = BSL_DATA_INIT_VIEW_CSTR(exA_5_kid);
- TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_AddRegistryKey(&keyid, keyhandle));
+ TEST_ASSERT_EQUAL_INT(0, MockBPA_KeyStore_AddKey(&keyid, keyhandle));
}
TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, exA_5_enc));
@@ -1401,11 +1401,11 @@ void test_AppendixA_Example6_BCB_Source(void)
TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_LoadKey(keymat.ptr, keymat.len, &keyhandle));
BSL_Data_Deinit(&keymat);
}
- BSL_IdValPair_SetInt64(BSL_Crypto_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
+ BSL_IdValPair_SetInt64(MockBPA_KeyStore_SetKeyParameter(keyhandle, BSLX_COSEMSG_KEY_PARAM_ALG),
BSLX_COSEMSG_KEY_PARAM_ALG, BSLX_COSEMSG_ALG_DIRECT_HKDF_SHA_512);
BSL_Data_t keyid = BSL_DATA_INIT_VIEW_CSTR(exA_6_kid);
- BSL_Crypto_AddRegistryKey(&keyid, keyhandle);
+ MockBPA_KeyStore_AddKey(&keyid, keyhandle);
}
TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, exA_nosec));
diff --git a/test/test_CryptoInterface.c b/test/test_CryptoInterface.c
index 18b24f32..25491605 100644
--- a/test/test_CryptoInterface.c
+++ b/test/test_CryptoInterface.c
@@ -212,7 +212,7 @@ void setUp(void)
{
TEST_ASSERT_EQUAL(0, BSL_API_InitLib(&bsl));
- BSL_CryptoInit();
+ MockBPA_KeyStore_Init();
// static keys
uint8_t test1[20] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
@@ -237,7 +237,7 @@ void setUp(void)
void tearDown(void)
{
- BSL_CryptoDeinit();
+ MockBPA_KeyStore_Deinit();
TEST_ASSERT_EQUAL(0, BSL_API_DeinitLib(&bsl));
}
@@ -456,8 +456,7 @@ void test_encrypt(const char *plaintext_in, const char *keyid)
BSL_SeqReader_Destroy(reader);
- res = BSL_Cipher_Deinit(&ctx);
- TEST_ASSERT_EQUAL(0, res);
+ BSL_Cipher_Deinit(&ctx);
BSL_Crypto_ReleaseKeyHandle(ekey);
BSL_Data_Deinit(&iv);
@@ -529,7 +528,7 @@ void test_decrypt(const char *plaintext_in, const char *keyid)
TEST_ASSERT_EQUAL_MEMORY(plaintext_in, plaintext, pt_size);
}
- TEST_ASSERT_EQUAL(0, BSL_Cipher_Deinit(&ctx));
+ BSL_Cipher_Deinit(&ctx);
BSL_Crypto_ReleaseKeyHandle(ckey);
BSL_Data_Deinit(&iv);
@@ -600,8 +599,8 @@ void test_key_wrap(const char *kek, const char *cek, const char *expected)
BSL_Data_Deinit(&kek_data);
BSL_Data_Deinit(&cek_data);
BSL_Data_Deinit(&wrapped_key);
- BSL_Crypto_RemoveRegistryKeyName("kek");
- BSL_Crypto_RemoveRegistryKeyName("cek");
+ MockBPA_KeyStore_RemoveKeyName("kek");
+ MockBPA_KeyStore_RemoveKeyName("cek");
}
// rfc3394 test vectors
@@ -659,8 +658,8 @@ void test_key_unwrap(const char *kek, const char *expected_cek, const char *wrap
BSL_Crypto_ReleaseKeyHandle(cek_handle);
BSL_Crypto_ReleaseKeyHandle(expect_handle);
BSL_Crypto_ReleaseKeyHandle(kek_handle);
- BSL_Crypto_RemoveRegistryKeyName("kek");
- BSL_Crypto_RemoveRegistryKeyName("cek");
+ MockBPA_KeyStore_RemoveKeyName("kek");
+ MockBPA_KeyStore_RemoveKeyName("cek");
}
// RFC 5869 test vectors
@@ -831,7 +830,7 @@ void test_key_stats(void)
BSL_Crypto_KeyHandle_t handle;
BSL_Crypto_LoadKey(test_128, sizeof(test_128), &handle);
TEST_ASSERT_NOT_NULL(handle);
- TEST_ASSERT_EQUAL_INT(0, BSL_Crypto_AddRegistryKey(&key_id, handle));
+ TEST_ASSERT_EQUAL_INT(0, MockBPA_KeyStore_AddKey(&key_id, handle));
test_encrypt("hello world!", "testkeystats");
diff --git a/test/test_DefaultSecurityContext.c b/test/test_DefaultSecurityContext.c
index ef47bc92..78928a57 100644
--- a/test/test_DefaultSecurityContext.c
+++ b/test/test_DefaultSecurityContext.c
@@ -65,7 +65,7 @@ int suiteTearDown(int failures)
void setUp(void)
{
- BSL_CryptoInit();
+ MockBPA_KeyStore_Init();
setenv("BSL_TEST_LOCAL_IPN_EID", "ipn:2.1", 1);
TEST_ASSERT_EQUAL(0, BSL_TestContext_Init(&LocalTestCtx));
BSL_TestUtils_SetupDefaultSecurityContext(&LocalTestCtx.bsl);
@@ -73,7 +73,7 @@ void setUp(void)
void tearDown(void)
{
- BSL_CryptoDeinit();
+ MockBPA_KeyStore_Deinit();
TEST_ASSERT_EQUAL(0, BSL_TestContext_Deinit(&LocalTestCtx));
}
diff --git a/test/test_DynamicMemCbs.c b/test/test_DynamicMemCbs.c
index 80350278..36c14f86 100644
--- a/test/test_DynamicMemCbs.c
+++ b/test/test_DynamicMemCbs.c
@@ -94,7 +94,7 @@ int suiteTearDown(int failures)
void _setUp(void)
{
setenv("BSL_TEST_LOCAL_IPN_EID", "ipn:2.1", 1);
- BSL_CryptoInit();
+ MockBPA_KeyStore_Init();
TEST_ASSERT_EQUAL(0, BSL_TestContext_Init(&LocalTestCtx));
BSL_TestUtils_SetupDefaultSecurityContext(&LocalTestCtx.bsl);
@@ -149,7 +149,7 @@ void _tearDown(void)
{
BSL_SecurityActionSet_Deinit(&action_set);
BSLP_PolicyProvider_Destroy(policy_provider);
- BSL_CryptoDeinit();
+ MockBPA_KeyStore_Deinit();
TEST_ASSERT_EQUAL(0, BSL_TestContext_Deinit(&LocalTestCtx));
BSL_IdValPair_Deinit(¶m_aes_variant_128);
diff --git a/test/test_PublicInterfaceImpl.c b/test/test_PublicInterfaceImpl.c
index ebc4a7bf..092c3454 100644
--- a/test/test_PublicInterfaceImpl.c
+++ b/test/test_PublicInterfaceImpl.c
@@ -118,7 +118,7 @@ void PublicInterfaceTestCtx_deinit(BSL_TestPublInterfaceCtx_t *ctx)
void setUp(void)
{
setenv("BSL_TEST_LOCAL_IPN_EID", "ipn:2.1", 1);
- BSL_CryptoInit();
+ MockBPA_KeyStore_Init();
TEST_ASSERT_EQUAL(0, BSL_TestContext_Init(&LocalTestCtx));
BSL_TestUtils_SetupDefaultSecurityContext(&LocalTestCtx.bsl);
BSL_SecurityActionSet_Init(&action_set);
@@ -506,7 +506,7 @@ void setUp(void)
void tearDown(void)
{
BSLP_PolicyProvider_Destroy(policy_provider);
- BSL_CryptoDeinit();
+ MockBPA_KeyStore_Deinit();
TEST_ASSERT_EQUAL(0, BSL_TestContext_Deinit(&LocalTestCtx));
BSL_SecurityActionSet_Deinit(&action_set);
PublicInterfaceTestCtx_deinit(&ctx);