Crypto operations to generate key pair when TFM profile is set to minimal.

Hi, I am using NRF connect sdk 2.6.1 and I am wondering what is the best way to run crypto operations when using TFM profile type minimal and building for nrf9160_ns. TFM_PROFILE_TYPE_NOT_SET takes up too much space but it seems there is no way to generate keys pair without it.

https://docs.nordicsemi.com/bundle/ncs-2.3.0/page/tfm/technical_references/design_docs/profiles/tfm_profile_small.html

This says that the minimal profile supports:
Symmetric cipher only
Cipher suite for symmetric-key algorithms based protocols, such as cipher suites defined in TLS pre-shared key (TLS-PSK) [1].
    Advanced Encryption Standard (AES) as symmetric crypto algorithm
    SHA256 as Hash function
    HMAC as Message Authentication Code algorithm


while the full profile supports:
        Support both symmetric ciphers and asymmetric ciphers
        Asymmetric key based cipher suites defined in TLS 1.2 [5] to support direct secure connection to major CSPs, including
                Authenticated Encryption with Associated Data (AEAD) algorithm
                Asymmetric key algorithm based signature and verification
                Public-key cryptography based key exchange
                Hash function
                HMAC for default Pseudorandom Function (PRF)
        Asymmetric digital signature and verification for Initial Attestation Token (IAT)
        Asymmetric algorithms for firmware image signature verification
        Key derivation


I have tried to generate the key pair using only mbedtls library but it seems like there is a lot missing in the nrf implementation. I am not able to use entropy at all, when i enable it with CONFIG_MBEDTLS_ENTROPY_C=y
i get:

warning: MBEDTLS_ENTROPY_C (defined at
ncs/v2.6.1/nrf/subsys/net/openthread/Kconfig.defconfig:138,
ncs/v2.6.1/nrf/subsys/nrf_security/Kconfig.legacy:350) was assigned the value 'y' but
got the value 'n'. Check these unsatisfied dependencies: (NET_L2_OPENTHREAD ||
(!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG && MBEDTLS_LEGACY_CRYPTO_C && NRF_SECURITY)) (=n). See
http://docs.zephyrproject.org/latest/kconfig.html#CONFIG_MBEDTLS_ENTROPY_C and/or look up
MBEDTLS_ENTROPY_C in the menuconfig/guiconfig interface. The Application Development Primer, Setting
Configuration Values, and Kconfig - Tips and Best Practices sections of the manual might be helpful
too.

and that makes it impossible to use this:
github.com/.../gen_key.c
Is there any other recommended way to do it or samples that i could look at?
Or is there any sample that describes a way to get a minimal working example with the profile set to NOT_SET?

Parents Reply Children
  • The documentation unfortunately doesn't clarify the core issue.

    I haven't been able to use hardware-accelerated random number generation or hardware AES encryption because of RAM constraints. Neither of these operations should require dozens of kilobytes of RAM.

    As it stands, the choices are:

    • TFM_PROFILE_TYPE_NOT_SET: Lose ~88 KB of RAM, get full TF-M functionality
    • TFM_PROFILE_TYPE_MINIMAL: Lose ~32 KB of RAM, get effectively nothing usable (no crypto operations work)

    There's no middle ground - no way to get basic hardware crypto (AES, RNG) without sacrificing a third of the nRF9160's 256 KB RAM.

    I ended up implementing software AES as a workaround. Not even Oberon - a custom AES implementation, because the nRF Security backend also appears to require the full TF-M RAM allocation to function.

    The project works now, but I have serious doubts about getting it through compliance/certification without hardware-backed crypto.

  • Hi,

    Configurable build is full TF-M implementation, but it should be possible to enable/disable specific TF-M features and services. 
    "To configure the features of the TF-M secure image, you must choose which TF-M partitions and which secure services to include in the build."
    There are Kconfig options which can be used for enabling/disabling specific services. You could try to disable those services which are not needed in your build.

    Best regards,
    Dejan

  • But if i use TFM_PROFILE_TYPE_MINIMAL and then set:

    CONFIG_TFM_PARTITION_PROTECTED_STORAGE=y
    CONFIG_TFM_PARTITION_CRYPTO=y


    i get:
    warning: TFM_PARTITION_PROTECTED_STORAGE (defined at /home/marcus/ncs/v2.6.1/nrf/modules/trusted-
    firmware-m/Kconfig.tfm.defconfig:69, modules/trusted-firmware-m/Kconfig.tfm.partitions:8,
    modules/trusted-firmware-m/Kconfig.tfm.partitions:8) was assigned the value 'y' but got the value
    'n'. See http://docs.zephyrproject.org/latest/kconfig.html#CONFIG_TFM_PARTITION_PROTECTED_STORAGE
    and/or look up TFM_PARTITION_PROTECTED_STORAGE in the menuconfig/guiconfig interface. The
    Application Development Primer, Setting Configuration Values, and Kconfig - Tips and Best Practices
    sections of the manual might be helpful too.

    and this:

    psa_status_t status = psa_crypto_init();
    psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT);
    psa_set_key_algorithm(&key_attributes, PSA_ALG_ECB_NO_PADDING);  
    psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
    psa_set_key_bits(&key_attributes, 16 * 8); 
    status = psa_import_key(&key_attributes, p_key, 16, &key_id);
        if (status != PSA_SUCCESS) {
            LOG_ERR("Failed to import key: %d", status);
            return;
        }


    still returns -134



    so what is it that is possible to configure?

  • The missing information is a fine grained table, which shows, how much ram/flash is required for each functions/profiles. Without such a table it's then left to the user, to find that out. Unfortunately, as this thread shows, this comes with a larger working time and unsatisfying results. Maybe it requires even more time, to get better results, but as this thread also shows, plain software solutions aren't that bad.    

  • CONFIG_TFM_PROFILE_TYPE_NOT_SET=y
    CONFIG_TFM_PARTITION_PLATFORM=n
    CONFIG_TFM_PARTITION_CRYPTO=n
    CONFIG_TFM_PARTITION_PROTECTED_STORAGE=n
    CONFIG_TFM_PARTITION_INTERNAL_TRUSTED_STORAGE=n


    with this configuration i get:
    fatal error: tfm_ioctl_api.h: No such file or directory
       10 | #include "tfm_ioctl_api.h"


    if i then set:
    CONFIG_TFM_PARTITION_PLATFORM=y


    i get:
    /ncs/toolchains/2be090971e/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: platform/libplatform_s.a(flash_otp_nv_counters_backend.o): in function `erase_flash_region':
    /ncs/v2.6.1/modules/tee/tf-m/trusted-firmware-m/platform/ext/common/template/flash_otp_nv_counters_backend.c:251: undefined reference to `Driver_FLASH0'
    /ncs/toolchains/2be090971e/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: platform/libplatform_s.a(flash_otp_nv_counters_backend.o): in function `copy_flash_region':
    /ncs/v2.6.1/modules/tee/tf-m/trusted-firmware-m/platform/ext/common/template/flash_otp_nv_counters_backend.c:277: undefined reference to `Driver_FLASH0'
    /ncs/toolchains/2be090971e/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: platform/libplatform_s.a(flash_otp_nv_counters_backend.o): in function `read_otp_nv_counters_flash':
    /ncs/v2.6.1/modules/tee/tf-m/trusted-firmware-m/platform/ext/common/template/flash_otp_nv_counters_backend.c:139: undefined reference to `Driver_FLASH0'
    /ncs/toolchains/2be090971e/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: platform/libplatform_s.a(flash_otp_nv_counters_backend.o): in function `copy_data_into_block':
    /ncs/v2.6.1/modules/tee/tf-m/trusted-firmware-m/platform/ext/common/template/flash_otp_nv_counters_backend.c:330: undefined reference to `Driver_FLASH0'
    /ncs/toolchains/2be090971e/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld: platform/libplatform_s.a(flash_otp_nv_counters_backend.o): in function `init_otp_nv_counters_flash':
    /ncs/v2.6.1/modules/tee/tf-m/trusted-firmware-m/platform/ext/common/template/flash_otp_nv_counters_backend.c:213: undefined reference to `Driver_FLASH0'

    if i also set:

    CONFIG_TFM_PARTITION_INTERNAL_TRUSTED_STORAGE=y


    i get:
    /ncs/toolchains/2be090971e/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd: zephyr/drivers/entropy/libdrivers__entropy.a(entropy_psa_crypto.c.obj): in function `entropy_psa_crypto_rng_get_entropy':
    ncs/v2.6.1/zephyr/drivers/entropy/entropy_psa_crypto.c:35: undefined reference to `psa_generate_random'
    /ncs/toolchains/2be090971e/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd: zephyr/drivers/entropy/libdrivers__entropy.a(entropy_psa_crypto.c.obj): in function `entropy_psa_crypto_rng_init':
    /ncs/v2.6.1/zephyr/drivers/entropy/entropy_psa_crypto.c:19: undefined reference to `psa_crypto_init'
    collect2: error: ld returned 1 exit status

    if i also set: 

    CONFIG_TFM_PARTITION_CRYPTO=y

    it builds and now i get:

    [194/198] Linking C executable bin/tfm_s.axf
    Memory region         Used Size  Region Size  %age Used
               FLASH:       64916 B       256 KB     24.76%
                 RAM:       45928 B        88 KB     50.97%
                 
    [336/338] Linking C executable zephyr/zephyr.elf
    Memory region         Used Size  Region Size  %age Used
               FLASH:      127852 B       704 KB     17.74%
                 RAM:       39376 B     154264 B     25.53%
            IDT_LIST:          0 GB        32 KB      0.00%


    Is this the smallest i can get that still lets me use psa crypto operations and trusted storage? 

Related