Reference for mutual TLS and private key handling

I intend to implement an application on nrf9160, that makes use of mutual-tls to communicate with a peer.

To this end, I need to store a private key in a save place on the nrf9160 and create tls-sockets from it.

My understanding of the recommended approach is as follows:

  1. Comparing the developer.nordicsemi.com/.../README.html flash a provisioning image to initialize the HUK, hardware unique keys.
  2. Flash the production image, that has protected storage enabled.
    1. Generate cryptographic randomness
    2. Write it to protected storage
    3. The protected storage will encrypt it using the identity key `NRF_KMU_SLOT_IDENT`
    4. Then write it to internal trusted storage (optionally additionaly encrypted with NRF_KMU_SLOTMKEK if configured that way by selecting CONFIG_TFM_ITS_ENCRYPTED)
    5. Read it to NSPE-RAM from protected storage to create csr with mbedtls.
    6. Read it to NSPE-RAM from protected storage to hand it off to zephyrs tls_credentials_add-API.

From devzone.nordicsemi.com/.../persistent-storage-of-keys-and-data-using-the-nrf-connect-sdk I understand, that the recommended approach would be to use the crypto api to generate a key with persistent live-time. This stores it in ITS, but would that not be unencrypted unless above config is set?

Am I understanding the recommended approach correctly?

Are there better alternative? For example:

  1. Can slots in the KMU be used to store the private key forgoing the need for protected storage altogether?
  2. Can the key be derrived from a HUK every time before use forgoing the need to store it anywhere persistently? If so which HUK shall be used?
  3. How many space is in the KMU? I understand 125 slots a 128 bits/slot?
  4. Is there an alternative to tls_credentials_add and mbedtls sockets, that allows to store the information persistently in some other way? Maybe developer.nordicsemi.com/.../sockets.html ?


Edit: please fix your forum. I had a much harder time making above text show properly then it should be.

Parents
  • I had one of our crypto experts read though my previous message, and they caught some misunderstandings. I will edit that comment soon after I have posted this.

    So instead of that comment, I will suggest how you can do mutual TLS for a client with the PSA Crypto API.

    Let's split this into some steps, to keep it tidy.

    • Provisioning
      • Generate private key
      • Get Client Certificate from Certificate Signing Request (CSR)
      • Get Clouds CA certificate
    • Runtime
      • Do TLS handshake

    Provisioning

    Generate private key

    Use the PSA Crypto API. See Crypto: ECDSA sample.

    This will generate the key in SPE and store it in ITS. Set CONFIG_TFM_ITS_ENCRYPTED if you want to encrypt ITS. This will use the MKEK to encrypt ITS.

    CSR

    We do not have a sample for this. See Using opaque ECDSA keys to generate certificate signing requests (CSRs) for a list of steps. Specifically the subsection "Application flow with PSA".

    Since we set up mbedtls to use opaque keys, the private key will never be in NSPE for this operation, which is good.

    Store the Client Certificate in PS from NSPE. The Client Certificate is public information, so it can be stored however you want really.

    The CSR will be done against a CA, often controlled by you. Normally you will sign the Client Certificate against a root certificate or intermediate certificate you have, so that you do not need to store every client certificate in the cloud.

    Get cloud server CA cert

    The device needs to know the servers certificate to be able to authenticate the cloud server. This is usually done with a Certificate Authority (CA) certificate.

    Since the cloud server CA certificate is not secret, it can be stored available to the NSPE. (For example using Protected Storage).

    Which cloud server CA certificate need and how you aquire it depends on the cloud server. For example for Azure IoT Hub, that would be the Baltimore CyberTrust Root Certificate.

    Runtime

    Now that you have configured your device, you have a Private Key in ITS, a Client certificate and Cloud CA certificate in your non-volatile storage (for example Persistent Storage).

    Our PSA TLS sample which I linked to earlier show you how to do the TLS handshake using the PSA Crypto API and then communicate over the established link.

    I will have a colleguae read through this as well tomorrow, so beware there might be edits. I am learning here as well.

    Let me know if you got any questions.

    EDIT: Last edit of this post 2024-02-01 09:40

  • Our PSA TLS sample which I linked to earlier show you how to do the TLS handshake using the PSA Crypto API and then communicate over the established link.

    I have maybe one follow up. In the sample, if I understand correctly, it still loads the key into NSPE RAM in the function `tls_set_credentials_from_ps`, did I understand correctly, that this can not be avoided?

  • From tls_set_credentials_from_ps:

    "

     Function for fetching the CA certificate from Protected Storage,

    "

    This gets the certificate, and the certificate is not secret, and is therefore it is not a problem to have this in NSPE RAM

  • Thanks, you are right.


    I do not fully understand. My understanding is now, the private information is in the `psk`, it is loaded with `tls_credential_add` in `tls_set_preshared_key` (in the sample from hard coded dummy_psk). The sample does not cover the safe storage of the psk. Do I understand correctly, that after a reset, the key is not persisted and needs to be loaded in (via NSPE-RAM) using `tls_credentila_add`-function again?

Reply
  • Thanks, you are right.


    I do not fully understand. My understanding is now, the private information is in the `psk`, it is loaded with `tls_credential_add` in `tls_set_preshared_key` (in the sample from hard coded dummy_psk). The sample does not cover the safe storage of the psk. Do I understand correctly, that after a reset, the key is not persisted and needs to be loaded in (via NSPE-RAM) using `tls_credentila_add`-function again?

Children
Related