aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYecheng Zhao <zyecheng@google.com>2023-03-10 21:09:37 +0000
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-03-10 21:09:37 +0000
commit2d3495c8c24f014d8e51d7878d2d1ab97373b6e2 (patch)
tree828562eef9dcb6e1a3c7c432c2e8217135c4cdd6
parentc59e42b1d9fe4a1ee614bea1d654d904c392d50e (diff)
downloadpigweed-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.cc62
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,