Skip to content

Commit

Permalink
feat: added EcDsa256 bit support for sign and verify (#651)
Browse files Browse the repository at this point in the history
* add key256 in upgrade keys

* updated security_key_generator for 256bit ecDsa key

* imageSignerEcDsa 224+256 support

* added verifierEcDsa for 256bit

* upgraderPackBuilderFacade support both 224 and 256 ecdsa key

* added unit test for material generator, fixed review comments

* fix sonarqube and build without mbedtls

* only include material generator test for emil_inlcude_mbedtls

* reworked after review
  • Loading branch information
dcayy authored Jun 18, 2024
1 parent e844dfe commit bc39360
Show file tree
Hide file tree
Showing 17 changed files with 794 additions and 254 deletions.
53 changes: 45 additions & 8 deletions upgrade/boot_loader/VerifierEcDsa.cpp
Original file line number Diff line number Diff line change
@@ -1,29 +1,66 @@
#include "upgrade/boot_loader/VerifierEcDsa.hpp"
#include "infra/util/ByteRange.hpp"
#include "infra/util/MemoryRange.hpp"
#include "mbedtls/sha256.h"
#include "uECC.h"

namespace application
{
VerifierEcDsa::VerifierEcDsa(infra::ConstByteRange key)
: key(key)
{
assert(key.size() == 56);
}
{}

bool VerifierEcDsa::IsValid(hal::SynchronousFlash& flash, const hal::SynchronousFlash::Range& signature, const hal::SynchronousFlash::Range& data) const
{
std::array<uint8_t, 32> messageHash = Hash(flash, data);
std::array<uint8_t, 56> storedSignature;
auto storedSignature = GetSignatureStorage(signature);

if (signature.second - signature.first != storedSignature.size())
if (storedSignature.empty())
return false;

flash.ReadBuffer(storedSignature, signature.first);

return uECC_verify(key.begin(),
messageHash.data(),
messageHash.size(),
storedSignature.data(),
uECC_secp224r1()) == 1;
storedSignature.begin(),
GetCurve()) == 1;
}

VerifierEcDsa224::VerifierEcDsa224(infra::ConstByteRange key)
: VerifierEcDsa(key)
{
assert(key.size() == signSize);
}

infra::ByteRange VerifierEcDsa224::GetSignatureStorage(const hal::SynchronousFlash::Range& signature) const
{
if (signature.second - signature.first != signatureStorage.size())
return infra::ByteRange();
else
return infra::MakeRange(signatureStorage);
}

uECC_Curve VerifierEcDsa224::GetCurve() const
{
return uECC_secp224r1();
}

VerifierEcDsa256::VerifierEcDsa256(infra::ConstByteRange key)
: VerifierEcDsa(key)
{
assert(key.size() == signSize);
}

infra::ByteRange VerifierEcDsa256::GetSignatureStorage(const hal::SynchronousFlash::Range& signature) const
{
if (signature.second - signature.first != signatureStorage.size())
return infra::ByteRange();
else
return infra::MakeRange(signatureStorage);
}

uECC_Curve VerifierEcDsa256::GetCurve() const
{
return uECC_secp256r1();
}
}
36 changes: 36 additions & 0 deletions upgrade/boot_loader/VerifierEcDsa.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef UPGRADE_VERIFIER_EC_DSA_HPP
#define UPGRADE_VERIFIER_EC_DSA_HPP

#include "infra/util/ByteRange.hpp"
#include "uECC.h"
#include "upgrade/boot_loader/VerifierHashOnly.hpp"

namespace application
Expand All @@ -13,9 +15,43 @@ namespace application

bool IsValid(hal::SynchronousFlash& flash, const hal::SynchronousFlash::Range& signature, const hal::SynchronousFlash::Range& data) const override;

protected:
virtual infra::ByteRange GetSignatureStorage(const hal::SynchronousFlash::Range& signature) const = 0;
virtual uECC_Curve GetCurve() const = 0;

private:
infra::ConstByteRange key;
};

class VerifierEcDsa224
: public VerifierEcDsa
{
public:
explicit VerifierEcDsa224(infra::ConstByteRange key);

protected:
infra::ByteRange GetSignatureStorage(const hal::SynchronousFlash::Range& signature) const override;
uECC_Curve GetCurve() const override;

private:
static constexpr size_t signSize = 224 / 8 * 2;
mutable std::array<uint8_t, signSize> signatureStorage;
};

class VerifierEcDsa256
: public VerifierEcDsa
{
public:
explicit VerifierEcDsa256(infra::ConstByteRange key);

protected:
infra::ByteRange GetSignatureStorage(const hal::SynchronousFlash::Range& signature) const override;
uECC_Curve GetCurve() const override;

private:
static constexpr size_t signSize = 256 / 8 * 2;
mutable std::array<uint8_t, signSize> signatureStorage;
};
}

#endif
64 changes: 59 additions & 5 deletions upgrade/boot_loader/test/TestVerifierEcDsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include "upgrade/boot_loader/VerifierEcDsa.hpp"
#include "gmock/gmock.h"

class VerifierEcDsaTest
class VerifierEcDsaTest224
: public testing::Test
{
public:
Expand All @@ -16,16 +16,16 @@ class VerifierEcDsaTest
0x7b, 0xb6, 0xbf, 0xe7, 0x3b, 0x16, 0x2a, 0x8e
};

application::VerifierEcDsa verifier{ infra::MakeConstByteRange(ecDsa224PublicKey) };
application::VerifierEcDsa224 verifier{ infra::MakeConstByteRange(ecDsa224PublicKey) };
};

TEST_F(VerifierEcDsaTest, incorrect_hash_size_is_invalid)
TEST_F(VerifierEcDsaTest224, incorrect_hash_size_is_invalid)
{
hal::SynchronousFlashStub flash(1, 64);
EXPECT_EQ(false, verifier.IsValid(flash, { 0, 0 }, { 0, 4 }));
}

TEST_F(VerifierEcDsaTest, incorrect_hash_is_invalid)
TEST_F(VerifierEcDsaTest224, incorrect_hash_is_invalid)
{
hal::SynchronousFlashStub flash(1, 64);

Expand All @@ -38,7 +38,7 @@ TEST_F(VerifierEcDsaTest, incorrect_hash_is_invalid)
EXPECT_EQ(false, verifier.IsValid(flash, { 4, 60 }, { 0, 4 }));
}

TEST_F(VerifierEcDsaTest, correct_hash_as_signature_is_valid)
TEST_F(VerifierEcDsaTest224, correct_hash_as_signature_is_valid)
{
hal::SynchronousFlashStub flash(1, 64);

Expand All @@ -55,3 +55,57 @@ TEST_F(VerifierEcDsaTest, correct_hash_as_signature_is_valid)

EXPECT_EQ(true, verifier.IsValid(flash, { 4, 60 }, { 0, 4 }));
}

class VerifierEcDsaTest256
: public testing::Test
{
public:
const std::array<uint8_t, 64> ecDsa256PublicKey = { { 0x3e, 0x6b, 0xe0, 0x8c, 0x64, 0x3e, 0xf8, 0x26,
0x3f, 0x9c, 0xdc, 0x7e, 0x75, 0x5d, 0x17, 0x04,
0xf2, 0xfd, 0xe0, 0xf4, 0x0f, 0x35, 0xc3, 0x01,
0x9d, 0x8b, 0x2b, 0xb1, 0xd2, 0x87, 0xdb, 0x5e,
0x92, 0x9e, 0x87, 0x66, 0x59, 0x44, 0xb5, 0xb7,
0xa5, 0xab, 0x7f, 0xbf, 0xe7, 0x8c, 0x8f, 0xee,
0x9d, 0xa2, 0x67, 0xf2, 0x7a, 0x27, 0xb4, 0x56,
0x92, 0x11, 0x90, 0x2e, 0x54, 0x64, 0x31, 0x4c } };

application::VerifierEcDsa256 verifier{ infra::MakeConstByteRange(ecDsa256PublicKey) };
};

TEST_F(VerifierEcDsaTest256, incorrect_hash_size_is_invalid)
{
hal::SynchronousFlashStub flash(1, 64);
EXPECT_EQ(false, verifier.IsValid(flash, { 0, 0 }, { 0, 4 }));
}

TEST_F(VerifierEcDsaTest256, incorrect_hash_is_invalid)
{
hal::SynchronousFlashStub flash(1, 64);

flash.sectors = {
{ 0, 1, 2, 3 }
};

flash.sectors[0].insert(flash.sectors[0].end(), 56, 0xFF);

EXPECT_EQ(false, verifier.IsValid(flash, { 4, 60 }, { 0, 4 }));
}

TEST_F(VerifierEcDsaTest256, correct_hash_as_signature_is_valid)
{
hal::SynchronousFlashStub flash(1, 128);

flash.sectors = {
{ 0, 1, 2, 3,
0x07, 0x81, 0x0e, 0xa9, 0x74, 0xce, 0xa5, 0x77,
0x3e, 0x63, 0xb8, 0x97, 0xf3, 0x7e, 0x3b, 0xe9,
0xa0, 0x9e, 0x7a, 0x5f, 0xe9, 0xb9, 0x71, 0xa4,
0x4d, 0x10, 0x65, 0xac, 0x2a, 0x3a, 0x93, 0x11,
0x94, 0xdb, 0x42, 0x97, 0xe8, 0x53, 0xc9, 0x8e,
0xe2, 0x8b, 0xd6, 0xb0, 0x43, 0x25, 0xd7, 0xc9,
0x32, 0x66, 0x12, 0x3a, 0xac, 0x6d, 0x7d, 0x0e,
0x5c, 0x3b, 0x79, 0x2d, 0xde, 0x78, 0xb1, 0xd5 }
};

EXPECT_EQ(true, verifier.IsValid(flash, { 4, 68 }, { 0, 4 }));
}
14 changes: 13 additions & 1 deletion upgrade/pack/UpgradeKeys.proto
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,20 @@ message ecDsa224key
bytes privateKey = 2 [(bytes_size) = 56];
}

message keys
message ecDsa256key
{
bytes publicKey = 1 [(bytes_size) = 64];
bytes privateKey = 2 [(bytes_size) = 64];
}

message keys224
{
aes128key aesKey = 1;
ecDsa224key ecDsaKey = 2;
}

message keys256
{
aes128key aesKey = 1;
ecDsa256key ecDsaKey = 2;
}
4 changes: 2 additions & 2 deletions upgrade/pack/UpgradePackHeader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ namespace application
uint32_t errorCode; // Set by the boot loaders upon detection of an error. 0-999 is reserved by the reference boot loaders.
uint32_t signedContentsLength;

uint16_t signatureMethod; // Identifier that indicates the signature method chosen. 1 = ECDSA.
uint16_t signatureLength; // Size of the signature. 56 for ECDSA.
uint16_t signatureMethod; // Identifier that indicates the signature method chosen. 1 = ECDSA-224, 2 = ECDSA-256.
uint16_t signatureLength; // Size of the signature. 56 for ECDSA-224, 64 for ECDSA-256.
};

static_assert(sizeof(UpgradePackHeaderPrologue) == 16, "Incorrect size");
Expand Down
70 changes: 48 additions & 22 deletions upgrade/pack_builder/ImageSignerEcDsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,20 @@ namespace application
uECC_set_rng(RandomNumberGenerator);
}

uint16_t ImageSignerEcDsa::SignatureMethod() const
{
return signatureMethod;
}

uint16_t ImageSignerEcDsa::SignatureLength() const
{
return static_cast<uint16_t>(signature.size());
}

std::vector<uint8_t> ImageSignerEcDsa::ImageSignature(const std::vector<uint8_t>& image)
{
CalculateSha256(image);
CalculateSignature(image);

return std::vector<uint8_t>(signature.begin(), signature.end());
CalculateSignature();
return signature;
}

bool ImageSignerEcDsa::CheckSignature(const std::vector<uint8_t>& signature, const std::vector<uint8_t>& image)
{
std::copy(signature.begin(), signature.end(), this->signature.begin());
CalculateSha256(image);

if (publicKey.size() != signature.size())
return false;

return uECC_verify(publicKey.begin(), hash.data(), hash.size(), signature.data(), uECC_secp224r1()) == 1;
CalculateSha256(image);
return uECC_verify(publicKey.begin(), hash.data(), static_cast<uint32_t>(hash.size()), signature.data(), GetCurve()) == 1;
}

void ImageSignerEcDsa::CalculateSha256(const std::vector<uint8_t>& image)
Expand All @@ -53,20 +40,21 @@ namespace application
mbedtls_sha256_free(&ctx);
}

void ImageSignerEcDsa::CalculateSignature(const std::vector<uint8_t>& image)
void ImageSignerEcDsa::CalculateSignature()
{
signature.resize(SignatureLength());
if (privateKey.size() != signature.size())
throw std::runtime_error("Key length wrong");

std::array<uint8_t, keyLength / 8 * 2> publicKeyForVerification;
int result = uECC_compute_public_key(privateKey.begin(), publicKeyForVerification.data(), uECC_secp224r1());
std::vector<uint8_t> publicKeyForVerification(SignatureLength());
int result = uECC_compute_public_key(privateKey.begin(), publicKeyForVerification.data(), GetCurve());
if (result != 1)
throw std::runtime_error("Failed to compute public key");

if (!std::equal(publicKey.begin(), publicKey.end(), publicKeyForVerification.begin()))
if (!std::equal(publicKey.begin(), publicKey.end(), publicKeyForVerification.data()))
throw std::runtime_error("Inconsistent private key pair");

int ret = uECC_sign(privateKey.begin(), hash.data(), hash.size(), signature.data(), uECC_secp224r1());
int ret = uECC_sign(privateKey.begin(), hash.data(), static_cast<uint32_t>(hash.size()), signature.data(), GetCurve());
if (ret != 1)
throw std::runtime_error("Failed to calculate signature");
}
Expand All @@ -78,4 +66,42 @@ namespace application
std::copy(entropy.begin(), entropy.end(), dest);
return 1;
}

ImageSignerEcDsa224::ImageSignerEcDsa224(hal::SynchronousRandomDataGenerator& randomDataGenerator, infra::ConstByteRange publicKey, infra::ConstByteRange privateKey)
: ImageSignerEcDsa(randomDataGenerator, publicKey, privateKey)
{}

uint16_t ImageSignerEcDsa224::SignatureMethod() const
{
return signatureMethod;
}

uint16_t ImageSignerEcDsa224::SignatureLength() const
{
return static_cast<uint16_t>(keyLength / 8 * 2);
}

uECC_Curve ImageSignerEcDsa224::GetCurve() const
{
return uECC_secp224r1();
}

ImageSignerEcDsa256::ImageSignerEcDsa256(hal::SynchronousRandomDataGenerator& randomDataGenerator, infra::ConstByteRange publicKey, infra::ConstByteRange privateKey)
: ImageSignerEcDsa(randomDataGenerator, publicKey, privateKey)
{}

uint16_t ImageSignerEcDsa256::SignatureMethod() const
{
return signatureMethod;
}

uint16_t ImageSignerEcDsa256::SignatureLength() const
{
return static_cast<uint16_t>(keyLength / 8 * 2);
}

uECC_Curve ImageSignerEcDsa256::GetCurve() const
{
return uECC_secp256r1();
}
}
Loading

0 comments on commit bc39360

Please sign in to comment.