Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hardware-based security support for the i.MX series chips. #38050

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Support P256KeyPair based on Trusty OS
move the p256keypair operations to Trusty OS to enhance
the crypto security.

Change-Id: I47ec6b440f91adf3e717ed8915f35b7844731c90
Signed-off-by: Ji Luo <ji.luo@nxp.com>
Reviewed-on: http://androidsource.nxp.com/project/21251
Reviewed-by: Elven Wang <elven.wang@nxp.com>
Reviewed-on: http://androidsource.nxp.com/project/23005
  • Loading branch information
luoji-nxp authored and “nxf90552” committed Mar 18, 2025
commit afe7e37f21b0d3887994da2fda3780c311d7c3c7
13 changes: 13 additions & 0 deletions src/crypto/BUILD.gn
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2020 Project CHIP Authors
# Copyright 2025 NXP
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -20,6 +21,8 @@ import("${chip_root}/build/chip/buildconfig_header.gni")

import("crypto.gni")

import("${chip_root}/src/lib/trusty.gni")

if (chip_crypto == "") {
if (current_os == "android" || current_os == "freertos" ||
current_os == "zephyr" || current_os == "mbed" || current_os == "webos" ||
@@ -74,6 +77,12 @@ buildconfig_header("crypto_buildconfig") {
"CHIP_CRYPTO_BORINGSSL=${chip_crypto_boringssl}",
"CHIP_CRYPTO_PLATFORM=${chip_crypto_platform}",
]

if (chip_with_trusty_os == 1) {
defines += [ "CHIP_CRYPTO_TRUSTY_OS=1" ]
} else {
defines += [ "CHIP_CRYPTO_TRUSTY_OS=0" ]
}
}

source_set("public_headers") {
@@ -92,6 +101,10 @@ source_set("public_headers") {
"${chip_root}/src/lib/support",
"${nlassert_root}:nlassert",
]

if (chip_with_trusty_os == 1) {
public_deps += [ "${chip_root}/third_party/libtrustymatter" ]
}
}

if (chip_crypto == "openssl") {
5 changes: 5 additions & 0 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
*
* Copyright (c) 2020-2023 Project CHIP Authors
* Copyright 2025 NXP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -588,6 +589,10 @@ class P256Keypair : public P256KeypairBase
/** Release resources associated with this key pair */
void Clear();

#if CHIP_CRYPTO_TRUSTY_OS
uint64_t p256_handler = 0;
#endif

protected:
P256PublicKey mPublicKey;
mutable P256KeypairContext mKeypair;
164 changes: 164 additions & 0 deletions src/crypto/CHIPCryptoPALOpenSSL.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
*
* Copyright (c) 2020-2023 Project CHIP Authors
* Copyright 2025 NXP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,9 +56,18 @@

#include <string.h>

#if CHIP_CRYPTO_TRUSTY_OS
#include <trusty_matter.h>
using namespace matter;
#endif

namespace chip {
namespace Crypto {

#if CHIP_CRYPTO_TRUSTY_OS
TrustyMatter trusty_matter;
#endif

// BoringSSL is designed to implement the same interface as OpenSSL in most
// cases. However, it removes some APIs that can allow very weak configuration.
// (Example: CCM ciphers with low tag lengths.) In order to support Matter,
@@ -744,6 +754,43 @@ static inline const EC_KEY * to_const_EC_KEY(const P256KeypairContext * context)
return *SafePointerCast<const EC_KEY * const *>(context);
}

#if CHIP_CRYPTO_TRUSTY_OS
CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
{
CHIP_ERROR error = CHIP_NO_ERROR;
size_t sig_size = 0;
int rc = 0;

VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);

uint8_t digest[kSHA256_Hash_Length];
uint8_t sig[kP256_ECDSA_Signature_Length_Raw];
memset(&digest[0], 0, sizeof(digest));
memset(&sig[0], 0, sizeof(sig));

ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));

ERR_clear_error();

static_assert(P256ECDSASignature::Capacity() >= kP256_ECDSA_Signature_Length_Raw, "P256ECDSASignature must be large enough");
VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);

rc = trusty_matter.P256KeypairECSignMsg(p256_handler, digest, kSHA256_Hash_Length, sig, sig_size);
VerifyOrExit(rc == MATTER_ERROR_OK, error = CHIP_ERROR_INTERNAL);
VerifyOrExit(sig_size == kP256_ECDSA_Signature_Length_Raw, error = CHIP_ERROR_INTERNAL);

VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
memcpy(out_signature.Bytes() + 0u, sig, sig_size);

exit:
if (error != CHIP_NO_ERROR)
{
_logSSLError();
}

return error;
}
#else
CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
{
CHIP_ERROR error = CHIP_NO_ERROR;
@@ -799,6 +846,7 @@ CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_len

return error;
}
#endif

CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length,
const P256ECDSASignature & signature) const
@@ -968,6 +1016,25 @@ static CHIP_ERROR _create_evp_key_from_binary_p256_key(const P256PublicKey & key
return error;
}

#if CHIP_CRYPTO_TRUSTY_OS
CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
{
ERR_clear_error();
CHIP_ERROR error = CHIP_NO_ERROR;
int result = -1;
size_t out_buf_length = 0;

result = trusty_matter.P256KeypairECDH_derive_secret(p256_handler, Uint8::to_const_uchar(remote_public_key),
remote_public_key.Length(), out_secret.Bytes(), out_buf_length);
VerifyOrExit(result == MATTER_ERROR_OK, error = CHIP_ERROR_INTERNAL);
VerifyOrExit((out_buf_length > 0), error = CHIP_ERROR_INTERNAL);
SuccessOrExit(error = out_secret.SetLength(out_buf_length));

exit:
_logSSLError();
return error;
}
#else
CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
{
ERR_clear_error();
@@ -1035,6 +1102,7 @@ CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_k
_logSSLError();
return error;
}
#endif

void ClearSecretData(uint8_t * buf, size_t len)
{
@@ -1082,6 +1150,101 @@ static CHIP_ERROR P256PublicKeyFromECKey(EC_KEY * ec_key, P256PublicKey & pubkey
return error;
}

#if CHIP_CRYPTO_TRUSTY_OS
CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
{
ERR_clear_error();
CHIP_ERROR error = CHIP_NO_ERROR;
uint8_t public_key[kP256_PublicKey_Length];
int rc = 0;

rc = trusty_matter.P256KeypairInitialize(p256_handler, public_key);
VerifyOrExit(rc == MATTER_ERROR_OK, error = CHIP_ERROR_INTERNAL);

memcpy(Uint8::to_uchar(mPublicKey), public_key, kP256_PublicKey_Length);

mInitialized = true;

exit:
_logSSLError();
return error;
}

CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const
{
CHIP_ERROR error = CHIP_NO_ERROR;
uint8_t privkey[kP256_PrivateKey_Length];
int rc = 0;

rc = trusty_matter.P256KeypairSerialize(p256_handler, privkey);
VerifyOrExit(rc == MATTER_ERROR_OK, error = CHIP_ERROR_INTERNAL);

{
size_t len = output.Length() == 0 ? output.Capacity() : output.Length();
Encoding::BufferWriter bbuf(output.Bytes(), len);
bbuf.Put(mPublicKey, mPublicKey.Length());
bbuf.Put(privkey, sizeof(privkey));
VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
output.SetLength(bbuf.Needed());
}

exit:
ClearSecretData(privkey, sizeof(privkey));
_logSSLError();
return error;
}

CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
{
CHIP_ERROR error = CHIP_NO_ERROR;
Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length());
int rc = 0;

uint8_t * pubkey = input.Bytes();
uint8_t * privkey = input.Bytes() + mPublicKey.Length();

VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
bbuf.Put(input.ConstBytes(), mPublicKey.Length());
VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);

rc = trusty_matter.P256KeypairDeserialize(p256_handler, pubkey, mPublicKey.Length(), privkey, kP256_PrivateKey_Length);
VerifyOrExit(rc == MATTER_ERROR_OK, error = CHIP_ERROR_INTERNAL);

mInitialized = true;

exit:
_logSSLError();
return error;
}

void P256Keypair::Clear()
{
mInitialized = false;
p256_handler = 0;
}

P256Keypair::~P256Keypair()
{
trusty_matter.P256KeypairDestory(p256_handler);
Clear();
}

CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
{
ERR_clear_error();
CHIP_ERROR error = CHIP_NO_ERROR;
int rc = 0;

VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);

rc = trusty_matter.P256KeypairNewCSR(p256_handler, out_csr, csr_length);
VerifyOrExit(rc == MATTER_ERROR_OK, error = CHIP_ERROR_INTERNAL);

exit:
_logSSLError();
return error;
}
#else
CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
{
ERR_clear_error();
@@ -1314,6 +1477,7 @@ CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t &
_logSSLError();
return error;
}
#endif

CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr, size_t csr_length, P256PublicKey & pubkey)
{