.. _hsm_programming_guide_cc27xx:

The Hardware Security Module (HSM)
==================================
The |DEVICEHIGH| includes an integrated hardware security module (HSM) which
supports an isolated environment for cryptographic, key management, secure 
counters, and random number generation operations. The HSM allows developers to
develop secure and future-proof IoT applications using energy efficient 
accelerators and RNG functions. 

HSM Firmware
------------
The HSM firmware is stored in a secured flash region (96Kb) that is verified by 
the HSM ROM before the HSM processor starts execution. This ensures that any 
firmware ran by the HSM has been properly signed by the TI RSA 3K private key.
The SimpleLink |DEVICEHIGH| software development kit includes the encrypted and 
signed HSM firmware needed for the HSM operation and includes drivers for all 
HSM functions. Additionally, secure firmware update of the HSM fimrware image 
on-chip is supported by the system ROM bootcode and the HSM ROM.

The HSM firmware consumes at most 96KB of main flash. Because of this, the last 
96kB of main flash will not be usable for application purposes and should be 
considered a reserved region. Additionally, system ROM will always write, erase,
and read protect this reserved region. The HSM firmware contains a version and 
rollback ID which is used to facilitate anti-rollback protection. If a critical 
security vulnerability is found in a version of HSM firmware, TI will work to 
resolve the vulnerability and release a new HSM firmware version with an
incremented rollback ID. Once this new firmware version has been programmed to 
the devices in the field, those devices will be unable to accept older versions
of the HSM firmware.

.. warning::
    If the device has undergone a chip erase, then anti-rollback protections are
    reset, allowing older, potentially vulnerable firmware images to be 
    programmed. Developers may refer to the `TRM <https://www.ti.com/lit/ug/swcu195/swcu195.pdf?ts=1746215283860&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FCC2745R10-Q1>`_ for more information.

.. note::
    The anti-rollback feature is non-configurable, and mandatory for the HSM.

HSM Feature Overview
--------------------
Supported cryptograhpic algorithms are listed below:

+---------------------------------+-----------------------------------------------------------------------------+
| Functions                       | Supported Algorithms                                                        |
+=================================+=============================================================================+
| Key Agreement Schemes           | ECDH, ECDHE, ECJ-PAKE, DH, DHE                                              |
+---------------------------------+-----------------------------------------------------------------------------+
| Key Derivation Methods          | Random (DRBG), SHA2 HMAC PRF, AES CMAC PRF                                  |
+---------------------------------+-----------------------------------------------------------------------------+
| Signature Processing            | ECDSA, pureEdDSA, RSA PKCS #1 v1.5, RSA PSS                                 |
+---------------------------------+-----------------------------------------------------------------------------+
| Message Authentication Codes    | AES CBC-MAC, AES CMAC, HMAC with SHA2-224, SHA2-256, SHA2-384, and SHA2-512 |
+---------------------------------+-----------------------------------------------------------------------------+
| Block Cipher Modes of Operation | AES CCM, CCM-Star, GCM, ECB, CBC, CTR                                       |
+---------------------------------+-----------------------------------------------------------------------------+
| Hash Algorithms                 | SHA2 224, 256, 384, 512                                                     |
+---------------------------------+-----------------------------------------------------------------------------+
| Random Number Generation        | NIST SP 800-90B Compliant TRNG, AES-CTR DRBG                                |
+---------------------------------+-----------------------------------------------------------------------------+

Supported Cryptographic key sizes and types include:

* Advanced Encryption Standard (AES) key sizes of 128, 192, and 256 bits.
* RSA key sizes up to 3072-bits (Sign and Verify supported), and up to 4096-bits (Verify only)
* Diffie-Hellman key sizes of 2048-bits and 3072-bits
* Ellipetic Curve Support

  * Short Weierstrass

    * NIST-P224, NIST-P256, NIST-P384, NIST-P521
    * Brainpool-256R1, Brainpool-384R1, Brainpool-512R1

  * Montgomery

    * Curve25519

  * Twisted Edwards form

    * Ed25519

Please refer to :ref:`keylifetimes_cc23xx` and :ref:`psa_to_sl_porting-guide` 
for more information key storage and PSA API support.

Programming the HSM
-------------------
The HSM firmware is not flashed on the |DEVICEHIGH| out of the factory. In order
to use the HSM, the developer must flash the device with the correct binary.
This hsm binary can be found in <sdk root>/bin/hsm.

The HSM resides in flash between the addresses 0xE8000 - 0x1FFFFFF. This region
is given special protection which includes write, erase, and read protections.
Due to these protections, developers will be unable to use the debugger or 
any such application in order to read or modify the HSM firmware region.

To flash the HSM firmware, please follow the steps below for your preferred IDE.
Additionally, the HSM may be flashed using Uniflash.

.. note::
    This page is only applicable to the |DEVICEHIGH| family of devices. 
    |DEVICELOW| does not have an HSM.

.. warning::
    Although the HSM FW is write/erase/read protected during the runtime of a
    user application, the HSM firmware may still be erased during chip erase
    operations (See TRM for more details on device chip erase functionality).

Uniflash
--------
1. Flash any application software to the device with a valid CCFG and SCFG. 
   Any example that comes with the SimpleLink SDK will work, in addition to your
   own device application software.

.. warning::
    Without a valid application image flashed to the device, the HSM flashing 
    will fail. 

2. Start a Uniflash session for the |DEVICEHIGH|, 
   and go to **Settings & Utilities Page**.

.. _fig-Uniflash_HSM_programming:
.. figure:: resources/uniflash_hsm_programming.png
    :align: center

    Programming the HSM.

3. Under the **HSM Image** section, enter the path to the HSM binary.
   This path may be located in `<sdk root>/bin/hsm/*.bin`.

4. Click the **Program HSM Image**.

5. After programming, click the **Read HSM System Information** to verify that
   the HSM binary has been successfully flashed.

Code Composer Studio
--------------------
1. Flash any application software to the device with a valid CCFG and SCFG. 
   Any example that comes with the SimpleLink SDK will work, in addition to your
   own device application software.

.. warning::
    Without a valid application image flashed to the device, the HSM flashing 
    will fail. 

2. Once flashed, start a debug session.

.. _fig-ccs_HSM_programming:
.. figure:: resources/ccs_HSM_programming_debug.png
    :align: center

    Starting a debug session in CCS.

3. Once the debug session has started, click on **Tools --> On-Chip Flash**.

.. _fig-ccs_HSM_on_chip_flash:
.. figure:: resources/ccs_HSM_on_chip_flash.png
    :align: center

    On-Chip Flash window.

4. Program the HSM firmware. The firmware can be found in 
    `<sdk root>/bin/hsm/*.bin`.

.. _fig-ccs_HSM_on_chip_flash_window:
.. figure:: resources/ccs_HSM_on_chip_flash_window.png
    :align: center

    On-Chip Flash window.

IAR
---
1. Flash any application software to the device with a valid CCFG and SCFG. 
   Any example that comes with the SimpleLink SDK will work, in addition to your
   own device application software.

.. warning::
    Without a valid application image flashed to the device, the HSM flashing 
    will fail. 

2. Under the **Project** tab, go to **Download --> Download file..**

3. Follow the instructions in the pop-up window, and flash the HSM IAR firmware
   found in `<sdk root>/bin/hsm/*_iar.hex`.

.. _fig-iar_HSM_programming:
.. figure:: resources/iar_HSM_programming.png
    :align: center

    IAR programming.

HSM Functionality in Software
=============================
There are three different sets of APIs that may be utilized to leverage the HSM.

* `SimpleLink Cryptography Driver |TI_SECURE_DRIVERS_API|`
* `PSA Certified Crypto API <https://developer.arm.com/documentation/ihi0086/latest/>`_.
* HSM BareMetal Module

The following sections will provide example code to leverage the HSM using these
APIs. For more detailed examples, please refer to the SDK examples repository
and the TI drivers API documentation.

SimpleLink Crypto Driver
------------------------
The SimpleLink crypto driver supports the full feature list for our 
cryptographic operations. The |DEVICEHIGH| family includes two different 
on-chip hardware accelerators that may be used to perform cryptograhpic 
operations (LAES and HSM). The SimpleLink driver layer extends support for both,
and offers the developer the option to choose the engine of choice for AES
operations.

The first on-chip hardware accelerator is a symmetric operations focused 
accelerator that performs only AES-128 operations called the LAES engine. 
The second on-chip hardware accelerator (HSM) offers a broader support for
cryptograhpic operations including AES-128/192/256, SHA2 hashing, asymmetric
operations, and random number generation. 

The SimpleLink layer consists of different drivers performing algorithm-specific
cryptographic operations.

.. note::
    SHA2, ECDH, ECDSA, TRNG, and RNG drivers are an HSM only implementation.

SimpleLink Crypto Driver Usage
------------------------------
The following code utilizes the HSM if `USE_HSM` is defined; otherwise it will
run LAES engine.

.. code-block:: C
    :linenos:
    :emphasize-lines: 31, 34

    #include <ti/drivers/AESCCM.h>
    #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>

    #define USE_HSM 

    AESCCM_Params params;
    AESCCM_Handle handle;
    CryptoKey cryptoKey;
    int_fast16_t encryptionResult;
    uint8_t nonce[] = "Thisisanonce";
    uint8_t aad[] = "This string will be authenticated but not encrypted.";
    uint8_t plaintext[] = "This string will be encrypted and authenticated.";
    uint8_t mac[16];
    uint8_t ciphertext[sizeof(plaintext)];
    uint8_t keyingMaterial[32] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                                  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
                                  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
                                  0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
    AESCCM_Params_init(&params)
    params.returnBehavior = AESCCM_RETURN_BEHAVIOR_POLLING;
    handle = AESCCM_open(0, &params);
    if (handle == NULL) {
        /* If the handle is returned as NULL, this indicates that the HSM 
         * firmware has not been flashed.
         */
        // handle error
    }

    #ifdef USE_HSM
    /* This uses the HSM. */
    CryptoKeyPlaintextHSM_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
    #else
    /* This uses the LAES engine. */
    CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
    #endif

    AESCCM_OneStepOperation operation;
    AESCCM_OneStepOperation_init(&operation);
    operation.key           = &cryptoKey;
    operation.aad           = aad;
    operation.aadLength     = sizeof(aad);
    operation.input         = plaintext;
    operation.output        = ciphertext;
    operation.inputLength   = sizeof(plaintext);
    operation.nonce         = nonce;
    operation.nonceLength   = sizeof(nonce);
    operation.mac           = mac;
    operation.macLength     = sizeof(mac);
    encryptionResult = AESCCM_oneStepEncrypt(handle, &operation);
    if (encryptionResult != AESCCM_STATUS_SUCCESS) {
        // handle error
    }
    AESCCM_close(handle);


Notice that the only difference between using the LAES and HSM is how the 
developer initializes the the cryptographic key. This can be visualized with the
following diagram.

.. _fig-psa_hsm_breakdown:
.. figure:: resources/psa_hsm_breakdown.png
    :align: center

PSA Module
----------
The PSA module is a wrapper around the SimpleLink cryptography drivers that
conform to the PSA specification. This API serves to be portable across hardware
that conforms to the PSA specification, and is the API that offers the most
security. However, the security that it offers comes at the cost of higher memory
usage and higher latency. 

PSA Module Usage
----------------
The code below shows how to setup an ECC operation for signature verification.

.. code-block:: C
    :linenos:

    #include <stdint.h>

    /* Driver Header files */
    #include <third_party/psa_crypto/include/psa/crypto.h>
    #include <ti/drivers/cryptoutils/hsm/HSMLPF3.h>

    /* Driver configuration */
    #include "ti_drivers_config.h"

    #define KEY_BITS 256
    #define KEY_TYPE PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)
    #define KEY_ALG  PSA_ALG_ECDSA(PSA_ALG_SHA_256)

    const uint8_t message[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};

    void *mainThread(void *arg0)
    {
        psa_status_t status;
        int_fast16_t ret;

        /** Initialize PSA **/
        status = psa_crypto_init();
        if (status != PSA_SUCCESS)
        {
            // Error handling.
            /* If this occurs, it indicates that the HSM has not been flashed. */
        }

        /** Provision the hardware unique key **/
        ret = HSMLPF3_provisionHUK();
        if (ret != HSMLPF3_STATUS_SUCCESS)
        {
            // Error handling.
            /* If this occurs, it indicates that the HSM has not been flashed. */
        }

        /**** ECDSA Key Generation ****/
        psa_key_id_t key_id;

        /* To store generated public key */
        uint8_t public_key[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(KEY_BITS)];
        size_t public_key_length = 0;

        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;

        /* Since we want to sign messages, we need PSA_KEY_USAGE_SIGN_HASH */
        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);

        /* We are using these keys for ECDSA, and the hashing algorithm used is SHA-256 */
        psa_set_key_algorithm(&attributes, KEY_ALG);

        /* This is where we are setting out curve */
        psa_set_key_type(&attributes, KEY_TYPE);

        /* This is the bit size of the hash algorithm we are using (SHA-256) */
        psa_set_key_bits(&attributes, KEY_BITS);

        /* This will generate our key */
        status = psa_generate_key(&attributes, &key_id);
        if (status != PSA_SUCCESS)
        {
            // Error handling.
        }

        /* Now we want to export our PUBLIC key */
        status = psa_export_public_key(key_id, public_key, sizeof(public_key), &public_key_length);
        if (status != PSA_SUCCESS)
        {
            // Error handling.
        }
        /**** ECDSA Key Generation Done ****/

        /**** ECDSA Signing ****/
        /** Our buffer to hold the signature **/
        uint8_t signature[PSA_SIGN_OUTPUT_SIZE(KEY_TYPE, KEY_BITS, KEY_ALG)];
        size_t signature_length = 0;

        status = psa_sign_message(key_id,
                                  KEY_ALG,
                                  message,
                                  6,
                                  signature,
                                  PSA_SIGN_OUTPUT_SIZE(KEY_TYPE, KEY_BITS, KEY_ALG),
                                  &signature_length);

        if (status != PSA_SUCCESS)
        {
            // Error handling.
        }
        /**** ECDSA Signing Done ****/

        /**** Import ECDSA Public Key ****/
        psa_key_id_t p_key_id = PSA_KEY_ID_USER_MIN + 1;
        psa_key_attributes_t p_attributes = PSA_KEY_ATTRIBUTES_INIT;

        /* the public key is used to verify */
        psa_set_key_usage_flags(&p_attributes, PSA_KEY_USAGE_VERIFY_HASH);

        /* We are using these keys for ECDSA, and the hashing algorithm used is SHA-256 */
        psa_set_key_algorithm(&p_attributes, KEY_ALG);

        /* This is where we are setting out curve */
        psa_set_key_type(&p_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));

        /* Key bits of the curve type */
        psa_set_key_bits(&p_attributes, KEY_BITS);

        status = psa_import_key(&p_attributes, public_key, public_key_length, &p_key_id);
        if (status != PSA_SUCCESS)
        {
            // Error handling.
        }
        /**** Import ECDSA Public Key Done ****/

        /**** Verify message ****/
        status = psa_verify_message(p_key_id,
                                  KEY_ALG,
                                  message,
                                  6,
                                  signature,
                                  signature_length);

        if (status != PSA_SUCCESS)
        {
            // Error handling.
        }
        /**** Verify message done ****/

        while(1);
    }


HSM BareMetal Module 
--------------------
The HSM BareMetal module offers a thin, simplified, and fast approach to 
leveraging the HSM hardware capabilities. It bypasses the software architecture
linked with operations via the PSA API and the SimpleLink driver layers. The 
HSM BareMetal module offers the same cryptographic operations as the SimpleLink
layer, except for segemented operations, and only supports synchronous polling
mode. Furthermore, the developer must manage the keys.

HSM BareMetal Module Usage
--------------------------
First the `HSMBareMetal.c`, `HSMBareMetal.h`, `HSMBareMetalUtility.h`, and the 
`HSMBareMetalUtility.c` files must be added to the project. The files are 
located in the `<sdk root>/ti/source/common/hsm`. The developer will need to add
these files to the root of their project. Close attention should be paid to the
header files, since they contain additional information that may not be 
covered here.

.. code-block:: C

    #include "HSMBareMetal.h"

    /* Struct to hold version information. */
    HSMBareMetal_systemInfoVersionStruct version;
    int_fast16_t status = HSMBAREMETAL_STATUS_ERROR;

    /* HSM must be initialized before any HSM operations can occur. */
    status = HSMBareMetal_init();
    if (HSMBAREMETAL_STATUS_SUCCESS != status)
    {
        /* Fail condition here */
        /* If this occurs, that means that the HSM firmware is not flashed on
         * on the chip, and must be re-flashed.
         */
        while(1);
    }

    /* Grab the firmware version. */
    status = HSMBareMetal_getHSMFirmwareVersion(&version);
    if (HSMBAREMETAL_STATUS_SUCCESS != status)
    {
        /* Fail condition here */
        /* If this occurs, that means that the HSM firmware is not flashed on
         * on the chip, and must be re-flashed.
         */
        while(1);
    }


Key Storage in the HSM
----------------------
Keys stored in the HSM cannot be exported back to the application, and are only
accessible inside the HSM. Keys that are stored in the HSM will be used for
cryptographic operations internal to the HSM. This prevents private keys from being exposed to the application, and thus, to an attacker.
be exposed to the application, and thus, to an attacker.

For more information regarding Key Storage, please refer to the 
:ref:`keylifetimes_cc23xx`.
