diff options
author | Yecheng Zhao <zyecheng@google.com> | 2023-03-10 21:09:37 +0000 |
---|---|---|
committer | CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-03-10 21:09:37 +0000 |
commit | 2d3495c8c24f014d8e51d7878d2d1ab97373b6e2 (patch) | |
tree | 828562eef9dcb6e1a3c7c432c2e8217135c4cdd6 | |
parent | c59e42b1d9fe4a1ee614bea1d654d904c392d50e (diff) | |
download | pigweed-2d3495c8c24f014d8e51d7878d2d1ab97373b6e2.tar.gz |
pw_crypto: Handle micro-ecc native little endian
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 <zyecheng@google.com>
Reviewed-by: Ali Zhang <alizhang@google.com>
-rw-r--r-- | pw_crypto/ecdsa_uecc.cc | 62 |
1 files changed, 45 insertions, 17 deletions
diff --git a/pw_crypto/ecdsa_uecc.cc b/pw_crypto/ecdsa_uecc.cc index 937d79d56..cbb7af565 100644 --- a/pw_crypto/ecdsa_uecc.cc +++ b/pw_crypto/ecdsa_uecc.cc @@ -14,6 +14,8 @@ #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" @@ -21,33 +23,59 @@ 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(); } @@ -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, |