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

Restyle CSR support in crypto HSM #7898

Closed
wants to merge 15 commits into from
Closed
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
231 changes: 227 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,18 @@
#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

namespace chip {
namespace Crypto {

Expand All @@ -55,8 +67,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 +239,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 +320,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 +337,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 +495,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 = buffer_index - 2;
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 = 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 = buffer_index - (1 + 1 + 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 = buffer_index - (1 + 1 + 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 = buffer_index - 2;
// 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),
(4 + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL);

buffer_index = buffer_index - 2;
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SET), (6 + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)),
NULL);

buffer_index = buffer_index - 2;
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
add_tlv(data_to_hash, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE),
(8 + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL);

buffer_index = buffer_index - 3;
VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
memcpy((void *) &data_to_hash[buffer_index], version, sizeof(version));

buffer_index = buffer_index - 2;
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 - 2), 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 + 2 + signature_len) >= 0x80)
{
csr[csr_index++] = 0x81;
}
csr[csr_index++] = (uint8_t)(data_to_hash_len + 14 + 2 + 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 + 2) <= csr_length, error = CHIP_ERROR_INTERNAL);
add_tlv(csr, csr_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE), 0x0C, NULL);
csr_index = csr_index + 2;

VerifyOrExit((csr_index + sizeof(signature_oid) + 2) <= csr_length, error = CHIP_ERROR_INTERNAL);
add_tlv(csr, csr_index, ASN1_OID, sizeof(signature_oid), signature_oid);
csr_index = csr_index + 2 + sizeof(signature_oid);

VerifyOrExit((csr_index + 2) <= csr_length, error = CHIP_ERROR_INTERNAL);
add_tlv(csr, csr_index, ASN1_NULL, 0x00, NULL);
csr_index = csr_index + 2;

VerifyOrExit((csr_index + 2) <= 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
2 changes: 1 addition & 1 deletion src/crypto/tests/CHIPCryptoPALTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,7 @@ static void TestCSR_Gen(nlTestSuite * inSuite, void * inContext)
static uint8_t csr[kMAX_CSR_Length];
size_t length = sizeof(csr);

static P256Keypair keypair;
static Test_P256Keypair keypair;
NL_TEST_ASSERT(inSuite, keypair.Initialize() == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, keypair.NewCertificateSigningRequest(csr, length) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, length > 0);
Expand Down
Loading