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 || out_len < 0) {
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
derivePrivateKey(const EC_GROUP * group,const uint8_t * seed,size_t seed_size,uint8_t * private_key,size_t private_key_len)86 static BIGNUM *derivePrivateKey(const EC_GROUP *group, const uint8_t *seed,
87 size_t seed_size, uint8_t *private_key,
88 size_t private_key_len) {
89 BIGNUM *candidate = NULL;
90 uint8_t v[64];
91 uint8_t k[64];
92 memset(v, 1, 64);
93 memset(k, 0, 64);
94
95 if (1 != hmac3(k, v, 0x00, seed, (unsigned int)seed_size, k)) {
96 goto err;
97 }
98 if (1 != hmac(k, v, v, sizeof(v))) {
99 goto err;
100 }
101 if (1 != hmac3(k, v, 0x01, seed, (unsigned int)seed_size, k)) {
102 goto err;
103 }
104 do {
105 if (1 != hmac(k, v, v, sizeof(v))) {
106 goto err;
107 }
108 if (1 != hmac(k, v, private_key, private_key_len)) {
109 goto err;
110 }
111 if (1 != hmac3(k, v, 0x00, NULL, 0, k)) {
112 goto err;
113 }
114 candidate = BN_bin2bn(private_key, private_key_len, NULL);
115 if (!candidate) {
116 goto err;
117 }
118 } while (BN_cmp(candidate, EC_GROUP_get0_order(group)) >= 0 ||
119 BN_is_zero(candidate));
120 goto out;
121
122 err:
123 BN_clear_free(candidate);
124 candidate = NULL;
125 out:
126 return candidate;
127 }
128
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])129 int P384KeypairFromSeed(uint8_t public_key[P384_PUBLIC_KEY_SIZE],
130 uint8_t private_key[P384_PRIVATE_KEY_SIZE],
131 const uint8_t seed[DICE_PRIVATE_KEY_SEED_SIZE]) {
132 int ret = 0;
133 EC_POINT *publicKey = NULL;
134 BIGNUM *pD = NULL;
135 BIGNUM *x = NULL;
136 BIGNUM *y = NULL;
137
138 EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
139 if (!key) {
140 goto out;
141 }
142 const EC_GROUP *group = EC_KEY_get0_group(key);
143 if (!group) {
144 goto out;
145 }
146 publicKey = EC_POINT_new(group);
147 if (!publicKey) {
148 goto out;
149 }
150
151 pD = derivePrivateKey(group, seed, DICE_PRIVATE_KEY_SEED_SIZE, private_key,
152 P384_PRIVATE_KEY_SIZE);
153 if (!pD) {
154 goto out;
155 }
156 if (1 != BN_bn2bin_padded(private_key, P384_PRIVATE_KEY_SIZE, pD)) {
157 goto out;
158 }
159 if (1 != EC_KEY_set_private_key(key, pD)) {
160 goto out;
161 }
162 if (1 != EC_POINT_mul(group, publicKey, pD, NULL, NULL, NULL)) {
163 goto out;
164 }
165 x = BN_new();
166 if (!x) {
167 goto out;
168 }
169 y = BN_new();
170 if (!y) {
171 goto out;
172 }
173 if (1 != EC_POINT_get_affine_coordinates_GFp(group, publicKey, x, y, NULL)) {
174 goto out;
175 }
176 if (BN_num_bytes(x) > P384_PRIVATE_KEY_SIZE) {
177 goto out;
178 }
179 BN_bn2bin(x, &public_key[0]);
180 if (BN_num_bytes(y) > P384_PRIVATE_KEY_SIZE) {
181 goto out;
182 }
183 BN_bn2bin(y, &public_key[P384_PRIVATE_KEY_SIZE]);
184 ret = 1;
185
186 out:
187 EC_POINT_free(publicKey);
188 BN_clear_free(x);
189 BN_clear_free(y);
190 EC_KEY_free(key);
191 BN_clear_free(pD);
192
193 return ret;
194 }
195
P384Sign(uint8_t signature[P384_SIGNATURE_SIZE],const uint8_t * message,size_t message_size,const uint8_t private_key[P384_PRIVATE_KEY_SIZE])196 int P384Sign(uint8_t signature[P384_SIGNATURE_SIZE], const uint8_t *message,
197 size_t message_size,
198 const uint8_t private_key[P384_PRIVATE_KEY_SIZE]) {
199 int ret = 0;
200 BIGNUM *pD = NULL;
201 EC_KEY *key = NULL;
202 uint8_t output[48];
203 ECDSA_SIG *sig = NULL;
204
205 pD = BN_bin2bn(private_key, P384_PRIVATE_KEY_SIZE, NULL);
206 if (!pD) {
207 goto out;
208 }
209 key = EC_KEY_new_by_curve_name(NID_secp384r1);
210 if (!key) {
211 goto out;
212 }
213 if (1 != EC_KEY_set_private_key(key, pD)) {
214 goto out;
215 }
216 SHA384(message, message_size, output);
217 sig = ECDSA_do_sign(output, 48, key);
218 if (!sig) {
219 goto out;
220 }
221
222 if (BN_num_bytes(sig->r) > P384_PRIVATE_KEY_SIZE) {
223 goto out;
224 }
225 BN_bn2bin(sig->r, &signature[0]);
226 if (BN_num_bytes(sig->s) > P384_PRIVATE_KEY_SIZE) {
227 goto out;
228 }
229 BN_bn2bin(sig->s, &signature[P384_PRIVATE_KEY_SIZE]);
230 ret = 1;
231
232 out:
233 EC_KEY_free(key);
234 BN_clear_free(pD);
235 ECDSA_SIG_free(sig);
236 return ret;
237 }
238
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])239 int P384Verify(const uint8_t *message, size_t message_size,
240 const uint8_t signature[P384_SIGNATURE_SIZE],
241 const uint8_t public_key[P384_PUBLIC_KEY_SIZE]) {
242 int ret = 0;
243 uint8_t output[48];
244 EC_KEY *key = NULL;
245 BIGNUM *bn_ret = NULL;
246 BIGNUM *x = NULL;
247 BIGNUM *y = NULL;
248 ECDSA_SIG *sig = NULL;
249
250 SHA384(message, message_size, output);
251 key = EC_KEY_new_by_curve_name(NID_secp384r1);
252 if (!key) {
253 goto out;
254 }
255 x = BN_new();
256 if (!x) {
257 goto out;
258 }
259 bn_ret = BN_bin2bn(&public_key[0], P384_PUBLIC_KEY_SIZE / 2, x);
260 if (!bn_ret) {
261 goto out;
262 }
263 y = BN_new();
264 if (!y) {
265 goto out;
266 }
267 bn_ret = BN_bin2bn(&public_key[P384_PUBLIC_KEY_SIZE / 2], P384_PUBLIC_KEY_SIZE / 2, y);
268 if (!bn_ret) {
269 goto out;
270 }
271 if (1 != EC_KEY_set_public_key_affine_coordinates(key, x, y)) {
272 goto out;
273 }
274
275
276 sig = ECDSA_SIG_new();
277 if (!sig) {
278 goto out;
279 }
280 bn_ret = BN_bin2bn(&signature[0], P384_SIGNATURE_SIZE / 2, sig->r);
281 if (!bn_ret) {
282 goto out;
283 }
284 bn_ret = BN_bin2bn(&signature[P384_SIGNATURE_SIZE / 2], P384_SIGNATURE_SIZE / 2,
285 sig->s);
286 if (!bn_ret) {
287 goto out;
288 }
289 ret = ECDSA_do_verify(output, 48, sig, key);
290
291 out:
292 BN_clear_free(y);
293 BN_clear_free(x);
294 EC_KEY_free(key);
295 ECDSA_SIG_free(sig);
296 return ret;
297 }
298