-
Notifications
You must be signed in to change notification settings - Fork 917
Add STSAFE-A120 Support #9614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add STSAFE-A120 Support #9614
Conversation
|
🛟 Devin Lifeguard found 3 likely issues in this PR
@dgarske |
|
Jenkins retest this please: "AgentOfflineException" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
|
Jenkins retest this please: "AgentOfflineException" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Jenkins retest this please. AgentOffline |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Jenkins retest this please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * With only NIST P-256 and P-384 enabled: | ||
| * STSE_ECC_KT_NIST_P_256 = 0, STSE_ECC_KT_NIST_P_384 = 1 | ||
| * NOTE: If other curves are enabled, these values change! */ | ||
| #define STSAFE_ECC_CURVE_P256 0 /* STSE_ECC_KT_NIST_P_256 */ | ||
| #define STSAFE_ECC_CURVE_P384 1 /* STSE_ECC_KT_NIST_P_384 */ |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comments warn that these curve ID values depend on stse_conf.h settings and change when other curves are enabled, but there's no compile-time validation. Consider adding static assertions or runtime checks in stsafe_interface_init() to verify that the STSE_ECC_KT_NIST_P_256 and STSE_ECC_KT_NIST_P_384 enum values from STSELib actually match the expected 0 and 1 values when WOLFSSL_STSAFEA120 is defined.
| * With only NIST P-256 and P-384 enabled: | |
| * STSE_ECC_KT_NIST_P_256 = 0, STSE_ECC_KT_NIST_P_384 = 1 | |
| * NOTE: If other curves are enabled, these values change! */ | |
| #define STSAFE_ECC_CURVE_P256 0 /* STSE_ECC_KT_NIST_P_256 */ | |
| #define STSAFE_ECC_CURVE_P384 1 /* STSE_ECC_KT_NIST_P_384 */ | |
| * With only NIST P-256 and P-384 enabled and no other curves: | |
| * STSE_ECC_KT_NIST_P_256 = 0, STSE_ECC_KT_NIST_P_384 = 1 | |
| * NOTE: If other curves are enabled or the order changes in STSELib, | |
| * these values may change. In that case, override the defaults | |
| * below by defining STSAFE_ECC_CURVE_P256 / STSAFE_ECC_CURVE_P384 | |
| * (for example via compiler -D flags) to match the actual | |
| * STSE_ECC_KT_NIST_P_256 / STSE_ECC_KT_NIST_P_384 enum values. */ | |
| #ifndef STSAFE_ECC_CURVE_P256 | |
| #define STSAFE_ECC_CURVE_P256 0 /* Default: STSE_ECC_KT_NIST_P_256 */ | |
| #endif | |
| #ifndef STSAFE_ECC_CURVE_P384 | |
| #define STSAFE_ECC_CURVE_P384 1 /* Default: STSE_ECC_KT_NIST_P_384 */ | |
| #endif |
| byte ephemeralPubKey[STSAFE_MAX_PUBKEY_RAW_LEN]; | ||
| int key_sz = stsafe_get_key_size(curve_id); | ||
| slot = STSAFE_KEY_SLOT_EPHEMERAL; | ||
|
|
||
| ret = stse_generate_ecc_key_pair(&g_stse_handler, slot, | ||
| (stse_ecc_key_type_t)curve_id, | ||
| STSAFE_EPHEMERAL_KEY_USAGE_LIMIT, | ||
| ephemeralPubKey); | ||
| if (ret != STSE_OK) { | ||
| STSAFE_INTERFACE_PRINTF("stse_generate_ecc_key_pair (ephemeral for ECDH) error: %d\n", ret); | ||
| rc = (int)ret; | ||
| } else { | ||
| WOLFSSL_MSG("STSAFE: Generated ephemeral key for ECDH"); | ||
| /* Update devCtx to reflect ephemeral slot for this key */ | ||
| if (info->pk.ecdh.private_key != NULL) { | ||
| info->pk.ecdh.private_key->devCtx = STSAFE_SLOT_TO_DEVCXT(slot); | ||
| } | ||
| /* Update the public key in the key structure to match the new ephemeral key */ | ||
| if (info->pk.ecdh.private_key != NULL && rc == 0) { | ||
| void* saved_devCtx = info->pk.ecdh.private_key->devCtx; | ||
| rc = wc_ecc_import_unsigned(info->pk.ecdh.private_key, | ||
| ephemeralPubKey, &ephemeralPubKey[key_sz], | ||
| NULL, ecc_curve); | ||
| /* Restore devCtx in case import cleared it */ | ||
| if (saved_devCtx != NULL && info->pk.ecdh.private_key->devCtx != saved_devCtx) { | ||
| info->pk.ecdh.private_key->devCtx = saved_devCtx; | ||
| } | ||
| } | ||
| } |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ephemeralPubKey buffer is declared on stack but could be large (96 bytes for P-384). When WOLFSSL_SMALL_STACK is defined, other buffers in this function are dynamically allocated but ephemeralPubKey is not. For consistency with the WOLFSSL_SMALL_STACK handling elsewhere in the file, consider conditionally allocating this buffer dynamically when WOLFSSL_SMALL_STACK is defined.
| byte ephemeralPubKey[STSAFE_MAX_PUBKEY_RAW_LEN]; | |
| int key_sz = stsafe_get_key_size(curve_id); | |
| slot = STSAFE_KEY_SLOT_EPHEMERAL; | |
| ret = stse_generate_ecc_key_pair(&g_stse_handler, slot, | |
| (stse_ecc_key_type_t)curve_id, | |
| STSAFE_EPHEMERAL_KEY_USAGE_LIMIT, | |
| ephemeralPubKey); | |
| if (ret != STSE_OK) { | |
| STSAFE_INTERFACE_PRINTF("stse_generate_ecc_key_pair (ephemeral for ECDH) error: %d\n", ret); | |
| rc = (int)ret; | |
| } else { | |
| WOLFSSL_MSG("STSAFE: Generated ephemeral key for ECDH"); | |
| /* Update devCtx to reflect ephemeral slot for this key */ | |
| if (info->pk.ecdh.private_key != NULL) { | |
| info->pk.ecdh.private_key->devCtx = STSAFE_SLOT_TO_DEVCXT(slot); | |
| } | |
| /* Update the public key in the key structure to match the new ephemeral key */ | |
| if (info->pk.ecdh.private_key != NULL && rc == 0) { | |
| void* saved_devCtx = info->pk.ecdh.private_key->devCtx; | |
| rc = wc_ecc_import_unsigned(info->pk.ecdh.private_key, | |
| ephemeralPubKey, &ephemeralPubKey[key_sz], | |
| NULL, ecc_curve); | |
| /* Restore devCtx in case import cleared it */ | |
| if (saved_devCtx != NULL && info->pk.ecdh.private_key->devCtx != saved_devCtx) { | |
| info->pk.ecdh.private_key->devCtx = saved_devCtx; | |
| } | |
| } | |
| } | |
| #ifdef WOLFSSL_SMALL_STACK | |
| byte* ephemeralPubKey = NULL; | |
| #else | |
| byte ephemeralPubKey[STSAFE_MAX_PUBKEY_RAW_LEN]; | |
| #endif | |
| int key_sz = stsafe_get_key_size(curve_id); | |
| slot = STSAFE_KEY_SLOT_EPHEMERAL; | |
| #ifdef WOLFSSL_SMALL_STACK | |
| ephemeralPubKey = (byte*)XMALLOC(STSAFE_MAX_PUBKEY_RAW_LEN, | |
| NULL, DYNAMIC_TYPE_TMP_BUFFER); | |
| if (ephemeralPubKey == NULL) { | |
| rc = MEMORY_E; | |
| } | |
| #endif | |
| if (rc == 0) { | |
| ret = stse_generate_ecc_key_pair(&g_stse_handler, slot, | |
| (stse_ecc_key_type_t)curve_id, | |
| STSAFE_EPHEMERAL_KEY_USAGE_LIMIT, | |
| ephemeralPubKey); | |
| if (ret != STSE_OK) { | |
| STSAFE_INTERFACE_PRINTF("stse_generate_ecc_key_pair (ephemeral for ECDH) error: %d\n", ret); | |
| rc = (int)ret; | |
| } else { | |
| WOLFSSL_MSG("STSAFE: Generated ephemeral key for ECDH"); | |
| /* Update devCtx to reflect ephemeral slot for this key */ | |
| if (info->pk.ecdh.private_key != NULL) { | |
| info->pk.ecdh.private_key->devCtx = STSAFE_SLOT_TO_DEVCXT(slot); | |
| } | |
| /* Update the public key in the key structure to match the new ephemeral key */ | |
| if (info->pk.ecdh.private_key != NULL && rc == 0) { | |
| void* saved_devCtx = info->pk.ecdh.private_key->devCtx; | |
| rc = wc_ecc_import_unsigned(info->pk.ecdh.private_key, | |
| ephemeralPubKey, &ephemeralPubKey[key_sz], | |
| NULL, ecc_curve); | |
| /* Restore devCtx in case import cleared it */ | |
| if (saved_devCtx != NULL && info->pk.ecdh.private_key->devCtx != saved_devCtx) { | |
| info->pk.ecdh.private_key->devCtx = saved_devCtx; | |
| } | |
| } | |
| } | |
| } | |
| #ifdef WOLFSSL_SMALL_STACK | |
| if (ephemeralPubKey != NULL) { | |
| XFREE(ephemeralPubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); | |
| } | |
| #endif |
| #ifndef STSAFE_HOST_KEY_MAC | ||
| static const uint8_t g_host_mac_key[16] = { | ||
| 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | ||
| 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF | ||
| }; | ||
| #endif | ||
| #ifndef STSAFE_HOST_KEY_CIPHER |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example host MAC and cipher keys are hardcoded with predictable values and visible in the binary. While the comment notes these are examples, production code could accidentally use these insecure defaults. Consider either removing these default keys entirely (requiring users to define STSAFE_HOST_KEY_MAC/CIPHER) or using a more prominent warning marker to prevent production use.
| #ifndef STSAFE_HOST_KEY_MAC | |
| static const uint8_t g_host_mac_key[16] = { | |
| 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | |
| 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF | |
| }; | |
| #endif | |
| #ifndef STSAFE_HOST_KEY_CIPHER | |
| #ifndef STSAFE_HOST_KEY_MAC | |
| #if defined(__GNUC__) || defined(__clang__) | |
| #warning "Insecure example STSAFE host MAC key in use. Define STSAFE_HOST_KEY_MAC with a secure, secret key for production builds." | |
| #elif defined(_MSC_VER) | |
| #pragma message("Insecure example STSAFE host MAC key in use. Define STSAFE_HOST_KEY_MAC with a secure, secret key for production builds.") | |
| #endif | |
| static const uint8_t g_host_mac_key[16] = { | |
| 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | |
| 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF | |
| }; | |
| #endif | |
| #ifndef STSAFE_HOST_KEY_CIPHER | |
| #if defined(__GNUC__) || defined(__clang__) | |
| #warning "Insecure example STSAFE host cipher key in use. Define STSAFE_HOST_KEY_CIPHER with a secure, secret key for production builds." | |
| #elif defined(_MSC_VER) | |
| #pragma message("Insecure example STSAFE host cipher key in use. Define STSAFE_HOST_KEY_CIPHER with a secure, secret key for production builds.") | |
| #endif |
| curve_id = stsafe_get_ecc_curve_id(ecc_curve); | ||
| /* Note: STSAFE_ECC_CURVE_P256 is 0, so we can't use STSAFE_DEFAULT_CURVE check. | ||
| * Instead, verify the curve_id is valid by checking it's one of the supported curves */ | ||
| if (curve_id != STSAFE_ECC_CURVE_P256 && curve_id != STSAFE_ECC_CURVE_P384) { |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The curve validation at line 1823 explicitly checks only P256 and P384, which will reject valid Brainpool curves even when STSAFE_ECC_CURVE_BP256/BP384 are defined. This validation should be updated to include the Brainpool curves when they are enabled, or use a more flexible validation approach like checking against the key_sz return value from stsafe_get_key_size().
| if (curve_id != STSAFE_ECC_CURVE_P256 && curve_id != STSAFE_ECC_CURVE_P384) { | |
| if (curve_id != STSAFE_ECC_CURVE_P256 && | |
| curve_id != STSAFE_ECC_CURVE_P384 | |
| #ifdef STSAFE_ECC_CURVE_BP256 | |
| && curve_id != STSAFE_ECC_CURVE_BP256 | |
| #endif | |
| #ifdef STSAFE_ECC_CURVE_BP384 | |
| && curve_id != STSAFE_ECC_CURVE_BP384 | |
| #endif | |
| ) { |
Add STSAFE-A120 Support via STSELib
Description
This PR adds support for the ST STSAFE-A120 secure element using the open-source STSELib SDK. The STSAFE-A120 is ST's latest secure element with enhanced cryptographic capabilities and is the successor to the STSAFE-A100/A110 series.
Changes
Files Modified:
wolfcrypt/src/port/st/stsafe.c- Added STSAFE-A120/STSELib implementationwolfssl/wolfcrypt/port/st/stsafe.h- Added type abstractions and curve mappingswolfcrypt/src/wc_port.c- Updated STSAFE initializationwolfcrypt/src/port/st/README.md- Added documentationFeatures
Configuration
Enable with:
Dependencies
API Compatibility
The new implementation maintains API compatibility with the existing STSAFE-A100 code:
stsafe_interface_init()- Initialize devicewolfSSL_STSAFE_CryptoDevCb()- Crypto callback handlerSSL_STSAFE_*callback functions for TLS integrationTesting
Tested on Raspberry Pi 5 with STSAFE-A120 connected via I2C:
Performance (Raspberry Pi 5)
Notes
stse_conf.hstsafe.hdepend on which curves are enabled instse_conf.hRelated
ZD 20780