xref: /aosp_15_r20/external/open-dice/src/boringssl_ecdsa_utils.c (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
1*60b67249SAndroid Build Coastguard Worker // Copyright 2022 Google LLC
2*60b67249SAndroid Build Coastguard Worker //
3*60b67249SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*60b67249SAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*60b67249SAndroid Build Coastguard Worker // the License at
6*60b67249SAndroid Build Coastguard Worker //
7*60b67249SAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*60b67249SAndroid Build Coastguard Worker //
9*60b67249SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*60b67249SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*60b67249SAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*60b67249SAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*60b67249SAndroid Build Coastguard Worker // the License.
14*60b67249SAndroid Build Coastguard Worker 
15*60b67249SAndroid Build Coastguard Worker // This is an implementation of the ECDSA crypto operations that uses boringssl.
16*60b67249SAndroid Build Coastguard Worker 
17*60b67249SAndroid Build Coastguard Worker #include "dice/boringssl_ecdsa_utils.h"
18*60b67249SAndroid Build Coastguard Worker 
19*60b67249SAndroid Build Coastguard Worker #include <stdint.h>
20*60b67249SAndroid Build Coastguard Worker #include <stdio.h>
21*60b67249SAndroid Build Coastguard Worker #include <string.h>
22*60b67249SAndroid Build Coastguard Worker 
23*60b67249SAndroid Build Coastguard Worker #include "openssl/bn.h"
24*60b67249SAndroid Build Coastguard Worker #include "openssl/crypto.h"
25*60b67249SAndroid Build Coastguard Worker #include "openssl/ec.h"
26*60b67249SAndroid Build Coastguard Worker #include "openssl/ec_key.h"
27*60b67249SAndroid Build Coastguard Worker #include "openssl/ecdsa.h"
28*60b67249SAndroid Build Coastguard Worker #include "openssl/evp.h"
29*60b67249SAndroid Build Coastguard Worker #include "openssl/hkdf.h"
30*60b67249SAndroid Build Coastguard Worker #include "openssl/hmac.h"
31*60b67249SAndroid Build Coastguard Worker #include "openssl/is_boringssl.h"
32*60b67249SAndroid Build Coastguard Worker #include "openssl/sha.h"
33*60b67249SAndroid Build Coastguard Worker 
hmac(uint8_t k[64],uint8_t in[64],uint8_t * out,unsigned int out_len)34*60b67249SAndroid Build Coastguard Worker static int hmac(uint8_t k[64], uint8_t in[64], uint8_t *out,
35*60b67249SAndroid Build Coastguard Worker                 unsigned int out_len) {
36*60b67249SAndroid Build Coastguard Worker   int ret = 0;
37*60b67249SAndroid Build Coastguard Worker 
38*60b67249SAndroid Build Coastguard Worker   if (out_len != 64) {
39*60b67249SAndroid Build Coastguard Worker     goto out;
40*60b67249SAndroid Build Coastguard Worker   }
41*60b67249SAndroid Build Coastguard Worker   HMAC_CTX ctx;
42*60b67249SAndroid Build Coastguard Worker   HMAC_CTX_init(&ctx);
43*60b67249SAndroid Build Coastguard Worker   if (1 != HMAC_Init_ex(&ctx, k, 64, EVP_sha512(), NULL /* impl */)) {
44*60b67249SAndroid Build Coastguard Worker     goto out;
45*60b67249SAndroid Build Coastguard Worker   }
46*60b67249SAndroid Build Coastguard Worker   if (1 != HMAC_Update(&ctx, in, 64)) {
47*60b67249SAndroid Build Coastguard Worker     goto out;
48*60b67249SAndroid Build Coastguard Worker   }
49*60b67249SAndroid Build Coastguard Worker   ret = HMAC_Final(&ctx, out, &out_len);
50*60b67249SAndroid Build Coastguard Worker   HMAC_CTX_cleanup(&ctx);
51*60b67249SAndroid Build Coastguard Worker 
52*60b67249SAndroid Build Coastguard Worker out:
53*60b67249SAndroid Build Coastguard Worker   return ret;
54*60b67249SAndroid Build Coastguard Worker }
55*60b67249SAndroid Build Coastguard Worker 
hmac3(uint8_t k[64],uint8_t in1[64],uint8_t in2,const uint8_t * in3,unsigned int in3_len,uint8_t out[64])56*60b67249SAndroid Build Coastguard Worker static int hmac3(uint8_t k[64], uint8_t in1[64], uint8_t in2,
57*60b67249SAndroid Build Coastguard Worker                  const uint8_t *in3, unsigned int in3_len, uint8_t out[64]) {
58*60b67249SAndroid Build Coastguard Worker   int ret = 0;
59*60b67249SAndroid Build Coastguard Worker 
60*60b67249SAndroid Build Coastguard Worker   HMAC_CTX ctx;
61*60b67249SAndroid Build Coastguard Worker   HMAC_CTX_init(&ctx);
62*60b67249SAndroid Build Coastguard Worker   if (1 != HMAC_Init_ex(&ctx, k, 64, EVP_sha512(), NULL /* impl */)) {
63*60b67249SAndroid Build Coastguard Worker     goto out;
64*60b67249SAndroid Build Coastguard Worker   }
65*60b67249SAndroid Build Coastguard Worker   if (1 != HMAC_Update(&ctx, in1, 64)) {
66*60b67249SAndroid Build Coastguard Worker     goto out;
67*60b67249SAndroid Build Coastguard Worker   }
68*60b67249SAndroid Build Coastguard Worker   if (1 != HMAC_Update(&ctx, &in2, 1)) {
69*60b67249SAndroid Build Coastguard Worker     goto out;
70*60b67249SAndroid Build Coastguard Worker   }
71*60b67249SAndroid Build Coastguard Worker   if (in3 != NULL && in3_len > 0) {
72*60b67249SAndroid Build Coastguard Worker     if (1 != HMAC_Update(&ctx, in3, in3_len)) {
73*60b67249SAndroid Build Coastguard Worker       goto out;
74*60b67249SAndroid Build Coastguard Worker     }
75*60b67249SAndroid Build Coastguard Worker   }
76*60b67249SAndroid Build Coastguard Worker   unsigned int out_len = 64;
77*60b67249SAndroid Build Coastguard Worker   ret = HMAC_Final(&ctx, out, &out_len);
78*60b67249SAndroid Build Coastguard Worker   HMAC_CTX_cleanup(&ctx);
79*60b67249SAndroid Build Coastguard Worker 
80*60b67249SAndroid Build Coastguard Worker out:
81*60b67249SAndroid Build Coastguard Worker   return ret;
82*60b67249SAndroid Build Coastguard Worker }
83*60b67249SAndroid Build Coastguard Worker 
84*60b67249SAndroid Build Coastguard Worker // Algorithm from section 3.2 of IETF RFC6979; limited to generating up to 64
85*60b67249SAndroid Build Coastguard Worker // byte private keys.
derivePrivateKey(const EC_GROUP * group,const uint8_t * seed,size_t seed_size,size_t private_key_len)86*60b67249SAndroid Build Coastguard Worker static BIGNUM *derivePrivateKey(const EC_GROUP *group, const uint8_t *seed,
87*60b67249SAndroid Build Coastguard Worker                                 size_t seed_size, size_t private_key_len) {
88*60b67249SAndroid Build Coastguard Worker   BIGNUM *candidate = NULL;
89*60b67249SAndroid Build Coastguard Worker   uint8_t v[64];
90*60b67249SAndroid Build Coastguard Worker   uint8_t k[64];
91*60b67249SAndroid Build Coastguard Worker   memset(v, 1, 64);
92*60b67249SAndroid Build Coastguard Worker   memset(k, 0, 64);
93*60b67249SAndroid Build Coastguard Worker 
94*60b67249SAndroid Build Coastguard Worker   if (private_key_len > 64) {
95*60b67249SAndroid Build Coastguard Worker     goto err;
96*60b67249SAndroid Build Coastguard Worker   }
97*60b67249SAndroid Build Coastguard Worker 
98*60b67249SAndroid Build Coastguard Worker   if (1 != hmac3(k, v, 0x00, seed, (unsigned int)seed_size, k)) {
99*60b67249SAndroid Build Coastguard Worker     goto err;
100*60b67249SAndroid Build Coastguard Worker   }
101*60b67249SAndroid Build Coastguard Worker   if (1 != hmac(k, v, v, sizeof(v))) {
102*60b67249SAndroid Build Coastguard Worker     goto err;
103*60b67249SAndroid Build Coastguard Worker   }
104*60b67249SAndroid Build Coastguard Worker   if (1 != hmac3(k, v, 0x01, seed, (unsigned int)seed_size, k)) {
105*60b67249SAndroid Build Coastguard Worker     goto err;
106*60b67249SAndroid Build Coastguard Worker   }
107*60b67249SAndroid Build Coastguard Worker   do {
108*60b67249SAndroid Build Coastguard Worker     if (1 != hmac(k, v, v, sizeof(v))) {
109*60b67249SAndroid Build Coastguard Worker       goto err;
110*60b67249SAndroid Build Coastguard Worker     }
111*60b67249SAndroid Build Coastguard Worker     if (1 != hmac(k, v, v, sizeof(v))) {
112*60b67249SAndroid Build Coastguard Worker       goto err;
113*60b67249SAndroid Build Coastguard Worker     }
114*60b67249SAndroid Build Coastguard Worker     candidate = BN_bin2bn(v, private_key_len, candidate);
115*60b67249SAndroid Build Coastguard Worker     if (!candidate) {
116*60b67249SAndroid Build Coastguard Worker       goto err;
117*60b67249SAndroid Build Coastguard Worker     }
118*60b67249SAndroid Build Coastguard Worker     if (1 != hmac3(k, v, 0x00, NULL, 0, k)) {
119*60b67249SAndroid Build Coastguard Worker       goto err;
120*60b67249SAndroid Build Coastguard Worker     }
121*60b67249SAndroid Build Coastguard Worker   } while (BN_cmp(candidate, EC_GROUP_get0_order(group)) >= 0 ||
122*60b67249SAndroid Build Coastguard Worker            BN_is_zero(candidate));
123*60b67249SAndroid Build Coastguard Worker   goto out;
124*60b67249SAndroid Build Coastguard Worker 
125*60b67249SAndroid Build Coastguard Worker err:
126*60b67249SAndroid Build Coastguard Worker   BN_clear_free(candidate);
127*60b67249SAndroid Build Coastguard Worker   candidate = NULL;
128*60b67249SAndroid Build Coastguard Worker out:
129*60b67249SAndroid Build Coastguard Worker   return candidate;
130*60b67249SAndroid Build Coastguard Worker }
131*60b67249SAndroid Build Coastguard Worker 
KeypairFromSeed(int nid,uint8_t * public_key,size_t public_key_size,uint8_t * private_key,size_t private_key_size,const uint8_t seed[DICE_PRIVATE_KEY_SEED_SIZE])132*60b67249SAndroid Build Coastguard Worker static int KeypairFromSeed(int nid, uint8_t *public_key, size_t public_key_size,
133*60b67249SAndroid Build Coastguard Worker                            uint8_t *private_key, size_t private_key_size,
134*60b67249SAndroid Build Coastguard Worker                            const uint8_t seed[DICE_PRIVATE_KEY_SEED_SIZE]) {
135*60b67249SAndroid Build Coastguard Worker   int ret = 0;
136*60b67249SAndroid Build Coastguard Worker   EC_POINT *publicKey = NULL;
137*60b67249SAndroid Build Coastguard Worker   BIGNUM *pD = NULL;
138*60b67249SAndroid Build Coastguard Worker   BIGNUM *x = NULL;
139*60b67249SAndroid Build Coastguard Worker   BIGNUM *y = NULL;
140*60b67249SAndroid Build Coastguard Worker 
141*60b67249SAndroid Build Coastguard Worker   EC_KEY *key = EC_KEY_new_by_curve_name(nid);
142*60b67249SAndroid Build Coastguard Worker   if (!key) {
143*60b67249SAndroid Build Coastguard Worker     goto out;
144*60b67249SAndroid Build Coastguard Worker   }
145*60b67249SAndroid Build Coastguard Worker   const EC_GROUP *group = EC_KEY_get0_group(key);
146*60b67249SAndroid Build Coastguard Worker   if (!group) {
147*60b67249SAndroid Build Coastguard Worker     goto out;
148*60b67249SAndroid Build Coastguard Worker   }
149*60b67249SAndroid Build Coastguard Worker   publicKey = EC_POINT_new(group);
150*60b67249SAndroid Build Coastguard Worker   if (!publicKey) {
151*60b67249SAndroid Build Coastguard Worker     goto out;
152*60b67249SAndroid Build Coastguard Worker   }
153*60b67249SAndroid Build Coastguard Worker 
154*60b67249SAndroid Build Coastguard Worker   pD = derivePrivateKey(group, seed, DICE_PRIVATE_KEY_SEED_SIZE,
155*60b67249SAndroid Build Coastguard Worker                         private_key_size);
156*60b67249SAndroid Build Coastguard Worker   if (!pD) {
157*60b67249SAndroid Build Coastguard Worker     goto out;
158*60b67249SAndroid Build Coastguard Worker   }
159*60b67249SAndroid Build Coastguard Worker   if (1 != BN_bn2bin_padded(private_key, private_key_size, pD)) {
160*60b67249SAndroid Build Coastguard Worker     goto out;
161*60b67249SAndroid Build Coastguard Worker   }
162*60b67249SAndroid Build Coastguard Worker   if (1 != EC_KEY_set_private_key(key, pD)) {
163*60b67249SAndroid Build Coastguard Worker     goto out;
164*60b67249SAndroid Build Coastguard Worker   }
165*60b67249SAndroid Build Coastguard Worker   if (1 != EC_POINT_mul(group, publicKey, pD, NULL, NULL, NULL)) {
166*60b67249SAndroid Build Coastguard Worker     goto out;
167*60b67249SAndroid Build Coastguard Worker   }
168*60b67249SAndroid Build Coastguard Worker   x = BN_new();
169*60b67249SAndroid Build Coastguard Worker   if (!x) {
170*60b67249SAndroid Build Coastguard Worker     goto out;
171*60b67249SAndroid Build Coastguard Worker   }
172*60b67249SAndroid Build Coastguard Worker   y = BN_new();
173*60b67249SAndroid Build Coastguard Worker   if (!y) {
174*60b67249SAndroid Build Coastguard Worker     goto out;
175*60b67249SAndroid Build Coastguard Worker   }
176*60b67249SAndroid Build Coastguard Worker   if (1 != EC_POINT_get_affine_coordinates_GFp(group, publicKey, x, y, NULL)) {
177*60b67249SAndroid Build Coastguard Worker     goto out;
178*60b67249SAndroid Build Coastguard Worker   }
179*60b67249SAndroid Build Coastguard Worker   size_t coord_size = public_key_size / 2;
180*60b67249SAndroid Build Coastguard Worker   if (1 != BN_bn2bin_padded(&public_key[0], coord_size, x)) {
181*60b67249SAndroid Build Coastguard Worker     goto out;
182*60b67249SAndroid Build Coastguard Worker   }
183*60b67249SAndroid Build Coastguard Worker   if (1 != BN_bn2bin_padded(&public_key[coord_size], coord_size, y)) {
184*60b67249SAndroid Build Coastguard Worker     goto out;
185*60b67249SAndroid Build Coastguard Worker   }
186*60b67249SAndroid Build Coastguard Worker   ret = 1;
187*60b67249SAndroid Build Coastguard Worker 
188*60b67249SAndroid Build Coastguard Worker out:
189*60b67249SAndroid Build Coastguard Worker   EC_POINT_free(publicKey);
190*60b67249SAndroid Build Coastguard Worker   BN_clear_free(x);
191*60b67249SAndroid Build Coastguard Worker   BN_clear_free(y);
192*60b67249SAndroid Build Coastguard Worker   EC_KEY_free(key);
193*60b67249SAndroid Build Coastguard Worker   BN_clear_free(pD);
194*60b67249SAndroid Build Coastguard Worker 
195*60b67249SAndroid Build Coastguard Worker   return ret;
196*60b67249SAndroid Build Coastguard Worker }
197*60b67249SAndroid Build Coastguard Worker 
P256KeypairFromSeed(uint8_t public_key[P256_PUBLIC_KEY_SIZE],uint8_t private_key[P256_PRIVATE_KEY_SIZE],const uint8_t seed[DICE_PRIVATE_KEY_SEED_SIZE])198*60b67249SAndroid Build Coastguard Worker int P256KeypairFromSeed(uint8_t public_key[P256_PUBLIC_KEY_SIZE],
199*60b67249SAndroid Build Coastguard Worker                         uint8_t private_key[P256_PRIVATE_KEY_SIZE],
200*60b67249SAndroid Build Coastguard Worker                         const uint8_t seed[DICE_PRIVATE_KEY_SEED_SIZE]) {
201*60b67249SAndroid Build Coastguard Worker   return KeypairFromSeed(NID_X9_62_prime256v1, public_key, P256_PUBLIC_KEY_SIZE,
202*60b67249SAndroid Build Coastguard Worker                          private_key, P256_PRIVATE_KEY_SIZE, seed);
203*60b67249SAndroid Build Coastguard Worker }
204*60b67249SAndroid Build Coastguard Worker 
P384KeypairFromSeed(uint8_t public_key[P384_PUBLIC_KEY_SIZE],uint8_t private_key[P384_PRIVATE_KEY_SIZE],const uint8_t seed[DICE_PRIVATE_KEY_SEED_SIZE])205*60b67249SAndroid Build Coastguard Worker int P384KeypairFromSeed(uint8_t public_key[P384_PUBLIC_KEY_SIZE],
206*60b67249SAndroid Build Coastguard Worker                         uint8_t private_key[P384_PRIVATE_KEY_SIZE],
207*60b67249SAndroid Build Coastguard Worker                         const uint8_t seed[DICE_PRIVATE_KEY_SEED_SIZE]) {
208*60b67249SAndroid Build Coastguard Worker   return KeypairFromSeed(NID_secp384r1, public_key, P384_PUBLIC_KEY_SIZE,
209*60b67249SAndroid Build Coastguard Worker                          private_key, P384_PRIVATE_KEY_SIZE, seed);
210*60b67249SAndroid Build Coastguard Worker }
211*60b67249SAndroid Build Coastguard Worker 
Sign(int nid,uint8_t * signature,size_t signature_size,const EVP_MD * md_type,const uint8_t * message,size_t message_size,const uint8_t * private_key,size_t private_key_size)212*60b67249SAndroid Build Coastguard Worker static int Sign(int nid, uint8_t *signature, size_t signature_size,
213*60b67249SAndroid Build Coastguard Worker                 const EVP_MD *md_type, const uint8_t *message,
214*60b67249SAndroid Build Coastguard Worker                 size_t message_size, const uint8_t *private_key,
215*60b67249SAndroid Build Coastguard Worker                 size_t private_key_size) {
216*60b67249SAndroid Build Coastguard Worker   int ret = 0;
217*60b67249SAndroid Build Coastguard Worker   BIGNUM *pD = NULL;
218*60b67249SAndroid Build Coastguard Worker   EC_KEY *key = NULL;
219*60b67249SAndroid Build Coastguard Worker   uint8_t output[EVP_MAX_MD_SIZE];
220*60b67249SAndroid Build Coastguard Worker   unsigned int md_size;
221*60b67249SAndroid Build Coastguard Worker   ECDSA_SIG *sig = NULL;
222*60b67249SAndroid Build Coastguard Worker 
223*60b67249SAndroid Build Coastguard Worker   pD = BN_bin2bn(private_key, private_key_size, NULL);
224*60b67249SAndroid Build Coastguard Worker   if (!pD) {
225*60b67249SAndroid Build Coastguard Worker     goto out;
226*60b67249SAndroid Build Coastguard Worker   }
227*60b67249SAndroid Build Coastguard Worker   key = EC_KEY_new_by_curve_name(nid);
228*60b67249SAndroid Build Coastguard Worker   if (!key) {
229*60b67249SAndroid Build Coastguard Worker     goto out;
230*60b67249SAndroid Build Coastguard Worker   }
231*60b67249SAndroid Build Coastguard Worker   if (1 != EC_KEY_set_private_key(key, pD)) {
232*60b67249SAndroid Build Coastguard Worker     goto out;
233*60b67249SAndroid Build Coastguard Worker   }
234*60b67249SAndroid Build Coastguard Worker   if (1 != EVP_Digest(message, message_size, output, &md_size, md_type, NULL)) {
235*60b67249SAndroid Build Coastguard Worker     goto out;
236*60b67249SAndroid Build Coastguard Worker   }
237*60b67249SAndroid Build Coastguard Worker   sig = ECDSA_do_sign(output, md_size, key);
238*60b67249SAndroid Build Coastguard Worker   if (!sig) {
239*60b67249SAndroid Build Coastguard Worker     goto out;
240*60b67249SAndroid Build Coastguard Worker   }
241*60b67249SAndroid Build Coastguard Worker   size_t coord_size = signature_size / 2;
242*60b67249SAndroid Build Coastguard Worker   if (1 != BN_bn2bin_padded(&signature[0], coord_size, sig->r)) {
243*60b67249SAndroid Build Coastguard Worker     goto out;
244*60b67249SAndroid Build Coastguard Worker   }
245*60b67249SAndroid Build Coastguard Worker   if (1 != BN_bn2bin_padded(&signature[coord_size], coord_size, sig->s)) {
246*60b67249SAndroid Build Coastguard Worker     goto out;
247*60b67249SAndroid Build Coastguard Worker   }
248*60b67249SAndroid Build Coastguard Worker   ret = 1;
249*60b67249SAndroid Build Coastguard Worker 
250*60b67249SAndroid Build Coastguard Worker out:
251*60b67249SAndroid Build Coastguard Worker   EC_KEY_free(key);
252*60b67249SAndroid Build Coastguard Worker   BN_clear_free(pD);
253*60b67249SAndroid Build Coastguard Worker   ECDSA_SIG_free(sig);
254*60b67249SAndroid Build Coastguard Worker   return ret;
255*60b67249SAndroid Build Coastguard Worker }
256*60b67249SAndroid Build Coastguard Worker 
P256Sign(uint8_t signature[P256_SIGNATURE_SIZE],const uint8_t * message,size_t message_size,const uint8_t private_key[P256_PRIVATE_KEY_SIZE])257*60b67249SAndroid Build Coastguard Worker int P256Sign(uint8_t signature[P256_SIGNATURE_SIZE], const uint8_t *message,
258*60b67249SAndroid Build Coastguard Worker              size_t message_size,
259*60b67249SAndroid Build Coastguard Worker              const uint8_t private_key[P256_PRIVATE_KEY_SIZE]) {
260*60b67249SAndroid Build Coastguard Worker   return Sign(NID_X9_62_prime256v1, signature, P256_SIGNATURE_SIZE,
261*60b67249SAndroid Build Coastguard Worker               EVP_sha256(), message, message_size, private_key,
262*60b67249SAndroid Build Coastguard Worker               P256_PRIVATE_KEY_SIZE);
263*60b67249SAndroid Build Coastguard Worker }
264*60b67249SAndroid Build Coastguard Worker 
P384Sign(uint8_t signature[P384_SIGNATURE_SIZE],const uint8_t * message,size_t message_size,const uint8_t private_key[P384_PRIVATE_KEY_SIZE])265*60b67249SAndroid Build Coastguard Worker int P384Sign(uint8_t signature[P384_SIGNATURE_SIZE], const uint8_t *message,
266*60b67249SAndroid Build Coastguard Worker              size_t message_size,
267*60b67249SAndroid Build Coastguard Worker              const uint8_t private_key[P384_PRIVATE_KEY_SIZE]) {
268*60b67249SAndroid Build Coastguard Worker   return Sign(NID_secp384r1, signature, P384_SIGNATURE_SIZE, EVP_sha384(),
269*60b67249SAndroid Build Coastguard Worker               message, message_size, private_key, P384_PRIVATE_KEY_SIZE);
270*60b67249SAndroid Build Coastguard Worker }
271*60b67249SAndroid Build Coastguard Worker 
Verify(int nid,const EVP_MD * md_type,const uint8_t * message,size_t message_size,const uint8_t * signature,size_t signature_size,const uint8_t * public_key,size_t public_key_size)272*60b67249SAndroid Build Coastguard Worker static int Verify(int nid, const EVP_MD *md_type, const uint8_t *message,
273*60b67249SAndroid Build Coastguard Worker                   size_t message_size, const uint8_t *signature,
274*60b67249SAndroid Build Coastguard Worker                   size_t signature_size, const uint8_t *public_key,
275*60b67249SAndroid Build Coastguard Worker                   size_t public_key_size) {
276*60b67249SAndroid Build Coastguard Worker   int ret = 0;
277*60b67249SAndroid Build Coastguard Worker   uint8_t output[EVP_MAX_MD_SIZE];
278*60b67249SAndroid Build Coastguard Worker   unsigned int md_size;
279*60b67249SAndroid Build Coastguard Worker   EC_KEY *key = NULL;
280*60b67249SAndroid Build Coastguard Worker   BIGNUM *bn_ret = NULL;
281*60b67249SAndroid Build Coastguard Worker   BIGNUM *x = NULL;
282*60b67249SAndroid Build Coastguard Worker   BIGNUM *y = NULL;
283*60b67249SAndroid Build Coastguard Worker   ECDSA_SIG *sig = NULL;
284*60b67249SAndroid Build Coastguard Worker 
285*60b67249SAndroid Build Coastguard Worker   if (1 != EVP_Digest(message, message_size, output, &md_size, md_type, NULL)) {
286*60b67249SAndroid Build Coastguard Worker     goto out;
287*60b67249SAndroid Build Coastguard Worker   }
288*60b67249SAndroid Build Coastguard Worker   key = EC_KEY_new_by_curve_name(nid);
289*60b67249SAndroid Build Coastguard Worker   if (!key) {
290*60b67249SAndroid Build Coastguard Worker     goto out;
291*60b67249SAndroid Build Coastguard Worker   }
292*60b67249SAndroid Build Coastguard Worker   x = BN_new();
293*60b67249SAndroid Build Coastguard Worker   if (!x) {
294*60b67249SAndroid Build Coastguard Worker     goto out;
295*60b67249SAndroid Build Coastguard Worker   }
296*60b67249SAndroid Build Coastguard Worker   size_t coord_size = public_key_size / 2;
297*60b67249SAndroid Build Coastguard Worker   bn_ret = BN_bin2bn(&public_key[0], coord_size, x);
298*60b67249SAndroid Build Coastguard Worker   if (!bn_ret) {
299*60b67249SAndroid Build Coastguard Worker     goto out;
300*60b67249SAndroid Build Coastguard Worker   }
301*60b67249SAndroid Build Coastguard Worker   y = BN_new();
302*60b67249SAndroid Build Coastguard Worker   if (!y) {
303*60b67249SAndroid Build Coastguard Worker     goto out;
304*60b67249SAndroid Build Coastguard Worker   }
305*60b67249SAndroid Build Coastguard Worker   bn_ret = BN_bin2bn(&public_key[coord_size], coord_size, y);
306*60b67249SAndroid Build Coastguard Worker   if (!bn_ret) {
307*60b67249SAndroid Build Coastguard Worker     goto out;
308*60b67249SAndroid Build Coastguard Worker   }
309*60b67249SAndroid Build Coastguard Worker   if (1 != EC_KEY_set_public_key_affine_coordinates(key, x, y)) {
310*60b67249SAndroid Build Coastguard Worker     goto out;
311*60b67249SAndroid Build Coastguard Worker   }
312*60b67249SAndroid Build Coastguard Worker 
313*60b67249SAndroid Build Coastguard Worker   sig = ECDSA_SIG_new();
314*60b67249SAndroid Build Coastguard Worker   if (!sig) {
315*60b67249SAndroid Build Coastguard Worker     goto out;
316*60b67249SAndroid Build Coastguard Worker   }
317*60b67249SAndroid Build Coastguard Worker   coord_size = signature_size / 2;
318*60b67249SAndroid Build Coastguard Worker   bn_ret = BN_bin2bn(&signature[0], coord_size, sig->r);
319*60b67249SAndroid Build Coastguard Worker   if (!bn_ret) {
320*60b67249SAndroid Build Coastguard Worker     goto out;
321*60b67249SAndroid Build Coastguard Worker   }
322*60b67249SAndroid Build Coastguard Worker   bn_ret = BN_bin2bn(&signature[coord_size], coord_size, sig->s);
323*60b67249SAndroid Build Coastguard Worker   if (!bn_ret) {
324*60b67249SAndroid Build Coastguard Worker     goto out;
325*60b67249SAndroid Build Coastguard Worker   }
326*60b67249SAndroid Build Coastguard Worker   ret = ECDSA_do_verify(output, md_size, sig, key);
327*60b67249SAndroid Build Coastguard Worker 
328*60b67249SAndroid Build Coastguard Worker out:
329*60b67249SAndroid Build Coastguard Worker   BN_clear_free(y);
330*60b67249SAndroid Build Coastguard Worker   BN_clear_free(x);
331*60b67249SAndroid Build Coastguard Worker   EC_KEY_free(key);
332*60b67249SAndroid Build Coastguard Worker   ECDSA_SIG_free(sig);
333*60b67249SAndroid Build Coastguard Worker   return ret;
334*60b67249SAndroid Build Coastguard Worker }
335*60b67249SAndroid Build Coastguard Worker 
P256Verify(const uint8_t * message,size_t message_size,const uint8_t signature[P256_SIGNATURE_SIZE],const uint8_t public_key[P256_PUBLIC_KEY_SIZE])336*60b67249SAndroid Build Coastguard Worker int P256Verify(const uint8_t *message, size_t message_size,
337*60b67249SAndroid Build Coastguard Worker                const uint8_t signature[P256_SIGNATURE_SIZE],
338*60b67249SAndroid Build Coastguard Worker                const uint8_t public_key[P256_PUBLIC_KEY_SIZE]) {
339*60b67249SAndroid Build Coastguard Worker   return Verify(NID_X9_62_prime256v1, EVP_sha256(), message, message_size,
340*60b67249SAndroid Build Coastguard Worker                 signature, P256_SIGNATURE_SIZE, public_key,
341*60b67249SAndroid Build Coastguard Worker                 P256_PUBLIC_KEY_SIZE);
342*60b67249SAndroid Build Coastguard Worker }
343*60b67249SAndroid Build Coastguard Worker 
P384Verify(const uint8_t * message,size_t message_size,const uint8_t signature[P384_SIGNATURE_SIZE],const uint8_t public_key[P384_PUBLIC_KEY_SIZE])344*60b67249SAndroid Build Coastguard Worker int P384Verify(const uint8_t *message, size_t message_size,
345*60b67249SAndroid Build Coastguard Worker                const uint8_t signature[P384_SIGNATURE_SIZE],
346*60b67249SAndroid Build Coastguard Worker                const uint8_t public_key[P384_PUBLIC_KEY_SIZE]) {
347*60b67249SAndroid Build Coastguard Worker   return Verify(NID_secp384r1, EVP_sha384(), message, message_size, signature,
348*60b67249SAndroid Build Coastguard Worker                 P384_SIGNATURE_SIZE, public_key, P384_PUBLIC_KEY_SIZE);
349*60b67249SAndroid Build Coastguard Worker }
350