blob: 059e1a30c003fc85b0f5bc3f2fb3d5f103574574 [file] [log] [blame]
nagendra modadugu4fae5422016-05-10 16:11:54 -07001// Copyright 2016 Google Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14#include <assert.h>
15#include <string.h>
16#include <stdlib.h>
17#include <stdio.h>
18#include <time.h>
19#include <ctype.h>
20
21#include <openssl/ec.h>
22#include <openssl/ecdsa.h>
23#include <openssl/obj_mac.h>
24
25#include "cryptoc/p256.h"
26#include "cryptoc/p256_ecdsa.h"
27#include "cryptoc/p256_prng.h"
28
29// Turn p256 point into ossl compatible binary array.
30// Returns # total bytes.
31static int to_oct(const p256_int* x, const p256_int* y, uint8_t* buf) {
32 buf[0] = 4;
33 p256_to_bin(x, buf + 1);
34 p256_to_bin(y, buf + 1 + 32);
35 return 65;
36}
37
38// Turn p256 r,s into ossl compatible signature array.
39// r and s are encoded as mpi ints:
40// - leading zeros are stripped.
41// - if high bit is set, a leading zero is added (i.e. positive numbers only).
42// Returns # total bytes.
43static int to_sig(const p256_int* r, const p256_int* s, uint8_t* buf) {
44 uint8_t* p = buf;
45 uint8_t tmp_r[32 + 1], tmp_s[32 + 1];
46 int size_r = sizeof(tmp_r), size_s = sizeof(tmp_s);
47 int i;
48
49 tmp_r[0] = 0;
50 p256_to_bin(r, tmp_r + 1);
51 tmp_s[0] = 0;
52 p256_to_bin(s, tmp_s + 1);
53
54 for (i = 0; !tmp_r[i] && i < sizeof(tmp_r); ++i) --size_r;
55 if (tmp_r[i] & 0x80) ++size_r;
56 for (i = 0; !tmp_s[i] && i < sizeof(tmp_s); ++i) --size_s;
57 if (tmp_s[i] & 0x80) ++size_s;
58
59 *p++ = 0x30; // sequence tag
60 *p++ = 2 + size_r + 2 + size_s;
61
62 *p++ = 0x02; // int tag
63 *p++ = size_r;
64 memcpy(p, &tmp_r[sizeof(tmp_r) - size_r], size_r);
65 p += size_r;
66
67 *p++ = 0x02; // int tag
68 *p++ = size_s;
69 memcpy(p, &tmp_s[sizeof(tmp_s) - size_s], size_s);
70 p += size_s;
71
72 return p - buf;
73}
74
75// Load public key into openssl and verify signature on message.
76// Returns 0 on fail.
77static int ossl_verify(const p256_int* Gx, const p256_int* Gy,
78 uint8_t* message,
79 const p256_int* r, const p256_int* s) {
80 int result = 0;
81
82 uint8_t pk[65];
83 uint8_t sig[72];
84
85 int siglen, pklen;
86
87 EC_KEY* key = EC_KEY_new();
88 EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
89 EC_POINT* point = EC_POINT_new(group);
90
91 EC_KEY_set_group(key, group);
92
93 pklen = to_oct(Gx, Gy, pk);
94
95 EC_POINT_oct2point(group, point, pk, pklen, 0);
96 EC_KEY_set_public_key(key, point);
97
98 siglen = to_sig(r, s, sig);
99
100 result = (ECDSA_verify(0, message, 32, sig, siglen, key) == 1);
101
102 EC_POINT_free(point);
103 EC_GROUP_free(group);
104 EC_KEY_free(key);
105
106 return result;
107}
108
109// Create and verify some random signatures against openssl.
110// time(NULL) is used as prng seed so repeat runs test different values.
111static void random_sigs_test() {
112 int n;
113 P256_PRNG_CTX prng;
114 uint8_t tmp[P256_PRNG_SIZE];
115 uint32_t boot_count = time(NULL);
116
117 // Setup deterministic prng.
118 p256_prng_init(&prng, "random_sigs_test", 16, boot_count);
119
120 for (n = 0; n < 100; ++n) {
121 p256_int a, b, Gx, Gy;
122 p256_int r, s;
123
124 // Make up private key
125 do {
126 // Pick well distributed random number 0 < a < n.
127 p256_int p1, p2;
128 p256_prng_draw(&prng, tmp);
129 p256_from_bin(tmp, &p1);
130 p256_prng_draw(&prng, tmp);
131 p256_from_bin(tmp, &p2);
132 p256_modmul(&SECP256r1_n, &p1, 0, &p2, &a);
133 } while (p256_is_zero(&a));
134
135 // Compute public key; a is our secret key.
136 p256_base_point_mul(&a, &Gx, &Gy);
137
138 // Pick random message to sign.
139 p256_prng_draw(&prng, tmp);
140 p256_from_bin(tmp, &b);
141
142 // Compute signature on b.
143 p256_ecdsa_sign(&a, &b, &r, &s);
144
145 if (!p256_ecdsa_verify(&Gx, &Gy, &b, &r, &s)) {
146 printf("random_sigs_test()"
147 ": p256_ecdsa_verify fail at %d! (boot_count %d)\n",
148 n, boot_count);
149 exit(1);
150 }
151
152 if (!ossl_verify(&Gx, &Gy, tmp, &r, &s)) {
153 printf("random_sigs_test()"
154 ": ossl_verify fail at %d! (boot_count %d)\n",
155 n, boot_count);
156 exit(1);
157 }
158 }
159}
160
161// Test signature parameter validation.
162static void invalid_sigs_test() {
163 P256_PRNG_CTX prng;
164 uint8_t tmp[P256_PRNG_SIZE];
165 uint32_t boot_count = time(NULL);
166
167 p256_prng_init(&prng, "invalid_sigs_test", 17, boot_count);
168
169 {
170 p256_int a, b, Gx, Gy;
171 p256_int r, s;
172 p256_int one = P256_ONE;
173 p256_int zero = P256_ZERO;
174
175 (void)one;
176 (void)zero;
177
178 // Make up private key.
179 do {
180 // Pick well distributed random number 0 < a < n.
181 p256_int p1, p2;
182 p256_prng_draw(&prng, tmp);
183 p256_from_bin(tmp, &p1);
184 p256_prng_draw(&prng, tmp);
185 p256_from_bin(tmp, &p2);
186 p256_modmul(&SECP256r1_n, &p1, 0, &p2, &a);
187 } while (p256_is_zero(&a));
188
189 // Compute public key; a is our secret key.
190 p256_base_point_mul(&a, &Gx, &Gy);
191
192 // Pick random message to sign.
193 p256_prng_draw(&prng, tmp);
194 p256_from_bin(tmp, &b);
195
196 // Compute signature on b.
197 p256_ecdsa_sign(&a, &b, &r, &s);
198
199 if (!p256_ecdsa_verify(&Gx, &Gy, &b, &r, &s)) {
200 printf("invalid_sigs_test()"
201 ": p256_ecdsa_verify fail! (boot_count %d)\n",
202 boot_count);
203 exit(1);
204 }
205
206 // Case 1: r = 0 % n, s = m
207 if (p256_ecdsa_verify(&Gx, &Gy, &b, &SECP256r1_n, &b)) {
208 printf("invalid_sigs_test()"
209 ": p256_ecdsa_verify didn't fail case 1! (boot_count %d)\n",
210 boot_count);
211 exit(1);
212 }
213 }
214}
215
216int main(int argc, char* argv[]) {
217 random_sigs_test();
218 invalid_sigs_test();
219 return 0;
220}