mirror of https://github.com/wolfSSL/wolfssl.git
Merge pull request #10971 from LinuxJedi/se050_applet72_ecdh
SE050: create ECDH derive target object for applet 7.2 middlewarepull/10974/head
commit
0ffedd2b69
|
|
@ -31,14 +31,16 @@ permissions:
|
|||
# We patch it to COPY the PR checkout instead so CI reflects the PR's source.
|
||||
|
||||
env:
|
||||
SIMULATORS_REF: 745893640e21a15b7df8c70567c522953aba2f2c
|
||||
SIMULATORS_REF: 895ff41b2447efe952e902c467c5ef479f3eda37
|
||||
|
||||
jobs:
|
||||
se050_sim:
|
||||
name: wolfCrypt against SE050 simulator (${{ matrix.name }})
|
||||
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
# Cold image rebuilds (registry cache miss after a SIMULATORS_REF bump,
|
||||
# until the weekend cron refreshes the cache) need well over 30 minutes.
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
|
@ -100,4 +102,12 @@ jobs:
|
|||
cache-to: ${{ ((github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.name == 'default') && 'type=registry,ref=ghcr.io/wolfssl/wolfssl-sim-cache:se050,mode=max' || '' }}
|
||||
|
||||
- name: Run wolfCrypt tests against simulator
|
||||
run: docker run --rm wolfssl-se050-sim:ci-${{ matrix.name }}
|
||||
# SE050_SIM_STRICT_ECDH=1 enforces the applet 7.2 InObject contract
|
||||
# (a Tag7 target must already exist as an exactly-sized HMACKey).
|
||||
# The port now always uses the Tag7-less direct variant, so this is
|
||||
# a regression guard: it fails the run if the InObject flow comes
|
||||
# back. Note the SDK in the image is built for applet 07_02, so only
|
||||
# the >= 7.2 side of the port's version split is compiled here; the
|
||||
# pre-7.2 Binary derive flow is hardware-verified (SE050C, applet
|
||||
# 3.1.1) until an 03_XX matrix leg is added.
|
||||
run: docker run --rm -e SE050_SIM_STRICT_ECDH=1 wolfssl-se050-sim:ci-${{ matrix.name }}
|
||||
|
|
|
|||
|
|
@ -609,6 +609,7 @@ SP_USE_DIVTI3
|
|||
SQRTMOD_USE_MOD_EXP
|
||||
SSL_SNIFFER_EXPORTS
|
||||
SSN_BUILDING_LIBYASSL
|
||||
SSS_HAVE_SE05X_VER_GTE_07_02
|
||||
STATIC_CHUNKS_ONLY
|
||||
STM32F107xC
|
||||
STM32F207xx
|
||||
|
|
@ -891,7 +892,6 @@ WOLFSSL_MAKE_SYSTEM_NAME_LINUX
|
|||
WOLFSSL_MAKE_SYSTEM_NAME_WSL
|
||||
WOLFSSL_MANUALLY_SELECT_DEVICE_CONFIG
|
||||
WOLFSSL_MDK5
|
||||
WOLFSSL_MEM_FAIL_COUNT
|
||||
WOLFSSL_MICROCHIP_AESGCM
|
||||
WOLFSSL_MLKEM_ASM_TEST
|
||||
WOLFSSL_MLKEM_INVNTT_UNROLL
|
||||
|
|
|
|||
|
|
@ -2754,14 +2754,16 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key,
|
|||
sss_key_store_t host_keystore;
|
||||
sss_object_t ref_private_key;
|
||||
sss_object_t ref_public_key;
|
||||
sss_object_t deriveKey;
|
||||
sss_derive_key_t ctx_derive_key;
|
||||
word32 keyId = 0;
|
||||
int keySize;
|
||||
int keySizeBits;
|
||||
sss_cipher_type_t curveType;
|
||||
#if !(defined(SSS_HAVE_SE05X_VER_GTE_07_02) && SSS_HAVE_SE05X_VER_GTE_07_02)
|
||||
sss_object_t deriveKey;
|
||||
sss_derive_key_t ctx_derive_key;
|
||||
word32 keyId = 0;
|
||||
int keyCreated = 0;
|
||||
int deriveKeyCreated = 0;
|
||||
#endif
|
||||
|
||||
#ifdef SE050_DEBUG
|
||||
printf("se050_ecc_shared_secret: priv %p, pub %p, out %p (%d)\n",
|
||||
|
|
@ -2801,6 +2803,7 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key,
|
|||
if (status == kStatus_SSS_Success) {
|
||||
status = sss_key_object_init(&ref_public_key, &host_keystore);
|
||||
}
|
||||
#if !(defined(SSS_HAVE_SE05X_VER_GTE_07_02) && SSS_HAVE_SE05X_VER_GTE_07_02)
|
||||
if (status == kStatus_SSS_Success) {
|
||||
keyId = public_key->keyId;
|
||||
if (public_key->keyIdSet == 0) {
|
||||
|
|
@ -2850,6 +2853,9 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key,
|
|||
status = sss_key_object_allocate_handle(&deriveKey,
|
||||
keyIdAes,
|
||||
kSSS_KeyPart_Default,
|
||||
/* The applet denies ReadObject on a symmetric key object no
|
||||
* matter what policy is attached, so the derive target must
|
||||
* be a Binary object, which ReadObject allows by default */
|
||||
kSSS_CipherType_Binary,
|
||||
keySize,
|
||||
kKeyObject_Mode_Transient);
|
||||
|
|
@ -2882,8 +2888,70 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key,
|
|||
sss_key_store_erase_key(&host_keystore, &deriveKey);
|
||||
sss_key_object_free(&deriveKey);
|
||||
}
|
||||
#else
|
||||
/* The direct APDU carries the peer public point in the command, so
|
||||
* the peer key is never uploaded to the SE050 on this path; a
|
||||
* reference object is only needed when the peer public key is
|
||||
* already SE050-resident. */
|
||||
if (status == kStatus_SSS_Success && public_key->keyIdSet != 0) {
|
||||
status = sss_key_object_get_handle(&ref_public_key,
|
||||
public_key->keyId);
|
||||
}
|
||||
if (status == kStatus_SSS_Success) {
|
||||
/* Middleware built for applet >= 7.2 derives into an SE05x
|
||||
* resident object, but the applet refuses to export a symmetric
|
||||
* key object regardless of the policy attached at its creation
|
||||
* (verified on SE051 applet 7.2.0 hardware), so a derived secret
|
||||
* stored in an object can never be read back. Use the direct
|
||||
* APDU that returns the shared secret in the response instead,
|
||||
* as the middleware itself does whenever the derived key lives
|
||||
* in a host keystore. */
|
||||
byte peerPoint[SE050_ECC_DER_MAX];
|
||||
word32 peerPointSz = (word32)sizeof(peerPoint);
|
||||
smStatus_t sm;
|
||||
|
||||
if (public_key->keyIdSet == 0) {
|
||||
ret = wc_ecc_export_x963(public_key, peerPoint, &peerPointSz);
|
||||
if (ret != 0) {
|
||||
status = kStatus_SSS_Fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Peer public key is SE050-resident: read the DER encoding
|
||||
* back and use the trailing uncompressed point */
|
||||
size_t derSz = sizeof(peerPoint);
|
||||
size_t derSzBits = derSz * 8;
|
||||
word32 pointSz = (word32)(1 + 2 * keySize);
|
||||
status = sss_key_store_get_key(&host_keystore, &ref_public_key,
|
||||
peerPoint, &derSz, &derSzBits);
|
||||
if (status == kStatus_SSS_Success && derSz >= pointSz &&
|
||||
peerPoint[derSz - pointSz] == 0x04) {
|
||||
XMEMMOVE(peerPoint, peerPoint + derSz - pointSz, pointSz);
|
||||
peerPointSz = pointSz;
|
||||
}
|
||||
else {
|
||||
status = kStatus_SSS_Fail;
|
||||
}
|
||||
}
|
||||
if (status == kStatus_SSS_Success) {
|
||||
size_t outSz = (size_t)*outlen;
|
||||
sm = Se05x_API_ECDHGenerateSharedSecret(
|
||||
&((sss_se05x_session_t*)cfg_se050_i2c_pi)->s_ctx,
|
||||
private_key->keyId, peerPoint, peerPointSz, out, &outSz);
|
||||
/* a NIST curve shared secret is always exactly keySize
|
||||
* bytes; anything else indicates a malformed response */
|
||||
if (sm == SM_OK && outSz == (size_t)keySize) {
|
||||
*outlen = (word32)outSz;
|
||||
}
|
||||
else {
|
||||
status = kStatus_SSS_Fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status == kStatus_SSS_Success) {
|
||||
#if !(defined(SSS_HAVE_SE05X_VER_GTE_07_02) && SSS_HAVE_SE05X_VER_GTE_07_02)
|
||||
#ifdef WOLFSSL_SE050_ONLY_KEY_ID
|
||||
if (keyCreated) {
|
||||
/* The peer's public key was uploaded for this derivation only. */
|
||||
|
|
@ -2896,13 +2964,16 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key,
|
|||
public_key->keyId = keyId;
|
||||
public_key->keyIdSet = 1;
|
||||
}
|
||||
#endif /* !SSS_HAVE_SE05X_VER_GTE_07_02 */
|
||||
ret = 0;
|
||||
}
|
||||
else {
|
||||
#if !(defined(SSS_HAVE_SE05X_VER_GTE_07_02) && SSS_HAVE_SE05X_VER_GTE_07_02)
|
||||
if (keyCreated) {
|
||||
sss_key_store_erase_key(&host_keystore, &ref_public_key);
|
||||
sss_key_object_free(&ref_public_key);
|
||||
}
|
||||
#endif
|
||||
if (ret == 0) {
|
||||
ret = WC_HW_E;
|
||||
}
|
||||
|
|
@ -3359,12 +3430,14 @@ int se050_curve25519_shared_secret(curve25519_key* private_key,
|
|||
sss_key_store_t host_keystore;
|
||||
sss_object_t ref_private_key;
|
||||
sss_object_t ref_public_key;
|
||||
#if !(defined(SSS_HAVE_SE05X_VER_GTE_07_02) && SSS_HAVE_SE05X_VER_GTE_07_02)
|
||||
int keySize = CURVE25519_KEYSIZE;
|
||||
sss_object_t deriveKey;
|
||||
sss_derive_key_t ctx_derive_key;
|
||||
word32 keyId;
|
||||
int keySize = CURVE25519_KEYSIZE;
|
||||
int keyCreated = 0;
|
||||
int deriveKeyCreated = 0;
|
||||
#endif
|
||||
|
||||
#ifdef SE050_DEBUG
|
||||
printf("se050_curve25519_shared_secret: priv %p, pub %p, out %p (%d)\n",
|
||||
|
|
@ -3399,6 +3472,7 @@ int se050_curve25519_shared_secret(curve25519_key* private_key,
|
|||
if (status == kStatus_SSS_Success) {
|
||||
status = sss_key_object_init(&ref_public_key, &host_keystore);
|
||||
}
|
||||
#if !(defined(SSS_HAVE_SE05X_VER_GTE_07_02) && SSS_HAVE_SE05X_VER_GTE_07_02)
|
||||
if (status == kStatus_SSS_Success) {
|
||||
keyId = public_key->keyId;
|
||||
if (public_key->keyIdSet == 0) {
|
||||
|
|
@ -3441,10 +3515,12 @@ int se050_curve25519_shared_secret(curve25519_key* private_key,
|
|||
}
|
||||
if (status == kStatus_SSS_Success) {
|
||||
word32 keyIdAes = se050_allocate_key(SE050_AES_KEY);
|
||||
deriveKeyCreated = 1;
|
||||
status = sss_key_object_allocate_handle(&deriveKey,
|
||||
keyIdAes,
|
||||
kSSS_KeyPart_Default,
|
||||
/* The applet denies ReadObject on a symmetric key object no
|
||||
* matter what policy is attached, so the derive target must
|
||||
* be a Binary object, which ReadObject allows by default */
|
||||
kSSS_CipherType_Binary,
|
||||
keySize,
|
||||
kKeyObject_Mode_Transient);
|
||||
|
|
@ -3454,12 +3530,16 @@ int se050_curve25519_shared_secret(curve25519_key* private_key,
|
|||
&ref_private_key, kAlgorithm_SSS_ECDH,
|
||||
kMode_SSS_ComputeSharedSecret);
|
||||
if (status == kStatus_SSS_Success) {
|
||||
/* Try to delete existing key first, ignore return since will
|
||||
* fail if no key exists yet */
|
||||
sss_key_store_erase_key(&host_keystore, &deriveKey);
|
||||
status = sss_derive_key_dh(&ctx_derive_key, &ref_public_key,
|
||||
&deriveKey);
|
||||
}
|
||||
if (status == kStatus_SSS_Success) {
|
||||
size_t outlenSz = sizeof(out->point);
|
||||
size_t outlenSzBits = outlenSz * 8;
|
||||
deriveKeyCreated = 1;
|
||||
/* derived key export */
|
||||
status = sss_key_store_get_key(&host_keystore, &deriveKey,
|
||||
out->point, &outlenSz, &outlenSzBits);
|
||||
|
|
@ -3473,8 +3553,85 @@ int se050_curve25519_shared_secret(curve25519_key* private_key,
|
|||
sss_key_store_erase_key(&host_keystore, &deriveKey);
|
||||
sss_key_object_free(&deriveKey);
|
||||
}
|
||||
#else
|
||||
/* The direct APDU carries the peer public point in the command, so
|
||||
* the peer key is never uploaded to the SE050 on this path; a
|
||||
* reference object is only needed when the peer public key is
|
||||
* already SE050-resident. */
|
||||
if (status == kStatus_SSS_Success && public_key->keyIdSet != 0) {
|
||||
status = sss_key_object_get_handle(&ref_public_key,
|
||||
public_key->keyId);
|
||||
}
|
||||
if (status == kStatus_SSS_Success) {
|
||||
/* Middleware built for applet >= 7.2 derives into an SE05x
|
||||
* resident object, but the applet refuses to export a symmetric
|
||||
* key object regardless of the policy attached at its creation
|
||||
* (verified on SE051 applet 7.2.0 hardware), so a derived secret
|
||||
* stored in an object can never be read back. Use the direct
|
||||
* APDU that returns the shared secret in the response instead,
|
||||
* as the middleware itself does whenever the derived key lives
|
||||
* in a host keystore. The applet speaks big endian for
|
||||
* Montgomery keys, so the peer point and the returned secret are
|
||||
* both byte swapped, matching sss_se05x_derive_key_dh. */
|
||||
byte peerPoint[CURVE25519_KEYSIZE];
|
||||
word32 peerPointSz = (word32)sizeof(peerPoint);
|
||||
smStatus_t sm;
|
||||
int i;
|
||||
byte swp;
|
||||
|
||||
if (public_key->keyIdSet == 0) {
|
||||
ret = wc_curve25519_export_public_ex(public_key, peerPoint,
|
||||
&peerPointSz, EC25519_LITTLE_ENDIAN);
|
||||
if (ret != 0) {
|
||||
status = kStatus_SSS_Fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Peer public key is SE050-resident: read the DER encoding
|
||||
* back; the raw little endian point is the trailing bytes */
|
||||
byte derBuf[CURVE25519_PUB_KEY_SIZE + 12];
|
||||
size_t derSz = sizeof(derBuf);
|
||||
size_t derSzBits = derSz * 8;
|
||||
status = sss_key_store_get_key(&host_keystore, &ref_public_key,
|
||||
derBuf, &derSz, &derSzBits);
|
||||
if (status == kStatus_SSS_Success &&
|
||||
derSz >= CURVE25519_KEYSIZE) {
|
||||
XMEMCPY(peerPoint, derBuf + derSz - CURVE25519_KEYSIZE,
|
||||
CURVE25519_KEYSIZE);
|
||||
peerPointSz = CURVE25519_KEYSIZE;
|
||||
}
|
||||
else {
|
||||
status = kStatus_SSS_Fail;
|
||||
}
|
||||
}
|
||||
if (status == kStatus_SSS_Success) {
|
||||
size_t outSz = sizeof(out->point);
|
||||
for (i = 0; i < CURVE25519_KEYSIZE / 2; i++) {
|
||||
swp = peerPoint[i];
|
||||
peerPoint[i] = peerPoint[CURVE25519_KEYSIZE - 1 - i];
|
||||
peerPoint[CURVE25519_KEYSIZE - 1 - i] = swp;
|
||||
}
|
||||
sm = Se05x_API_ECDHGenerateSharedSecret(
|
||||
&((sss_se05x_session_t*)cfg_se050_i2c_pi)->s_ctx,
|
||||
private_key->keyId, peerPoint, peerPointSz,
|
||||
out->point, &outSz);
|
||||
if (sm == SM_OK && outSz == CURVE25519_KEYSIZE) {
|
||||
for (i = 0; i < CURVE25519_KEYSIZE / 2; i++) {
|
||||
swp = out->point[i];
|
||||
out->point[i] = out->point[CURVE25519_KEYSIZE - 1 - i];
|
||||
out->point[CURVE25519_KEYSIZE - 1 - i] = swp;
|
||||
}
|
||||
out->pointSz = (word32)outSz;
|
||||
}
|
||||
else {
|
||||
status = kStatus_SSS_Fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status == kStatus_SSS_Success) {
|
||||
#if !(defined(SSS_HAVE_SE05X_VER_GTE_07_02) && SSS_HAVE_SE05X_VER_GTE_07_02)
|
||||
#ifdef WOLFSSL_SE050_ONLY_KEY_ID
|
||||
if (keyCreated) {
|
||||
/* The peer's public key was uploaded for this derivation only.*/
|
||||
|
|
@ -3487,13 +3644,16 @@ int se050_curve25519_shared_secret(curve25519_key* private_key,
|
|||
public_key->keyId = keyId;
|
||||
public_key->keyIdSet = 1;
|
||||
}
|
||||
#endif /* !SSS_HAVE_SE05X_VER_GTE_07_02 */
|
||||
ret = 0;
|
||||
}
|
||||
else {
|
||||
#if !(defined(SSS_HAVE_SE05X_VER_GTE_07_02) && SSS_HAVE_SE05X_VER_GTE_07_02)
|
||||
if (keyCreated) {
|
||||
sss_key_store_erase_key(&host_keystore, &ref_public_key);
|
||||
sss_key_object_free(&ref_public_key);
|
||||
}
|
||||
#endif
|
||||
if (ret == 0)
|
||||
ret = WC_HW_E;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue