diff --git a/sw/device/lib/crypto/BUILD b/sw/device/lib/crypto/BUILD index d7725b04dd491..bcbd236c7b5df 100644 --- a/sw/device/lib/crypto/BUILD +++ b/sw/device/lib/crypto/BUILD @@ -22,6 +22,7 @@ cc_library( "//sw/device/lib/crypto/impl:aes", "//sw/device/lib/crypto/impl:aes_gcm", "//sw/device/lib/crypto/impl:cmac", + "//sw/device/lib/crypto/impl:cmvp", "//sw/device/lib/crypto/impl:config", "//sw/device/lib/crypto/impl:cryptolib_build_info", "//sw/device/lib/crypto/impl:drbg", diff --git a/sw/device/lib/crypto/configs/crypto_fips_all.txt b/sw/device/lib/crypto/configs/crypto_fips_all.txt index 149d847c7928d..84e87114b127f 100644 --- a/sw/device/lib/crypto/configs/crypto_fips_all.txt +++ b/sw/device/lib/crypto/configs/crypto_fips_all.txt @@ -174,3 +174,4 @@ otcrypto_ecdsa_p384_hash_sign_verify otcrypto_ecdsa_p384_hash_verify otcrypto_rsa_hash_sign_verify otcrypto_rsa_hash_verify +otcrypto_cmvp_service_indicator diff --git a/sw/device/lib/crypto/impl/BUILD b/sw/device/lib/crypto/impl/BUILD index a064529c0a8f2..55f05337a5396 100644 --- a/sw/device/lib/crypto/impl/BUILD +++ b/sw/device/lib/crypto/impl/BUILD @@ -34,6 +34,7 @@ cc_library( srcs = ["aes.c"], hdrs = ["//sw/device/lib/crypto/include:aes.h"], deps = [ + ":cmvp", ":config", ":integrity", ":keyblob", @@ -51,6 +52,7 @@ cc_library( srcs = ["aes_gcm.c"], hdrs = ["//sw/device/lib/crypto/include:aes_gcm.h"], deps = [ + ":cmvp", ":config", ":integrity", ":keyblob", @@ -83,6 +85,7 @@ cc_library( srcs = ["drbg.c"], hdrs = ["//sw/device/lib/crypto/include:drbg.h"], deps = [ + ":cmvp", ":config", ":integrity", ":status", @@ -99,6 +102,7 @@ cc_library( srcs = ["cmac.c"], hdrs = ["//sw/device/lib/crypto/include:cmac.h"], deps = [ + ":cmvp", ":config", ":integrity", ":keyblob", @@ -122,6 +126,7 @@ cc_library( }), target_compatible_with = [OPENTITAN_CPU], deps = [ + ":cmvp", ":config", ":hmac", ":integrity", @@ -140,6 +145,7 @@ cc_library( hdrs = ["//sw/device/lib/crypto/include:ecc_p256.h"], target_compatible_with = [OPENTITAN_CPU], deps = [ + ":cmvp", ":config", ":hash", ":keyblob", @@ -155,6 +161,7 @@ cc_library( hdrs = ["//sw/device/lib/crypto/include:ecc_p384.h"], target_compatible_with = [OPENTITAN_CPU], deps = [ + ":cmvp", ":config", ":hash", ":keyblob", @@ -169,6 +176,7 @@ cc_library( srcs = ["hkdf.c"], hdrs = ["//sw/device/lib/crypto/include:hkdf.h"], deps = [ + ":cmvp", ":config", ":cryptolib_build_info", ":hmac", @@ -203,6 +211,7 @@ cc_library( "//conditions:default": [], }), deps = [ + ":cmvp", ":state", ":status", "//sw/device/lib/base:hardened", @@ -266,6 +275,7 @@ cc_library( srcs = ["kdf_ctr.c"], hdrs = ["//sw/device/lib/crypto/include:kdf_ctr.h"], deps = [ + ":cmvp", ":config", ":hmac", ":integrity", @@ -308,6 +318,7 @@ cc_library( srcs = ["key_transport.c"], hdrs = ["//sw/device/lib/crypto/include:key_transport.h"], deps = [ + ":cmvp", ":config", ":status", "//sw/device/lib/crypto/drivers:aes", @@ -339,6 +350,7 @@ cc_library( srcs = ["kmac_kdf.c"], hdrs = ["//sw/device/lib/crypto/include:kmac_kdf.h"], deps = [ + ":cmvp", ":config", ":integrity", ":keyblob", @@ -363,6 +375,7 @@ cc_library( "//conditions:default": [], }), deps = [ + ":cmvp", ":config", ":hash", ":integrity", @@ -386,6 +399,7 @@ cc_library( "//conditions:default": [], }), deps = [ + ":cmvp", ":cryptolib_build_info", ":entropy_src", ":integrity", @@ -432,6 +446,49 @@ dual_cc_library( ), ) +dual_cc_library( + name = "cmvp", + srcs = dual_inputs( + device = ["cmvp.c"], + host = ["cmvp.c"], + ), + hdrs = [ + "cmvp.h", + "//sw/device/lib/crypto/include:cmvp.h", + ], + defines = select({ + "//sw/device/lib/crypto/configs:hashed": ["FIPS_MODE"], + "//conditions:default": [], + }), + deps = dual_inputs( + shared = [ + ":state", + ":status", + "//sw/device/lib/crypto/include:datatypes", + ], + ), +) + +dual_cc_library( + name = "cmvp_fips", + srcs = dual_inputs( + device = ["cmvp.c"], + host = ["cmvp.c"], + ), + hdrs = [ + "cmvp.h", + "//sw/device/lib/crypto/include:cmvp.h", + ], + defines = ["FIPS_MODE"], + deps = dual_inputs( + shared = [ + ":state", + ":status", + "//sw/device/lib/crypto/include:datatypes", + ], + ), +) + cc_library( name = "hash", srcs = ["hash.c"], @@ -454,6 +511,7 @@ cc_library( ], target_compatible_with = [OPENTITAN_CPU], deps = [ + ":cmvp", ":config", ":integrity", ":status", @@ -473,6 +531,7 @@ cc_library( ], target_compatible_with = [OPENTITAN_CPU], deps = [ + ":cmvp", ":config", ":status", "//sw/device/lib/base:hardened", @@ -533,6 +592,7 @@ cc_library( "//sw/device/lib/crypto/include:hmac.h", ], deps = [ + ":cmvp", ":config", ":integrity", ":keyblob", @@ -551,6 +611,7 @@ cc_library( "//sw/device/lib/crypto/include:kmac.h", ], deps = [ + ":cmvp", ":config", ":integrity", ":keyblob", @@ -573,9 +634,36 @@ cc_library( ], ) +cc_test( + name = "cmvp_unittest", + srcs = ["cmvp_unittest.cc"], + defines = ["FIPS_MODE"], + deps = [ + ":cmvp_fips", + ":state", + ":status", + "//sw/device/lib/crypto/include:datatypes", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "cmvp_nofips_unittest", + srcs = ["cmvp_unittest.cc"], + deps = [ + ":cmvp", + ":state", + ":status", + "//sw/device/lib/crypto/include:datatypes", + "@googletest//:gtest_main", + ], +) + test_suite( name = "impl_unittest_suite", tests = [ + ":cmvp_nofips_unittest", + ":cmvp_unittest", ":integrity_unittest", ":key_transport_unittest", ":keyblob_unittest", diff --git a/sw/device/lib/crypto/impl/aes.c b/sw/device/lib/crypto/impl/aes.c index b2ca99e7c07dc..d8741d9016335 100644 --- a/sw/device/lib/crypto/impl/aes.c +++ b/sw/device/lib/crypto/impl/aes.c @@ -10,6 +10,7 @@ #include "sw/device/lib/base/memory.h" #include "sw/device/lib/crypto/drivers/aes.h" #include "sw/device/lib/crypto/drivers/keymgr.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/impl/status.h" @@ -618,6 +619,7 @@ otcrypto_status_t otcrypto_aes(otcrypto_blinded_key_t *key, const otcrypto_const_byte_buf_t *cipher_input, otcrypto_aes_padding_t aes_padding, otcrypto_byte_buf_t *cipher_output) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers in input pointers and data buffers. if (key == NULL || key->keyblob == NULL || diff --git a/sw/device/lib/crypto/impl/aes_gcm.c b/sw/device/lib/crypto/impl/aes_gcm.c index 0b41e0e2b1f8c..94364ea7c33ce 100644 --- a/sw/device/lib/crypto/impl/aes_gcm.c +++ b/sw/device/lib/crypto/impl/aes_gcm.c @@ -13,6 +13,7 @@ #include "sw/device/lib/crypto/drivers/rv_core_ibex.h" #include "sw/device/lib/crypto/impl/aes_gcm/aes_gcm.h" #include "sw/device/lib/crypto/impl/aes_gcm/ghash.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/impl/status.h" @@ -281,6 +282,7 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt( const otcrypto_const_word32_buf_t *iv, const otcrypto_const_byte_buf_t *aad, otcrypto_aes_gcm_tag_len_t tag_len, otcrypto_byte_buf_t *ciphertext, otcrypto_word32_buf_t *auth_tag) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers in input pointers and required-nonzero-length data // buffers. @@ -340,6 +342,7 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt( otcrypto_aes_gcm_tag_len_t tag_len, const otcrypto_const_word32_buf_t *auth_tag, otcrypto_byte_buf_t *plaintext, hardened_bool_t *success) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES_GCM_DECRYPT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers in input pointers and required-nonzero-length data // buffers. @@ -392,6 +395,7 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt( otcrypto_status_t otcrypto_aes_gcm_encrypt_init( otcrypto_blinded_key_t *key, const otcrypto_const_word32_buf_t *iv, otcrypto_aes_gcm_context_t *ctx) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_INIT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (key == NULL || key->keyblob == NULL || iv == NULL || iv->data == NULL || ctx == NULL) { @@ -428,6 +432,7 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_init( otcrypto_status_t otcrypto_aes_gcm_decrypt_init( otcrypto_blinded_key_t *key, const otcrypto_const_word32_buf_t *iv, otcrypto_aes_gcm_context_t *ctx) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_INIT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (key == NULL || key->keyblob == NULL || iv == NULL || iv->data == NULL || ctx == NULL) { @@ -463,6 +468,7 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_init( otcrypto_status_t otcrypto_aes_gcm_update_aad( otcrypto_aes_gcm_context_t *ctx, const otcrypto_const_byte_buf_t *aad) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES_GCM_UPDATE_AAD); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || aad == NULL || aad->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -500,6 +506,7 @@ otcrypto_status_t otcrypto_aes_gcm_update_aad( otcrypto_status_t otcrypto_aes_gcm_update_encrypted_data( otcrypto_aes_gcm_context_t *ctx, const otcrypto_const_byte_buf_t *input, otcrypto_byte_buf_t *output, size_t *output_bytes_written) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES_GCM_UPDATE_ENCRYPTED_DATA); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || input == NULL || input->data == NULL || output == NULL || output->data == NULL || output_bytes_written == NULL) { @@ -557,6 +564,7 @@ otcrypto_status_t otcrypto_aes_gcm_encrypt_final( otcrypto_aes_gcm_context_t *ctx, otcrypto_aes_gcm_tag_len_t tag_len, otcrypto_byte_buf_t *ciphertext, size_t *ciphertext_bytes_written, otcrypto_word32_buf_t *auth_tag) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_FINAL); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || ciphertext_bytes_written == NULL || auth_tag == NULL || auth_tag->data == NULL) { @@ -612,6 +620,7 @@ otcrypto_status_t otcrypto_aes_gcm_decrypt_final( const otcrypto_const_word32_buf_t *auth_tag, otcrypto_aes_gcm_tag_len_t tag_len, otcrypto_byte_buf_t *plaintext, size_t *plaintext_bytes_written, hardened_bool_t *success) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_FINAL); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || plaintext_bytes_written == NULL || auth_tag == NULL || auth_tag->data == NULL || success == NULL) { diff --git a/sw/device/lib/crypto/impl/cmac.c b/sw/device/lib/crypto/impl/cmac.c index c9621ec1c1121..6e2c5f64c6edd 100644 --- a/sw/device/lib/crypto/impl/cmac.c +++ b/sw/device/lib/crypto/impl/cmac.c @@ -8,6 +8,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/crypto/drivers/aes.h" #include "sw/device/lib/crypto/drivers/keymgr.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/impl/status.h" @@ -342,12 +343,19 @@ OT_WARN_UNUSED_RESULT otcrypto_status_t otcrypto_cmac(const otcrypto_blinded_key_t *key, const otcrypto_const_byte_buf_t *input_message, otcrypto_word32_buf_t *tag) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_CMAC); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (tag == NULL || tag->data == NULL || input_message == NULL || (input_message->data == NULL && input_message->len != 0)) { return OTCRYPTO_BAD_ARGS; } #endif + // Tag length must be between 2 and 4 words (64 to 128 bits) per SP 800-38B. + if (launder32(tag->len) < 2 || launder32(tag->len) > kAesBlockNumWords) { + return OTCRYPTO_BAD_ARGS; + } + HARDENED_CHECK_GE(tag->len, 2); + HARDENED_CHECK_LE(tag->len, kAesBlockNumWords); // Clear AES unconditionally, and clear sideload if requested. uint32_t hw_cleanup_guard __attribute__((cleanup(aes_wipe_guard))) = 1; @@ -435,6 +443,7 @@ otcrypto_status_t otcrypto_cmac(const otcrypto_blinded_key_t *key, otcrypto_status_t otcrypto_cmac_init(otcrypto_cmac_context_t *ctx, const otcrypto_blinded_key_t *key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_CMAC_INIT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL) { return OTCRYPTO_BAD_ARGS; @@ -501,6 +510,7 @@ otcrypto_status_t otcrypto_cmac_init(otcrypto_cmac_context_t *ctx, otcrypto_status_t otcrypto_cmac_update( otcrypto_cmac_context_t *const ctx, const otcrypto_const_byte_buf_t *input_message) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_CMAC_UPDATE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || input_message == NULL) { return OTCRYPTO_BAD_ARGS; @@ -554,11 +564,18 @@ otcrypto_status_t otcrypto_cmac_update( otcrypto_status_t otcrypto_cmac_final(otcrypto_cmac_context_t *const ctx, otcrypto_word32_buf_t *tag) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_CMAC_FINAL); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || tag == NULL || tag->data == NULL) { return OTCRYPTO_BAD_ARGS; } #endif + // Tag length must be between 2 and 4 words (64 to 128 bits) per SP 800-38B. + if (launder32(tag->len) < 2 || launder32(tag->len) > kAesBlockNumWords) { + return OTCRYPTO_BAD_ARGS; + } + HARDENED_CHECK_GE(tag->len, 2); + HARDENED_CHECK_LE(tag->len, kAesBlockNumWords); uint32_t hw_cleanup_guard __attribute__((cleanup(aes_wipe_guard))) = 1; barrier32(hw_cleanup_guard); diff --git a/sw/device/lib/crypto/impl/cmvp.c b/sw/device/lib/crypto/impl/cmvp.c new file mode 100644 index 0000000000000..e40e7d57c7465 --- /dev/null +++ b/sw/device/lib/crypto/impl/cmvp.c @@ -0,0 +1,72 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "sw/device/lib/crypto/impl/cmvp.h" + +#include "sw/device/lib/crypto/impl/status.h" + +#ifdef FIPS_MODE + +static void cmvp_start_service(otcrypto_cmvp_service_indicator_t indicator) { + crypto_state_t *state = NULL; + if (status_ok(read_state_pointer(&state)) && state != NULL) { + if (state->cmvp_call_depth == 0) { + state->cmvp_service_indicator = indicator; + } + state->cmvp_call_depth++; + } +} + +void otcrypto_cmvp_start_approved(void) { + cmvp_start_service(kOtcryptoCmvpApprovedService); +} + +void otcrypto_cmvp_start_not_approved(void) { + cmvp_start_service(kOtcryptoCmvpNotApprovedService); +} + +void otcrypto_cmvp_override_not_approved(void) { + crypto_state_t *state = NULL; + if (status_ok(read_state_pointer(&state)) && state != NULL) { + state->cmvp_service_indicator = kOtcryptoCmvpNotApprovedService; + } +} + +void otcrypto_cmvp_end_service(void) { + crypto_state_t *state = NULL; + if (status_ok(read_state_pointer(&state)) && state != NULL) { + if (state->cmvp_call_depth > 0) { + state->cmvp_call_depth--; + } + } +} + +otcrypto_status_t otcrypto_cmvp_service_indicator( + otcrypto_cmvp_service_indicator_t *indicator) { + if (indicator == NULL) { + return OTCRYPTO_BAD_ARGS; + } + crypto_state_t *state = NULL; + if (!status_ok(read_state_pointer(&state)) || state == NULL) { + *indicator = kOtcryptoCmvpNoService; + return OTCRYPTO_OK; + } + *indicator = state->cmvp_service_indicator; + state->cmvp_service_indicator = kOtcryptoCmvpNoService; + state->cmvp_call_depth = 0; + return OTCRYPTO_OK; +} + +#else // !defined(FIPS_MODE) + +otcrypto_status_t otcrypto_cmvp_service_indicator( + otcrypto_cmvp_service_indicator_t *indicator) { + if (indicator == NULL) { + return OTCRYPTO_BAD_ARGS; + } + *indicator = kOtcryptoCmvpNoService; + return OTCRYPTO_OK; +} + +#endif // FIPS_MODE diff --git a/sw/device/lib/crypto/impl/cmvp.h b/sw/device/lib/crypto/impl/cmvp.h new file mode 100644 index 0000000000000..366290e5994a6 --- /dev/null +++ b/sw/device/lib/crypto/impl/cmvp.h @@ -0,0 +1,408 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_CMVP_H_ +#define OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_CMVP_H_ + +#include +#include +#include + +#include "sw/device/lib/crypto/impl/state.h" +#include "sw/device/lib/crypto/include/cmvp.h" +#include "sw/device/lib/crypto/include/datatypes.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enum for Cryptolib API functions for CMVP service indicator. + */ +typedef enum otcrypto_cmvp_function { + // Symmetric ciphers + OTCRYPTO_FUNCTION_AES, + OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT, + OTCRYPTO_FUNCTION_AES_GCM_DECRYPT, + OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_INIT, + OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_INIT, + OTCRYPTO_FUNCTION_AES_GCM_UPDATE_AAD, + OTCRYPTO_FUNCTION_AES_GCM_UPDATE_ENCRYPTED_DATA, + OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_FINAL, + OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_FINAL, + + // MACs + OTCRYPTO_FUNCTION_CMAC, + OTCRYPTO_FUNCTION_CMAC_INIT, + OTCRYPTO_FUNCTION_CMAC_UPDATE, + OTCRYPTO_FUNCTION_CMAC_FINAL, + OTCRYPTO_FUNCTION_HMAC, + OTCRYPTO_FUNCTION_HMAC_INIT, + OTCRYPTO_FUNCTION_HMAC_UPDATE, + OTCRYPTO_FUNCTION_HMAC_FINAL, + OTCRYPTO_FUNCTION_KMAC, + OTCRYPTO_FUNCTION_KMAC_KDF, + + // Hash / XOF + OTCRYPTO_FUNCTION_SHA2_256, + OTCRYPTO_FUNCTION_SHA2_384, + OTCRYPTO_FUNCTION_SHA2_512, + OTCRYPTO_FUNCTION_SHA2_INIT, + OTCRYPTO_FUNCTION_SHA2_UPDATE, + OTCRYPTO_FUNCTION_SHA2_FINAL, + OTCRYPTO_FUNCTION_SHA3_224, + OTCRYPTO_FUNCTION_SHA3_256, + OTCRYPTO_FUNCTION_SHA3_384, + OTCRYPTO_FUNCTION_SHA3_512, + OTCRYPTO_FUNCTION_SHAKE128, + OTCRYPTO_FUNCTION_SHAKE256, + OTCRYPTO_FUNCTION_CSHAKE128, + OTCRYPTO_FUNCTION_CSHAKE256, + + // DRBG + OTCRYPTO_FUNCTION_DRBG_INSTANTIATE, + OTCRYPTO_FUNCTION_DRBG_RESEED, + OTCRYPTO_FUNCTION_DRBG_GENERATE, + OTCRYPTO_FUNCTION_DRBG_MANUAL_INSTANTIATE, + OTCRYPTO_FUNCTION_DRBG_MANUAL_RESEED, + OTCRYPTO_FUNCTION_DRBG_MANUAL_GENERATE, + + // KDF + OTCRYPTO_FUNCTION_HKDF, + OTCRYPTO_FUNCTION_HKDF_EXTRACT, + OTCRYPTO_FUNCTION_HKDF_EXPAND, + OTCRYPTO_FUNCTION_KDF_CTR_HMAC, + + // Key transport / keyblob + OTCRYPTO_FUNCTION_SYMMETRIC_KEYGEN, + OTCRYPTO_FUNCTION_HW_BACKED_KEYGEN, + OTCRYPTO_FUNCTION_KEY_WRAP, + OTCRYPTO_FUNCTION_KEY_UNWRAP, + + // RSA + OTCRYPTO_FUNCTION_RSA_PUBLIC_KEY_CONSTRUCT, + OTCRYPTO_FUNCTION_RSA_PRIVATE_KEY_FROM_EXPONENTS, + OTCRYPTO_FUNCTION_RSA_KEYGEN, + OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR, + OTCRYPTO_FUNCTION_RSA_SIGN, + OTCRYPTO_FUNCTION_RSA_VERIFY, + OTCRYPTO_FUNCTION_RSA_ENCRYPT, + OTCRYPTO_FUNCTION_RSA_DECRYPT, + OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_START, + OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_START, + OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_START, + OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_START, + OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_START, + OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_START, + OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_FINALIZE, + + // ECC P-256 + OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN, + OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN, + OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_CONFIG_K, + OTCRYPTO_FUNCTION_ECDSA_P256_SIGN, + OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_VERIFY, + OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY, + OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN, + OTCRYPTO_FUNCTION_ECDH_P256, + OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_CONFIG_K_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDSA_P256_DICE_SIGN_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P256_DICE_SIGN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_START, + OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_START, + OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECC_P256_POINT_ON_CURVE, + OTCRYPTO_FUNCTION_ECC_P256_BASE_POINT_MULT, + + // ECC P-384 + OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN, + OTCRYPTO_FUNCTION_ECDSA_P384_SIGN, + OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_CONFIG_K, + OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_VERIFY, + OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY, + OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN, + OTCRYPTO_FUNCTION_ECDH_P384, + OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_CONFIG_K_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_START, + OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_START, + OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_START, + OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ECC_P384_POINT_ON_CURVE, + OTCRYPTO_FUNCTION_ECC_P384_BASE_POINT_MULT, + + // Curve25519 (Ed25519 / X25519) + OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE, + OTCRYPTO_FUNCTION_ED25519_SIGN, + OTCRYPTO_FUNCTION_ED25519_SIGN_VERIFY, + OTCRYPTO_FUNCTION_ED25519_VERIFY, + OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_START, + OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ED25519_SIGN_PART1_ASYNC_START, + OTCRYPTO_FUNCTION_ED25519_SIGN_PART2_ASYNC_START, + OTCRYPTO_FUNCTION_ED25519_SIGN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_START, + OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_X25519_KEYGEN, + OTCRYPTO_FUNCTION_X25519, + OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_START, + OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_FINALIZE, + OTCRYPTO_FUNCTION_X25519_ASYNC_START, + OTCRYPTO_FUNCTION_X25519_ASYNC_FINALIZE, + + // Self-integrity + OTCRYPTO_FUNCTION_INTEGRITY_CHECK, + + // Last element sentinel + OTCRYPTO_FUNCTION_MAX, +} otcrypto_cmvp_function_t; + +/** + * Compile-time approved status for Cryptolib API functions. + * 1 indicates CMVP approved service, 0 indicates non-approved service. + */ +// Symmetric ciphers +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_DECRYPT 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_INIT 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_INIT 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_UPDATE_AAD 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_UPDATE_ENCRYPTED_DATA 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_FINAL 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_FINAL 1 + +// MACs +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CMAC 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CMAC_INIT 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CMAC_UPDATE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CMAC_FINAL 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HMAC 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HMAC_INIT 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HMAC_UPDATE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HMAC_FINAL 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KMAC 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KMAC_KDF 1 + +// Hash / XOF +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_256 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_384 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_512 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_INIT 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_UPDATE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_FINAL 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA3_224 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA3_256 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA3_384 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA3_512 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHAKE128 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHAKE256 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CSHAKE128 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CSHAKE256 1 + +// DRBG +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_INSTANTIATE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_RESEED 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_GENERATE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_MANUAL_INSTANTIATE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_MANUAL_RESEED 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_MANUAL_GENERATE 0 + +// KDF +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HKDF 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HKDF_EXTRACT 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HKDF_EXPAND 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KDF_CTR_HMAC 1 + +// Key transport / keyblob +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SYMMETRIC_KEYGEN 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HW_BACKED_KEYGEN 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KEY_WRAP 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KEY_UNWRAP 1 + +// RSA +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_PUBLIC_KEY_CONSTRUCT 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_PRIVATE_KEY_FROM_EXPONENTS 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYGEN 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_SIGN 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_VERIFY 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_ENCRYPT 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_DECRYPT 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_START 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_FINALIZE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_START \ + 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_FINALIZE \ + 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_FINALIZE 0 + +// ECC P-256 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_CONFIG_K 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_VERIFY 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_START 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_FINALIZE \ + 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN_ASYNC_START \ + 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN_ASYNC_FINALIZE \ + 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_CONFIG_K_ASYNC_START \ + 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_SIGN_ASYNC_START \ + 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_SIGN_ASYNC_FINALIZE \ + 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_FINALIZE \ + 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECC_P256_POINT_ON_CURVE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECC_P256_BASE_POINT_MULT 1 + +// ECC P-384 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_CONFIG_K 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_VERIFY 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_START 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_FINALIZE \ + 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_CONFIG_K_ASYNC_START \ + 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_FINALIZE \ + 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECC_P384_POINT_ON_CURVE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECC_P384_BASE_POINT_MULT 1 + +// Curve25519 (Ed25519 / X25519) +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN_VERIFY 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_VERIFY 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_START \ + 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_FINALIZE \ + 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN_PART1_ASYNC_START 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN_PART2_ASYNC_START 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN_ASYNC_FINALIZE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_START 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_FINALIZE 1 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_KEYGEN 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_FINALIZE 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_ASYNC_START 0 +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_ASYNC_FINALIZE 0 + +// Self-integrity +#define OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_INTEGRITY_CHECK 1 + +#ifdef FIPS_MODE + +/** + * Marks the start of a CMVP-approved service. + * + * If this is the outermost call (cmvp_call_depth == 0), the indicator is set + * to kOtcryptoCmvpApprovedService. Increments cmvp_call_depth. + */ +void otcrypto_cmvp_start_approved(void); + +/** + * Marks the start of a non-approved service. + * + * If this is the outermost call (cmvp_call_depth == 0), the indicator is set + * to kOtcryptoCmvpNotApprovedService. Increments cmvp_call_depth. + */ +void otcrypto_cmvp_start_not_approved(void); + +/** + * Overrides the CMVP service indicator to not approved. + * + * Used when parameter validation determines the service is non-compliant + * (e.g. non-approved key size, short tag, user-supplied DRBG, etc.). + */ +void otcrypto_cmvp_override_not_approved(void); + +/** + * Decrements cmvp_call_depth when a service finishes. + */ +void otcrypto_cmvp_end_service(void); + +#define OTCRYPTO_CMVP_DISPATCH_1 otcrypto_cmvp_start_approved() +#define OTCRYPTO_CMVP_DISPATCH_0 otcrypto_cmvp_start_not_approved() +#define OTCRYPTO_CMVP_GLUE(a, b) a##b +#define OTCRYPTO_CMVP_EXPAND_DISPATCH(approved) \ + OTCRYPTO_CMVP_GLUE(OTCRYPTO_CMVP_DISPATCH_, approved) +#define OTCRYPTO_SET_CMVP_INDICATOR(func) \ + OTCRYPTO_CMVP_EXPAND_DISPATCH(OTCRYPTO_IS_APPROVED_##func) + +#define OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED() \ + otcrypto_cmvp_override_not_approved() + +#else // !defined(FIPS_MODE) + +static inline void otcrypto_cmvp_start_approved(void) {} +static inline void otcrypto_cmvp_start_not_approved(void) {} +static inline void otcrypto_cmvp_override_not_approved(void) {} +static inline void otcrypto_cmvp_end_service(void) {} + +#define OTCRYPTO_SET_CMVP_INDICATOR(func) ((void)(func)) +#define OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED() ((void)0) + +#endif // FIPS_MODE + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_CMVP_H_ diff --git a/sw/device/lib/crypto/impl/cmvp_unittest.cc b/sw/device/lib/crypto/impl/cmvp_unittest.cc new file mode 100644 index 0000000000000..73269ad271353 --- /dev/null +++ b/sw/device/lib/crypto/impl/cmvp_unittest.cc @@ -0,0 +1,528 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "sw/device/lib/crypto/impl/cmvp.h" + +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "sw/device/lib/crypto/impl/state.h" +#include "sw/device/lib/crypto/impl/status.h" +#include "sw/device/lib/crypto/include/cmvp.h" +#include "sw/device/lib/crypto/include/datatypes.h" + +namespace cmvp_unittest { +namespace { + +#define EXPECT_OK(status_) EXPECT_EQ(status_.value, OTCRYPTO_OK.value) + +#ifdef FIPS_MODE +const bool kCryptoFunctionApproved[OTCRYPTO_FUNCTION_MAX] = { + [OTCRYPTO_FUNCTION_AES] = (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES != 0), + [OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT != 0), + [OTCRYPTO_FUNCTION_AES_GCM_DECRYPT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_DECRYPT != 0), + [OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_INIT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_INIT != 0), + [OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_INIT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_INIT != 0), + [OTCRYPTO_FUNCTION_AES_GCM_UPDATE_AAD] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_UPDATE_AAD != 0), + [OTCRYPTO_FUNCTION_AES_GCM_UPDATE_ENCRYPTED_DATA] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_UPDATE_ENCRYPTED_DATA != + 0), + [OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_FINAL] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_FINAL != 0), + [OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_FINAL] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_FINAL != 0), + [OTCRYPTO_FUNCTION_CMAC] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CMAC != 0), + [OTCRYPTO_FUNCTION_CMAC_INIT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CMAC_INIT != 0), + [OTCRYPTO_FUNCTION_CMAC_UPDATE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CMAC_UPDATE != 0), + [OTCRYPTO_FUNCTION_CMAC_FINAL] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CMAC_FINAL != 0), + [OTCRYPTO_FUNCTION_HMAC] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HMAC != 0), + [OTCRYPTO_FUNCTION_HMAC_INIT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HMAC_INIT != 0), + [OTCRYPTO_FUNCTION_HMAC_UPDATE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HMAC_UPDATE != 0), + [OTCRYPTO_FUNCTION_HMAC_FINAL] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HMAC_FINAL != 0), + [OTCRYPTO_FUNCTION_KMAC] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KMAC != 0), + [OTCRYPTO_FUNCTION_KMAC_KDF] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KMAC_KDF != 0), + [OTCRYPTO_FUNCTION_SHA2_256] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_256 != 0), + [OTCRYPTO_FUNCTION_SHA2_384] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_384 != 0), + [OTCRYPTO_FUNCTION_SHA2_512] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_512 != 0), + [OTCRYPTO_FUNCTION_SHA2_INIT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_INIT != 0), + [OTCRYPTO_FUNCTION_SHA2_UPDATE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_UPDATE != 0), + [OTCRYPTO_FUNCTION_SHA2_FINAL] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA2_FINAL != 0), + [OTCRYPTO_FUNCTION_SHA3_224] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA3_224 != 0), + [OTCRYPTO_FUNCTION_SHA3_256] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA3_256 != 0), + [OTCRYPTO_FUNCTION_SHA3_384] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA3_384 != 0), + [OTCRYPTO_FUNCTION_SHA3_512] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHA3_512 != 0), + [OTCRYPTO_FUNCTION_SHAKE128] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHAKE128 != 0), + [OTCRYPTO_FUNCTION_SHAKE256] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SHAKE256 != 0), + [OTCRYPTO_FUNCTION_CSHAKE128] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CSHAKE128 != 0), + [OTCRYPTO_FUNCTION_CSHAKE256] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_CSHAKE256 != 0), + [OTCRYPTO_FUNCTION_DRBG_INSTANTIATE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_INSTANTIATE != 0), + [OTCRYPTO_FUNCTION_DRBG_RESEED] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_RESEED != 0), + [OTCRYPTO_FUNCTION_DRBG_GENERATE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_GENERATE != 0), + [OTCRYPTO_FUNCTION_DRBG_MANUAL_INSTANTIATE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_MANUAL_INSTANTIATE != 0), + [OTCRYPTO_FUNCTION_DRBG_MANUAL_RESEED] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_MANUAL_RESEED != 0), + [OTCRYPTO_FUNCTION_DRBG_MANUAL_GENERATE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_DRBG_MANUAL_GENERATE != 0), + [OTCRYPTO_FUNCTION_HKDF] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HKDF != 0), + [OTCRYPTO_FUNCTION_HKDF_EXTRACT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HKDF_EXTRACT != 0), + [OTCRYPTO_FUNCTION_HKDF_EXPAND] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HKDF_EXPAND != 0), + [OTCRYPTO_FUNCTION_KDF_CTR_HMAC] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KDF_CTR_HMAC != 0), + [OTCRYPTO_FUNCTION_SYMMETRIC_KEYGEN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_SYMMETRIC_KEYGEN != 0), + [OTCRYPTO_FUNCTION_HW_BACKED_KEYGEN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_HW_BACKED_KEYGEN != 0), + [OTCRYPTO_FUNCTION_KEY_WRAP] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KEY_WRAP != 0), + [OTCRYPTO_FUNCTION_KEY_UNWRAP] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_KEY_UNWRAP != 0), + [OTCRYPTO_FUNCTION_RSA_PUBLIC_KEY_CONSTRUCT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_PUBLIC_KEY_CONSTRUCT != 0), + [OTCRYPTO_FUNCTION_RSA_PRIVATE_KEY_FROM_EXPONENTS] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_PRIVATE_KEY_FROM_EXPONENTS != + 0), + [OTCRYPTO_FUNCTION_RSA_KEYGEN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYGEN != 0), + [OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR != 0), + [OTCRYPTO_FUNCTION_RSA_SIGN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_SIGN != 0), + [OTCRYPTO_FUNCTION_RSA_VERIFY] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_VERIFY != 0), + [OTCRYPTO_FUNCTION_RSA_ENCRYPT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_ENCRYPT != 0), + [OTCRYPTO_FUNCTION_RSA_DECRYPT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_DECRYPT != 0), + [OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_START != 0), + [OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_FINALIZE != 0), + [OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_START != 0), + [OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_FINALIZE != 0), + [OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_START != 0), + [OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_FINALIZE != 0), + [OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_START != 0), + [OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_START != 0), + [OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN != 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN != 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_CONFIG_K] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_CONFIG_K != 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_SIGN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN != 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_VERIFY] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_VERIFY != 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY != 0), + [OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN != 0), + [OTCRYPTO_FUNCTION_ECDH_P256] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256 != 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_CONFIG_K_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_CONFIG_K_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_DICE_SIGN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_SIGN_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_DICE_SIGN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_DICE_SIGN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_START != 0), + [OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_FINALIZE != 0), + [OTCRYPTO_FUNCTION_ECC_P256_POINT_ON_CURVE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECC_P256_POINT_ON_CURVE != 0), + [OTCRYPTO_FUNCTION_ECC_P256_BASE_POINT_MULT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECC_P256_BASE_POINT_MULT != 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN != 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_SIGN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN != 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_CONFIG_K] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_CONFIG_K != 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_VERIFY] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_VERIFY != 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY != 0), + [OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN != 0), + [OTCRYPTO_FUNCTION_ECDH_P384] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384 != 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_CONFIG_K_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_CONFIG_K_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_START != 0), + [OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_FINALIZE != 0), + [OTCRYPTO_FUNCTION_ECC_P384_POINT_ON_CURVE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECC_P384_POINT_ON_CURVE != 0), + [OTCRYPTO_FUNCTION_ECC_P384_BASE_POINT_MULT] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ECC_P384_BASE_POINT_MULT != 0), + [OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE != + 0), + [OTCRYPTO_FUNCTION_ED25519_SIGN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN != 0), + [OTCRYPTO_FUNCTION_ED25519_SIGN_VERIFY] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN_VERIFY != 0), + [OTCRYPTO_FUNCTION_ED25519_VERIFY] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_VERIFY != 0), + [OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ED25519_SIGN_PART1_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN_PART1_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ED25519_SIGN_PART2_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN_PART2_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ED25519_SIGN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_SIGN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_START != + 0), + [OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_X25519_KEYGEN] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_KEYGEN != 0), + [OTCRYPTO_FUNCTION_X25519] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519 != 0), + [OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_START != 0), + [OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_FINALIZE != + 0), + [OTCRYPTO_FUNCTION_X25519_ASYNC_START] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_ASYNC_START != 0), + [OTCRYPTO_FUNCTION_X25519_ASYNC_FINALIZE] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_X25519_ASYNC_FINALIZE != 0), + [OTCRYPTO_FUNCTION_INTEGRITY_CHECK] = + (OTCRYPTO_IS_APPROVED_OTCRYPTO_FUNCTION_INTEGRITY_CHECK != 0), +}; + +static void otcrypto_cmvp_set_indicator(otcrypto_cmvp_function_t function_id) { + if (kCryptoFunctionApproved[function_id]) { + otcrypto_cmvp_start_approved(); + } else { + otcrypto_cmvp_start_not_approved(); + } +} +#else +static void otcrypto_cmvp_set_indicator(otcrypto_cmvp_function_t function_id) { + (void)function_id; +} +#endif + +class CmvpTest : public ::testing::Test { + protected: + void SetUp() override { + // Reset the internal state + otcrypto_cmvp_service_indicator_t indicator; + otcrypto_cmvp_service_indicator(&indicator); + } +}; + +TEST_F(CmvpTest, NullIndicatorReturnsBadArgs) { + EXPECT_EQ(otcrypto_cmvp_service_indicator(nullptr).value, + OTCRYPTO_BAD_ARGS.value); +} + +TEST_F(CmvpTest, InitialIndicatorIsNoService) { + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpApprovedService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpNoService); +} + +#ifdef FIPS_MODE + +TEST_F(CmvpTest, QueryResetsIndicatorToNoService) { + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_AES); + otcrypto_cmvp_end_service(); + + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpNoService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpApprovedService); + + // Subsequent call should return kOtcryptoCmvpNoService + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpNoService); +} + +TEST_F(CmvpTest, ApprovedService) { + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_AES); + otcrypto_cmvp_end_service(); + + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpNoService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpApprovedService); +} + +TEST_F(CmvpTest, NotApprovedService) { + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_HKDF); + otcrypto_cmvp_end_service(); + + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpNoService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpNotApprovedService); +} + +TEST_F(CmvpTest, OverrideNotApproved) { + // Start with an approved function + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_AES); + // Override to not approved (e.g., due to unapproved key size) + otcrypto_cmvp_override_not_approved(); + otcrypto_cmvp_end_service(); + + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpNoService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpNotApprovedService); +} + +TEST_F(CmvpTest, NestedCallPreservesOuterApprovedStatus) { + // Outer call: approved (e.g. AES) + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_AES); + + // Inner call: not approved (e.g. HKDF) + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_HKDF); + otcrypto_cmvp_end_service(); + + // Outer call finishes + otcrypto_cmvp_end_service(); + + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpNoService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpApprovedService); +} + +TEST_F(CmvpTest, NestedCallPreservesOuterNotApprovedStatus) { + // Outer call: not approved (e.g. HKDF) + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_HKDF); + + // Inner call: approved (e.g. AES) + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_AES); + otcrypto_cmvp_end_service(); + + // Outer call finishes + otcrypto_cmvp_end_service(); + + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpNoService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpNotApprovedService); +} + +TEST_F(CmvpTest, QueryResetsCallDepth) { + // Suppose an error occurred and end_service was missed (call depth > 0) + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_AES); + // indicator called resets depth to 0 + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpNoService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpApprovedService); + + // Next call should be recognized as outermost (depth 0) + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_HKDF); + otcrypto_cmvp_end_service(); + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpNotApprovedService); +} + +TEST_F(CmvpTest, ApprovedTableCompleteness) { + for (size_t i = 0; i < OTCRYPTO_FUNCTION_MAX; ++i) { + otcrypto_cmvp_function_t func = static_cast(i); + otcrypto_cmvp_set_indicator(func); + otcrypto_cmvp_end_service(); + + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpNoService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + + if (kCryptoFunctionApproved[i]) { + EXPECT_EQ(indicator, kOtcryptoCmvpApprovedService) + << "Function index " << i << " expected approved"; + } else { + EXPECT_EQ(indicator, kOtcryptoCmvpNotApprovedService) + << "Function index " << i << " expected not approved"; + } + } +} + +// Verification of key requirements from user specification +TEST_F(CmvpTest, SpecificationKeyRequirements) { + // AES-GCM Encrypt is not approved (caller provides IV) + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT]); + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_AES_GCM_ENCRYPT_INIT]); + // AES-GCM Decrypt is approved + EXPECT_TRUE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_AES_GCM_DECRYPT]); + EXPECT_TRUE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_AES_GCM_DECRYPT_INIT]); + + // DRBG: generate, instantiate, reseed are approved, manual is not + EXPECT_TRUE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_DRBG_GENERATE]); + EXPECT_TRUE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_DRBG_INSTANTIATE]); + EXPECT_TRUE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_DRBG_RESEED]); + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_DRBG_MANUAL_GENERATE]); + + // HKDF is not approved + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_HKDF]); + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_HKDF_EXTRACT]); + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_HKDF_EXPAND]); + + // ECDH is not approved + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_ECDH_P256]); + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_ECDH_P384]); + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN]); + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN]); + + // Ed25519 is approved + EXPECT_TRUE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_ED25519_SIGN]); + EXPECT_TRUE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_ED25519_VERIFY]); + EXPECT_TRUE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_ED25519_SIGN_VERIFY]); + + // X25519 is not approved + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_X25519]); + EXPECT_FALSE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_X25519_KEYGEN]); + + // Self-integrity check is approved + EXPECT_TRUE(kCryptoFunctionApproved[OTCRYPTO_FUNCTION_INTEGRITY_CHECK]); +} + +#else // !defined(FIPS_MODE) + +TEST_F(CmvpTest, NonFipsAlwaysReturnsNoService) { + otcrypto_cmvp_set_indicator(OTCRYPTO_FUNCTION_AES); + otcrypto_cmvp_end_service(); + + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpApprovedService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpNoService); +} + +TEST_F(CmvpTest, NonFipsMacrosAreNoOps) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_AES); + OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED(); + otcrypto_cmvp_end_service(); + + otcrypto_cmvp_service_indicator_t indicator = kOtcryptoCmvpApprovedService; + EXPECT_OK(otcrypto_cmvp_service_indicator(&indicator)); + EXPECT_EQ(indicator, kOtcryptoCmvpNoService); +} + +#endif // FIPS_MODE + +} // namespace +} // namespace cmvp_unittest diff --git a/sw/device/lib/crypto/impl/config.c b/sw/device/lib/crypto/impl/config.c index f39f508d9ed6f..a0b221498378a 100644 --- a/sw/device/lib/crypto/impl/config.c +++ b/sw/device/lib/crypto/impl/config.c @@ -11,6 +11,7 @@ #include "sw/device/lib/crypto/drivers/keymgr.h" #include "sw/device/lib/crypto/drivers/otbn.h" #include "sw/device/lib/crypto/drivers/rv_core_ibex.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/include/entropy_src.h" #include "sw/device/lib/crypto/include/self_integrity.h" @@ -111,6 +112,12 @@ otcrypto_status_t otcrypto_eval_exit(otcrypto_status_t status) { HARDENED_TRY(read_state_pointer(&state)); +#ifdef FIPS_MODE + if (state != NULL && state->cmvp_call_depth > 0) { + state->cmvp_call_depth--; + } +#endif + if (state->security_level != kOtcryptoKeySecurityLevelLow) { if (read_alert_registers()) { return OTCRYPTO_FATAL_ERR; diff --git a/sw/device/lib/crypto/impl/drbg.c b/sw/device/lib/crypto/impl/drbg.c index 7e44d9747488a..545ddad160a00 100644 --- a/sw/device/lib/crypto/impl/drbg.c +++ b/sw/device/lib/crypto/impl/drbg.c @@ -8,6 +8,7 @@ #include "sw/device/lib/base/math.h" #include "sw/device/lib/base/memory.h" #include "sw/device/lib/crypto/drivers/entropy.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/impl/status.h" #include "sw/device/lib/crypto/include/config.h" @@ -113,6 +114,7 @@ static otcrypto_status_t seed_material_xor( otcrypto_status_t otcrypto_drbg_instantiate( const otcrypto_const_byte_buf_t *perso_string) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_DRBG_INSTANTIATE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers or bad length. if (perso_string != NULL && perso_string->len != 0 && @@ -133,6 +135,7 @@ otcrypto_status_t otcrypto_drbg_instantiate( otcrypto_status_t otcrypto_drbg_reseed( const otcrypto_const_byte_buf_t *additional_input) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_DRBG_RESEED); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers or bad length. if (additional_input == NULL || @@ -153,6 +156,7 @@ otcrypto_status_t otcrypto_drbg_reseed( otcrypto_status_t otcrypto_drbg_manual_instantiate( const otcrypto_const_byte_buf_t *entropy, const otcrypto_const_byte_buf_t *perso_string) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_DRBG_MANUAL_INSTANTIATE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers or bad length. if (perso_string->len != 0 && perso_string->data == NULL) { @@ -181,6 +185,7 @@ otcrypto_status_t otcrypto_drbg_manual_instantiate( otcrypto_status_t otcrypto_drbg_manual_reseed( const otcrypto_const_byte_buf_t *entropy, const otcrypto_const_byte_buf_t *additional_input) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_DRBG_MANUAL_RESEED); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers or bad length. if (additional_input == NULL || @@ -232,6 +237,7 @@ static otcrypto_status_t generate( otcrypto_status_t otcrypto_drbg_generate( const otcrypto_const_byte_buf_t *additional_input, otcrypto_word32_buf_t *drbg_output) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_DRBG_GENERATE); if (drbg_output->len == 0) { // Nothing to do. return OTCRYPTO_OK; @@ -254,6 +260,7 @@ otcrypto_status_t otcrypto_drbg_generate( otcrypto_status_t otcrypto_drbg_manual_generate( const otcrypto_const_byte_buf_t *additional_input, otcrypto_word32_buf_t *drbg_output) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_DRBG_MANUAL_GENERATE); if (drbg_output->len == 0) { // Nothing to do. return OTCRYPTO_OK; diff --git a/sw/device/lib/crypto/impl/ecc_curve25519.c b/sw/device/lib/crypto/impl/ecc_curve25519.c index 0758a9f07e49f..db4a43c657891 100644 --- a/sw/device/lib/crypto/impl/ecc_curve25519.c +++ b/sw/device/lib/crypto/impl/ecc_curve25519.c @@ -6,6 +6,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/crypto/drivers/hmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/ecc/curve25519.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/state.h" @@ -422,6 +423,8 @@ static status_t ed25519_pct_verify(const otcrypto_blinded_key_t *private_key, otcrypto_status_t otcrypto_ed25519_public_key_from_private( const otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (public_key == NULL || public_key->key == NULL) { return OTCRYPTO_BAD_ARGS; @@ -537,6 +540,8 @@ otcrypto_status_t otcrypto_ed25519_sign_verify( otcrypto_status_t otcrypto_ed25519_public_key_from_private_async_start( const otcrypto_blinded_key_t *private_key) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_START); // Check the private key. HARDENED_TRY(curve25519_private_key_length_check(private_key, kOtcryptoKeyModeEd25519)); @@ -561,6 +566,8 @@ otcrypto_status_t otcrypto_ed25519_public_key_from_private_async_start( otcrypto_status_t otcrypto_ed25519_public_key_from_private_async_finalize( otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ED25519_PUBLIC_KEY_FROM_PRIVATE_ASYNC_FINALIZE); // Finalize the keygen operation and retrieve the public key. HARDENED_TRY_WIPE_DMEM(curve25519_keygen_finalize(public_key->key)); // Calculate the public key checksum. @@ -574,6 +581,7 @@ otcrypto_status_t otcrypto_ed25519_sign_part1_async_start( otcrypto_eddsa_sign_mode_t sign_mode, otcrypto_word32_buf_t *s0, otcrypto_word32_buf_t *s1, otcrypto_word32_buf_t *r0, otcrypto_word32_buf_t *r1) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ED25519_SIGN_PART1_ASYNC_START); // Check the private key. HARDENED_TRY(curve25519_private_key_length_check(private_key, kOtcryptoKeyModeEd25519)); @@ -644,6 +652,7 @@ otcrypto_status_t otcrypto_ed25519_sign_part2_async_start( otcrypto_eddsa_sign_mode_t sign_mode, otcrypto_word32_buf_t *signature, otcrypto_word32_buf_t *s0, otcrypto_word32_buf_t *s1, otcrypto_word32_buf_t *r0, otcrypto_word32_buf_t *r1) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ED25519_SIGN_PART2_ASYNC_START); // Check the signature. HARDENED_TRY(ed25519_signature_check(signature)); @@ -708,6 +717,7 @@ otcrypto_status_t otcrypto_ed25519_sign_part2_async_start( otcrypto_status_t otcrypto_ed25519_sign_async_finalize( otcrypto_word32_buf_t *signature) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ED25519_SIGN_ASYNC_FINALIZE); // Check the signature. HARDENED_TRY(ed25519_signature_check(signature)); @@ -725,6 +735,7 @@ otcrypto_status_t otcrypto_ed25519_verify_async_start( const otcrypto_const_byte_buf_t *input_message_ph, otcrypto_eddsa_sign_mode_t sign_mode, const otcrypto_const_word32_buf_t *signature) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_START); // Check the public key. HARDENED_TRY( curve25519_public_key_length_check(public_key, kOtcryptoKeyModeEd25519)); @@ -781,6 +792,7 @@ otcrypto_status_t otcrypto_ed25519_verify_async_start( otcrypto_status_t otcrypto_ed25519_verify_async_finalize( hardened_bool_t *verification_result) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ED25519_VERIFY_ASYNC_FINALIZE); // Finalize the verify operation and retrieve the verification result. HARDENED_TRY_WIPE_DMEM(curve25519_verify_finalize(verification_result)); return otcrypto_eval_exit(OTCRYPTO_OK); @@ -801,6 +813,7 @@ otcrypto_status_t otcrypto_x25519(const otcrypto_blinded_key_t *private_key, otcrypto_status_t otcrypto_x25519_keygen_async_start( const otcrypto_blinded_key_t *private_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_START); // Check the private key. HARDENED_TRY( curve25519_private_key_length_check(private_key, kOtcryptoKeyModeX25519)); @@ -828,6 +841,7 @@ otcrypto_status_t otcrypto_x25519_keygen_async_start( otcrypto_status_t otcrypto_x25519_keygen_async_finalize( otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_X25519_KEYGEN_ASYNC_FINALIZE); (void)private_key; HARDENED_TRY_WIPE_DMEM(curve25519_x25519_keygen_finalize(public_key->key)); public_key->checksum = otcrypto_integrity_unblinded_checksum(public_key); @@ -838,6 +852,7 @@ otcrypto_status_t otcrypto_x25519_keygen_async_finalize( otcrypto_status_t otcrypto_x25519_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_X25519_ASYNC_START); // Check the private key. HARDENED_TRY( curve25519_private_key_length_check(private_key, kOtcryptoKeyModeX25519)); @@ -870,6 +885,7 @@ otcrypto_status_t otcrypto_x25519_async_start( otcrypto_status_t otcrypto_x25519_async_finalize( otcrypto_blinded_key_t *shared_secret) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_X25519_ASYNC_FINALIZE); HARDENED_TRY_WIPE_DMEM(curve25519_x25519_finalize(shared_secret->keyblob)); shared_secret->checksum = otcrypto_integrity_blinded_checksum(shared_secret); // Clear the OTBN sideload slot (in case the seed was sideloaded). diff --git a/sw/device/lib/crypto/impl/ecc_p256.c b/sw/device/lib/crypto/impl/ecc_p256.c index d445fd654bc1e..7ec59f64c4cf1 100644 --- a/sw/device/lib/crypto/impl/ecc_p256.c +++ b/sw/device/lib/crypto/impl/ecc_p256.c @@ -6,6 +6,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/crypto/drivers/hmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/ecc/p256.h" #include "sw/device/lib/crypto/impl/hash.h" #include "sw/device/lib/crypto/impl/keyblob.h" @@ -414,6 +415,7 @@ otcrypto_status_t otcrypto_ecdh_p256(const otcrypto_blinded_key_t *private_key, otcrypto_status_t otcrypto_ecc_p256_point_on_curve( const otcrypto_unblinded_key_t *point, hardened_bool_t *check_result) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECC_P256_POINT_ON_CURVE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (point == NULL || point->key == NULL || check_result == NULL) { return OTCRYPTO_BAD_ARGS; @@ -429,6 +431,7 @@ otcrypto_status_t otcrypto_ecc_p256_point_on_curve( status_t otcrypto_ecc_p256_base_point_mult( const otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECC_P256_BASE_POINT_MULT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || public_key == NULL) { return OTCRYPTO_BAD_ARGS; @@ -449,11 +452,12 @@ status_t otcrypto_ecc_p256_base_point_mult( hardened_memshred((uint32_t *)&private_scalar, kP256MaskedScalarTotalShareWords); - return OTCRYPTO_OK; + return otcrypto_eval_exit(OTCRYPTO_OK); } otcrypto_status_t otcrypto_ecdsa_p256_keygen_async_start( const otcrypto_blinded_key_t *private_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || private_key->keyblob == NULL) { return OTCRYPTO_BAD_ARGS; @@ -473,6 +477,8 @@ otcrypto_status_t otcrypto_ecdsa_p256_keygen_async_start( otcrypto_status_t otcrypto_ecdsa_p256_keygen_async_finalize( otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDSA_P256_KEYGEN_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for any NULL pointers. if (private_key == NULL || public_key == NULL || @@ -498,6 +504,8 @@ otcrypto_status_t otcrypto_ecdsa_p256_keygen_async_finalize( otcrypto_status_t otcrypto_ecdsa_p256_dice_keygen_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_const_word32_buf_t *attestation_seed) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDSA_P256_DICE_KEYGEN_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || private_key->keyblob == NULL) { return OTCRYPTO_BAD_ARGS; @@ -526,6 +534,8 @@ otcrypto_status_t otcrypto_ecdsa_p256_sign_config_k_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_blinded_key_t *secret_scalar, const otcrypto_hash_digest_t message_digest) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_CONFIG_K_ASYNC_START); // Do initial checks on the private key and digest. HARDENED_TRY( otcrypto_ecdsa_p256_sign_async_start_setup(private_key, message_digest)); @@ -561,6 +571,7 @@ otcrypto_status_t otcrypto_ecdsa_p256_sign_config_k_async_start( otcrypto_status_t otcrypto_ecdsa_p256_sign_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_hash_digest_t message_digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_START); // Do initial checks on the private key and digest. HARDENED_TRY( otcrypto_ecdsa_p256_sign_async_start_setup(private_key, message_digest)); @@ -597,6 +608,7 @@ otcrypto_status_t otcrypto_ecdsa_p256_sign_async_start( otcrypto_status_t otcrypto_ecdsa_p256_sign_async_finalize( otcrypto_word32_buf_t *signature) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDSA_P256_SIGN_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (signature->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -621,6 +633,8 @@ otcrypto_status_t otcrypto_ecdsa_p256_dice_sign_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_hash_digest_t message_digest, const otcrypto_const_word32_buf_t *attestation_seed) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDSA_P256_DICE_SIGN_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || private_key->keyblob == NULL || message_digest.data == NULL) { @@ -664,6 +678,7 @@ otcrypto_status_t otcrypto_ecdsa_p256_verify_async_start( const otcrypto_unblinded_key_t *public_key, const otcrypto_hash_digest_t message_digest, const otcrypto_const_word32_buf_t *signature) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (public_key == NULL || signature->data == NULL || message_digest.data == NULL || public_key->key == NULL) { @@ -718,6 +733,8 @@ otcrypto_status_t otcrypto_ecdsa_p256_verify_async_start( otcrypto_status_t otcrypto_ecdsa_p256_verify_async_finalize( const otcrypto_const_word32_buf_t *signature, hardened_bool_t *verification_result) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDSA_P256_VERIFY_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (verification_result == NULL) { return OTCRYPTO_BAD_ARGS; @@ -735,6 +752,7 @@ otcrypto_status_t otcrypto_ecdsa_p256_verify_async_finalize( otcrypto_status_t otcrypto_ecdh_p256_keygen_async_start( const otcrypto_blinded_key_t *private_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || private_key->keyblob == NULL) { return OTCRYPTO_BAD_ARGS; @@ -753,6 +771,8 @@ otcrypto_status_t otcrypto_ecdh_p256_keygen_async_start( otcrypto_status_t otcrypto_ecdh_p256_keygen_async_finalize( otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDH_P256_KEYGEN_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for any NULL pointers. if (private_key == NULL || public_key == NULL || @@ -775,6 +795,7 @@ otcrypto_status_t otcrypto_ecdh_p256_keygen_async_finalize( otcrypto_status_t otcrypto_ecdh_p256_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || public_key == NULL || public_key->key == NULL || private_key->keyblob == NULL) { @@ -837,6 +858,7 @@ otcrypto_status_t otcrypto_ecdh_p256_async_start( otcrypto_status_t otcrypto_ecdh_p256_async_finalize( otcrypto_blinded_key_t *shared_secret) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDH_P256_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (shared_secret == NULL || shared_secret->keyblob == NULL) { return OTCRYPTO_BAD_ARGS; diff --git a/sw/device/lib/crypto/impl/ecc_p384.c b/sw/device/lib/crypto/impl/ecc_p384.c index 8f3436b9349ed..2b30fe075a60b 100644 --- a/sw/device/lib/crypto/impl/ecc_p384.c +++ b/sw/device/lib/crypto/impl/ecc_p384.c @@ -6,6 +6,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/crypto/drivers/hmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/ecc/p384.h" #include "sw/device/lib/crypto/impl/hash.h" #include "sw/device/lib/crypto/impl/keyblob.h" @@ -53,6 +54,7 @@ OT_NOINLINE static status_t load_private_scalar( otcrypto_status_t otcrypto_ecdsa_p384_keygen_async_start( const otcrypto_blinded_key_t *private_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || private_key->keyblob == NULL) { return OTCRYPTO_BAD_ARGS; @@ -315,6 +317,7 @@ otcrypto_status_t otcrypto_ecdh_p384(const otcrypto_blinded_key_t *private_key, otcrypto_status_t otcrypto_ecc_p384_point_on_curve( const otcrypto_unblinded_key_t *point, hardened_bool_t *check_result) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECC_P384_POINT_ON_CURVE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (point == NULL || point->key == NULL || check_result == NULL) { return OTCRYPTO_BAD_ARGS; @@ -330,6 +333,7 @@ otcrypto_status_t otcrypto_ecc_p384_point_on_curve( status_t otcrypto_ecc_p384_base_point_mult( const otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECC_P384_BASE_POINT_MULT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || public_key == NULL) { return OTCRYPTO_BAD_ARGS; @@ -350,11 +354,13 @@ status_t otcrypto_ecc_p384_base_point_mult( hardened_memshred((uint32_t *)&private_scalar, kP384MaskedScalarTotalShareWords); - return OTCRYPTO_OK; + return otcrypto_eval_exit(OTCRYPTO_OK); } otcrypto_status_t otcrypto_ecdsa_p384_keygen_async_finalize( otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDSA_P384_KEYGEN_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for any NULL pointers. if (private_key == NULL || public_key == NULL || @@ -436,6 +442,8 @@ otcrypto_status_t otcrypto_ecdsa_p384_sign_config_k_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_blinded_key_t *secret_scalar, const otcrypto_hash_digest_t message_digest) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_CONFIG_K_ASYNC_START); // Do initial checks on the private key and digest. HARDENED_TRY( otcrypto_ecdsa_p384_sign_async_start_setup(private_key, message_digest)); @@ -474,6 +482,7 @@ otcrypto_status_t otcrypto_ecdsa_p384_sign_config_k_async_start( otcrypto_status_t otcrypto_ecdsa_p384_sign_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_hash_digest_t message_digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_START); // Do initial checks on the private key and digest. HARDENED_TRY( otcrypto_ecdsa_p384_sign_async_start_setup(private_key, message_digest)); @@ -511,6 +520,7 @@ otcrypto_status_t otcrypto_ecdsa_p384_sign_async_start( otcrypto_status_t otcrypto_ecdsa_p384_sign_async_finalize( otcrypto_word32_buf_t *signature) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDSA_P384_SIGN_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (signature->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -535,6 +545,7 @@ otcrypto_status_t otcrypto_ecdsa_p384_verify_async_start( const otcrypto_unblinded_key_t *public_key, const otcrypto_hash_digest_t message_digest, const otcrypto_const_word32_buf_t *signature) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (public_key == NULL || signature->data == NULL || message_digest.data == NULL || public_key->key == NULL) { @@ -589,6 +600,8 @@ otcrypto_status_t otcrypto_ecdsa_p384_verify_async_start( otcrypto_status_t otcrypto_ecdsa_p384_verify_async_finalize( const otcrypto_const_word32_buf_t *signature, hardened_bool_t *verification_result) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDSA_P384_VERIFY_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (verification_result == NULL) { return OTCRYPTO_BAD_ARGS; @@ -609,6 +622,7 @@ otcrypto_status_t otcrypto_ecdsa_p384_verify_async_finalize( otcrypto_status_t otcrypto_ecdh_p384_keygen_async_start( const otcrypto_blinded_key_t *private_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || private_key->keyblob == NULL) { return OTCRYPTO_BAD_ARGS; @@ -625,6 +639,8 @@ otcrypto_status_t otcrypto_ecdh_p384_keygen_async_start( otcrypto_status_t otcrypto_ecdh_p384_keygen_async_finalize( otcrypto_blinded_key_t *private_key, otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_ECDH_P384_KEYGEN_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for any NULL pointers. if (private_key == NULL || public_key == NULL || @@ -647,6 +663,7 @@ otcrypto_status_t otcrypto_ecdh_p384_keygen_async_finalize( otcrypto_status_t otcrypto_ecdh_p384_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (private_key == NULL || public_key == NULL || public_key->key == NULL || private_key->keyblob == NULL) { @@ -709,6 +726,7 @@ otcrypto_status_t otcrypto_ecdh_p384_async_start( otcrypto_status_t otcrypto_ecdh_p384_async_finalize( otcrypto_blinded_key_t *shared_secret) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_ECDH_P384_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (shared_secret == NULL || shared_secret->keyblob == NULL) { return OTCRYPTO_BAD_ARGS; diff --git a/sw/device/lib/crypto/impl/hkdf.c b/sw/device/lib/crypto/impl/hkdf.c index e9ea1337fc044..4df85c708c56b 100644 --- a/sw/device/lib/crypto/impl/hkdf.c +++ b/sw/device/lib/crypto/impl/hkdf.c @@ -7,6 +7,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/base/math.h" #include "sw/device/lib/crypto/drivers/hmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/status.h" #include "sw/device/lib/crypto/include/config.h" @@ -139,6 +140,7 @@ static status_t hkdf_check_prk(size_t digest_words, otcrypto_status_t otcrypto_hkdf_extract(const otcrypto_blinded_key_t *ikm, const otcrypto_const_byte_buf_t *salt, otcrypto_blinded_key_t *prk) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_HKDF_EXTRACT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for null pointers. if (ikm == NULL || ikm->keyblob == NULL || prk == NULL || @@ -248,6 +250,7 @@ otcrypto_status_t otcrypto_hkdf_extract(const otcrypto_blinded_key_t *ikm, otcrypto_status_t otcrypto_hkdf_expand(const otcrypto_blinded_key_t *prk, const otcrypto_const_byte_buf_t *info, otcrypto_blinded_key_t *okm) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_HKDF_EXPAND); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (okm == NULL || okm->keyblob == NULL || prk == NULL || prk->keyblob == NULL) { diff --git a/sw/device/lib/crypto/impl/hmac.c b/sw/device/lib/crypto/impl/hmac.c index 9d0f35f7d6e55..2b51ae2d48992 100644 --- a/sw/device/lib/crypto/impl/hmac.c +++ b/sw/device/lib/crypto/impl/hmac.c @@ -7,6 +7,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/crypto/drivers/hmac.h" #include "sw/device/lib/crypto/drivers/rv_core_ibex.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/impl/status.h" @@ -189,6 +190,7 @@ OT_WARN_UNUSED_RESULT otcrypto_status_t otcrypto_hmac(const otcrypto_blinded_key_t *key, const otcrypto_const_byte_buf_t *input_message, otcrypto_word32_buf_t *tag) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_HMAC); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for null pointers. if (tag == NULL || tag->data == NULL || input_message == NULL || @@ -196,12 +198,16 @@ otcrypto_status_t otcrypto_hmac(const otcrypto_blinded_key_t *key, return OTCRYPTO_BAD_ARGS; } #endif - // Preload the tag with randomness. - HARDENED_TRY(hardened_memshred(tag->data, tag->len)); - // Check the key for null pointers or invalid configurations. HARDENED_TRY(check_key(key)); + if (key->config.key_length < 14) { + OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED(); + } + + // Preload the tag with randomness. + HARDENED_TRY(hardened_memshred(tag->data, tag->len)); + if (key->config.key_mode == kOtcryptoKeyModeHmacSha256) { HARDENED_TRY(stateful_health_check(kTestHmacSha256Bit)); } else { @@ -300,6 +306,7 @@ otcrypto_status_t otcrypto_hmac(const otcrypto_blinded_key_t *key, otcrypto_status_t otcrypto_hmac_init(otcrypto_hmac_context_t *ctx, const otcrypto_blinded_key_t *key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_HMAC_INIT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL) { return OTCRYPTO_BAD_ARGS; @@ -309,6 +316,10 @@ otcrypto_status_t otcrypto_hmac_init(otcrypto_hmac_context_t *ctx, // Check the key for null pointers or invalid configurations. HARDENED_TRY(check_key(key)); + if (key->config.key_length < 14) { + OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED(); + } + if (key->config.key_mode == kOtcryptoKeyModeHmacSha256) { HARDENED_TRY(stateful_health_check(kTestHmacSha256Bit)); } else { @@ -390,6 +401,7 @@ otcrypto_status_t otcrypto_hmac_init(otcrypto_hmac_context_t *ctx, otcrypto_status_t otcrypto_hmac_update( otcrypto_hmac_context_t *const ctx, const otcrypto_const_byte_buf_t *input_message) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_HMAC_UPDATE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || input_message == NULL) { return OTCRYPTO_BAD_ARGS; @@ -438,6 +450,7 @@ otcrypto_status_t otcrypto_hmac_update( otcrypto_status_t otcrypto_hmac_final(otcrypto_hmac_context_t *const ctx, otcrypto_word32_buf_t *tag) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_HMAC_FINAL); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || tag == NULL || tag->data == NULL) { return OTCRYPTO_BAD_ARGS; diff --git a/sw/device/lib/crypto/impl/kdf_ctr.c b/sw/device/lib/crypto/impl/kdf_ctr.c index def55832961a5..7693876b05de0 100644 --- a/sw/device/lib/crypto/impl/kdf_ctr.c +++ b/sw/device/lib/crypto/impl/kdf_ctr.c @@ -7,6 +7,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/base/math.h" #include "sw/device/lib/crypto/drivers/hmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/status.h" #include "sw/device/lib/crypto/include/config.h" @@ -72,6 +73,7 @@ otcrypto_status_t otcrypto_kdf_ctr_hmac( const otcrypto_const_byte_buf_t *label, const otcrypto_const_byte_buf_t *context, otcrypto_blinded_key_t *output_key_material) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_KDF_CTR_HMAC); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check NULL pointers. if (output_key_material == NULL || output_key_material->keyblob == NULL || @@ -90,6 +92,11 @@ otcrypto_status_t otcrypto_kdf_ctr_hmac( } #endif + if (key_derivation_key->config.key_length < 14 || + output_key_material->config.key_length < 14) { + OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED(); + } + // Check the private key checksum. if (otcrypto_integrity_blinded_key_check(key_derivation_key) != kHardenedBoolTrue) { diff --git a/sw/device/lib/crypto/impl/key_transport.c b/sw/device/lib/crypto/impl/key_transport.c index 508d30c6b04b2..a2b45091e6dfd 100644 --- a/sw/device/lib/crypto/impl/key_transport.c +++ b/sw/device/lib/crypto/impl/key_transport.c @@ -10,6 +10,7 @@ #include "sw/device/lib/crypto/drivers/aes.h" #include "sw/device/lib/crypto/drivers/cryptolib_build_info.h" #include "sw/device/lib/crypto/impl/aes_kwp/aes_kwp.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/status.h" #include "sw/device/lib/crypto/include/config.h" @@ -23,6 +24,7 @@ otcrypto_status_t otcrypto_symmetric_keygen( const otcrypto_const_byte_buf_t *perso_string, otcrypto_blinded_key_t *key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SYMMETRIC_KEYGEN); if (key == NULL || key->keyblob == NULL) { // COVERAGE (MISSING) We do not cover null inputs return OTCRYPTO_BAD_ARGS; @@ -118,6 +120,7 @@ otcrypto_status_t otcrypto_hw_backed_attestation_key( otcrypto_status_t ot_crypto_hw_backed_keygen(hardened_bool_t attestation, otcrypto_blinded_key_t *key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_HW_BACKED_KEYGEN); if (key == NULL || key->keyblob == NULL) { return OTCRYPTO_BAD_ARGS; } @@ -264,6 +267,7 @@ static void hw_wipe_guard(uint32_t *dummy) { otcrypto_status_t otcrypto_key_wrap(const otcrypto_blinded_key_t *key_to_wrap, const otcrypto_blinded_key_t *key_kek, otcrypto_word32_buf_t *wrapped_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_KEY_WRAP); if (key_to_wrap == NULL || key_to_wrap->keyblob == NULL || key_kek == NULL || key_kek->keyblob == NULL || wrapped_key == NULL || wrapped_key->data == NULL) { @@ -327,6 +331,7 @@ otcrypto_status_t otcrypto_key_unwrap( const otcrypto_const_word32_buf_t *wrapped_key, const otcrypto_blinded_key_t *key_kek, hardened_bool_t *success, otcrypto_blinded_key_t *unwrapped_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_KEY_UNWRAP); if (wrapped_key == NULL || wrapped_key->data == NULL || key_kek == NULL || key_kek->keyblob == NULL || success == NULL || unwrapped_key == NULL || unwrapped_key->keyblob == NULL) { diff --git a/sw/device/lib/crypto/impl/kmac.c b/sw/device/lib/crypto/impl/kmac.c index 601d91c1bc35a..7e360a30d4299 100644 --- a/sw/device/lib/crypto/impl/kmac.c +++ b/sw/device/lib/crypto/impl/kmac.c @@ -6,6 +6,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/crypto/drivers/kmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/impl/status.h" @@ -28,6 +29,7 @@ otcrypto_status_t otcrypto_kmac( otcrypto_blinded_key_t *key, const otcrypto_const_byte_buf_t *input_message, const otcrypto_const_byte_buf_t *customization_string, size_t required_output_len, otcrypto_word32_buf_t *tag) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_KMAC); // TODO (#16410) Revisit/complete error checks #ifndef OTCRYPTO_DISABLE_NULL_CHECKS diff --git a/sw/device/lib/crypto/impl/kmac_kdf.c b/sw/device/lib/crypto/impl/kmac_kdf.c index f3cb36cb39bb5..a41492e9bc12d 100644 --- a/sw/device/lib/crypto/impl/kmac_kdf.c +++ b/sw/device/lib/crypto/impl/kmac_kdf.c @@ -8,6 +8,7 @@ #include "sw/device/lib/base/math.h" #include "sw/device/lib/crypto/drivers/keymgr.h" #include "sw/device/lib/crypto/drivers/kmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/keyblob.h" #include "sw/device/lib/crypto/impl/status.h" #include "sw/device/lib/crypto/include/config.h" @@ -31,6 +32,7 @@ otcrypto_status_t otcrypto_kmac_kdf( const otcrypto_const_byte_buf_t *label, const otcrypto_const_byte_buf_t *context, otcrypto_blinded_key_t *output_key_material) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_KMAC_KDF); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check NULL pointers. if (key_derivation_key == NULL || key_derivation_key->keyblob == NULL || @@ -45,6 +47,10 @@ otcrypto_status_t otcrypto_kmac_kdf( } #endif + if (output_key_material->config.key_length < 14) { + OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED(); + } + hardened_bool_t is_sideloaded __attribute__((cleanup(sideload_wipe_guard))) = kHardenedBoolFalse; diff --git a/sw/device/lib/crypto/impl/mock_state.cc b/sw/device/lib/crypto/impl/mock_state.cc index 17808d30a1c52..06820ab218f25 100644 --- a/sw/device/lib/crypto/impl/mock_state.cc +++ b/sw/device/lib/crypto/impl/mock_state.cc @@ -17,7 +17,10 @@ static crypto_state_t default_state = { .self_check_state = kHardenedBoolFalse, .locked_state = kHardenedBoolFalse, .csrng_instantiated = kHardenedBoolFalse, - .csrng_is_default = kHardenedBoolFalse, +#ifdef FIPS_MODE + .cmvp_service_indicator = kOtcryptoCmvpNoService, + .cmvp_call_depth = 0, +#endif }; otcrypto_status_t init_state(otcrypto_state_t *state, @@ -28,6 +31,10 @@ otcrypto_status_t init_state(otcrypto_state_t *state, internal_state->self_check_state = kHardenedBoolFalse; internal_state->csrng_instantiated = kHardenedBoolFalse; internal_state->csrng_is_default = kHardenedBoolFalse; +#ifdef FIPS_MODE + internal_state->cmvp_service_indicator = kOtcryptoCmvpNoService; + internal_state->cmvp_call_depth = 0; +#endif internal_state->security_level = security_level; return OTCRYPTO_OK; } diff --git a/sw/device/lib/crypto/impl/rsa.c b/sw/device/lib/crypto/impl/rsa.c index 0a618aab5e4c3..c21dc451bdc50 100644 --- a/sw/device/lib/crypto/impl/rsa.c +++ b/sw/device/lib/crypto/impl/rsa.c @@ -10,6 +10,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/base/math.h" #include "sw/device/lib/crypto/drivers/otbn.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/hash.h" #include "sw/device/lib/crypto/impl/rsa/rsa_encryption.h" #include "sw/device/lib/crypto/impl/rsa/rsa_signature.h" @@ -104,6 +105,7 @@ static hardened_bool_t bignum_lt(const uint32_t *a, const uint32_t *b, otcrypto_status_t otcrypto_rsa_public_key_construct( otcrypto_rsa_size_t size, const otcrypto_const_word32_buf_t *modulus, otcrypto_unblinded_key_t *public_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_PUBLIC_KEY_CONSTRUCT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (modulus == NULL || modulus->data == NULL || public_key == NULL || public_key->key == NULL) { @@ -296,6 +298,10 @@ static status_t public_key_structural_check( } otcrypto_status_t otcrypto_rsa_keygen_async_start(otcrypto_rsa_size_t size) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_START); + if (size == kOtcryptoRsaSize2048) { + OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED(); + } switch (launder32(size)) { case kOtcryptoRsaSize2048: HARDENED_CHECK_EQ(size, kOtcryptoRsaSize2048); @@ -343,6 +349,7 @@ otcrypto_status_t otcrypto_rsa_private_key_from_exponents( const otcrypto_const_word32_buf_t *d_share0, const otcrypto_const_word32_buf_t *d_share1, otcrypto_blinded_key_t *private_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_PRIVATE_KEY_FROM_EXPONENTS); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (modulus == NULL || modulus->data == NULL || d_share0 == NULL || d_share0->data == NULL || d_share1 == NULL || d_share1->data == NULL || @@ -581,6 +588,7 @@ static otcrypto_status_t rsa_pct_verify( otcrypto_status_t otcrypto_rsa_keygen_async_finalize( otcrypto_unblinded_key_t *public_key, otcrypto_blinded_key_t *private_key) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_KEYGEN_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers. if (public_key == NULL || public_key->key == NULL || private_key == NULL || @@ -592,6 +600,9 @@ otcrypto_status_t otcrypto_rsa_keygen_async_finalize( // Infer the RSA size from the public key modulus. otcrypto_rsa_size_t size; HARDENED_TRY(rsa_size_from_public_key(public_key, &size)); + if (size == kOtcryptoRsaSize2048) { + OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED(); + } // Check the caller-provided public key buffer. HARDENED_TRY(public_key_structural_check(public_key)); @@ -670,6 +681,8 @@ otcrypto_status_t otcrypto_rsa_keypair_from_cofactor_async_start( otcrypto_rsa_size_t size, const otcrypto_const_word32_buf_t *modulus, const otcrypto_const_word32_buf_t *cofactor_share0, const otcrypto_const_word32_buf_t *cofactor_share1) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (modulus == NULL || modulus->data == NULL || cofactor_share0 == NULL || cofactor_share0->data == NULL || cofactor_share1 == NULL || @@ -677,6 +690,9 @@ otcrypto_status_t otcrypto_rsa_keypair_from_cofactor_async_start( return OTCRYPTO_BAD_ARGS; } #endif + if (size == kOtcryptoRsaSize2048) { + OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED(); + } // Verify the input buffers HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(modulus)); @@ -742,6 +758,8 @@ otcrypto_status_t otcrypto_rsa_keypair_from_cofactor_async_start( otcrypto_status_t otcrypto_rsa_keypair_from_cofactor_async_finalize( otcrypto_unblinded_key_t *public_key, otcrypto_blinded_key_t *private_key) { + OTCRYPTO_SET_CMVP_INDICATOR( + OTCRYPTO_FUNCTION_RSA_KEYPAIR_FROM_COFACTOR_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers. if (public_key == NULL || public_key->key == NULL || private_key == NULL || @@ -753,6 +771,9 @@ otcrypto_status_t otcrypto_rsa_keypair_from_cofactor_async_finalize( // Infer the RSA size from the public key modulus. otcrypto_rsa_size_t size; HARDENED_TRY(rsa_size_from_public_key(public_key, &size)); + if (size == kOtcryptoRsaSize2048) { + OTCRYPTO_CMVP_OVERRIDE_NOT_APPROVED(); + } // Check the caller-provided public key buffer. HARDENED_TRY(public_key_structural_check(public_key)); @@ -851,6 +872,7 @@ otcrypto_status_t otcrypto_rsa_sign_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_hash_digest_t message_digest, otcrypto_rsa_padding_t padding_mode) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers. if (message_digest.data == NULL || private_key == NULL || @@ -919,6 +941,7 @@ otcrypto_status_t otcrypto_rsa_sign_async_start( otcrypto_status_t otcrypto_rsa_sign_async_finalize( otcrypto_word32_buf_t *signature) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_SIGN_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers. if (signature == NULL || signature->data == NULL) { @@ -959,6 +982,7 @@ otcrypto_status_t otcrypto_rsa_sign_async_finalize( otcrypto_status_t otcrypto_rsa_verify_async_start( const otcrypto_unblinded_key_t *public_key, const otcrypto_const_word32_buf_t *signature) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers. if (public_key == NULL || public_key->key == NULL || signature == NULL || @@ -1044,6 +1068,7 @@ otcrypto_status_t otcrypto_rsa_verify_async_start( otcrypto_status_t otcrypto_rsa_verify_async_finalize( const otcrypto_hash_digest_t message_digest, otcrypto_rsa_padding_t padding_mode, hardened_bool_t *verification_result) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_VERIFY_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers. if (message_digest.data == NULL || verification_result == NULL) { @@ -1067,6 +1092,7 @@ otcrypto_status_t otcrypto_rsa_encrypt_async_start( const otcrypto_hash_mode_t hash_mode, const otcrypto_const_byte_buf_t *message, const otcrypto_const_byte_buf_t *label) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers. if (public_key == NULL || public_key->key == NULL) { @@ -1143,6 +1169,7 @@ otcrypto_status_t otcrypto_rsa_encrypt_async_start( otcrypto_status_t otcrypto_rsa_encrypt_async_finalize( otcrypto_word32_buf_t *ciphertext) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_ENCRYPT_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers. if (ciphertext == NULL || ciphertext->data == NULL) { @@ -1185,6 +1212,7 @@ otcrypto_status_t otcrypto_rsa_encrypt_async_finalize( otcrypto_status_t otcrypto_rsa_decrypt_async_start( const otcrypto_blinded_key_t *private_key, const otcrypto_const_word32_buf_t *ciphertext) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_START); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS // Check for NULL pointers. if (private_key == NULL || private_key->keyblob == NULL || @@ -1297,6 +1325,7 @@ otcrypto_status_t otcrypto_rsa_decrypt_async_finalize( const otcrypto_hash_mode_t hash_mode, const otcrypto_const_byte_buf_t *label, otcrypto_byte_buf_t *plaintext, size_t *plaintext_bytelen) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_RSA_DECRYPT_ASYNC_FINALIZE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (plaintext == NULL || plaintext->data == NULL || label == NULL || label->data == NULL || plaintext_bytelen == NULL) { diff --git a/sw/device/lib/crypto/impl/self_integrity.c b/sw/device/lib/crypto/impl/self_integrity.c index 3921bd24b2e2d..bfbb217529998 100644 --- a/sw/device/lib/crypto/impl/self_integrity.c +++ b/sw/device/lib/crypto/impl/self_integrity.c @@ -5,6 +5,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/base/macros.h" #include "sw/device/lib/crypto/drivers/hmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/impl/status.h" #include "sw/device/lib/crypto/include/integrity.h" @@ -15,11 +16,13 @@ extern const uint8_t _libotcrypto_start_[]; extern const uint8_t _libotcrypto_end_[]; otcrypto_status_t otcrypto_integrity_check(void) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_INTEGRITY_CHECK); crypto_state_t *state = NULL; HARDENED_TRY(read_state_pointer(&state)); if (state->locked_state == kHardenedBoolTrue) { + otcrypto_cmvp_end_service(); return OTCRYPTO_FATAL_ERR; } @@ -67,16 +70,22 @@ otcrypto_status_t otcrypto_integrity_check(void) { if (diff != 0) { // Lock the cryptolib if the self-integrity check failed state->locked_state = kHardenedBoolTrue; + otcrypto_cmvp_end_service(); return OTCRYPTO_FATAL_ERR; } // Set the stateful word that the self-integrity check is done state->self_check_state = kHardenedBoolTrue; + otcrypto_cmvp_end_service(); return OTCRYPTO_OK; } #else -otcrypto_status_t otcrypto_integrity_check(void) { return OTCRYPTO_OK; } +otcrypto_status_t otcrypto_integrity_check(void) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_INTEGRITY_CHECK); + otcrypto_cmvp_end_service(); + return OTCRYPTO_OK; +} #endif diff --git a/sw/device/lib/crypto/impl/sha2.c b/sw/device/lib/crypto/impl/sha2.c index f1a79f4545655..2c27b18ec1a60 100644 --- a/sw/device/lib/crypto/impl/sha2.c +++ b/sw/device/lib/crypto/impl/sha2.c @@ -8,6 +8,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/crypto/drivers/hmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/impl/status.h" #include "sw/device/lib/crypto/include/config.h" @@ -23,6 +24,7 @@ static_assert( otcrypto_status_t otcrypto_sha2_256(const otcrypto_const_byte_buf_t *message, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA2_256); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (message == NULL || (message->data == NULL && message->len != 0)) { return OTCRYPTO_BAD_ARGS; @@ -44,6 +46,7 @@ otcrypto_status_t otcrypto_sha2_256(const otcrypto_const_byte_buf_t *message, otcrypto_status_t otcrypto_sha2_384(const otcrypto_const_byte_buf_t *message, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA2_384); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (message == NULL || (message->data == NULL && message->len != 0)) { return OTCRYPTO_BAD_ARGS; @@ -65,6 +68,7 @@ otcrypto_status_t otcrypto_sha2_384(const otcrypto_const_byte_buf_t *message, otcrypto_status_t otcrypto_sha2_512(const otcrypto_const_byte_buf_t *message, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA2_512); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (message == NULL || (message->data == NULL && message->len != 0)) { return OTCRYPTO_BAD_ARGS; @@ -86,6 +90,7 @@ otcrypto_status_t otcrypto_sha2_512(const otcrypto_const_byte_buf_t *message, otcrypto_status_t otcrypto_sha2_init(otcrypto_hash_mode_t hash_mode, otcrypto_sha2_context_t *ctx) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA2_INIT); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL) { return OTCRYPTO_BAD_ARGS; @@ -155,6 +160,7 @@ static status_t check_lengths(hmac_ctx_t *hmac_ctx) { otcrypto_status_t otcrypto_sha2_update( otcrypto_sha2_context_t *ctx, const otcrypto_const_byte_buf_t *message) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA2_UPDATE); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || message == NULL) { return OTCRYPTO_BAD_ARGS; @@ -179,6 +185,7 @@ otcrypto_status_t otcrypto_sha2_update( otcrypto_status_t otcrypto_sha2_final(otcrypto_sha2_context_t *ctx, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA2_FINAL); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (ctx == NULL || digest == NULL || digest->data == NULL) { return OTCRYPTO_BAD_ARGS; diff --git a/sw/device/lib/crypto/impl/sha3.c b/sw/device/lib/crypto/impl/sha3.c index b3b16e650cd4b..96dc5ae92d969 100644 --- a/sw/device/lib/crypto/impl/sha3.c +++ b/sw/device/lib/crypto/impl/sha3.c @@ -8,6 +8,7 @@ #include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/crypto/drivers/kmac.h" +#include "sw/device/lib/crypto/impl/cmvp.h" #include "sw/device/lib/crypto/impl/state.h" #include "sw/device/lib/crypto/impl/status.h" #include "sw/device/lib/crypto/include/config.h" @@ -17,6 +18,7 @@ otcrypto_status_t otcrypto_sha3_224(const otcrypto_const_byte_buf_t *message, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA3_224); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (digest == NULL || digest->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -36,6 +38,7 @@ otcrypto_status_t otcrypto_sha3_224(const otcrypto_const_byte_buf_t *message, otcrypto_status_t otcrypto_sha3_256(const otcrypto_const_byte_buf_t *message, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA3_256); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (digest == NULL || digest->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -55,6 +58,7 @@ otcrypto_status_t otcrypto_sha3_256(const otcrypto_const_byte_buf_t *message, otcrypto_status_t otcrypto_sha3_384(const otcrypto_const_byte_buf_t *message, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA3_384); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (digest == NULL || digest->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -74,6 +78,7 @@ otcrypto_status_t otcrypto_sha3_384(const otcrypto_const_byte_buf_t *message, otcrypto_status_t otcrypto_sha3_512(const otcrypto_const_byte_buf_t *message, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHA3_512); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (digest == NULL || digest->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -93,6 +98,7 @@ otcrypto_status_t otcrypto_sha3_512(const otcrypto_const_byte_buf_t *message, otcrypto_status_t otcrypto_shake128(const otcrypto_const_byte_buf_t *message, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHAKE128); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (digest == NULL || digest->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -108,6 +114,7 @@ otcrypto_status_t otcrypto_shake128(const otcrypto_const_byte_buf_t *message, otcrypto_status_t otcrypto_shake256(const otcrypto_const_byte_buf_t *message, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_SHAKE256); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (digest == NULL || digest->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -126,6 +133,7 @@ otcrypto_status_t otcrypto_cshake128( const otcrypto_const_byte_buf_t *function_name_string, const otcrypto_const_byte_buf_t *customization_string, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_CSHAKE128); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (digest == NULL || digest->data == NULL) { return OTCRYPTO_BAD_ARGS; @@ -155,6 +163,7 @@ otcrypto_status_t otcrypto_cshake256( const otcrypto_const_byte_buf_t *function_name_string, const otcrypto_const_byte_buf_t *customization_string, otcrypto_hash_digest_t *digest) { + OTCRYPTO_SET_CMVP_INDICATOR(OTCRYPTO_FUNCTION_CSHAKE256); #ifndef OTCRYPTO_DISABLE_NULL_CHECKS if (digest == NULL || digest->data == NULL) { return OTCRYPTO_BAD_ARGS; diff --git a/sw/device/lib/crypto/impl/state.c b/sw/device/lib/crypto/impl/state.c index ee07b735e14bf..e06446a811084 100644 --- a/sw/device/lib/crypto/impl/state.c +++ b/sw/device/lib/crypto/impl/state.c @@ -22,6 +22,10 @@ otcrypto_status_t init_state(otcrypto_state_t *state, internal_state->self_check_state = kHardenedBoolFalse; internal_state->csrng_instantiated = kHardenedBoolFalse; internal_state->csrng_is_default = kHardenedBoolFalse; +#ifdef FIPS_MODE + internal_state->cmvp_service_indicator = kOtcryptoCmvpNoService; + internal_state->cmvp_call_depth = 0; +#endif internal_state->security_level = security_level; return OTCRYPTO_OK; } diff --git a/sw/device/lib/crypto/impl/state.h b/sw/device/lib/crypto/impl/state.h index a799f4303ed7a..3e2a961c67e8c 100644 --- a/sw/device/lib/crypto/impl/state.h +++ b/sw/device/lib/crypto/impl/state.h @@ -21,6 +21,8 @@ typedef struct crypto_state { hardened_bool_t locked_state; hardened_bool_t csrng_instantiated; hardened_bool_t csrng_is_default; + otcrypto_cmvp_service_indicator_t cmvp_service_indicator; + uint32_t cmvp_call_depth; } crypto_state_t; static_assert(sizeof(otcrypto_state_t) >= sizeof(crypto_state_t), diff --git a/sw/device/lib/crypto/include/BUILD b/sw/device/lib/crypto/include/BUILD index 1eabecca06823..c022d17ad6d5a 100644 --- a/sw/device/lib/crypto/include/BUILD +++ b/sw/device/lib/crypto/include/BUILD @@ -49,6 +49,7 @@ cc_library( "aes.h", "aes_gcm.h", "cmac.h", + "cmvp.h", "config.h", "cryptolib_build_info.h", "datatypes.h", @@ -87,6 +88,7 @@ cc_library( "aes.h", "aes_gcm.h", "cmac.h", + "cmvp.h", "config.h", "cryptolib_build_info.h", "datatypes.h", diff --git a/sw/device/lib/crypto/include/cmvp.h b/sw/device/lib/crypto/include/cmvp.h new file mode 100644 index 0000000000000..97aadad74fc9c --- /dev/null +++ b/sw/device/lib/crypto/include/cmvp.h @@ -0,0 +1,37 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OPENTITAN_SW_DEVICE_LIB_CRYPTO_INCLUDE_CMVP_H_ +#define OPENTITAN_SW_DEVICE_LIB_CRYPTO_INCLUDE_CMVP_H_ + +#include "datatypes.h" + +/** + * @file + * @brief CMVP service indicator for the OpenTitan cryptography library. + */ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Provides the service indicator for the most recently used cryptolib API. + * + * Checks if the last called cryptolib function was a CMVP + * (Cryptographic Module Validation Program) approved service. The result is + * returned through the `indicator` output parameter. + * After each call the service indicator is reset to `kOtcryptoCmvpNoService`. + * + * @param[out] indicator Pointer to receive the indicator status. + * @return Result of the operation. + */ +otcrypto_status_t otcrypto_cmvp_service_indicator( + otcrypto_cmvp_service_indicator_t *indicator); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_INCLUDE_CMVP_H_ diff --git a/sw/device/lib/crypto/include/datatypes.h b/sw/device/lib/crypto/include/datatypes.h index b029a71a2d740..d0b1377410569 100644 --- a/sw/device/lib/crypto/include/datatypes.h +++ b/sw/device/lib/crypto/include/datatypes.h @@ -560,6 +560,20 @@ typedef struct otcrypto_state { uint32_t data[24]; } otcrypto_state_t; +/** + * CMVP service indicator states. + */ +typedef enum otcrypto_cmvp_service_indicator { + // No service called or indicator cleared. + kOtcryptoCmvpNoService = 0, + // Approved crypto service. + kOtcryptoCmvpApprovedService = 1, + // Non-approved crypto service. + kOtcryptoCmvpNotApprovedService = 2, +} otcrypto_cmvp_service_indicator_t; + +typedef otcrypto_cmvp_service_indicator_t otcrypto_cmvp_indicator_t; + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/sw/device/lib/crypto/include/otcrypto.h b/sw/device/lib/crypto/include/otcrypto.h index 324f71666c6ad..17673fe0a810b 100644 --- a/sw/device/lib/crypto/include/otcrypto.h +++ b/sw/device/lib/crypto/include/otcrypto.h @@ -8,6 +8,7 @@ #include "aes.h" #include "aes_gcm.h" #include "cmac.h" +#include "cmvp.h" #include "config.h" #include "cryptolib_build_info.h" #include "datatypes.h" diff --git a/sw/device/tests/crypto/otcrypto_interface.c b/sw/device/tests/crypto/otcrypto_interface.c index fe6c393c2043e..c82a00de8620f 100644 --- a/sw/device/tests/crypto/otcrypto_interface.c +++ b/sw/device/tests/crypto/otcrypto_interface.c @@ -18,6 +18,9 @@ volatile otcrypto_interface_t otcrypto = { .lib_version = &otcrypto_lib_version, .version_decode = &otcrypto_version_decode, + // CMVP service indicator. + .cmvp_service_indicator = &otcrypto_cmvp_service_indicator, + // Entropy. .entropy_init = &otcrypto_entropy_init, .entropy_check = &otcrypto_entropy_check, diff --git a/sw/device/tests/crypto/otcrypto_interface.h b/sw/device/tests/crypto/otcrypto_interface.h index da8b51d96596f..a530c6cd2eba5 100644 --- a/sw/device/tests/crypto/otcrypto_interface.h +++ b/sw/device/tests/crypto/otcrypto_interface.h @@ -28,6 +28,10 @@ typedef struct otcrypto_interface_t { otcrypto_lib_version_t (*lib_version)(void); void (*version_decode)(uint32_t, uint32_t *, uint32_t *, uint32_t *); + // CMVP service indicator + otcrypto_status_t (*cmvp_service_indicator)( + otcrypto_cmvp_service_indicator_t *); + // Entropy otcrypto_status_t (*entropy_init)(void); otcrypto_status_t (*entropy_check)(void);