Skip to content

Commit

Permalink
CSR support in crypto HSM (#7897)
Browse files Browse the repository at this point in the history
* Added CSR support in HSM

* updated keyid

* added support for linux in simw build file

* build fix

* Added logs

* build fix

* Using HSM for ops key

* Using HSM for OPS key

* Using HSM for ops key

* added logs

* logs

* restyled

* updated readme

* updated readme

* restyled

* using kTlvHeader for buffer index update

* updating buffer index using kTlvHeader

* restyled

* Trigger Build

* Trigger Build

* Trigger Build

Co-authored-by: Jagadish B E <[email protected]>
Co-authored-by: Jagadish-NXP <[email protected]>
  • Loading branch information
3 people authored Jul 7, 2021
1 parent 6e6c267 commit 1f44fdb
Show file tree
Hide file tree
Showing 12 changed files with 309 additions and 22 deletions.
4 changes: 3 additions & 1 deletion src/crypto/hsm/CHIPCryptoPALHsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class P256KeypairHSM : public P256Keypair

virtual CHIP_ERROR Initialize() override;

virtual CHIP_ERROR Serialize(P256SerializedKeypair & output) override;
virtual CHIP_ERROR Serialize(P256SerializedKeypair & output) const override;

virtual CHIP_ERROR Deserialize(P256SerializedKeypair & input) override;

Expand All @@ -127,6 +127,8 @@ class P256KeypairHSM : public P256Keypair
virtual CHIP_ERROR ECDH_derive_secret(const P256PublicKey & remote_public_key,
P256ECDHDerivedSecret & out_secret) const override;

CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) override;

const P256PublicKeyHSM & Pubkey() const override { return mPublicKeyHSM; }

bool provisioned_key;
Expand Down
4 changes: 3 additions & 1 deletion src/crypto/hsm/CHIPCryptoPALHsm_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
/*
* Enable HSM for PBKDF SHA256
*/
#define ENABLE_HSM_PBKDF2_SHA256 1
#define ENABLE_HSM_PBKDF2_SHA256 0

/*
* Enable HSM for HKDF SHA256
Expand All @@ -54,6 +54,8 @@

#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_GENERATE_EC_KEY))
#define ENABLE_HSM_EC_KEY
#define ENABLE_HSM_CASE_EPHERMAL_KEY
#define ENABLE_HSM_CASE_OPS_KEY
#endif

#if ((CHIP_CRYPTO_HSM) && (ENABLE_HSM_PBKDF2_SHA256))
Expand Down
233 changes: 229 additions & 4 deletions src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_P256.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@
#define MAX_SHA_ONE_SHOT_DATA_LEN 900
#define NIST256_HEADER_OFFSET 26

/* 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;

namespace chip {
namespace Crypto {

Expand All @@ -55,8 +69,8 @@ CHIP_ERROR P256KeypairHSM::Initialize()
uint8_t pubkey[128] = {
0,
};
constexpr size_t pubKeyLen = sizeof(pubkey);
constexpr size_t pbKeyBitLen = sizeof(pubkey) * 8;
size_t pubKeyLen = sizeof(pubkey);
size_t pbKeyBitLen = sizeof(pubkey) * 8;

if (keyid == 0)
{
Expand Down Expand Up @@ -227,7 +241,7 @@ CHIP_ERROR P256KeypairHSM::ECDSA_sign_hash(const uint8_t * hash, size_t hash_len
return error;
}

CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output)
CHIP_ERROR P256KeypairHSM::Serialize(P256SerializedKeypair & output) const
{
const size_t len = output.Length() == 0 ? output.Capacity() : output.Length();
Encoding::BufferWriter bbuf(output, len);
Expand Down Expand Up @@ -308,6 +322,7 @@ CHIP_ERROR SE05X_Set_ECDSA_Public_Key(sss_object_t * keyObject, const uint8_t *
uint8_t public_key[128] = {
0,
};
size_t public_key_len = 0;

/* ECC NIST-256 Public Key header */
const uint8_t nist256_header[] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
Expand All @@ -324,7 +339,7 @@ CHIP_ERROR SE05X_Set_ECDSA_Public_Key(sss_object_t * keyObject, const uint8_t *
VerifyOrReturnError((sizeof(nist256_header) + keylen) <= sizeof(public_key), CHIP_ERROR_INTERNAL);

memcpy(public_key, nist256_header, sizeof(nist256_header));
size_t public_key_len = public_key_len + sizeof(nist256_header);
public_key_len = sizeof(nist256_header);
memcpy(public_key + public_key_len, key, keylen);
public_key_len = public_key_len + keylen;

Expand Down Expand Up @@ -482,6 +497,216 @@ CHIP_ERROR P256PublicKeyHSM::ECDSA_validate_hash_signature(const uint8_t * hash,
return error;
}

static void add_tlv(uint8_t * buf, size_t buf_index, uint8_t tag, size_t len, uint8_t * val)
{
buf[buf_index++] = (uint8_t) tag;
buf[buf_index++] = (uint8_t) len;
if (len > 0 && val != NULL)
{
memcpy(&buf[buf_index], val, len);
buf_index = buf_index + len;
}
}

/*
* CSR format used in the below function,
*
*
* (ASN1_CONSTRUCTED | ASN1_SEQUENCE) LENGTH
*
* (ASN1_CONSTRUCTED | ASN1_SEQUENCE) LENGTH
*
* VERSION ::= INTEGER { v1(0), v2(1), v3(2) }
*
* (ASN1_CONSTRUCTED | ASN1_SEQUENCE) LENGTH
*
* (ASN1_CONSTRUCTED | ASN1_SET) LENGTH
*
* (ASN1_CONSTRUCTED | ASN1_SEQUENCE) LENGTH
*
* (ASN1_OID) LENGTH VALUE(Organisation OID)
*
* (ASN1_UTF8_STRING) LENGTH VALUE(Subject Str == "CSR")
*
* PUBLIC KEY {WITH HEADER. 91 Bytes}
*
* (ASN1_CONSTRUCTED | ASN1_SEQUENCE) LENGTH
*
* (ASN1_OID) LENGTH VALUE(ECDSA SHA256 OID)
*
* (ASN1_NULL) 0x00
*
* (ASN1_BIT_STRING) LENGTH VALUE(SIGNATURE)
*
*/

CHIP_ERROR P256KeypairHSM::NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length)
{
CHIP_ERROR error = CHIP_ERROR_INTERNAL;
sss_status_t status = kStatus_SSS_Success;
sss_asymmetric_t asymm_ctx = { 0 };
sss_object_t keyObject = { 0 };
sss_digest_t digest_ctx = { 0 };

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 hash[32] = { 0 };
size_t hash_length = sizeof(hash);
uint8_t signature[128] = { 0 };
size_t signature_len = sizeof(signature);

size_t csr_index = 0;
size_t buffer_index = data_to_hash_len;

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 };

ChipLogDetail(Crypto, "NewCertificateSigningRequest: Using SE05X for creating CSR !");

// 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)
{
P256PublicKeyHSM & public_key = const_cast<P256PublicKeyHSM &>(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;
// Subject TLV ==> 1 + 1 + len(subject)
// Org OID TLV ==> 1 + 1 + len(organisation_oid)
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);

/* Create hash of `data_to_hash` buffer */
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);

status = sss_digest_one_go(&digest_ctx, data_to_hash, data_to_hash_len, hash, &hash_length);
VerifyOrExit(status == kStatus_SSS_Success, error = CHIP_ERROR_INTERNAL);

// Sign on hash
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, hash_length, Uint8::to_uchar(signature), &signature_len);
VerifyOrExit(status == kStatus_SSS_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[0] != 0) ? (signature_len + 1) : (signature_len));

if (signature[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, signature_len);

csr_length = (csr_index + signature_len);

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;
}

} // namespace Crypto
} // namespace chip

Expand Down
16 changes: 15 additions & 1 deletion src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_Spake2p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ CHIP_ERROR Spake2p_ComputeRoundOne_HSM(hsm_pake_context_t * phsm_pake_context, c
#endif
SE05x_CryptoObjectID_t spakeObjectId = phsm_pake_context->spake_objId;

ChipLogProgress(Crypto, "Using HSM for spake2p ComputeRoundOne \n");

VerifyOrReturnError(out != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(out_len != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
if (pab_len > 0)
Expand All @@ -159,6 +161,7 @@ CHIP_ERROR Spake2p_ComputeRoundOne_HSM(hsm_pake_context_t * phsm_pake_context, c

if (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER)
{
/* Need X/Y value to verify abort condition */
VerifyOrReturnError(pab != NULL, CHIP_ERROR_INVALID_ARGUMENT);
}

Expand Down Expand Up @@ -206,6 +209,8 @@ CHIP_ERROR Spake2p_ComputeRoundTwo_HSM(hsm_pake_context_t * phsm_pake_context, c
VerifyOrReturnError(pKeyKe != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(pkeyKeLen != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

ChipLogProgress(Crypto, "Using HSM for spake2p ComputeRoundTwo \n");

const uint8_t * const pab = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER) ? NULL : in;
const size_t pab_len = (role == chip::Crypto::CHIP_SPAKE2P_ROLE::VERIFIER) ? 0 : in_len;

Expand All @@ -226,6 +231,8 @@ CHIP_ERROR Spake2p_KeyConfirm_HSM(hsm_pake_context_t * phsm_pake_context, chip::
VerifyOrReturnError(in != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(gex_sss_chip_ctx.ks.session != NULL, CHIP_ERROR_INTERNAL);

ChipLogProgress(Crypto, "Using HSM for spake2p KeyConfirm \n");

uint8_t presult = 0;
const SE05x_CryptoObjectID_t spakeObjectId = phsm_pake_context->spake_objId;
const smStatus_t smstatus = Se05x_API_PAKEVerifySessionKeys(&((sss_se05x_session_t *) &gex_sss_chip_ctx.session)->s_ctx,
Expand Down Expand Up @@ -258,7 +265,10 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::Init(const uint8_t * context, size_
}
VerifyOrReturnError(context_len <= sizeof(hsm_pake_context.spake_context), CHIP_ERROR_INTERNAL);
memset(hsm_pake_context.spake_context, 0, sizeof(hsm_pake_context.spake_context));
memcpy(hsm_pake_context.spake_context, context, context_len);
if (context_len > 0)
{
memcpy(hsm_pake_context.spake_context, context, context_len);
}
hsm_pake_context.spake_context_len = context_len;

const CHIP_ERROR error = Spake2p::Init(context, context_len);
Expand Down Expand Up @@ -295,6 +305,8 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::BeginVerifier(const uint8_t * my_id
VerifyOrReturnError(peer_identity != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
}

ChipLogProgress(Crypto, "HSM - BeginVerifier \n");

error = FELoad(w0in, w0in_len, w0);
VerifyOrReturnError(error == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL);

Expand Down Expand Up @@ -373,6 +385,8 @@ CHIP_ERROR Spake2pHSM_P256_SHA256_HKDF_HMAC::BeginProver(const uint8_t * my_iden

VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::INIT, CHIP_ERROR_INTERNAL);

ChipLogProgress(Crypto, "HSM - BeginProver \n");

error = FELoad(w0in, w0in_len, w0);
VerifyOrReturnError(error == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL);

Expand Down
2 changes: 1 addition & 1 deletion src/crypto/hsm/nxp/CHIPCryptoPALHsm_SE05X_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ void se05x_delete_key(uint32_t keyid)
}
else
{
ChipLogError(Crypto, "se05x error: %s\n", "Key doesnot exists");
ChipLogError(Crypto, "se05x warn: %s\n", "Key doesnot exists");
}
}
else
Expand Down
Loading

0 comments on commit 1f44fdb

Please sign in to comment.