diff --git a/src/crypto/BUILD.gn b/src/crypto/BUILD.gn index d1751178f33115..6df86dbdf6b8cc 100644 --- a/src/crypto/BUILD.gn +++ b/src/crypto/BUILD.gn @@ -87,6 +87,7 @@ static_library("crypto") { if (chip_with_se05x == 1) { sources += [ "hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp" ] + sources += [ "hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp" ] sources += [ "hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp" ] public_deps += [ "${chip_root}/third_party/simw-top-mini:se05x" ] public_configs += [ "${chip_root}/third_party/simw-top-mini:se05x_config" ] diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 1bd00bb9e9116c..a62eec9fb86e4a 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -243,17 +243,17 @@ class P256Keypair : public ECPKeypair NIST256_HEADER_OFFSET, error = CHIP_ERROR_INTERNAL); + VerifyOrExit( (pubKeyLen - NIST256_HEADER_OFFSET) <= kP256_PublicKey_Length, error = CHIP_ERROR_INTERNAL); + memcpy((void*)Uint8::to_const_uchar(public_key), pubkey + NIST256_HEADER_OFFSET, pubKeyLen - NIST256_HEADER_OFFSET); + } + + error = CHIP_NO_ERROR; +exit: + return error; +} + + +CHIP_ERROR P256KeypairHSM::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) +{ + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_digest_t digest_ctx = { 0 }; + sss_asymmetric_t asymm_ctx = { 0 }; + uint8_t hash[32] = { 0,}; + size_t hashLen = sizeof(hash); + sss_status_t status = kStatus_SSS_Success; + sss_object_t keyObject = { 0 }; + size_t siglen = out_signature.Capacity(); + + VerifyOrExit(msg != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(msg_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(out_signature != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(keyid != 0, error = CHIP_ERROR_HSM); + + ChipLogDetail(Crypto, "ECDSA_sign_msg: Using SE05X for Ecc Sign!"); + + se05x_sessionOpen(); + + status = sss_digest_context_init(&digest_ctx, &gex_sss_chip_ctx.session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + if (msg_length <= MAX_SHA_ONE_SHOT_DATA_LEN) + { + status = sss_digest_one_go(&digest_ctx, msg, msg_length, hash, &hashLen); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + } + else + { + /* Calculate SHA using multistep calls */ + size_t datalenTemp = 0; + size_t rem_len = msg_length; + + status = sss_digest_init(&digest_ctx); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + while (rem_len > 0) + { + datalenTemp = (rem_len > MAX_SHA_ONE_SHOT_DATA_LEN) ? MAX_SHA_ONE_SHOT_DATA_LEN : rem_len; + status = sss_digest_update(&digest_ctx, (msg + (msg_length - rem_len)), datalenTemp); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + rem_len = rem_len - datalenTemp; + } + + status = sss_digest_finish(&digest_ctx, hash, &hashLen); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + } + + status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + status = sss_key_object_get_handle(&keyObject, keyid); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + status = + sss_asymmetric_context_init(&asymm_ctx, &gex_sss_chip_ctx.session, &keyObject, kAlgorithm_SSS_SHA256, kMode_SSS_Sign); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + status = sss_asymmetric_sign_digest(&asymm_ctx, hash, hashLen, Uint8::to_uchar(out_signature), &siglen); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + SuccessOrExit(out_signature.SetLength(siglen)); + + error = CHIP_NO_ERROR; +exit: + if (asymm_ctx.session != NULL) + { + sss_asymmetric_context_free(&asymm_ctx); + } + if (digest_ctx.session != NULL) + { + sss_digest_context_free(&digest_ctx); + } + return error; +} + + +CHIP_ERROR P256KeypairHSM::ECDSA_sign_hash(const uint8_t * hash, size_t hash_length, P256ECDSASignature & out_signature) +{ + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_asymmetric_t asymm_ctx = { 0 }; + sss_status_t status = kStatus_SSS_Success; + sss_object_t keyObject = { 0 }; + size_t siglen = out_signature.Capacity(); + + VerifyOrExit(hash != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(hash_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(out_signature != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(keyid != 0, error = CHIP_ERROR_HSM); + + ChipLogDetail(Crypto, "ECDSA_sign_hash: Using SE05X for Ecc Sign!"); + + se05x_sessionOpen(); + + status = sss_key_object_init(&keyObject, &gex_sss_chip_ctx.ks); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + status = sss_key_object_get_handle(&keyObject, keyid); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + status = + sss_asymmetric_context_init(&asymm_ctx, &gex_sss_chip_ctx.session, &keyObject, kAlgorithm_SSS_SHA256, kMode_SSS_Sign); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + status = sss_asymmetric_sign_digest(&asymm_ctx, (uint8_t*)hash, hash_length, Uint8::to_uchar(out_signature), &siglen); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + SuccessOrExit(out_signature.SetLength(siglen)); + + error = CHIP_NO_ERROR; +exit: + if (asymm_ctx.session != NULL) + { + sss_asymmetric_context_free(&asymm_ctx); + } + + return error; +} + +CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output) +{ + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + size_t len = output.Length() == 0 ? output.Capacity() : output.Length(); + Encoding::BufferWriter bbuf(output, len); + uint8_t privkey[kP256_PrivateKey_Length]; + + { + /* Set the public key */ + const P256PublicKey & public_key = Pubkey(); + bbuf.Put((void*)Uint8::to_const_uchar(public_key), public_key.Length()); + } + + VerifyOrExit(bbuf.Available() == sizeof(privkey), error = CHIP_ERROR_INTERNAL); + + /* When HSM is used for ECC key generation, store key info in private key buffer */ + privkey[0] = (uint8_t)(keyid >> 24) & 0xFF; + privkey[1] = (uint8_t)(keyid >> 16) & 0xFF; + privkey[2] = (uint8_t)(keyid >> 8) & 0xFF; + privkey[3] = (uint8_t) keyid & 0xFF; + + bbuf.Put(privkey, sizeof(privkey)); + VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_BUFFER_TOO_SMALL); + + output.SetLength(bbuf.Needed()); + + error = CHIP_NO_ERROR; +exit: + return error; +} + +CHIP_ERROR P256KeypairHSM::Deserialize(P256SerializedKeypair & input) +{ + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + + /* Set the public key */ + const P256PublicKey & public_key = Pubkey(); + Encoding::BufferWriter bbuf((uint8_t*)Uint8::to_const_uchar(public_key), public_key.Length()); + + VerifyOrExit(input.Length() == public_key.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT); + bbuf.Put((const uint8_t *) input, public_key.Length()); + + /* Set private key info */ + VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY); + { + const uint8_t * privkey = Uint8::to_const_uchar(input) + public_key.Length(); + /* When HSM is used for ECC key generation, key info in stored in private key buffer */ + keyid = privkey[3] | privkey[2] << 8 | privkey[1] << 16 | privkey[0] << 24; + } + + error = CHIP_NO_ERROR; +exit: + return error; +} + +CHIP_ERROR P256KeypairHSM::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const +{ + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + const uint8_t *rem_pubKey = NULL; + size_t rem_pubKeyLen = 0; + size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(); + smStatus_t smstatus = SM_NOT_OK; + + VerifyOrExit(keyid != 0, error = CHIP_ERROR_HSM); + + ChipLogDetail(Crypto, "ECDH_derive_secret: Using SE05X for ECDH !"); + + se05x_sessionOpen(); + + rem_pubKey = Uint8::to_const_uchar(remote_public_key); + rem_pubKeyLen = remote_public_key.Length(); + + VerifyOrExit(rem_pubKey != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(out_secret != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(gex_sss_chip_ctx.ks.session != NULL, error = CHIP_ERROR_INTERNAL); + + smstatus = Se05x_API_ECGenSharedSecret(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx, keyid, rem_pubKey, + rem_pubKeyLen, Uint8::to_uchar(out_secret), &secret_length); + VerifyOrExit(smstatus == SM_OK, error = CHIP_ERROR_INTERNAL); + + SuccessOrExit(out_secret.SetLength(secret_length)); + + error = CHIP_NO_ERROR; +exit: + return error; +} + +} // namespace Crypto { +} // namespace chip { \ No newline at end of file diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index 903ffd35b17304..84f47a330a6daf 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -662,7 +662,12 @@ static void TestECDSA_Signing_SHA256_Msg(nlTestSuite * inSuite, void * inContext const char * msg = "Hello World!"; size_t msg_length = strlen(msg); +#ifdef ENABLE_HSM_EC_KEY + P256KeypairHSM keypair; + keypair.SetKeyId(0x11223344); +#else P256Keypair keypair; +#endif NL_TEST_ASSERT(inSuite, keypair.Initialize() == CHIP_NO_ERROR); P256ECDSASignature signature; @@ -680,7 +685,13 @@ static void TestECDSA_Signing_SHA256_Hash(nlTestSuite * inSuite, void * inContex 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; size_t hash_length = sizeof(hash); +#ifdef ENABLE_HSM_EC_KEY + P256KeypairHSM keypair; + keypair.SetKeyId(0x11223344); +#else P256Keypair keypair; +#endif + NL_TEST_ASSERT(inSuite, keypair.Initialize() == CHIP_NO_ERROR); P256ECDSASignature signature; @@ -849,10 +860,21 @@ static void TestECDSA_ValidationHashInvalidParam(nlTestSuite * inSuite, void * i static void TestECDH_EstablishSecret(nlTestSuite * inSuite, void * inContext) { +#ifdef ENABLE_HSM_EC_KEY + P256KeypairHSM keypair1; + keypair1.SetKeyId(0x11223344); +#else P256Keypair keypair1; +#endif + NL_TEST_ASSERT(inSuite, keypair1.Initialize() == CHIP_NO_ERROR); +#ifdef ENABLE_HSM_EC_KEY + P256KeypairHSM keypair2; + keypair2.SetKeyId(0x11223355); +#else P256Keypair keypair2; +#endif NL_TEST_ASSERT(inSuite, keypair2.Initialize() == CHIP_NO_ERROR); P256ECDHDerivedSecret out_secret1; @@ -959,13 +981,23 @@ static void TestCSR_Gen(nlTestSuite * inSuite, void * inContext) static void TestKeypair_Serialize(nlTestSuite * inSuite, void * inContext) { +#ifdef ENABLE_HSM_EC_KEY + P256KeypairHSM keypair; + keypair.SetKeyId(0x11223344); +#else P256Keypair keypair; +#endif + NL_TEST_ASSERT(inSuite, keypair.Initialize() == CHIP_NO_ERROR); P256SerializedKeypair serialized; NL_TEST_ASSERT(inSuite, keypair.Serialize(serialized) == CHIP_NO_ERROR); +#ifdef ENABLE_HSM_EC_KEY + P256KeypairHSM keypair_dup; +#else P256Keypair keypair_dup; +#endif NL_TEST_ASSERT(inSuite, keypair_dup.Deserialize(serialized) == CHIP_NO_ERROR); const char * msg = "Test Message for Keygen"; @@ -989,7 +1021,7 @@ static void TestSPAKE2P_spake2p_FEMul(nlTestSuite * inSuite, void * inContext) for (int vectorIndex = 0; vectorIndex < numOfTestVectors; vectorIndex++) { const struct spake2p_fe_mul_tv * vector = fe_mul_tvs[vectorIndex]; -#if CHIP_CRYPTO_HSM +#ifdef ENABLE_HSM_SPAKE Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p; #else Spake2p_P256_SHA256_HKDF_HMAC spake2p; @@ -1026,7 +1058,7 @@ static void TestSPAKE2P_spake2p_FELoadWrite(nlTestSuite * inSuite, void * inCont { const struct spake2p_fe_rw_tv * vector = fe_rw_tvs[vectorIndex]; -#if CHIP_CRYPTO_HSM +#ifdef ENABLE_HSM_SPAKE Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p; #else Spake2p_P256_SHA256_HKDF_HMAC spake2p; @@ -1057,7 +1089,7 @@ static void TestSPAKE2P_spake2p_Mac(nlTestSuite * inSuite, void * inContext) { const struct spake2p_hmac_tv * vector = hmac_tvs[vectorIndex]; -#if CHIP_CRYPTO_HSM +#ifdef ENABLE_HSM_SPAKE Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p; #else Spake2p_P256_SHA256_HKDF_HMAC spake2p; @@ -1091,7 +1123,7 @@ static void TestSPAKE2P_spake2p_PointMul(nlTestSuite * inSuite, void * inContext out_len = sizeof(output); const struct spake2p_point_mul_tv * vector = point_mul_tvs[vectorIndex]; -#if CHIP_CRYPTO_HSM +#ifdef ENABLE_HSM_SPAKE Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p; #else Spake2p_P256_SHA256_HKDF_HMAC spake2p; @@ -1131,7 +1163,7 @@ static void TestSPAKE2P_spake2p_PointMulAdd(nlTestSuite * inSuite, void * inCont out_len = sizeof(output); const struct spake2p_point_muladd_tv * vector = point_muladd_tvs[vectorIndex]; -#if CHIP_CRYPTO_HSM +#ifdef ENABLE_HSM_SPAKE Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p; #else Spake2p_P256_SHA256_HKDF_HMAC spake2p; @@ -1177,7 +1209,7 @@ static void TestSPAKE2P_spake2p_PointLoadWrite(nlTestSuite * inSuite, void * inC out_len = sizeof(output); const struct spake2p_point_rw_tv * vector = point_rw_tvs[vectorIndex]; -#if CHIP_CRYPTO_HSM +#ifdef ENABLE_HSM_SPAKE Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p; #else Spake2p_P256_SHA256_HKDF_HMAC spake2p; @@ -1207,7 +1239,7 @@ static void TestSPAKE2P_spake2p_PointIsValid(nlTestSuite * inSuite, void * inCon { const struct spake2p_point_valid_tv * vector = point_valid_tvs[vectorIndex]; -#if CHIP_CRYPTO_HSM +#ifdef ENABLE_HSM_SPAKE Spake2pHSM_P256_SHA256_HKDF_HMAC spake2p; #else Spake2p_P256_SHA256_HKDF_HMAC spake2p; @@ -1231,7 +1263,7 @@ static void TestSPAKE2P_spake2p_PointIsValid(nlTestSuite * inSuite, void * inCon // We need to "generate" specific field elements // to do so we need to override the specific method class Test_Spake2p_P256_SHA256_HKDF_HMAC : -#if CHIP_CRYPTO_HSM +#ifdef ENABLE_HSM_SPAKE public Spake2pHSM_P256_SHA256_HKDF_HMAC #else public Spake2p_P256_SHA256_HKDF_HMAC