Skip to content

Commit

Permalink
pw_crypto: Handle micro-ecc native little endian
Browse files Browse the repository at this point in the history
Adjust input into little endian order when micro-ecc is configured with
uECC_VLI_NATIVE_LITTLE_ENDIAN=1.

Bug: b/271895100
Change-Id: Id8e24a38b97f76725d11b0b0f0b74216bf159aee
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/133475
Commit-Queue: Yecheng Zhao <[email protected]>
Reviewed-by: Ali Zhang <[email protected]>
  • Loading branch information
Yecheng Zhao authored and CQ Bot Account committed Mar 10, 2023
1 parent c59e42b commit 2d3495c
Showing 1 changed file with 45 additions and 17 deletions.
62 changes: 45 additions & 17 deletions pw_crypto/ecdsa_uecc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,68 @@
#define PW_LOG_MODULE_NAME "ECDSA-UECC"
#define PW_LOG_LEVEL PW_LOG_LEVEL_WARN

#include <cstring>

#include "pw_crypto/ecdsa.h"
#include "pw_log/log.h"
#include "uECC.h"

namespace pw::crypto::ecdsa {

constexpr size_t kP256CurveOrderBytes = 32;
constexpr size_t kP256PublicKeySize = 2 * kP256CurveOrderBytes + 1;
constexpr size_t kP256SignatureSize = kP256CurveOrderBytes * 2;

Status VerifyP256Signature(ConstByteSpan public_key,
ConstByteSpan digest,
ConstByteSpan signature) {
const uint8_t* public_key_bytes =
reinterpret_cast<const uint8_t*>(public_key.data());
const uint8_t* digest_bytes = reinterpret_cast<const uint8_t*>(digest.data());
const uint8_t* signature_bytes =
reinterpret_cast<const uint8_t*>(signature.data());

uECC_Curve curve = uECC_secp256r1();
// Signature expected in raw format (r||s)
if (signature.size() != kP256SignatureSize) {
PW_LOG_DEBUG("Bad signature format");
return Status::InvalidArgument();
}

// Supports SEC 1 uncompressed form (04||X||Y) only.
if (public_key.size() != (2 * kP256CurveOrderBytes + 1) ||
public_key_bytes[0] != 0x04) {
if (public_key.size() != kP256PublicKeySize ||
std::to_integer<uint8_t>(public_key.data()[0]) != 0x04) {
PW_LOG_DEBUG("Bad public key format");
return Status::InvalidArgument();
}

// Make sure the public key is on the curve.
if (!uECC_valid_public_key(public_key_bytes + 1, curve)) {
return Status::InvalidArgument();
}
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
// VerifyP256Signature always assume big endian input. If the library is
// configured to expect native little endian, we need to convert the input
// into little endian.
uint8_t signature_bytes[kP256SignatureSize]
__attribute__((__aligned__(sizeof(uint64_t))));
memcpy(signature_bytes, signature.data(), sizeof(signature_bytes));
std::reverse(signature_bytes, signature_bytes + kP256CurveOrderBytes); // r
std::reverse(signature_bytes + kP256CurveOrderBytes,
signature_bytes + sizeof(signature_bytes)); // s

// Signature expected in raw format (r||s)
if (signature.size() != kP256CurveOrderBytes * 2) {
PW_LOG_DEBUG("Bad signature format");
uint8_t public_key_bytes[kP256PublicKeySize - 1]
__attribute__((__aligned__(sizeof(uint64_t))));
memcpy(public_key_bytes, public_key.data() + 1, sizeof(public_key_bytes));
std::reverse(public_key_bytes, public_key_bytes + kP256CurveOrderBytes); // X
std::reverse(public_key_bytes + kP256CurveOrderBytes,
public_key_bytes + sizeof(public_key_bytes)); // Y

uint8_t digest_bytes[kP256CurveOrderBytes]
__attribute__((__aligned__(sizeof(uint64_t))));
memcpy(digest_bytes, digest.data(), sizeof(digest_bytes));
std::reverse(digest_bytes, digest_bytes + sizeof(digest_bytes));
#else
const uint8_t* public_key_bytes =
reinterpret_cast<const uint8_t*>(public_key.data()) + 1;
const uint8_t* digest_bytes = reinterpret_cast<const uint8_t*>(digest.data());
const uint8_t* signature_bytes =
reinterpret_cast<const uint8_t*>(signature.data());
#endif

uECC_Curve curve = uECC_secp256r1();
// Make sure the public key is on the curve.
if (!uECC_valid_public_key(public_key_bytes, curve)) {
PW_LOG_DEBUG("Bad public key curve");
return Status::InvalidArgument();
}

Expand All @@ -59,7 +87,7 @@ Status VerifyP256Signature(ConstByteSpan public_key,
}

// Verify the signature.
if (!uECC_verify(public_key_bytes + 1,
if (!uECC_verify(public_key_bytes,
digest_bytes,
digest.size(),
signature_bytes,
Expand Down

0 comments on commit 2d3495c

Please sign in to comment.