blob: f1ce8ce245ab7e19928604f67a5cbd88f35426f3 [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 "cryptoc/p256_ecdsa.h"
15#include "cryptoc/p256.h"
16#include "cryptoc/hmac.h"
17#include "cryptoc/sha256.h"
18
19// Compute k based on given {key, message} pair, 0 < k < n.
20static void determine_k(const p256_int* key,
21 const p256_int* message,
22 char* tweak,
23 p256_int* k) {
24 p256_int p;
25
26 do {
27 // HMAC prng pick until p <= SECP256r1_n - 2,
28 // in a (re)pick and test fashion for a clean distribution.
29 LITE_HMAC_CTX hmac;
30
31 p256_to_bin(key, (uint8_t*)&p); // key as endian neutral bytes.
32 HMAC_SHA256_init(&hmac, &p, P256_NBYTES);
33 HMAC_update(&hmac, tweak, 1);
34 HMAC_update(&hmac, message, P256_NBYTES);
35 ++(*tweak);
36 p256_from_bin(HMAC_final(&hmac), &p); // p from endian neutral bytes.
37 } while (p256_cmp(&p, &SECP256r1_nMin2) > 0);
38
39 p256_add_d(&p, 1, k); // 0 < k < SECP256r1_n
40 p256_clear(&p);
41}
42
43void p256_ecdsa_sign(const p256_int* key,
44 const p256_int* message,
45 p256_int* r, p256_int* s) {
46 char tweak = 'A';
47 p256_digit top;
48
49 for (;;) {
50 p256_int k, kinv;
51
52 determine_k(key, message, &tweak, &k);
53 p256_base_point_mul(&k, r, s);
54 p256_mod(&SECP256r1_n, r, r);
55
56 // Make sure r != 0
57 if (p256_is_zero(r)) continue;
58
59 p256_modmul(&SECP256r1_n, r, 0, key, s);
60 top = p256_add(s, message, s);
61 p256_modinv(&SECP256r1_n, &k, &kinv);
62 p256_modmul(&SECP256r1_n, &kinv, top, s, s);
63
64 // (Attempt to) clear stack state.
65 p256_clear(&k);
66 p256_clear(&kinv);
67
68 // Make sure s != 0
69 if (p256_is_zero(s)) continue;
70
71 break;
72 }
73}
74
75int p256_ecdsa_verify(const p256_int* key_x, const p256_int* key_y,
76 const p256_int* message,
77 const p256_int* r, const p256_int* s) {
78 p256_int u, v;
79
80 // Check public key.
81 if (!p256_is_valid_point(key_x, key_y)) return 0;
82
83 // Check r and s are != 0 % n.
84 p256_mod(&SECP256r1_n, r, &u);
85 p256_mod(&SECP256r1_n, s, &v);
86 if (p256_is_zero(&u) || p256_is_zero(&v)) return 0;
87
88 p256_modinv_vartime(&SECP256r1_n, s, &v);
89 p256_modmul(&SECP256r1_n, message, 0, &v, &u); // message / s % n
90 p256_modmul(&SECP256r1_n, r, 0, &v, &v); // r / s % n
91
92 p256_points_mul_vartime(&u, &v,
93 key_x, key_y,
94 &u, &v);
95
96 p256_mod(&SECP256r1_n, &u, &u); // (x coord % p) % n
97 return p256_cmp(r, &u) == 0;
98}