Skip to content

Commit

Permalink
HSM support for ECC Public key operations (project-chip#6858)
Browse files Browse the repository at this point in the history
* Added HSM support for ECC Public key crypto operations

* restyled

Co-authored-by: Jagadish B E <[email protected]>
  • Loading branch information
sujaygkulkarni-nxp and Jagadish-NXP authored May 20, 2021
1 parent 38e12dd commit dfb2285
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 3 deletions.
26 changes: 26 additions & 0 deletions src/crypto/hsm/CHIPCryptoPALHsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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; }
Expand All @@ -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
Expand Down
194 changes: 191 additions & 3 deletions src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,11 @@ CHIP_ERROR P256KeypairHSM::Initialize()

{
/* Set the public key */
const P256PublicKey & public_key = Pubkey();
P256PublicKeyHSM & public_key = const_cast<P256PublicKeyHSM &>(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;
Expand Down Expand Up @@ -241,7 +242,7 @@ CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output)

{
/* Set the public key */
P256PublicKey & public_key = const_cast<P256PublicKey &>(Pubkey());
P256PublicKeyHSM & public_key = const_cast<P256PublicKeyHSM &>(Pubkey());
bbuf.Put(Uint8::to_uchar(public_key), public_key.Length());
}

Expand Down Expand Up @@ -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<P256PublicKeyHSM &>(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);
Expand All @@ -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;
Expand Down Expand Up @@ -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<uint8_t *>(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

Expand Down
1 change: 1 addition & 0 deletions src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit dfb2285

Please sign in to comment.