1*61c4878aSAndroid Build Coastguard Worker // Copyright 2021 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Worker #include "pw_crypto/ecdsa.h"
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard Worker #include <cstring>
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
20*61c4878aSAndroid Build Coastguard Worker
21*61c4878aSAndroid Build Coastguard Worker namespace pw::crypto::ecdsa {
22*61c4878aSAndroid Build Coastguard Worker namespace {
23*61c4878aSAndroid Build Coastguard Worker
24*61c4878aSAndroid Build Coastguard Worker #define AS_BYTES(s) as_bytes(span(s, sizeof(s) - 1))
25*61c4878aSAndroid Build Coastguard Worker
26*61c4878aSAndroid Build Coastguard Worker #define ASSERT_FAIL(expr) ASSERT_NE(OkStatus(), expr)
27*61c4878aSAndroid Build Coastguard Worker
28*61c4878aSAndroid Build Coastguard Worker // TEST_DIGEST/PUBKEY/SIGNATURE are generated using the pkey/ecdsa.c
29*61c4878aSAndroid Build Coastguard Worker // example in Mbed TLS.
30*61c4878aSAndroid Build Coastguard Worker
31*61c4878aSAndroid Build Coastguard Worker // The SHA256 digest of "Hello, Pigweed!", 32 bytes.
32*61c4878aSAndroid Build Coastguard Worker #define TEST_DIGEST \
33*61c4878aSAndroid Build Coastguard Worker "\x8D\xCE\x14\xEE\x2C\xD9\xFD\x9B\xBD\x8C\x8D\x57\x68\x50\x2C\x2F" \
34*61c4878aSAndroid Build Coastguard Worker "\xFB\xB3\x52\x36\xCE\x93\x47\x1B\x80\xFC\xA4\x7D\xB5\xF8\x41\x9D"
35*61c4878aSAndroid Build Coastguard Worker
36*61c4878aSAndroid Build Coastguard Worker // The public key in uncompressed form, 65 bytes.
37*61c4878aSAndroid Build Coastguard Worker #define TEST_PUBKEY \
38*61c4878aSAndroid Build Coastguard Worker "\x04" \
39*61c4878aSAndroid Build Coastguard Worker "\xD1\x82\x2E\x6A\xD2\x4B\x2A\x80\x2E\x8F\xBC\x03\x00\x95\x11\xF9" \
40*61c4878aSAndroid Build Coastguard Worker "\x81\x24\xA7\x3C\x45\xC8\xBA\xDD\x5F\x77\x1C\xC3\x71\x8B\xB2\xE9" \
41*61c4878aSAndroid Build Coastguard Worker "\x3A\x0A\x84\xFF\xEA\x13\xC2\x27\xD2\xCF\x42\x7D\xA5\x95\xD6\x88" \
42*61c4878aSAndroid Build Coastguard Worker "\xCD\x23\x00\x3F\xF9\xD9\x75\x46\xFF\x58\xE9\xBE\xC3\x74\x13\xB8"
43*61c4878aSAndroid Build Coastguard Worker
44*61c4878aSAndroid Build Coastguard Worker // The ECDSA P256 signature of `DIGEST`.
45*61c4878aSAndroid Build Coastguard Worker #define TEST_SIGNATURE \
46*61c4878aSAndroid Build Coastguard Worker "\x16\x54\x43\xD4\x00\x07\xC4\xD7\x26\x2E\x3C\xB1\x65\x54\x00\x6A" \
47*61c4878aSAndroid Build Coastguard Worker "\x6A\x5B\x4A\xBB\x16\x6F\x44\xD0\x91\x3F\xD3\xC2\x50\xAC\x1A\x87" \
48*61c4878aSAndroid Build Coastguard Worker "\x86\x41\xEE\x56\xDA\x31\xF2\xFF\x38\x3C\xBB\x32\x3E\x2D\xDB\x98" \
49*61c4878aSAndroid Build Coastguard Worker "\xEA\x05\x9E\x8F\x91\x8E\x0E\x99\xE5\x4F\x32\x13\x92\x7F\x17\x68"
50*61c4878aSAndroid Build Coastguard Worker
51*61c4878aSAndroid Build Coastguard Worker // The public key in uncompressed form, missing the header byte.
52*61c4878aSAndroid Build Coastguard Worker #define MALFORMED_PUBKEY_MISSING_HEADER \
53*61c4878aSAndroid Build Coastguard Worker "\xD1\x82\x2E\x6A\xD2\x4B\x2A\x80\x2E\x8F\xBC\x03\x00\x95\x11\xF9" \
54*61c4878aSAndroid Build Coastguard Worker "\x81\x24\xA7\x3C\x45\xC8\xBA\xDD\x5F\x77\x1C\xC3\x71\x8B\xB2\xE9" \
55*61c4878aSAndroid Build Coastguard Worker "\x3A\x0A\x84\xFF\xEA\x13\xC2\x27\xD2\xCF\x42\x7D\xA5\x95\xD6\x88" \
56*61c4878aSAndroid Build Coastguard Worker "\xCD\x23\x00\x3F\xF9\xD9\x75\x46\xFF\x58\xE9\xBE\xC3\x74\x13\xB8"
57*61c4878aSAndroid Build Coastguard Worker
58*61c4878aSAndroid Build Coastguard Worker // The public key in compressed form, wrong the header byte (03 instead of 02).
59*61c4878aSAndroid Build Coastguard Worker #define MALFORMED_PUBKEY_WRONG_HEADER \
60*61c4878aSAndroid Build Coastguard Worker "\x03" \
61*61c4878aSAndroid Build Coastguard Worker "\xD1\x82\x2E\x6A\xD2\x4B\x2A\x80\x2E\x8F\xBC\x03\x00\x95\x11\xF9" \
62*61c4878aSAndroid Build Coastguard Worker "\x81\x24\xA7\x3C\x45\xC8\xBA\xDD\x5F\x77\x1C\xC3\x71\x8B\xB2\xE9"
63*61c4878aSAndroid Build Coastguard Worker
64*61c4878aSAndroid Build Coastguard Worker // Tampered signature (first bit flipped).
65*61c4878aSAndroid Build Coastguard Worker #define TAMPERED_SIGNATURE \
66*61c4878aSAndroid Build Coastguard Worker "\x17\x54\x43\xD4\x00\x07\xC4\xD7\x26\x2E\x3C\xB1\x65\x54\x00\x6A" \
67*61c4878aSAndroid Build Coastguard Worker "\x6A\x5B\x4A\xBB\x16\x6F\x44\xD0\x91\x3F\xD3\xC2\x50\xAC\x1A\x87" \
68*61c4878aSAndroid Build Coastguard Worker "\x86\x41\xEE\x56\xDA\x31\xF2\xFF\x38\x3C\xBB\x32\x3E\x2D\xDB\x98" \
69*61c4878aSAndroid Build Coastguard Worker "\xEA\x05\x9E\x8F\x91\x8E\x0E\x99\xE5\x4F\x32\x13\x92\x7F\x17\x68"
70*61c4878aSAndroid Build Coastguard Worker
71*61c4878aSAndroid Build Coastguard Worker // Short signature (last byte removed).
72*61c4878aSAndroid Build Coastguard Worker #define SHORT_SIGNATURE \
73*61c4878aSAndroid Build Coastguard Worker "\x16\x54\x43\xD4\x00\x07\xC4\xD7\x26\x2E\x3C\xB1\x65\x54\x00\x6A" \
74*61c4878aSAndroid Build Coastguard Worker "\x6A\x5B\x4A\xBB\x16\x6F\x44\xD0\x91\x3F\xD3\xC2\x50\xAC\x1A\x87" \
75*61c4878aSAndroid Build Coastguard Worker "\x86\x41\xEE\x56\xDA\x31\xF2\xFF\x38\x3C\xBB\x32\x3E\x2D\xDB\x98" \
76*61c4878aSAndroid Build Coastguard Worker "\xEA\x05\x9E\x8F\x91\x8E\x0E\x99\xE5\x4F\x32\x13\x92\x7F\x17"
77*61c4878aSAndroid Build Coastguard Worker
78*61c4878aSAndroid Build Coastguard Worker // Short digest (last byte removed)
79*61c4878aSAndroid Build Coastguard Worker #define SHORT_DIGEST \
80*61c4878aSAndroid Build Coastguard Worker "\x8D\xCE\x14\xEE\x2C\xD9\xFD\x9B\xBD\x8C\x8D\x57\x68\x50\x2C\x2F" \
81*61c4878aSAndroid Build Coastguard Worker "\xFB\xB3\x52\x36\xCE\x93\x47\x1B\x80\xFC\xA4\x7D\xB5\xF8\x41"
82*61c4878aSAndroid Build Coastguard Worker
83*61c4878aSAndroid Build Coastguard Worker // Tampered digest (first bit flipped)
84*61c4878aSAndroid Build Coastguard Worker #define TAMPERED_DIGEST \
85*61c4878aSAndroid Build Coastguard Worker "\x8C\xCE\x14\xEE\x2C\xD9\xFD\x9B\xBD\x8C\x8D\x57\x68\x50\x2C\x2F" \
86*61c4878aSAndroid Build Coastguard Worker "\xFB\xB3\x52\x36\xCE\x93\x47\x1B\x80\xFC\xA4\x7D\xB5\xF8\x41\x9D"
87*61c4878aSAndroid Build Coastguard Worker
88*61c4878aSAndroid Build Coastguard Worker // Tampered public key (last bit flipped).
89*61c4878aSAndroid Build Coastguard Worker #define TAMPERED_PUBKEY \
90*61c4878aSAndroid Build Coastguard Worker "\x04" \
91*61c4878aSAndroid Build Coastguard Worker "\xD1\x82\x2E\x6A\xD2\x4B\x2A\x80\x2E\x8F\xBC\x03\x00\x95\x11\xF9" \
92*61c4878aSAndroid Build Coastguard Worker "\x81\x24\xA7\x3C\x45\xC8\xBA\xDD\x5F\x77\x1C\xC3\x71\x8B\xB2\xE9" \
93*61c4878aSAndroid Build Coastguard Worker "\x3A\x0A\x84\xFF\xEA\x13\xC2\x27\xD2\xCF\x42\x7D\xA5\x95\xD6\x88" \
94*61c4878aSAndroid Build Coastguard Worker "\xCD\x23\x00\x3F\xF9\xD9\x75\x46\xFF\x58\xE9\xBE\xC3\x74\x13\xB9"
95*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,ValidSignature)96*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, ValidSignature) {
97*61c4878aSAndroid Build Coastguard Worker PW_TEST_ASSERT_OK(VerifyP256Signature(
98*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_PUBKEY), AS_BYTES(TEST_DIGEST), AS_BYTES(TEST_SIGNATURE)));
99*61c4878aSAndroid Build Coastguard Worker }
100*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,LongerDigestGetsTruncated)101*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, LongerDigestGetsTruncated) {
102*61c4878aSAndroid Build Coastguard Worker PW_TEST_ASSERT_OK(VerifyP256Signature(AS_BYTES(TEST_PUBKEY),
103*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_DIGEST "extra stuff"),
104*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_SIGNATURE)));
105*61c4878aSAndroid Build Coastguard Worker }
106*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,MalformedPublicKeyMissingHeader)107*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, MalformedPublicKeyMissingHeader) {
108*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(Status::InvalidArgument(),
109*61c4878aSAndroid Build Coastguard Worker VerifyP256Signature(AS_BYTES(MALFORMED_PUBKEY_MISSING_HEADER),
110*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_DIGEST),
111*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_SIGNATURE)));
112*61c4878aSAndroid Build Coastguard Worker }
113*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,MalformedPublicKeyWrongHeader)114*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, MalformedPublicKeyWrongHeader) {
115*61c4878aSAndroid Build Coastguard Worker ASSERT_FAIL(VerifyP256Signature(AS_BYTES(MALFORMED_PUBKEY_WRONG_HEADER),
116*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_DIGEST),
117*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_SIGNATURE)));
118*61c4878aSAndroid Build Coastguard Worker }
119*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,TamperedSignature)120*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, TamperedSignature) {
121*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(Status::Unauthenticated(),
122*61c4878aSAndroid Build Coastguard Worker VerifyP256Signature(AS_BYTES(TEST_PUBKEY),
123*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_DIGEST),
124*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TAMPERED_SIGNATURE)));
125*61c4878aSAndroid Build Coastguard Worker }
126*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,SignatureTooLong)127*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, SignatureTooLong) {
128*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(Status::InvalidArgument(),
129*61c4878aSAndroid Build Coastguard Worker VerifyP256Signature(AS_BYTES(TEST_PUBKEY),
130*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_DIGEST),
131*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_SIGNATURE "extra stuff")));
132*61c4878aSAndroid Build Coastguard Worker }
133*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,SignatureTooShort)134*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, SignatureTooShort) {
135*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(Status::InvalidArgument(),
136*61c4878aSAndroid Build Coastguard Worker VerifyP256Signature(AS_BYTES(TEST_PUBKEY),
137*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_DIGEST),
138*61c4878aSAndroid Build Coastguard Worker AS_BYTES(SHORT_SIGNATURE)));
139*61c4878aSAndroid Build Coastguard Worker }
140*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,DigestTooShort)141*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, DigestTooShort) {
142*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(Status::InvalidArgument(),
143*61c4878aSAndroid Build Coastguard Worker VerifyP256Signature(AS_BYTES(TEST_PUBKEY),
144*61c4878aSAndroid Build Coastguard Worker AS_BYTES(SHORT_DIGEST),
145*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_SIGNATURE)));
146*61c4878aSAndroid Build Coastguard Worker }
147*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,TamperedDigest)148*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, TamperedDigest) {
149*61c4878aSAndroid Build Coastguard Worker ASSERT_EQ(Status::Unauthenticated(),
150*61c4878aSAndroid Build Coastguard Worker VerifyP256Signature(AS_BYTES(TEST_PUBKEY),
151*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TAMPERED_DIGEST),
152*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_SIGNATURE)));
153*61c4878aSAndroid Build Coastguard Worker }
154*61c4878aSAndroid Build Coastguard Worker
TEST(EcdsaP256,TamperedPubkey)155*61c4878aSAndroid Build Coastguard Worker TEST(EcdsaP256, TamperedPubkey) {
156*61c4878aSAndroid Build Coastguard Worker ASSERT_FAIL(VerifyP256Signature(AS_BYTES(TAMPERED_PUBKEY),
157*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_DIGEST),
158*61c4878aSAndroid Build Coastguard Worker AS_BYTES(TEST_SIGNATURE)));
159*61c4878aSAndroid Build Coastguard Worker }
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker } // namespace
162*61c4878aSAndroid Build Coastguard Worker } // namespace pw::crypto::ecdsa
163