Security Key Migration between SDKs#

With the release of SiSDK 2024.12, Connect stack migrated to the new, PSA backed security library for its IEEE 802.15.4-like MAC security.

This has the benefit of improved speed with the PSA backed key storage that Connect is using since GSDK 4.1.

PSA is required to use the secure element-based storage on the parts that have the feature, and provides a much more secure key storage on parts that do not have secure element.

The main difference is that the legacy implementation requires a PSA key with algorithm set to PSA_ALG_ECB_NO_PADDING, while the new implementation needs PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4). Note that the security algorithm itself did not change and devices using the legacy implementation can communicate with devices using the new implementation. The legacy implementation ran part of the encryption on the CPU, hence the different algorithm required from PSA.

If you start a new project, the example project in Simplicity Studio are all set up with the new key storage, and the legacy methods are not recommended for new designs.

However, if you need to update an existing application, the key stored in the legacy method is not supported and migration is not straight forward. This document targets to help with that.

The target of the migration is always to get the key in "plain text", i.e., unencrypted, as a 16 Byte array and reimport it with the new method.

Migration from GSDK 4.1.0 and Newer#

Using Legacy Key Storage#

Connect stack in SiSDK 2024.12 still has the legacy encryption library available which supports the key storage. To enable this option, go to the project's component explorer enable the Deprecated Quality components, and install AES Security (Library) | Legacy from the Connect category. You can also remove AES Security (Library), which is the new version, but you can have both installed to help migration.

Moving the Legacy Key to the New Storage#

If the key was stored with the flag PSA_KEY_USAGE_EXPORT, it's recommended to enable both AES libraries as documented in the previous chapter, and export the key:

   uint8_t exported_key[EMBER_ENCRYPTION_KEY_SIZE];
   size_t exported_key_length;
   psa_status_t psa_status;

   psa_status = psa_export_key(security_key_id, exported_key EMBER_ENCRYPTION_KEY_SIZE, &exported_key_length);

If the key is successfully exported, you can use the code in the bottom of the article to reimport it with the new requirements.

Note that if you relied on our examples to import the key into PSA, your key is not exportable. In this case, getting the key from a device is not possible. However, in most cases, the key is available somewhere else, e.g., on the gateway in plain text, so a key redistribution is the recommended method.

Migration from GSDK 4.0.x and Older#

In GSDK 4.0.x and older, the key was stored in the token TOKEN_STACK_SECURITY_KEY with tokTypeStackKey type, which is simply a 16 Byte long uint8_t array. The token can be read by halCommonGetToken(). Note though that we used SimEEv1 as the default backend for tokens in GSDK v2, and we switched to NVMv3 in GSDK v3, so be careful, as other migrations might be necessary from such an old version of Connect.

Once you have the key as a plain text, you can use the code in the bottom of the article to reimport it with the new requirements.

Importing the Key#

The following code is the recommended way to configure and import the key with SiSDK 2024.12 and newer. This code was copied from the Connect Sensor example, and should be executed before emberNetworkInit()

  EmberKeyData security_key = { .contents = <your security key as 16B uint8 array> };

  security_key_id = PSA_AES_KEY_ID;
  psa_key_attributes_t key_attr = psa_key_attributes_init();
  psa_status_t psa_status = psa_get_key_attributes(security_key_id, &key_attr);
  if (psa_status == PSA_ERROR_INVALID_HANDLE) {
    app_log_info("No PSA AES key found, creating one.\n");
    psa_set_key_id(&key_attr, security_key_id);
    psa_set_key_algorithm(&key_attr, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4));
    //Add PSA_KEY_USAGE_EXPORT below if you want an exportable key
    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
    psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
    psa_set_key_bits(&key_attr, 128);

#ifdef PSA_KEY_LOCATION_SLI_SE_OPAQUE
    psa_set_key_lifetime(&key_attr,
                         PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
                           PSA_KEY_LIFETIME_PERSISTENT,
                           PSA_KEY_LOCATION_SLI_SE_OPAQUE));
#else
#ifdef MBEDTLS_PSA_CRYPTO_STORAGE_C
    psa_set_key_lifetime(&key_attr,
                         PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
                           PSA_KEY_LIFETIME_PERSISTENT,
                           PSA_KEY_LOCATION_LOCAL_STORAGE));
#else
    psa_set_key_lifetime(&key_attr,
                         PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
                           PSA_KEY_LIFETIME_VOLATILE,
                           PSA_KEY_LOCATION_LOCAL_STORAGE));
#endif
#endif

    psa_status = psa_import_key(&key_attr,
                                security_key.contents,
                                (size_t)EMBER_ENCRYPTION_KEY_SIZE,
                                &security_key_id);

    if (psa_status == PSA_SUCCESS) {
      app_log_info("Security key import successful, key id: %lu\n", security_key_id);
    } else {
      app_log_info("Security Key import failed: %ld\n", psa_status);
    }
  } else {
    app_log_info("PSA AES key found, using the existing one.\n");
  }

  em_status = emberSetPsaSecurityKey(security_key_id);