blob: afa988d3ce8cb705842db60ab75006f79f804726 [file] [log] [blame]
/*
*
* Copyright (c) 2024 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* HSM based implementation of CHIP crypto primitives
* Based on configurations in CHIPCryptoPALHsm_config.h file,
* chip crypto apis use either HSM or rollback to software implementation.
*/
#include "CHIPCryptoPALHsm_utils_trustm.h"
#include "optiga/optiga_util.h"
#include "optiga_crypt.h"
#include "optiga_lib_common.h"
#include "optiga_lib_types.h"
#include <lib/core/CHIPEncoding.h>
#define NIST256_HEADER_OFFSET 26
#define CRYPTO_KEYPAIR_KEYID_OFFSET 4
/* Used for CSR generation */
// Organisation info.
#define SUBJECT_STR "CSR"
#define ASN1_BIT_STRING 0x03
#define ASN1_NULL 0x05
#define ASN1_OID 0x06
#define ASN1_SEQUENCE 0x10
#define ASN1_SET 0x11
#define ASN1_UTF8_STRING 0x0C
#define ASN1_CONSTRUCTED 0x20
#define ASN1_CONTEXT_SPECIFIC 0x80
const uint8_t kTlvHeader = 2;
// Define keyid
uint32_t keyid = 0;
namespace chip {
namespace Crypto {
#define EC_NIST_P256_KP_HEADER \
{ \
0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, \
0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02, 0x01, 0x01, 0x04, 0x20, \
}
#define EC_NIST_P256_KP_PUB_HEADER \
{ \
0xA1, 0x44, 0x03, 0x42, 0x00, \
}
#define NIST256_HEADER_LENGTH (26)
extern CHIP_ERROR Initialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair);
extern CHIP_ERROR ECDSA_sign_msg_H(P256KeypairContext * mKeypair, const uint8_t * msg, const size_t msg_length,
P256ECDSASignature & out_signature);
extern CHIP_ERROR ECDH_derive_secret_H(P256KeypairContext * mKeypair, const P256PublicKey & remote_public_key,
P256ECDHDerivedSecret & out_secret);
extern CHIP_ERROR NewCertificateSigningRequest_H(P256KeypairContext * mKeypair, uint8_t * out_csr, size_t & csr_length);
extern CHIP_ERROR Deserialize_H(P256Keypair * pk, P256PublicKey * mPublicKey, P256KeypairContext * mKeypair,
P256SerializedKeypair & input);
extern CHIP_ERROR Serialize_H(const P256KeypairContext mKeypair, const P256PublicKey mPublicKey, P256SerializedKeypair & output);
extern CHIP_ERROR ECDSA_validate_msg_signature_H(const P256PublicKey * public_key, const uint8_t * msg, const size_t msg_length,
const P256ECDSASignature & signature);
extern CHIP_ERROR ECDSA_validate_hash_signature_H(const P256PublicKey * public_key, const uint8_t * hash, const size_t hash_length,
const P256ECDSASignature & signature);
#if (ENABLE_TRUSTM_GENERATE_EC_KEY || ENABLE_TRUSTM_ECDSA_VERIFY)
static CHIP_ERROR get_trustm_keyid_from_keypair(const P256KeypairContext mKeypair, uint32_t * key_id)
{
if (0 != memcmp(&mKeypair.mBytes[0], trustm_magic_no, sizeof(trustm_magic_no)))
{
return CHIP_ERROR_INTERNAL;
}
*key_id += (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET]) | (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 1] << 8);
return CHIP_NO_ERROR;
}
#endif // #if (ENABLE_TRUSTM_GENERATE_EC_KEY || ENABLE_TRUSTM_ECDSA_VERIFY)
P256Keypair::~P256Keypair()
{
// Add method to get the keyid
if (CHIP_NO_ERROR != get_trustm_keyid_from_keypair(mKeypair, &keyid))
{
Clear();
}
else
{
// Delete the key in SE
}
}
CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
{
CHIP_ERROR error = CHIP_ERROR_INTERNAL;
#if !ENABLE_TRUSTM_GENERATE_EC_KEY
if (CHIP_NO_ERROR == Initialize_H(this, &mPublicKey, &mKeypair))
{
mInitialized = true;
}
error = CHIP_NO_ERROR;
return error;
#else
uint8_t pubkey[128] = {
0,
};
uint16_t pubKeyLen = sizeof(pubkey);
optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
P256PublicKey & public_key = const_cast<P256PublicKey &>(Pubkey());
optiga_key_usage_t key_usage;
uint16_t keyid;
if (key_target == ECPKeyTarget::ECDH)
{
keyid = TRUSTM_ECDH_OID_KEY;
// Trust M ECC 256 Key Gen
ChipLogDetail(Crypto, "Generating NIST256 key for ECDH!");
key_usage = OPTIGA_KEY_USAGE_KEY_AGREEMENT;
}
else
{
// Add the logic to use different keyid
keyid = TRUSTM_NODE_OID_KEY_START;
// Trust M ECC 256 Key Gen
ChipLogDetail(Crypto, "Generating NIST256 key in TrustM !");
key_usage = (optiga_key_usage_t) (OPTIGA_KEY_USAGE_SIGN | OPTIGA_KEY_USAGE_AUTHENTICATION);
}
// Trust M init
trustm_Open();
return_status = trustm_ecc_keygen(keyid, key_usage, OPTIGA_ECC_CURVE_NIST_P_256, pubkey, &pubKeyLen);
// Add signature length
VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
/* Set the public key */
VerifyOrReturnError((size_t) pubKeyLen > NIST256_HEADER_OFFSET, CHIP_ERROR_INTERNAL);
VerifyOrReturnError(((size_t) pubKeyLen - NIST256_HEADER_OFFSET) <= kP256_PublicKey_Length, CHIP_ERROR_INTERNAL);
memcpy((void *) Uint8::to_const_uchar(public_key), pubkey + NIST256_HEADER_OFFSET, pubKeyLen - NIST256_HEADER_OFFSET);
memcpy(&mKeypair.mBytes[0], trustm_magic_no, sizeof(trustm_magic_no));
mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET] = (keyid >> (0 * 8)) & 0xFF;
mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 1] = (keyid >> (1 * 8)) & 0xFF;
mInitialized = true;
error = CHIP_NO_ERROR;
exit:
if (error != CHIP_NO_ERROR)
{
trustm_close();
}
return error;
#endif
}
CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const
{
#if !ENABLE_TRUSTM_GENERATE_EC_KEY
return ECDSA_sign_msg_H(&mKeypair, msg, msg_length, out_signature);
#else
CHIP_ERROR error = CHIP_ERROR_INTERNAL;
optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
uint8_t signature_trustm[kMax_ECDSA_Signature_Length_Der] = { 0 };
uint16_t signature_trustm_len = (uint16_t) kMax_ECDSA_Signature_Length_Der;
uint8_t digest[32];
uint8_t digest_length = sizeof(digest);
memset(&digest[0], 0, sizeof(digest));
MutableByteSpan out_raw_sig_span(out_signature.Bytes(), out_signature.Capacity());
VerifyOrReturnError(msg != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(msg_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
ChipLogDetail(Crypto, "TrustM: ECDSA_sign_msg");
// Trust M Init
trustm_Open();
// Hash to get the digest
Hash_SHA256(msg, msg_length, &digest[0]);
uint16_t keyid = (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET]) | (mKeypair.mBytes[CRYPTO_KEYPAIR_KEYID_OFFSET + 1] << 8);
// Api call to calculate the signature
if (keyid == OPTIGA_KEY_ID_E0F2)
{
return_status = trustm_ecdsa_sign(OPTIGA_KEY_ID_E0F2, digest, digest_length, signature_trustm, &signature_trustm_len);
}
else
{
return_status = trustm_ecdsa_sign(OPTIGA_KEY_ID_E0F0, digest, digest_length, signature_trustm, &signature_trustm_len);
}
VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
error = EcdsaAsn1SignatureToRaw(kP256_FE_Length, ByteSpan{ signature_trustm, signature_trustm_len }, out_raw_sig_span);
SuccessOrExit(error);
out_signature.SetLength(2 * kP256_FE_Length);
error = CHIP_NO_ERROR;
exit:
if (error != CHIP_NO_ERROR)
{
trustm_close();
}
return error;
#endif
}
CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
{
#if !ENABLE_TRUSTM_GENERATE_EC_KEY
return ECDH_derive_secret_H(&mKeypair, remote_public_key, out_secret);
#else
CHIP_ERROR error = CHIP_ERROR_INTERNAL;
optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
size_t secret_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length();
uint32_t keyid = 0;
if (CHIP_NO_ERROR != get_trustm_keyid_from_keypair(mKeypair, &keyid))
{
ChipLogDetail(Crypto, "ECDH_derive_secret : Host");
return ECDH_derive_secret_H(&mKeypair, remote_public_key, out_secret);
}
ChipLogDetail(Crypto, "TrustM: ECDH_derive_secret");
trustm_Open();
const uint8_t * const rem_pubKey = Uint8::to_const_uchar(remote_public_key);
const size_t rem_pubKeyLen = remote_public_key.Length();
uint8_t remote_key[68];
uint8_t header[3] = { 0x03, 0x42, 0x00 };
memcpy(remote_key, &header, 3);
memcpy(remote_key + 3, rem_pubKey, rem_pubKeyLen);
return_status = trustm_ecdh_derive_secret(OPTIGA_KEY_ID_E100, (uint8_t *) remote_key, (uint16_t) rem_pubKeyLen + 3,
out_secret.Bytes(), (uint8_t) secret_length);
VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
exit:
if (error != CHIP_NO_ERROR)
{
trustm_close();
}
return out_secret.SetLength(secret_length);
#endif
}
CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length,
const P256ECDSASignature & signature) const
{
#if !ENABLE_TRUSTM_ECDSA_VERIFY
return ECDSA_validate_hash_signature_H(this, hash, hash_length, signature);
#else
CHIP_ERROR error = CHIP_ERROR_INTERNAL;
optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
uint8_t signature_trustm[kMax_ECDSA_Signature_Length_Der] = { 0 };
size_t signature_trustm_len = sizeof(signature_trustm);
MutableByteSpan out_der_sig_span(signature_trustm, signature_trustm_len);
uint8_t hash_length_u8 = static_cast<uint8_t>(hash_length);
uint16_t signature_trustm_len_u16 = static_cast<uint16_t>(signature_trustm_len);
VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(hash_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
ChipLogDetail(Crypto, "TrustM: ECDSA_validate_hash_signature");
// Trust M init
trustm_Open();
error = EcdsaRawSignatureToAsn1(kP256_FE_Length, ByteSpan{ Uint8::to_const_uchar(signature.ConstBytes()), signature.Length() },
out_der_sig_span);
SuccessOrExit(error);
signature_trustm_len = out_der_sig_span.size();
// ECC verify
return_status = trustm_ecdsa_verify((uint8_t *) hash, hash_length_u8, (uint8_t *) signature_trustm, signature_trustm_len_u16,
(uint8_t *) bytes, (uint8_t) kP256_PublicKey_Length);
VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
exit:
if (error != CHIP_NO_ERROR)
{
trustm_close();
}
return error;
#endif
}
CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const
{
const size_t len = output.Length() == 0 ? output.Capacity() : output.Length();
Encoding::BufferWriter bbuf(output.Bytes(), len);
uint8_t privkey[kP256_PrivateKey_Length] = {
0,
};
/* Set the public key */
P256PublicKey & public_key = const_cast<P256PublicKey &>(Pubkey());
bbuf.Put(Uint8::to_uchar(public_key), public_key.Length());
VerifyOrReturnError(bbuf.Available() == sizeof(privkey), CHIP_ERROR_INTERNAL);
/* Set the private key trustm_magic_no */
bbuf.Put(mKeypair.mBytes, kP256_PrivateKey_Length);
VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL);
output.SetLength(bbuf.Needed());
return CHIP_NO_ERROR;
}
CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
{
CHIP_ERROR error = CHIP_ERROR_INTERNAL;
const uint8_t * privkey;
/* Set the public key */
P256PublicKey & public_key = const_cast<P256PublicKey &>(Pubkey());
Encoding::BufferWriter bbuf((uint8_t *) Uint8::to_const_uchar(public_key), public_key.Length());
VerifyOrReturnError(input.Length() == public_key.Length() + kP256_PrivateKey_Length, CHIP_ERROR_INVALID_ARGUMENT);
privkey = input.ConstBytes() + public_key.Length();
if (0 == memcmp(privkey, trustm_magic_no, sizeof(trustm_magic_no)))
{
/* trustm_magic_no + KeyID is passed */
ChipLogDetail(Crypto, "Deserialize: key found");
bbuf.Put(input.Bytes(), public_key.Length());
VerifyOrReturnError(bbuf.Fit(), CHIP_ERROR_NO_MEMORY);
memcpy(&mKeypair.mBytes[0], trustm_magic_no, sizeof(trustm_magic_no));
mKeypair.mBytes[4] = *(privkey + 4);
mKeypair.mBytes[5] = *(privkey + 5);
mInitialized = true;
return CHIP_NO_ERROR;
}
else
{
#if !ENABLE_TRUSTM_KEY_IMPORT
if (CHIP_NO_ERROR == (error = Deserialize_H(this, &mPublicKey, &mKeypair, input)))
{
mInitialized = true;
}
return error;
#else
// Add in code for Trust M
return CHIP_NO_ERROR;
#endif
}
}
CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length,
const P256ECDSASignature & signature) const
{
#if !ENABLE_TRUSTM_ECDSA_VERIFY
return ECDSA_validate_msg_signature_H(this, msg, msg_length, signature);
#else
CHIP_ERROR error = CHIP_ERROR_INTERNAL;
uint8_t signature_trustm[kMax_ECDSA_Signature_Length_Der] = { 0 };
size_t signature_trustm_len = sizeof(signature_trustm);
uint8_t digest[32];
uint8_t digest_length = sizeof(digest);
MutableByteSpan out_der_sig_span(signature_trustm, signature_trustm_len);
optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
uint16_t signature_trustm_len_u16 = static_cast<uint16_t>(signature_trustm_len);
VerifyOrReturnError(msg != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(msg_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
ChipLogDetail(Crypto, "TrustM: ECDSA_validate_msg_signature");
// Trust M init
trustm_Open();
error = EcdsaRawSignatureToAsn1(kP256_FE_Length, ByteSpan{ Uint8::to_const_uchar(signature.ConstBytes()), signature.Length() },
out_der_sig_span);
SuccessOrExit(error);
signature_trustm_len = out_der_sig_span.size();
// Hash to get the digest
memset(&digest[0], 0, sizeof(digest));
Hash_SHA256(msg, msg_length, &digest[0]);
// ECC verify
return_status = trustm_ecdsa_verify(digest, digest_length, (uint8_t *) signature_trustm, signature_trustm_len_u16,
(uint8_t *) bytes, (uint8_t) kP256_PublicKey_Length);
VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
exit:
if (error != CHIP_NO_ERROR)
{
trustm_close();
}
return error;
#endif
}
static void add_tlv(uint8_t * buf, size_t buf_index, uint8_t tag, size_t len, uint8_t * val)
{
buf[buf_index++] = tag;
buf[buf_index++] = (uint8_t) len;
if (len > 0 && val != NULL)
{
memcpy(&buf[buf_index], val, len);
buf_index = buf_index + len;
}
}
CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const
{
#if !ENABLE_TRUSTM_GENERATE_EC_KEY
return NewCertificateSigningRequest_H(&mKeypair, csr, csr_length);
#else
CHIP_ERROR error = CHIP_ERROR_INTERNAL;
optiga_lib_status_t return_status = OPTIGA_LIB_BUSY;
uint8_t data_to_hash[128] = { 0 };
size_t data_to_hash_len = sizeof(data_to_hash);
uint8_t pubkey[128] = { 0 };
size_t pubKeyLen = 0;
uint8_t digest[32] = { 0 };
uint8_t digest_length = sizeof(digest);
uint8_t signature_trustm[128] = { 0 };
uint16_t signature_len = sizeof(signature_trustm);
size_t csr_index = 0;
size_t buffer_index = data_to_hash_len;
// Dummy value
uint8_t organisation_oid[3] = { 0x55, 0x04, 0x0a };
// Version ::= INTEGER { v1(0), v2(1), v3(2) }
uint8_t version[3] = { 0x02, 0x01, 0x00 };
uint8_t signature_oid[8] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02 };
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 };
VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED);
if (CHIP_NO_ERROR != get_trustm_keyid_from_keypair(mKeypair, &keyid))
{
ChipLogDetail(Crypto, "NewCertificateSigningRequest : Host");
return NewCertificateSigningRequest_H(&mKeypair, csr, csr_length);
}
ChipLogDetail(Crypto, "NewCertificateSigningRequest: TrustM");
// No extensions are copied
buffer_index -= kTlvHeader;
add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC), 0, NULL);
// Copy public key (with header)
{
P256PublicKey & public_key = const_cast<P256PublicKey &>(Pubkey());
VerifyOrExit((sizeof(nist256_header) + public_key.Length()) <= sizeof(pubkey), error = CHIP_ERROR_INTERNAL);
memcpy(pubkey, nist256_header, sizeof(nist256_header));
pubKeyLen = pubKeyLen + sizeof(nist256_header);
memcpy((pubkey + pubKeyLen), Uint8::to_uchar(public_key), public_key.Length());
pubKeyLen = pubKeyLen + public_key.Length();
}
buffer_index -= pubKeyLen;
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
memcpy((void *) &data_to_hash[buffer_index], pubkey, pubKeyLen);
// Copy subject (in the current implementation only organisation name info is added) and organisation OID
buffer_index -= (kTlvHeader + sizeof(SUBJECT_STR) - 1);
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
add_tlv(data_to_hash, buffer_index, ASN1_UTF8_STRING, sizeof(SUBJECT_STR) - 1, (uint8_t *) SUBJECT_STR);
buffer_index -= (kTlvHeader + sizeof(organisation_oid));
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
add_tlv(data_to_hash, buffer_index, ASN1_OID, sizeof(organisation_oid), organisation_oid);
// Add length
buffer_index -= kTlvHeader;
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE),
((2 * kTlvHeader) + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL);
buffer_index -= kTlvHeader;
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SET),
((3 * kTlvHeader) + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL);
buffer_index -= kTlvHeader;
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE),
((4 * kTlvHeader) + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL);
buffer_index -= 3;
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
memcpy((void *) &data_to_hash[buffer_index], version, sizeof(version));
buffer_index -= kTlvHeader;
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE), (data_to_hash_len - buffer_index - kTlvHeader), NULL);
// TLV data is created by copying from backwards. move it to start of buffer.
data_to_hash_len = (data_to_hash_len - buffer_index);
memmove(data_to_hash, (data_to_hash + buffer_index), data_to_hash_len);
// Hash to get the digest
memset(&digest[0], 0, sizeof(digest));
error = Hash_SHA256(data_to_hash, data_to_hash_len, digest);
SuccessOrExit(error);
// Trust M Init
trustm_Open();
// Sign on hash
return_status = trustm_ecdsa_sign(OPTIGA_KEY_ID_E0F2, digest, digest_length, signature_trustm, &signature_len);
VerifyOrExit(return_status == OPTIGA_LIB_SUCCESS, error = CHIP_ERROR_INTERNAL);
VerifyOrExit((csr_index + 3) <= csr_length, error = CHIP_ERROR_INTERNAL);
csr[csr_index++] = (ASN1_CONSTRUCTED | ASN1_SEQUENCE);
if ((data_to_hash_len + 14 + kTlvHeader + signature_len) >= 0x80)
{
csr[csr_index++] = 0x81;
}
csr[csr_index++] = (uint8_t) (data_to_hash_len + 14 + kTlvHeader + signature_len);
VerifyOrExit((csr_index + data_to_hash_len) <= csr_length, error = CHIP_ERROR_INTERNAL);
memcpy((csr + csr_index), data_to_hash, data_to_hash_len);
csr_index = csr_index + data_to_hash_len;
// ECDSA SHA256 Signature OID TLV ==> 1 + 1 + len(signature_oid) (8)
// ASN_NULL ==> 1 + 1
VerifyOrExit((csr_index + kTlvHeader) <= csr_length, error = CHIP_ERROR_INTERNAL);
add_tlv(csr, csr_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE), 0x0C, NULL);
csr_index = csr_index + kTlvHeader;
VerifyOrExit((csr_index + sizeof(signature_oid) + kTlvHeader) <= csr_length, error = CHIP_ERROR_INTERNAL);
add_tlv(csr, csr_index, ASN1_OID, sizeof(signature_oid), signature_oid);
csr_index = csr_index + kTlvHeader + sizeof(signature_oid);
VerifyOrExit((csr_index + kTlvHeader) <= csr_length, error = CHIP_ERROR_INTERNAL);
add_tlv(csr, csr_index, ASN1_NULL, 0x00, NULL);
csr_index = csr_index + kTlvHeader;
VerifyOrExit((csr_index + kTlvHeader) <= csr_length, error = CHIP_ERROR_INTERNAL);
csr[csr_index++] = ASN1_BIT_STRING;
csr[csr_index++] = (uint8_t) ((signature_trustm[0] != 0) ? (signature_len + 1) : (signature_len));
if (signature_trustm[0] != 0)
{
VerifyOrExit(csr_index <= csr_length, error = CHIP_ERROR_INTERNAL);
csr[csr_index++] = 0x00;
// Increament total count by 1
csr[2]++;
}
VerifyOrExit((csr_index + signature_len) <= csr_length, error = CHIP_ERROR_INTERNAL);
memcpy(&csr[csr_index], signature_trustm, signature_len);
csr_length = (csr_index + signature_len);
error = CHIP_NO_ERROR;
exit:
if (error != CHIP_NO_ERROR)
{
trustm_close();
}
return error;
#endif
}
} // namespace Crypto
} // namespace chip