The Hardware Security Module (HSM)

The CC35xx 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 Feature Overview

Supported cryptograhpic algorithms are listed below:

Functions Supported Algorithms
Key Agreement Schemes ECDH
Key Derivation Methods Random (DRBG)
Signature Processing ECDSA, pureEdDSA
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, GCM, ECB, CBC, CTR
Hash Algorithms SHA2 (224, 256, 384, 512)
Random Number Generation NIST SP 800-90B Compliant TRNG, AES-CTR DRBG

Note

SHA 3 is not yet supported by the Cryptographic driver. But, it is supported by the HSM HW module. Future SDK release will support this feature.

Supported Cryptographic key sizes and types include:

  • Advanced Encryption Standard (AES) key sizes of 128, 192, and 256 bits.
  • Diffie-Hellman key sizes of 2048-bits and 3072-bits
  • Ellipetic Curve Support
    • Short Weierstrass
      • NIST-P224, NIST-P256, NIST-P384, NIST-P521
    • Montgomery
      • Curve25519
    • Twisted Edwards form
      • Ed25519

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.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#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);
}

Key Storage in the HSM

A keystore is a secure storage mechanism for cryptographic keys and certificates. It is used to store, manage, and protect private keys and public keys, often required for encryption and authentication in software systems. 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.

HUK (Hardware Unique Key) is a 256-bit key that is used to encrypt a key or derive a Trusted Derive Key (TKDK) or Trusted Wrap Key (TKEK). TKDK is used to derive a key and TKEK is to encrypt/decrypt a key.

One HUK is allowed per device and HSMXXF3_provisionHUK( ) is the API to provision a HUK. This API generates a 256-bit random number and programs it to OTP, which is a special flash region that is only accessible by the HSM.

Note

Note that HUK is not required for any crypto operations except:

  • TKDK Key Derivation
  • Key Encryption/decryption