]>
Commit | Line | Data |
---|---|---|
14a7cfb3 | 1 | /* |
bb315ca7 | 2 | * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. |
aa8f3d76 | 3 | * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved |
14a7cfb3 | 4 | * |
a7f182b7 | 5 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
aa6bb135 RS |
6 | * this file except in compliance with the License. You can obtain a copy |
7 | * in the file LICENSE in the source distribution or at | |
8 | * https://www.openssl.org/source/license.html | |
14a7cfb3 | 9 | */ |
aa6bb135 | 10 | |
5f8dd0f8 | 11 | #include "internal/cryptlib.h" |
5454829a | 12 | #include <string.h> |
14a7cfb3 | 13 | #include "ec_lcl.h" |
cd420b0b | 14 | #include "internal/refcount.h" |
14a7cfb3 | 15 | #include <openssl/err.h> |
3c27208f | 16 | #include <openssl/engine.h> |
14a7cfb3 | 17 | |
a9612d6c | 18 | #ifndef FIPS_MODE |
14a7cfb3 | 19 | EC_KEY *EC_KEY_new(void) |
0f113f3e | 20 | { |
a9612d6c | 21 | return ec_key_new_method_int(NULL, NULL); |
0f113f3e | 22 | } |
a9612d6c | 23 | #endif |
14a7cfb3 | 24 | |
a9612d6c MC |
25 | EC_KEY *EC_KEY_new_ex(OPENSSL_CTX *ctx) |
26 | { | |
27 | return ec_key_new_method_int(ctx, NULL); | |
28 | } | |
29 | ||
30 | EC_KEY *EC_KEY_new_by_curve_name_ex(OPENSSL_CTX *ctx, int nid) | |
0f113f3e | 31 | { |
a9612d6c | 32 | EC_KEY *ret = EC_KEY_new_ex(ctx); |
0f113f3e MC |
33 | if (ret == NULL) |
34 | return NULL; | |
a9612d6c | 35 | ret->group = EC_GROUP_new_by_curve_name_ex(ctx, nid); |
0f113f3e MC |
36 | if (ret->group == NULL) { |
37 | EC_KEY_free(ret); | |
38 | return NULL; | |
39 | } | |
91e7bcc2 DSH |
40 | if (ret->meth->set_group != NULL |
41 | && ret->meth->set_group(ret, ret->group) == 0) { | |
3475bc96 DSH |
42 | EC_KEY_free(ret); |
43 | return NULL; | |
44 | } | |
0f113f3e MC |
45 | return ret; |
46 | } | |
14a7cfb3 | 47 | |
a9612d6c MC |
48 | #ifndef FIPS_MODE |
49 | EC_KEY *EC_KEY_new_by_curve_name(int nid) | |
50 | { | |
51 | return EC_KEY_new_by_curve_name_ex(NULL, nid); | |
52 | } | |
53 | #endif | |
54 | ||
14a7cfb3 | 55 | void EC_KEY_free(EC_KEY *r) |
0f113f3e MC |
56 | { |
57 | int i; | |
14a7cfb3 | 58 | |
0f113f3e MC |
59 | if (r == NULL) |
60 | return; | |
14a7cfb3 | 61 | |
2f545ae4 | 62 | CRYPTO_DOWN_REF(&r->references, &i, r->lock); |
f3f1cf84 | 63 | REF_PRINT_COUNT("EC_KEY", r); |
0f113f3e MC |
64 | if (i > 0) |
65 | return; | |
f3f1cf84 | 66 | REF_ASSERT_ISNT(i < 0); |
14a7cfb3 | 67 | |
0c5d725e | 68 | if (r->meth != NULL && r->meth->finish != NULL) |
0d6ff6d3 DSH |
69 | r->meth->finish(r); |
70 | ||
a9612d6c | 71 | #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) |
7c96dbcd | 72 | ENGINE_finish(r->engine); |
51966416 DSH |
73 | #endif |
74 | ||
6903e2e7 DSH |
75 | if (r->group && r->group->meth->keyfinish) |
76 | r->group->meth->keyfinish(r); | |
77 | ||
a9612d6c | 78 | #ifndef FIPS_MODE |
3aef36ff | 79 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data); |
a9612d6c | 80 | #endif |
9b398ef2 | 81 | CRYPTO_THREAD_lock_free(r->lock); |
8fdc3734 RS |
82 | EC_GROUP_free(r->group); |
83 | EC_POINT_free(r->pub_key); | |
23a1d5e9 | 84 | BN_clear_free(r->priv_key); |
14a7cfb3 | 85 | |
4b45c6e5 | 86 | OPENSSL_clear_free((void *)r, sizeof(EC_KEY)); |
0f113f3e | 87 | } |
14a7cfb3 | 88 | |
4a9a0d9b | 89 | EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src) |
0f113f3e | 90 | { |
0f113f3e MC |
91 | if (dest == NULL || src == NULL) { |
92 | ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER); | |
93 | return NULL; | |
94 | } | |
ea0392b9 | 95 | if (src->meth != dest->meth) { |
91e7bcc2 | 96 | if (dest->meth->finish != NULL) |
ea0392b9 | 97 | dest->meth->finish(dest); |
6903e2e7 DSH |
98 | if (dest->group && dest->group->meth->keyfinish) |
99 | dest->group->meth->keyfinish(dest); | |
a9612d6c | 100 | #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) |
7c96dbcd | 101 | if (ENGINE_finish(dest->engine) == 0) |
ea0392b9 DSH |
102 | return 0; |
103 | dest->engine = NULL; | |
104 | #endif | |
105 | } | |
a9612d6c | 106 | dest->libctx = src->libctx; |
0f113f3e | 107 | /* copy the parameters */ |
91e7bcc2 | 108 | if (src->group != NULL) { |
0f113f3e MC |
109 | const EC_METHOD *meth = EC_GROUP_method_of(src->group); |
110 | /* clear the old group */ | |
8fdc3734 | 111 | EC_GROUP_free(dest->group); |
a9612d6c | 112 | dest->group = EC_GROUP_new_ex(src->libctx, meth); |
0f113f3e MC |
113 | if (dest->group == NULL) |
114 | return NULL; | |
115 | if (!EC_GROUP_copy(dest->group, src->group)) | |
116 | return NULL; | |
40a8643a MC |
117 | |
118 | /* copy the public key */ | |
119 | if (src->pub_key != NULL) { | |
120 | EC_POINT_free(dest->pub_key); | |
121 | dest->pub_key = EC_POINT_new(src->group); | |
122 | if (dest->pub_key == NULL) | |
123 | return NULL; | |
124 | if (!EC_POINT_copy(dest->pub_key, src->pub_key)) | |
125 | return NULL; | |
126 | } | |
127 | /* copy the private key */ | |
128 | if (src->priv_key != NULL) { | |
129 | if (dest->priv_key == NULL) { | |
130 | dest->priv_key = BN_new(); | |
131 | if (dest->priv_key == NULL) | |
132 | return NULL; | |
133 | } | |
134 | if (!BN_copy(dest->priv_key, src->priv_key)) | |
135 | return NULL; | |
136 | if (src->group->meth->keycopy | |
137 | && src->group->meth->keycopy(dest, src) == 0) | |
0f113f3e MC |
138 | return NULL; |
139 | } | |
0f113f3e | 140 | } |
0f113f3e | 141 | |
6903e2e7 | 142 | |
0f113f3e MC |
143 | /* copy the rest */ |
144 | dest->enc_flag = src->enc_flag; | |
145 | dest->conv_form = src->conv_form; | |
146 | dest->version = src->version; | |
147 | dest->flags = src->flags; | |
a9612d6c | 148 | #ifndef FIPS_MODE |
3aef36ff RS |
149 | if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, |
150 | &dest->ex_data, &src->ex_data)) | |
151 | return NULL; | |
a9612d6c | 152 | #endif |
0f113f3e | 153 | |
ea0392b9 | 154 | if (src->meth != dest->meth) { |
a9612d6c | 155 | #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) |
91e7bcc2 DSH |
156 | if (src->engine != NULL && ENGINE_init(src->engine) == 0) |
157 | return NULL; | |
ea0392b9 DSH |
158 | dest->engine = src->engine; |
159 | #endif | |
160 | dest->meth = src->meth; | |
161 | } | |
162 | ||
91e7bcc2 DSH |
163 | if (src->meth->copy != NULL && src->meth->copy(dest, src) == 0) |
164 | return NULL; | |
ea0392b9 | 165 | |
0f113f3e MC |
166 | return dest; |
167 | } | |
14a7cfb3 | 168 | |
4a9a0d9b | 169 | EC_KEY *EC_KEY_dup(const EC_KEY *ec_key) |
0f113f3e | 170 | { |
a9612d6c | 171 | EC_KEY *ret = ec_key_new_method_int(ec_key->libctx, ec_key->engine); |
3aef36ff | 172 | |
0f113f3e MC |
173 | if (ret == NULL) |
174 | return NULL; | |
9b398ef2 | 175 | |
0f113f3e MC |
176 | if (EC_KEY_copy(ret, ec_key) == NULL) { |
177 | EC_KEY_free(ret); | |
178 | return NULL; | |
179 | } | |
180 | return ret; | |
181 | } | |
14a7cfb3 | 182 | |
e172d60d | 183 | int EC_KEY_up_ref(EC_KEY *r) |
0f113f3e | 184 | { |
9b398ef2 AG |
185 | int i; |
186 | ||
2f545ae4 | 187 | if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) |
9b398ef2 | 188 | return 0; |
f3f1cf84 RS |
189 | |
190 | REF_PRINT_COUNT("EC_KEY", r); | |
191 | REF_ASSERT_ISNT(i < 2); | |
0f113f3e MC |
192 | return ((i > 1) ? 1 : 0); |
193 | } | |
e172d60d | 194 | |
d1da335c RL |
195 | ENGINE *EC_KEY_get0_engine(const EC_KEY *eckey) |
196 | { | |
197 | return eckey->engine; | |
198 | } | |
199 | ||
14a7cfb3 | 200 | int EC_KEY_generate_key(EC_KEY *eckey) |
0f113f3e | 201 | { |
91e7bcc2 | 202 | if (eckey == NULL || eckey->group == NULL) { |
0f113f3e MC |
203 | ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); |
204 | return 0; | |
205 | } | |
91e7bcc2 | 206 | if (eckey->meth->keygen != NULL) |
5a6a1029 DSH |
207 | return eckey->meth->keygen(eckey); |
208 | ECerr(EC_F_EC_KEY_GENERATE_KEY, EC_R_OPERATION_NOT_SUPPORTED); | |
209 | return 0; | |
210 | } | |
211 | ||
212 | int ossl_ec_key_gen(EC_KEY *eckey) | |
77470e98 | 213 | { |
77470e98 DSH |
214 | return eckey->group->meth->keygen(eckey); |
215 | } | |
216 | ||
bb315ca7 SL |
217 | /* |
218 | * ECC Key generation. | |
219 | * See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates" | |
220 | * | |
221 | * Params: | |
222 | * eckey An EC key object that contains domain params. The generated keypair | |
223 | * is stored in this object. | |
224 | * Returns 1 if the keypair was generated or 0 otherwise. | |
225 | */ | |
77470e98 | 226 | int ec_key_simple_generate_key(EC_KEY *eckey) |
5a6a1029 DSH |
227 | { |
228 | int ok = 0; | |
be2e334f DSH |
229 | BIGNUM *priv_key = NULL; |
230 | const BIGNUM *order = NULL; | |
5a6a1029 | 231 | EC_POINT *pub_key = NULL; |
bb315ca7 | 232 | const EC_GROUP *group = eckey->group; |
a9612d6c MC |
233 | BN_CTX *ctx = BN_CTX_secure_new_ex(eckey->libctx); |
234 | ||
235 | if (ctx == NULL) | |
236 | goto err; | |
0f113f3e MC |
237 | |
238 | if (eckey->priv_key == NULL) { | |
bb315ca7 | 239 | priv_key = BN_secure_new(); |
0f113f3e MC |
240 | if (priv_key == NULL) |
241 | goto err; | |
242 | } else | |
243 | priv_key = eckey->priv_key; | |
244 | ||
bb315ca7 SL |
245 | /* |
246 | * Steps (1-2): Check domain parameters and security strength. | |
247 | * These steps must be done by the user. This would need to be | |
248 | * stated in the security policy. | |
249 | */ | |
250 | ||
251 | order = EC_GROUP_get0_order(group); | |
be2e334f | 252 | if (order == NULL) |
0f113f3e MC |
253 | goto err; |
254 | ||
bb315ca7 SL |
255 | /* |
256 | * Steps (3-7): priv_key = DRBG_RAND(order_n_bits) (range [1, n-1]). | |
257 | * Although this is slightly different from the standard, it is effectively | |
258 | * equivalent as it gives an unbiased result ranging from 1..n-1. It is also | |
259 | * faster as the standard needs to retry more often. Also doing | |
260 | * 1 + rand[0..n-2] would effect the way that tests feed dummy entropy into | |
261 | * rand so the simpler backward compatible method has been used here. | |
262 | */ | |
0f113f3e | 263 | do |
a9612d6c | 264 | if (!BN_priv_rand_range_ex(priv_key, order, ctx)) |
0f113f3e MC |
265 | goto err; |
266 | while (BN_is_zero(priv_key)) ; | |
267 | ||
268 | if (eckey->pub_key == NULL) { | |
bb315ca7 | 269 | pub_key = EC_POINT_new(group); |
0f113f3e MC |
270 | if (pub_key == NULL) |
271 | goto err; | |
272 | } else | |
273 | pub_key = eckey->pub_key; | |
274 | ||
bb315ca7 | 275 | /* Step (8) : pub_key = priv_key * G (where G is a point on the curve) */ |
a9612d6c | 276 | if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) |
0f113f3e MC |
277 | goto err; |
278 | ||
279 | eckey->priv_key = priv_key; | |
280 | eckey->pub_key = pub_key; | |
bb315ca7 SL |
281 | priv_key = NULL; |
282 | pub_key = NULL; | |
0f113f3e MC |
283 | |
284 | ok = 1; | |
285 | ||
bb315ca7 SL |
286 | err: |
287 | /* Step (9): If there is an error return an invalid keypair. */ | |
288 | if (!ok) { | |
289 | BN_clear(eckey->priv_key); | |
290 | if (eckey->pub_key != NULL) | |
291 | EC_POINT_set_to_infinity(group, eckey->pub_key); | |
292 | } | |
293 | ||
294 | EC_POINT_free(pub_key); | |
295 | BN_clear_free(priv_key); | |
a9612d6c | 296 | BN_CTX_free(ctx); |
77470e98 DSH |
297 | return ok; |
298 | } | |
299 | ||
300 | int ec_key_simple_generate_public_key(EC_KEY *eckey) | |
301 | { | |
bb315ca7 SL |
302 | /* |
303 | * See SP800-56AR3 5.6.1.2.2: Step (8) | |
304 | * pub_key = priv_key * G (where G is a point on the curve) | |
305 | */ | |
77470e98 DSH |
306 | return EC_POINT_mul(eckey->group, eckey->pub_key, eckey->priv_key, NULL, |
307 | NULL, NULL); | |
0f113f3e | 308 | } |
14a7cfb3 BM |
309 | |
310 | int EC_KEY_check_key(const EC_KEY *eckey) | |
77470e98 DSH |
311 | { |
312 | if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { | |
313 | ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); | |
314 | return 0; | |
315 | } | |
316 | ||
317 | if (eckey->group->meth->keycheck == NULL) { | |
318 | ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); | |
319 | return 0; | |
320 | } | |
321 | ||
322 | return eckey->group->meth->keycheck(eckey); | |
323 | } | |
324 | ||
5173cdde SL |
325 | /* |
326 | * Check the range of the EC public key. | |
327 | * See SP800-56A R3 Section 5.6.2.3.3 (Part 2) | |
328 | * i.e. | |
329 | * - If q = odd prime p: Verify that xQ and yQ are integers in the | |
7a228c39 | 330 | * interval[0, p - 1], OR |
5173cdde SL |
331 | * - If q = 2m: Verify that xQ and yQ are bit strings of length m bits. |
332 | * Returns 1 if the public key has a valid range, otherwise it returns 0. | |
333 | */ | |
334 | static int ec_key_public_range_check(BN_CTX *ctx, const EC_KEY *key) | |
335 | { | |
336 | int ret = 0; | |
337 | BIGNUM *x, *y; | |
338 | ||
339 | BN_CTX_start(ctx); | |
340 | x = BN_CTX_get(ctx); | |
341 | y = BN_CTX_get(ctx); | |
342 | if (y == NULL) | |
343 | goto err; | |
344 | ||
345 | if (!EC_POINT_get_affine_coordinates(key->group, key->pub_key, x, y, ctx)) | |
346 | goto err; | |
347 | ||
348 | if (EC_METHOD_get_field_type(key->group->meth) == NID_X9_62_prime_field) { | |
349 | if (BN_is_negative(x) | |
350 | || BN_cmp(x, key->group->field) >= 0 | |
351 | || BN_is_negative(y) | |
352 | || BN_cmp(y, key->group->field) >= 0) { | |
353 | goto err; | |
354 | } | |
355 | } else { | |
356 | int m = EC_GROUP_get_degree(key->group); | |
357 | if (BN_num_bits(x) > m || BN_num_bits(y) > m) { | |
358 | goto err; | |
359 | } | |
360 | } | |
361 | ret = 1; | |
362 | err: | |
363 | BN_CTX_end(ctx); | |
364 | return ret; | |
365 | } | |
366 | ||
367 | /* | |
368 | * ECC Key validation as specified in SP800-56A R3. | |
369 | * Section 5.6.2.3.3 ECC Full Public-Key Validation | |
370 | * Section 5.6.2.1.2 Owner Assurance of Private-Key Validity | |
371 | * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency | |
372 | * NOTES: | |
373 | * Before calling this method in fips mode, there should be an assurance that | |
374 | * an approved elliptic-curve group is used. | |
375 | * Returns 1 if the key is valid, otherwise it returns 0. | |
376 | */ | |
77470e98 | 377 | int ec_key_simple_check_key(const EC_KEY *eckey) |
0f113f3e MC |
378 | { |
379 | int ok = 0; | |
380 | BN_CTX *ctx = NULL; | |
381 | const BIGNUM *order = NULL; | |
382 | EC_POINT *point = NULL; | |
383 | ||
91e7bcc2 | 384 | if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) { |
77470e98 | 385 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER); |
0f113f3e MC |
386 | return 0; |
387 | } | |
388 | ||
5173cdde | 389 | /* 5.6.2.3.3 (Step 1): Q != infinity */ |
0f113f3e | 390 | if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) { |
77470e98 | 391 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_AT_INFINITY); |
0f113f3e MC |
392 | goto err; |
393 | } | |
394 | ||
a9612d6c | 395 | if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) |
0f113f3e | 396 | goto err; |
5173cdde | 397 | |
0f113f3e MC |
398 | if ((point = EC_POINT_new(eckey->group)) == NULL) |
399 | goto err; | |
400 | ||
5173cdde SL |
401 | /* 5.6.2.3.3 (Step 2) Test if the public key is in range */ |
402 | if (!ec_key_public_range_check(ctx, eckey)) { | |
403 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_COORDINATES_OUT_OF_RANGE); | |
404 | goto err; | |
405 | } | |
406 | ||
407 | /* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */ | |
68886be7 | 408 | if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { |
77470e98 | 409 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); |
0f113f3e MC |
410 | goto err; |
411 | } | |
5173cdde | 412 | |
0f113f3e MC |
413 | order = eckey->group->order; |
414 | if (BN_is_zero(order)) { | |
77470e98 | 415 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_GROUP_ORDER); |
0f113f3e MC |
416 | goto err; |
417 | } | |
5173cdde | 418 | /* 5.6.2.3.3 (Step 4) : pub_key * order is the point at infinity. */ |
0f113f3e | 419 | if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) { |
77470e98 | 420 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); |
0f113f3e MC |
421 | goto err; |
422 | } | |
423 | if (!EC_POINT_is_at_infinity(eckey->group, point)) { | |
77470e98 | 424 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); |
0f113f3e MC |
425 | goto err; |
426 | } | |
5173cdde | 427 | |
91e7bcc2 | 428 | if (eckey->priv_key != NULL) { |
5173cdde SL |
429 | /* |
430 | * 5.6.2.1.2 Owner Assurance of Private-Key Validity | |
431 | * The private key is in the range [1, order-1] | |
432 | */ | |
433 | if (BN_cmp(eckey->priv_key, BN_value_one()) < 0 | |
434 | || BN_cmp(eckey->priv_key, order) >= 0) { | |
77470e98 | 435 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER); |
0f113f3e MC |
436 | goto err; |
437 | } | |
5173cdde SL |
438 | /* |
439 | * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency (b) | |
440 | * Check if generator * priv_key = pub_key | |
441 | */ | |
0f113f3e MC |
442 | if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, |
443 | NULL, NULL, ctx)) { | |
77470e98 | 444 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB); |
0f113f3e MC |
445 | goto err; |
446 | } | |
447 | if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) { | |
77470e98 | 448 | ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY); |
0f113f3e MC |
449 | goto err; |
450 | } | |
451 | } | |
452 | ok = 1; | |
453 | err: | |
23a1d5e9 | 454 | BN_CTX_free(ctx); |
8fdc3734 | 455 | EC_POINT_free(point); |
77470e98 | 456 | return ok; |
0f113f3e MC |
457 | } |
458 | ||
459 | int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, | |
460 | BIGNUM *y) | |
461 | { | |
462 | BN_CTX *ctx = NULL; | |
463 | BIGNUM *tx, *ty; | |
464 | EC_POINT *point = NULL; | |
8d11b7c7 | 465 | int ok = 0; |
0f113f3e | 466 | |
91e7bcc2 | 467 | if (key == NULL || key->group == NULL || x == NULL || y == NULL) { |
0f113f3e MC |
468 | ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, |
469 | ERR_R_PASSED_NULL_PARAMETER); | |
470 | return 0; | |
471 | } | |
a9612d6c | 472 | ctx = BN_CTX_new_ex(key->libctx); |
90945fa3 | 473 | if (ctx == NULL) |
2ab851b7 | 474 | return 0; |
0f113f3e | 475 | |
2ab851b7 | 476 | BN_CTX_start(ctx); |
0f113f3e MC |
477 | point = EC_POINT_new(key->group); |
478 | ||
90945fa3 | 479 | if (point == NULL) |
0f113f3e MC |
480 | goto err; |
481 | ||
8d11b7c7 MC |
482 | tx = BN_CTX_get(ctx); |
483 | ty = BN_CTX_get(ctx); | |
dd67493c BB |
484 | if (ty == NULL) |
485 | goto err; | |
8d11b7c7 | 486 | |
9cc570d4 MC |
487 | if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx)) |
488 | goto err; | |
489 | if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx)) | |
490 | goto err; | |
0f113f3e | 491 | |
0f113f3e | 492 | /* |
5173cdde SL |
493 | * Check if retrieved coordinates match originals. The range check is done |
494 | * inside EC_KEY_check_key(). | |
0f113f3e | 495 | */ |
5173cdde | 496 | if (BN_cmp(x, tx) || BN_cmp(y, ty)) { |
0f113f3e MC |
497 | ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES, |
498 | EC_R_COORDINATES_OUT_OF_RANGE); | |
499 | goto err; | |
500 | } | |
501 | ||
502 | if (!EC_KEY_set_public_key(key, point)) | |
503 | goto err; | |
504 | ||
505 | if (EC_KEY_check_key(key) == 0) | |
506 | goto err; | |
507 | ||
508 | ok = 1; | |
509 | ||
510 | err: | |
2ab851b7 | 511 | BN_CTX_end(ctx); |
23a1d5e9 | 512 | BN_CTX_free(ctx); |
8fdc3734 | 513 | EC_POINT_free(point); |
0f113f3e MC |
514 | return ok; |
515 | ||
516 | } | |
fef1c40b | 517 | |
9dd84053 | 518 | const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) |
0f113f3e MC |
519 | { |
520 | return key->group; | |
521 | } | |
9dd84053 NL |
522 | |
523 | int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group) | |
0f113f3e | 524 | { |
91e7bcc2 | 525 | if (key->meth->set_group != NULL && key->meth->set_group(key, group) == 0) |
3475bc96 | 526 | return 0; |
8fdc3734 | 527 | EC_GROUP_free(key->group); |
0f113f3e MC |
528 | key->group = EC_GROUP_dup(group); |
529 | return (key->group == NULL) ? 0 : 1; | |
530 | } | |
9dd84053 NL |
531 | |
532 | const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key) | |
0f113f3e MC |
533 | { |
534 | return key->priv_key; | |
535 | } | |
9dd84053 NL |
536 | |
537 | int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) | |
0f113f3e | 538 | { |
6903e2e7 DSH |
539 | if (key->group == NULL || key->group->meth == NULL) |
540 | return 0; | |
acde647f KY |
541 | if (key->group->meth->set_private != NULL |
542 | && key->group->meth->set_private(key, priv_key) == 0) | |
6903e2e7 | 543 | return 0; |
91e7bcc2 DSH |
544 | if (key->meth->set_private != NULL |
545 | && key->meth->set_private(key, priv_key) == 0) | |
3475bc96 | 546 | return 0; |
23a1d5e9 | 547 | BN_clear_free(key->priv_key); |
0f113f3e MC |
548 | key->priv_key = BN_dup(priv_key); |
549 | return (key->priv_key == NULL) ? 0 : 1; | |
550 | } | |
9dd84053 NL |
551 | |
552 | const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key) | |
0f113f3e MC |
553 | { |
554 | return key->pub_key; | |
555 | } | |
9dd84053 NL |
556 | |
557 | int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key) | |
0f113f3e | 558 | { |
91e7bcc2 DSH |
559 | if (key->meth->set_public != NULL |
560 | && key->meth->set_public(key, pub_key) == 0) | |
3475bc96 | 561 | return 0; |
8fdc3734 | 562 | EC_POINT_free(key->pub_key); |
0f113f3e MC |
563 | key->pub_key = EC_POINT_dup(pub_key, key->group); |
564 | return (key->pub_key == NULL) ? 0 : 1; | |
565 | } | |
9dd84053 NL |
566 | |
567 | unsigned int EC_KEY_get_enc_flags(const EC_KEY *key) | |
0f113f3e MC |
568 | { |
569 | return key->enc_flag; | |
570 | } | |
9dd84053 NL |
571 | |
572 | void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags) | |
0f113f3e MC |
573 | { |
574 | key->enc_flag = flags; | |
575 | } | |
9dd84053 NL |
576 | |
577 | point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key) | |
0f113f3e MC |
578 | { |
579 | return key->conv_form; | |
580 | } | |
9dd84053 NL |
581 | |
582 | void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) | |
0f113f3e MC |
583 | { |
584 | key->conv_form = cform; | |
585 | if (key->group != NULL) | |
586 | EC_GROUP_set_point_conversion_form(key->group, cform); | |
587 | } | |
9dd84053 | 588 | |
9dd84053 | 589 | void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) |
0f113f3e MC |
590 | { |
591 | if (key->group != NULL) | |
592 | EC_GROUP_set_asn1_flag(key->group, flag); | |
593 | } | |
9dd84053 NL |
594 | |
595 | int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx) | |
0f113f3e MC |
596 | { |
597 | if (key->group == NULL) | |
598 | return 0; | |
599 | return EC_GROUP_precompute_mult(key->group, ctx); | |
600 | } | |
cac4fb58 DSH |
601 | |
602 | int EC_KEY_get_flags(const EC_KEY *key) | |
0f113f3e MC |
603 | { |
604 | return key->flags; | |
605 | } | |
cac4fb58 DSH |
606 | |
607 | void EC_KEY_set_flags(EC_KEY *key, int flags) | |
0f113f3e MC |
608 | { |
609 | key->flags |= flags; | |
610 | } | |
cac4fb58 DSH |
611 | |
612 | void EC_KEY_clear_flags(EC_KEY *key, int flags) | |
0f113f3e MC |
613 | { |
614 | key->flags &= ~flags; | |
615 | } | |
981bd8a2 DSH |
616 | |
617 | size_t EC_KEY_key2buf(const EC_KEY *key, point_conversion_form_t form, | |
618 | unsigned char **pbuf, BN_CTX *ctx) | |
619 | { | |
620 | if (key == NULL || key->pub_key == NULL || key->group == NULL) | |
621 | return 0; | |
622 | return EC_POINT_point2buf(key->group, key->pub_key, form, pbuf, ctx); | |
623 | } | |
624 | ||
625 | int EC_KEY_oct2key(EC_KEY *key, const unsigned char *buf, size_t len, | |
626 | BN_CTX *ctx) | |
627 | { | |
628 | if (key == NULL || key->group == NULL) | |
629 | return 0; | |
630 | if (key->pub_key == NULL) | |
631 | key->pub_key = EC_POINT_new(key->group); | |
632 | if (key->pub_key == NULL) | |
633 | return 0; | |
6ea04154 DSH |
634 | if (EC_POINT_oct2point(key->group, key->pub_key, buf, len, ctx) == 0) |
635 | return 0; | |
636 | /* | |
637 | * Save the point conversion form. | |
638 | * For non-custom curves the first octet of the buffer (excluding | |
639 | * the last significant bit) contains the point conversion form. | |
640 | * EC_POINT_oct2point() has already performed sanity checking of | |
641 | * the buffer so we know it is valid. | |
642 | */ | |
643 | if ((key->group->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) | |
644 | key->conv_form = (point_conversion_form_t)(buf[0] & ~0x01); | |
645 | return 1; | |
981bd8a2 | 646 | } |
cf241395 | 647 | |
700b8145 | 648 | size_t EC_KEY_priv2oct(const EC_KEY *eckey, |
25d57dc7 | 649 | unsigned char *buf, size_t len) |
cf241395 | 650 | { |
cf241395 DSH |
651 | if (eckey->group == NULL || eckey->group->meth == NULL) |
652 | return 0; | |
77470e98 DSH |
653 | if (eckey->group->meth->priv2oct == NULL) { |
654 | ECerr(EC_F_EC_KEY_PRIV2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); | |
655 | return 0; | |
656 | } | |
657 | ||
658 | return eckey->group->meth->priv2oct(eckey, buf, len); | |
659 | } | |
660 | ||
661 | size_t ec_key_simple_priv2oct(const EC_KEY *eckey, | |
662 | unsigned char *buf, size_t len) | |
663 | { | |
664 | size_t buf_len; | |
cf241395 | 665 | |
fe56d8e8 | 666 | buf_len = (EC_GROUP_order_bits(eckey->group) + 7) / 8; |
cf241395 DSH |
667 | if (eckey->priv_key == NULL) |
668 | return 0; | |
669 | if (buf == NULL) | |
670 | return buf_len; | |
671 | else if (len < buf_len) | |
672 | return 0; | |
673 | ||
cf241395 DSH |
674 | /* Octetstring may need leading zeros if BN is to short */ |
675 | ||
907e9500 | 676 | if (BN_bn2binpad(eckey->priv_key, buf, buf_len) == -1) { |
77470e98 | 677 | ECerr(EC_F_EC_KEY_SIMPLE_PRIV2OCT, EC_R_BUFFER_TOO_SMALL); |
cf241395 DSH |
678 | return 0; |
679 | } | |
680 | ||
cf241395 DSH |
681 | return buf_len; |
682 | } | |
683 | ||
25d57dc7 | 684 | int EC_KEY_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len) |
cf241395 DSH |
685 | { |
686 | if (eckey->group == NULL || eckey->group->meth == NULL) | |
687 | return 0; | |
77470e98 DSH |
688 | if (eckey->group->meth->oct2priv == NULL) { |
689 | ECerr(EC_F_EC_KEY_OCT2PRIV, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); | |
690 | return 0; | |
691 | } | |
692 | return eckey->group->meth->oct2priv(eckey, buf, len); | |
693 | } | |
cf241395 | 694 | |
25d57dc7 | 695 | int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len) |
77470e98 | 696 | { |
cf241395 DSH |
697 | if (eckey->priv_key == NULL) |
698 | eckey->priv_key = BN_secure_new(); | |
699 | if (eckey->priv_key == NULL) { | |
77470e98 | 700 | ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_MALLOC_FAILURE); |
cf241395 DSH |
701 | return 0; |
702 | } | |
703 | eckey->priv_key = BN_bin2bn(buf, len, eckey->priv_key); | |
704 | if (eckey->priv_key == NULL) { | |
77470e98 | 705 | ECerr(EC_F_EC_KEY_SIMPLE_OCT2PRIV, ERR_R_BN_LIB); |
cf241395 DSH |
706 | return 0; |
707 | } | |
708 | return 1; | |
709 | } | |
7fc7d1a7 DSH |
710 | |
711 | size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf) | |
712 | { | |
713 | size_t len; | |
714 | unsigned char *buf; | |
cdb10bae | 715 | |
7fc7d1a7 | 716 | len = EC_KEY_priv2oct(eckey, NULL, 0); |
afcee950 RS |
717 | if (len == 0) |
718 | return 0; | |
cdb10bae RS |
719 | if ((buf = OPENSSL_malloc(len)) == NULL) { |
720 | ECerr(EC_F_EC_KEY_PRIV2BUF, ERR_R_MALLOC_FAILURE); | |
7fc7d1a7 | 721 | return 0; |
cdb10bae | 722 | } |
7fc7d1a7 DSH |
723 | len = EC_KEY_priv2oct(eckey, buf, len); |
724 | if (len == 0) { | |
725 | OPENSSL_free(buf); | |
726 | return 0; | |
727 | } | |
728 | *pbuf = buf; | |
729 | return len; | |
730 | } | |
4b0555ec DSH |
731 | |
732 | int EC_KEY_can_sign(const EC_KEY *eckey) | |
733 | { | |
734 | if (eckey->group == NULL || eckey->group->meth == NULL | |
735 | || (eckey->group->meth->flags & EC_FLAGS_NO_SIGN)) | |
736 | return 0; | |
737 | return 1; | |
738 | } |