• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 crypto operations that uses boringssl. The
16 // algorithms used are SHA512, HKDF-SHA512, and ECDSA P384-SHA384.
17 
18 #include "dice/boringssl_ecdsa_utils.h"
19 
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include "openssl/bn.h"
25 #include "openssl/crypto.h"
26 #include "openssl/ec.h"
27 #include "openssl/ec_key.h"
28 #include "openssl/ecdsa.h"
29 #include "openssl/evp.h"
30 #include "openssl/hkdf.h"
31 #include "openssl/hmac.h"
32 #include "openssl/is_boringssl.h"
33 #include "openssl/sha.h"
34 
hmac(uint8_t k[64],uint8_t in[64],uint8_t * out,unsigned int out_len)35 static int hmac(uint8_t k[64], uint8_t in[64], uint8_t *out,
36                 unsigned int out_len) {
37   int ret = 0;
38 
39   if (out_len != 64) {
40     goto out;
41   }
42   HMAC_CTX ctx;
43   HMAC_CTX_init(&ctx);
44   if (1 != HMAC_Init_ex(&ctx, k, 64, EVP_sha512(), NULL /* impl */)) {
45     goto out;
46   }
47   if (1 != HMAC_Update(&ctx, in, 64)) {
48     goto out;
49   }
50   ret = HMAC_Final(&ctx, out, &out_len);
51   HMAC_CTX_cleanup(&ctx);
52 
53 out:
54   return ret;
55 }
56 
hmac3(uint8_t k[64],uint8_t in1[64],uint8_t in2,const uint8_t * in3,unsigned int in3_len,uint8_t out[64])57 static int hmac3(uint8_t k[64], uint8_t in1[64], uint8_t in2,
58                  const uint8_t *in3, unsigned int in3_len, uint8_t out[64]) {
59   int ret = 0;
60 
61   HMAC_CTX ctx;
62   HMAC_CTX_init(&ctx);
63   if (1 != HMAC_Init_ex(&ctx, k, 64, EVP_sha512(), NULL /* impl */)) {
64     goto out;
65   }
66   if (1 != HMAC_Update(&ctx, in1, 64)) {
67     goto out;
68   }
69   if (1 != HMAC_Update(&ctx, &in2, 1)) {
70     goto out;
71   }
72   if (in3 != NULL && in3_len > 0) {
73     if (1 != HMAC_Update(&ctx, in3, in3_len)) {
74       goto out;
75     }
76   }
77   unsigned int out_len = 64;
78   ret = HMAC_Final(&ctx, out, &out_len);
79   HMAC_CTX_cleanup(&ctx);
80 
81 out:
82   return ret;
83 }
84 
85 // Algorithm from section 3.2 of IETF RFC6979; limited to generating up to 64
86 // byte private keys.
derivePrivateKey(const EC_GROUP * group,const uint8_t * seed,size_t seed_size,size_t private_key_len)87 static BIGNUM *derivePrivateKey(const EC_GROUP *group, const uint8_t *seed,
88                                 size_t seed_size, size_t private_key_len) {
89   BIGNUM *candidate = NULL;
90   uint8_t v[64];
91   uint8_t k[64];
92   uint8_t temp[64];
93   memset(v, 1, 64);
94   memset(k, 0, 64);
95   memset(temp, 0, 64);
96 
97   if (private_key_len > 64) {
98     goto err;
99   }
100 
101   if (1 != hmac3(k, v, 0x00, seed, (unsigned int)seed_size, k)) {
102     goto err;
103   }
104   if (1 != hmac(k, v, v, sizeof(v))) {
105     goto err;
106   }
107   if (1 != hmac3(k, v, 0x01, seed, (unsigned int)seed_size, k)) {
108     goto err;
109   }
110   do {
111     if (1 != hmac(k, v, v, sizeof(v))) {
112       goto err;
113     }
114     if (1 != hmac(k, v, temp, sizeof(temp))) {
115       goto err;
116     }
117     if (1 != hmac3(k, v, 0x00, NULL, 0, k)) {
118       goto err;
119     }
120     candidate = BN_bin2bn(temp, private_key_len, NULL);
121     if (!candidate) {
122       goto err;
123     }
124   } while (BN_cmp(candidate, EC_GROUP_get0_order(group)) >= 0 ||
125            BN_is_zero(candidate));
126   goto out;
127 
128 err:
129   BN_clear_free(candidate);
130   candidate = NULL;
131 out:
132   return candidate;
133 }
134 
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])135 int P384KeypairFromSeed(uint8_t public_key[P384_PUBLIC_KEY_SIZE],
136                         uint8_t private_key[P384_PRIVATE_KEY_SIZE],
137                         const uint8_t seed[DICE_PRIVATE_KEY_SEED_SIZE]) {
138   int ret = 0;
139   EC_POINT *publicKey = NULL;
140   BIGNUM *pD = NULL;
141   BIGNUM *x = NULL;
142   BIGNUM *y = NULL;
143 
144   EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
145   if (!key) {
146     goto out;
147   }
148   const EC_GROUP *group = EC_KEY_get0_group(key);
149   if (!group) {
150     goto out;
151   }
152   publicKey = EC_POINT_new(group);
153   if (!publicKey) {
154     goto out;
155   }
156 
157   pD = derivePrivateKey(group, seed, DICE_PRIVATE_KEY_SEED_SIZE,
158                         P384_PRIVATE_KEY_SIZE);
159   if (!pD) {
160     goto out;
161   }
162   if (1 != BN_bn2bin_padded(private_key, P384_PRIVATE_KEY_SIZE, pD)) {
163     goto out;
164   }
165   if (1 != EC_KEY_set_private_key(key, pD)) {
166     goto out;
167   }
168   if (1 != EC_POINT_mul(group, publicKey, pD, NULL, NULL, NULL)) {
169     goto out;
170   }
171   x = BN_new();
172   if (!x) {
173     goto out;
174   }
175   y = BN_new();
176   if (!y) {
177     goto out;
178   }
179   if (1 != EC_POINT_get_affine_coordinates_GFp(group, publicKey, x, y, NULL)) {
180     goto out;
181   }
182   if (1 != BN_bn2bin_padded(&public_key[0], P384_PUBLIC_KEY_SIZE / 2, x)) {
183     goto out;
184   }
185   if (1 != BN_bn2bin_padded(&public_key[P384_PUBLIC_KEY_SIZE / 2],
186                             P384_PUBLIC_KEY_SIZE / 2, y)) {
187     goto out;
188   }
189   ret = 1;
190 
191 out:
192   EC_POINT_free(publicKey);
193   BN_clear_free(x);
194   BN_clear_free(y);
195   EC_KEY_free(key);
196   BN_clear_free(pD);
197 
198   return ret;
199 }
200 
P384Sign(uint8_t signature[P384_SIGNATURE_SIZE],const uint8_t * message,size_t message_size,const uint8_t private_key[P384_PRIVATE_KEY_SIZE])201 int P384Sign(uint8_t signature[P384_SIGNATURE_SIZE], const uint8_t *message,
202              size_t message_size,
203              const uint8_t private_key[P384_PRIVATE_KEY_SIZE]) {
204   int ret = 0;
205   BIGNUM *pD = NULL;
206   EC_KEY *key = NULL;
207   uint8_t output[48];
208   ECDSA_SIG *sig = NULL;
209 
210   pD = BN_bin2bn(private_key, P384_PRIVATE_KEY_SIZE, NULL);
211   if (!pD) {
212     goto out;
213   }
214   key = EC_KEY_new_by_curve_name(NID_secp384r1);
215   if (!key) {
216     goto out;
217   }
218   if (1 != EC_KEY_set_private_key(key, pD)) {
219     goto out;
220   }
221   SHA384(message, message_size, output);
222   sig = ECDSA_do_sign(output, 48, key);
223   if (!sig) {
224     goto out;
225   }
226   if (1 != BN_bn2bin_padded(&signature[0], P384_SIGNATURE_SIZE / 2, sig->r)) {
227     goto out;
228   }
229   if (1 != BN_bn2bin_padded(&signature[P384_SIGNATURE_SIZE / 2],
230                             P384_SIGNATURE_SIZE / 2, sig->s)) {
231     goto out;
232   }
233   ret = 1;
234 
235 out:
236   EC_KEY_free(key);
237   BN_clear_free(pD);
238   ECDSA_SIG_free(sig);
239   return ret;
240 }
241 
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])242 int P384Verify(const uint8_t *message, size_t message_size,
243                const uint8_t signature[P384_SIGNATURE_SIZE],
244                const uint8_t public_key[P384_PUBLIC_KEY_SIZE]) {
245   int ret = 0;
246   uint8_t output[48];
247   EC_KEY *key = NULL;
248   BIGNUM *bn_ret = NULL;
249   BIGNUM *x = NULL;
250   BIGNUM *y = NULL;
251   ECDSA_SIG *sig = NULL;
252 
253   SHA384(message, message_size, output);
254   key = EC_KEY_new_by_curve_name(NID_secp384r1);
255   if (!key) {
256     goto out;
257   }
258   x = BN_new();
259   if (!x) {
260     goto out;
261   }
262   bn_ret = BN_bin2bn(&public_key[0], P384_PUBLIC_KEY_SIZE / 2, x);
263   if (!bn_ret) {
264     goto out;
265   }
266   y = BN_new();
267   if (!y) {
268     goto out;
269   }
270   bn_ret = BN_bin2bn(&public_key[P384_PUBLIC_KEY_SIZE / 2],
271                      P384_PUBLIC_KEY_SIZE / 2, y);
272   if (!bn_ret) {
273     goto out;
274   }
275   if (1 != EC_KEY_set_public_key_affine_coordinates(key, x, y)) {
276     goto out;
277   }
278 
279   sig = ECDSA_SIG_new();
280   if (!sig) {
281     goto out;
282   }
283   bn_ret = BN_bin2bn(&signature[0], P384_SIGNATURE_SIZE / 2, sig->r);
284   if (!bn_ret) {
285     goto out;
286   }
287   bn_ret = BN_bin2bn(&signature[P384_SIGNATURE_SIZE / 2],
288                      P384_SIGNATURE_SIZE / 2, sig->s);
289   if (!bn_ret) {
290     goto out;
291   }
292   ret = ECDSA_do_verify(output, 48, sig, key);
293 
294 out:
295   BN_clear_free(y);
296   BN_clear_free(x);
297   EC_KEY_free(key);
298   ECDSA_SIG_free(sig);
299   return ret;
300 }
301