diff --git a/src/crypto/hsm/CHIPCryptoPALHsm.h b/src/crypto/hsm/CHIPCryptoPALHsm.h index bce797da8af93b..6701c795edf082 100644 --- a/src/crypto/hsm/CHIPCryptoPALHsm.h +++ b/src/crypto/hsm/CHIPCryptoPALHsm.h @@ -81,6 +81,28 @@ class Spake2pHSM_P256_SHA256_HKDF_HMAC : public Spake2p_P256_SHA256_HKDF_HMAC #if ENABLE_HSM_GENERATE_EC_KEY /* Nist256 Key pair HSM class */ +class P256PublicKeyHSM : public P256PublicKey +{ +public: + P256PublicKeyHSM() { PublicKeyid = 0; } + + size_t Length() const override { return kP256_PublicKey_Length; } + operator uint8_t *() override { return bytes; } + operator const uint8_t *() const override { return bytes; } + + void SetPublicKeyId(uint32_t id) { PublicKeyid = id; } + + CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length, + const P256ECDSASignature & signature) const override; + + CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length, + const P256ECDSASignature & signature) const override; + +private: + uint8_t bytes[kP256_PublicKey_Length]; + uint32_t PublicKeyid; +}; + class P256KeypairHSM : public P256Keypair { public: @@ -105,6 +127,8 @@ class P256KeypairHSM : public P256Keypair virtual CHIP_ERROR ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const override; + const P256PublicKeyHSM & Pubkey() const override { return mPublicKeyHSM; } + bool provisioned_key; void SetKeyId(uint32_t id) { keyid = id; } @@ -113,7 +137,9 @@ class P256KeypairHSM : public P256Keypair private: uint32_t keyid; + P256PublicKeyHSM mPublicKeyHSM; }; + #endif //#if ENABLE_HSM_GENERATE_EC_KEY #if ENABLE_HSM_PBKDF2_SHA256 diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp index f96c35d73cc568..71960d9bd4de7b 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp +++ b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp @@ -99,10 +99,11 @@ CHIP_ERROR P256KeypairHSM::Initialize() { /* Set the public key */ - const P256PublicKey & public_key = Pubkey(); + P256PublicKeyHSM & public_key = const_cast(Pubkey()); VerifyOrExit(pubKeyLen > 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); + public_key.SetPublicKeyId(keyid); } error = CHIP_NO_ERROR; @@ -241,7 +242,7 @@ CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output) { /* Set the public key */ - P256PublicKey & public_key = const_cast(Pubkey()); + P256PublicKeyHSM & public_key = const_cast(Pubkey()); bbuf.Put(Uint8::to_uchar(public_key), public_key.Length()); } @@ -269,7 +270,7 @@ CHIP_ERROR P256KeypairHSM::Deserialize(P256SerializedKeypair & input) CHIP_ERROR error = CHIP_ERROR_INTERNAL; /* Set the public key */ - const P256PublicKey & public_key = Pubkey(); + P256PublicKeyHSM & public_key = const_cast(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); @@ -281,6 +282,7 @@ CHIP_ERROR P256KeypairHSM::Deserialize(P256SerializedKeypair & input) /* When HSM is used for ECC key generation, key info in stored in private key buffer */ const uint8_t * privkey = Uint8::to_const_uchar(input) + public_key.Length(); keyid = Encoding::LittleEndian::Get32(privkey); + public_key.SetPublicKeyId(keyid); } error = CHIP_NO_ERROR; @@ -318,6 +320,192 @@ CHIP_ERROR P256KeypairHSM::ECDH_derive_secret(const P256PublicKey & remote_publi return error; } +/* EC Public key HSM implementation */ + +CHIP_ERROR SE05X_Set_ECDSA_Public_Key(sss_object_t * keyObject, const uint8_t * key, size_t keylen) +{ + sss_status_t status = kStatus_SSS_Fail; + uint8_t public_key[128] = { + 0, + }; + size_t public_key_len = 0; + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + + /* ECC NIST-256 Public Key header */ + const uint8_t nist256_header[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00 }; + + /* Set public key */ + status = sss_key_object_init(keyObject, &gex_sss_chip_ctx.ks); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + status = sss_key_object_allocate_handle(keyObject, kKeyId_sha256_ecc_pub_keyid, kSSS_KeyPart_Public, kSSS_CipherType_EC_NIST_P, + 256, kKeyObject_Mode_Transient); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + VerifyOrExit((sizeof(nist256_header) + keylen) <= sizeof(public_key), error = CHIP_ERROR_INTERNAL); + + memcpy(public_key, nist256_header, sizeof(nist256_header)); + public_key_len = public_key_len + sizeof(nist256_header); + memcpy(public_key + public_key_len, key, keylen); + public_key_len = public_key_len + keylen; + + status = sss_key_store_set_key(&gex_sss_chip_ctx.ks, keyObject, public_key, public_key_len, 256, NULL, 0); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + error = CHIP_NO_ERROR; +exit: + return error; +} + +CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length, + const P256ECDSASignature & signature) const +{ + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_status_t status = kStatus_SSS_Success; + sss_asymmetric_t asymm_ctx = { 0 }; + sss_digest_t ctx_digest = { 0 }; + uint8_t hash[32] = { + 0, + }; + size_t hash_length = sizeof(hash); + sss_object_t keyObject = { 0 }; + + VerifyOrExit(msg != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(msg_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + ChipLogDetail(Crypto, "ECDSA_validate_msg_signature: Using SE05X for ECDSA verify (msg) !"); + + se05x_sessionOpen(); + + /* Create hash of input data */ + status = sss_digest_context_init(&ctx_digest, &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(&ctx_digest, msg, msg_length, hash, &hash_length); + 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(&ctx_digest); + 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(&ctx_digest, (msg + (msg_length - rem_len)), datalenTemp); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + rem_len = rem_len - datalenTemp; + } + + status = sss_digest_finish(&ctx_digest, hash, &hash_length); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + } + + if (PublicKeyid == kKeyId_NotInitialized) + { + error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); + SuccessOrExit(error); + error = CHIP_ERROR_INTERNAL; + } + else + { + 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, PublicKeyid); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + } + + /* ECC Verify */ + status = + sss_asymmetric_context_init(&asymm_ctx, &gex_sss_chip_ctx.session, &keyObject, kAlgorithm_SSS_SHA256, kMode_SSS_Verify); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + status = sss_asymmetric_verify_digest(&asymm_ctx, hash, hash_length, (uint8_t *) Uint8::to_const_uchar(signature), + signature.Length()); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INVALID_SIGNATURE); + + error = CHIP_NO_ERROR; +exit: + if (asymm_ctx.session != NULL) + { + sss_asymmetric_context_free(&asymm_ctx); + } + + if (ctx_digest.session != NULL) + { + sss_digest_context_free(&ctx_digest); + } + + if (PublicKeyid == kKeyId_NotInitialized) + { + sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + } + + return error; +} + +CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length, + const P256ECDSASignature & signature) const +{ + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + sss_status_t status = kStatus_SSS_Success; + sss_asymmetric_t asymm_ctx = { 0 }; + sss_object_t keyObject = { 0 }; + + VerifyOrExit(hash != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(hash_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + ChipLogDetail(Crypto, "ECDSA_validate_hash_signature: Using SE05X for ECDSA verify (hash) !"); + + se05x_sessionOpen(); + + if (PublicKeyid == kKeyId_NotInitialized) + { + error = SE05X_Set_ECDSA_Public_Key(&keyObject, bytes, kP256_PublicKey_Length); + SuccessOrExit(error); + error = CHIP_ERROR_INTERNAL; + } + else + { + 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, PublicKeyid); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + } + + /* ECC Verify */ + status = + sss_asymmetric_context_init(&asymm_ctx, &gex_sss_chip_ctx.session, &keyObject, kAlgorithm_SSS_SHA256, kMode_SSS_Verify); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL); + + status = sss_asymmetric_verify_digest(&asymm_ctx, const_cast(hash), hash_length, + (uint8_t *) Uint8::to_const_uchar(signature), signature.Length()); + VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INVALID_SIGNATURE); + + error = CHIP_NO_ERROR; +exit: + if (asymm_ctx.session != NULL) + { + sss_asymmetric_context_free(&asymm_ctx); + } + + if (PublicKeyid == kKeyId_NotInitialized) + { + sss_key_store_erase_key(&gex_sss_chip_ctx.ks, &keyObject); + } + + return error; +} + } // namespace Crypto } // namespace chip diff --git a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h index d7d84c24c188c6..5b50539f38debc 100644 --- a/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h +++ b/src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h @@ -45,6 +45,7 @@ enum keyid_values kKeyId_NotInitialized = 0, kKeyId_pbkdf2_sha256_hmac_keyid = 0xBCBCBCBC, kKeyId_hkdf_sha256_hmac_keyid, + kKeyId_sha256_ecc_pub_keyid, }; // Enable the below macro to make spake HSM imlementation reentrant.