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