diff --git a/.github/workflows/se050-sim.yml b/.github/workflows/se050-sim.yml index 9799ddb307..5aa49bafe0 100644 --- a/.github/workflows/se050-sim.yml +++ b/.github/workflows/se050-sim.yml @@ -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: 41f85a521c66a3f7ed57fda745a39495f493e9d9 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,8 @@ 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 makes the simulator enforce the applet 7.2 + # ECDH InObject contract: the Tag7 target must be pre-created as an + # HMACKey object of exactly the shared-secret size or the derive is + # refused with SW 0x6985, matching SE05x applet >= 7.2 hardware. + run: docker run --rm -e SE050_SIM_STRICT_ECDH=1 wolfssl-se050-sim:ci-${{ matrix.name }} diff --git a/wolfcrypt/src/port/nxp/se050_port.c b/wolfcrypt/src/port/nxp/se050_port.c index 5e62fed708..1b9aa7db45 100644 --- a/wolfcrypt/src/port/nxp/se050_port.c +++ b/wolfcrypt/src/port/nxp/se050_port.c @@ -2850,25 +2850,42 @@ int se050_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, status = sss_key_object_allocate_handle(&deriveKey, keyIdAes, kSSS_KeyPart_Default, - kSSS_CipherType_Binary, + kSSS_CipherType_HMAC, keySize, kKeyObject_Mode_Transient); } + if (status == kStatus_SSS_Success) { + byte keyBuf[MAX_ECC_BYTES]; + + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &deriveKey); + + /* SE05x applet 7.2 and later stores the ECDH result into an + * existing HMACKey object whose size must equal the shared + * secret exactly, so the object must be created before the + * derive (returns SW 0x6985 otherwise) */ + XMEMSET(keyBuf, 0, sizeof(keyBuf)); + status = sss_key_store_set_key(&host_keystore, &deriveKey, + keyBuf, keySize, keySize * 8, NULL, 0); + if (status == kStatus_SSS_Success) { + deriveKeyCreated = 1; + } + } if (status == kStatus_SSS_Success) { status = sss_derive_key_context_init(&ctx_derive_key, cfg_se050_i2c_pi, &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 = (size_t)*outlen; size_t outlenSzBits = outlenSz * 8; - deriveKeyCreated = 1; + /* sss_key_store_get_key has no HMAC read case, so read the + * object back as AES type (both are a plain ReadObject) */ + deriveKey.cipherType = kSSS_CipherType_AES; /* derived key export */ status = sss_key_store_get_key(&host_keystore, &deriveKey, out, &outlenSz, &outlenSzBits); @@ -3441,14 +3458,31 @@ 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, - kSSS_CipherType_Binary, + kSSS_CipherType_HMAC, keySize, kKeyObject_Mode_Transient); } + if (status == kStatus_SSS_Success) { + byte keyBuf[CURVE25519_KEYSIZE]; + + /* Try to delete existing key first, ignore return since will + * fail if no key exists yet */ + sss_key_store_erase_key(&host_keystore, &deriveKey); + + /* SE05x applet 7.2 and later stores the ECDH result into an + * existing HMACKey object whose size must equal the shared + * secret exactly, so the object must be created before the + * derive (returns SW 0x6985 otherwise) */ + XMEMSET(keyBuf, 0, sizeof(keyBuf)); + status = sss_key_store_set_key(&host_keystore, &deriveKey, + keyBuf, keySize, keySize * 8, NULL, 0); + if (status == kStatus_SSS_Success) { + deriveKeyCreated = 1; + } + } if (status == kStatus_SSS_Success) { status = sss_derive_key_context_init(&ctx_derive_key, cfg_se050_i2c_pi, &ref_private_key, kAlgorithm_SSS_ECDH, @@ -3460,6 +3494,9 @@ int se050_curve25519_shared_secret(curve25519_key* private_key, if (status == kStatus_SSS_Success) { size_t outlenSz = sizeof(out->point); size_t outlenSzBits = outlenSz * 8; + /* sss_key_store_get_key has no HMAC read case, so read the + * object back as AES type (both are a plain ReadObject) */ + deriveKey.cipherType = kSSS_CipherType_AES; /* derived key export */ status = sss_key_store_get_key(&host_keystore, &deriveKey, out->point, &outlenSz, &outlenSzBits);