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