From fe98fdc2d12623399b5338aacb3feea33d28cb48 Mon Sep 17 00:00:00 2001 From: kangping Date: Tue, 22 Dec 2020 01:59:50 +0800 Subject: [PATCH] [ecdsa] fix ECDSA public key size for DNSKEY (#5989) Per Sec 4 of RFC 6605: "ECDSA public keys consist of a single value, called "Q" in FIPS 186-3. In DNSSEC keys, Q is a simple bit string that represents the uncompressed form of a curve point, "x | y"." The bit string of the two curve points (X, Y) should have a fixed length of 64 bytes and the additional `1` byte prefix should not be included, because only uncompressed form is allowed. --- src/core/crypto/ecdsa.cpp | 14 +++++++++----- src/core/crypto/ecdsa.hpp | 2 +- tests/unit/test_ecdsa.cpp | 8 ++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/core/crypto/ecdsa.cpp b/src/core/crypto/ecdsa.cpp index f9a63240a..e46e6c2c0 100644 --- a/src/core/crypto/ecdsa.cpp +++ b/src/core/crypto/ecdsa.cpp @@ -97,16 +97,16 @@ otError P256::KeyPair::GetPublicKey(PublicKey &aPublicKey) const mbedtls_pk_context pk; mbedtls_ecp_keypair *keyPair; int ret; - size_t len; SuccessOrExit(error = Parse(&pk)); keyPair = mbedtls_pk_ec(pk); - ret = mbedtls_ecp_point_write_binary(&keyPair->grp, &keyPair->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &len, - aPublicKey.mData, sizeof(aPublicKey.mData)); + ret = mbedtls_mpi_write_binary(&keyPair->Q.X, aPublicKey.mData, kMpiSize); + VerifyOrExit(ret == 0, error = MbedTls::MapError(ret)); + + ret = mbedtls_mpi_write_binary(&keyPair->Q.Y, aPublicKey.mData + kMpiSize, kMpiSize); VerifyOrExit(ret == 0, error = MbedTls::MapError(ret)); - VerifyOrExit(len == sizeof(aPublicKey.mData), error = OT_ERROR_PARSE); exit: mbedtls_pk_free(&pk); @@ -170,7 +170,11 @@ otError P256::PublicKey::Verify(const Sha256::Hash &aHash, const Signature &aSig ret = mbedtls_ecp_group_load(&ecdsa.grp, MBEDTLS_ECP_DP_SECP256R1); VerifyOrExit(ret == 0, error = MbedTls::MapError(ret)); - ret = mbedtls_ecp_point_read_binary(&ecdsa.grp, &ecdsa.Q, mData, sizeof(mData)); + ret = mbedtls_mpi_read_binary(&ecdsa.Q.X, GetBytes(), kMpiSize); + VerifyOrExit(ret == 0, error = MbedTls::MapError(ret)); + ret = mbedtls_mpi_read_binary(&ecdsa.Q.Y, GetBytes() + kMpiSize, kMpiSize); + VerifyOrExit(ret == 0, error = MbedTls::MapError(ret)); + ret = mbedtls_mpi_lset(&ecdsa.Q.Z, 1); VerifyOrExit(ret == 0, error = MbedTls::MapError(ret)); ret = mbedtls_mpi_read_binary(&r, aSignature.mShared.mMpis.mR, kMpiSize); diff --git a/src/core/crypto/ecdsa.hpp b/src/core/crypto/ecdsa.hpp index 1264bf64f..772e489de 100644 --- a/src/core/crypto/ecdsa.hpp +++ b/src/core/crypto/ecdsa.hpp @@ -240,7 +240,7 @@ public: public: enum { - kSize = (kMpiSize * 2) + 1, ///< Size of the public key in bytes (two MPIs + one overhead byte). + kSize = kMpiSize * 2, ///< Size of the public key in bytes. }; /** diff --git a/tests/unit/test_ecdsa.cpp b/tests/unit/test_ecdsa.cpp index f8a3847ee..b52bb041f 100644 --- a/tests/unit/test_ecdsa.cpp +++ b/tests/unit/test_ecdsa.cpp @@ -58,10 +58,10 @@ void TestEcdsaVector(void) 0xB2, 0x0C, 0x2D, 0x7E, 0x9F, 0x51, 0x77, 0xA3, 0xC2, 0x94, 0xD4, 0x46, 0x22, 0x99}; const uint8_t kPublicKey[] = { - 0x04, 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0x9D, 0x31, 0xC9, 0x61, 0xEB, 0x74, 0xC6, 0x35, 0x6D, 0x68, - 0xC0, 0x49, 0xB8, 0x92, 0x3B, 0x61, 0xFA, 0x6C, 0xE6, 0x69, 0x62, 0x2E, 0x60, 0xF2, 0x9F, 0xB6, 0x79, - 0x03, 0xFE, 0x10, 0x08, 0xB8, 0xBC, 0x99, 0xA4, 0x1A, 0xE9, 0xE9, 0x56, 0x28, 0xBC, 0x64, 0xF2, 0xF1, - 0xB2, 0x0C, 0x2D, 0x7E, 0x9F, 0x51, 0x77, 0xA3, 0xC2, 0x94, 0xD4, 0x46, 0x22, 0x99, + 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0x9D, 0x31, 0xC9, 0x61, 0xEB, 0x74, 0xC6, 0x35, 0x6D, 0x68, + 0xC0, 0x49, 0xB8, 0x92, 0x3B, 0x61, 0xFA, 0x6C, 0xE6, 0x69, 0x62, 0x2E, 0x60, 0xF2, 0x9F, 0xB6, + 0x79, 0x03, 0xFE, 0x10, 0x08, 0xB8, 0xBC, 0x99, 0xA4, 0x1A, 0xE9, 0xE9, 0x56, 0x28, 0xBC, 0x64, + 0xF2, 0xF1, 0xB2, 0x0C, 0x2D, 0x7E, 0x9F, 0x51, 0x77, 0xA3, 0xC2, 0x94, 0xD4, 0x46, 0x22, 0x99, }; const uint8_t kMessage[] = {'s', 'a', 'm', 'p', 'l', 'e'};