/src/opensc/openpace/src/pace_mappings.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2010-2012 Frank Morgner and Dominik Oepen |
3 | | * |
4 | | * This file is part of OpenPACE. |
5 | | * |
6 | | * OpenPACE is free software: you can redistribute it and/or modify it under |
7 | | * the terms of the GNU General Public License as published by the Free |
8 | | * Software Foundation, either version 3 of the License, or (at your option) |
9 | | * any later version. |
10 | | * |
11 | | * OpenPACE is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
13 | | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
14 | | * details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License along with |
17 | | * OpenPACE. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | * Additional permission under GNU GPL version 3 section 7 |
20 | | * |
21 | | * If you modify this Program, or any covered work, by linking or combining it |
22 | | * with OpenSSL (or a modified version of that library), containing |
23 | | * parts covered by the terms of OpenSSL's license, the licensors of |
24 | | * this Program grant you additional permission to convey the resulting work. |
25 | | * Corresponding Source for a non-source form of such a combination shall include |
26 | | * the source code for the parts of OpenSSL used as well as that of the |
27 | | * covered work. |
28 | | * |
29 | | * If you modify this Program, or any covered work, by linking or combining it |
30 | | * with OpenSC (or a modified version of that library), containing |
31 | | * parts covered by the terms of OpenSC's license, the licensors of |
32 | | * this Program grant you additional permission to convey the resulting work. |
33 | | * Corresponding Source for a non-source form of such a combination shall include |
34 | | * the source code for the parts of OpenSC used as well as that of the |
35 | | * covered work. |
36 | | */ |
37 | | |
38 | | /** |
39 | | * @file pace_mappings.c |
40 | | * @brief Functions for domain parameter mappings |
41 | | * |
42 | | * @author Frank Morgner <frankmorgner@gmail.com> |
43 | | * @author Dominik Oepen <oepen@informatik.hu-berlin.de> |
44 | | */ |
45 | | |
46 | | #ifdef HAVE_CONFIG_H |
47 | | #include "config.h" |
48 | | #endif |
49 | | |
50 | | #include "eac_dh.h" |
51 | | #include "eac_ecdh.h" |
52 | | #include "eac_err.h" |
53 | | #include "eac_util.h" |
54 | | #include "misc.h" |
55 | | #include "pace_mappings.h" |
56 | | #include "ssl_compat.h" |
57 | | #include <openssl/bn.h> |
58 | | #include <openssl/crypto.h> |
59 | | #include <openssl/ec.h> |
60 | | #include <openssl/ecdh.h> |
61 | | |
62 | | BUF_MEM * |
63 | | dh_gm_generate_key(const PACE_CTX * ctx, BN_CTX *bn_ctx) |
64 | 0 | { |
65 | 0 | check_return(ctx, "Invalid arguments"); |
66 | |
|
67 | 0 | return dh_generate_key(ctx->static_key, bn_ctx); |
68 | 0 | } |
69 | | |
70 | | int |
71 | | dh_gm_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, |
72 | | BN_CTX *bn_ctx) |
73 | 0 | { |
74 | 0 | int ret = 0; |
75 | 0 | BUF_MEM * mem_h = NULL; |
76 | 0 | BIGNUM * bn_s = NULL, *bn_h = NULL, *bn_g = NULL, *new_g = NULL; |
77 | 0 | DH *static_key = NULL, *ephemeral_key = NULL; |
78 | 0 | const BIGNUM *p, *q, *g; |
79 | |
|
80 | 0 | check(ctx && ctx->static_key && s && ctx->ka_ctx, "Invalid arguments"); |
81 | |
|
82 | 0 | BN_CTX_start(bn_ctx); |
83 | |
|
84 | 0 | static_key = EVP_PKEY_get1_DH(ctx->static_key); |
85 | 0 | if (!static_key) |
86 | 0 | goto err; |
87 | | |
88 | | /* Convert nonce to BIGNUM */ |
89 | 0 | bn_s = BN_bin2bn((unsigned char *) s->data, s->length, bn_s); |
90 | 0 | if (!bn_s) |
91 | 0 | goto err; |
92 | | |
93 | | /* complete the DH and convert the result to a BIGNUM */ |
94 | 0 | mem_h = dh_compute_key(ctx->static_key, in, bn_ctx); |
95 | 0 | if (!mem_h) |
96 | 0 | goto err; |
97 | 0 | bn_h = BN_bin2bn((unsigned char *) mem_h->data, mem_h->length, bn_h); |
98 | 0 | if (!bn_h) |
99 | 0 | goto err; |
100 | | |
101 | | /* Initialize ephemeral parameters with parameters from the static key */ |
102 | 0 | ephemeral_key = DHparams_dup(static_key); |
103 | 0 | if (!ephemeral_key) |
104 | 0 | goto err; |
105 | | |
106 | 0 | DH_get0_pqg(static_key, &p, &q, &g); |
107 | | |
108 | | /* map to new generator */ |
109 | 0 | bn_g = BN_CTX_get(bn_ctx); |
110 | 0 | new_g = BN_new(); |
111 | 0 | if (!bn_g || !new_g || |
112 | | /* bn_g = g^s mod p */ |
113 | 0 | !BN_mod_exp(bn_g, g, bn_s, p, bn_ctx) || |
114 | | /* ephemeral_key->g = bn_g * h mod p = g^s * h mod p */ |
115 | 0 | !BN_mod_mul(new_g, bn_g, bn_h, p, bn_ctx)) |
116 | 0 | goto err; |
117 | | |
118 | 0 | if (!DH_set0_pqg(ephemeral_key, BN_dup(p), BN_dup(q), new_g)) |
119 | 0 | goto err; |
120 | 0 | new_g = NULL; |
121 | | |
122 | | /* Copy ephemeral key to context structure */ |
123 | 0 | if (!EVP_PKEY_set1_DH(ctx->ka_ctx->key, ephemeral_key)) |
124 | 0 | goto err; |
125 | | |
126 | 0 | ret = 1; |
127 | |
|
128 | 0 | err: |
129 | 0 | if (mem_h) { |
130 | 0 | OPENSSL_cleanse(mem_h->data, mem_h->max); |
131 | 0 | BUF_MEM_free(mem_h); |
132 | 0 | } |
133 | 0 | if (bn_h) |
134 | 0 | BN_clear_free(bn_h); |
135 | 0 | if (bn_s) |
136 | 0 | BN_clear_free(bn_s); |
137 | | /* Decrement reference count, keys are still available via PACE_CTX */ |
138 | 0 | if (static_key) |
139 | 0 | DH_free(static_key); |
140 | 0 | if (ephemeral_key) |
141 | 0 | DH_free(ephemeral_key); |
142 | 0 | BN_CTX_end(bn_ctx); |
143 | 0 | if (new_g) |
144 | 0 | BN_clear_free(new_g); |
145 | |
|
146 | 0 | return ret; |
147 | 0 | } |
148 | | |
149 | | BUF_MEM * |
150 | | dh_im_generate_key(const PACE_CTX * ctx, BN_CTX *bn_ctx) |
151 | 0 | { |
152 | 0 | check_return((ctx && ctx->ka_ctx), "Invalid arguments"); |
153 | |
|
154 | 0 | return randb(EVP_CIPHER_key_length(ctx->ka_ctx->cipher)); |
155 | 0 | } |
156 | | |
157 | | int |
158 | | dh_im_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, |
159 | | BN_CTX *bn_ctx) |
160 | 0 | { |
161 | 0 | int ret = 0; |
162 | 0 | BUF_MEM * x_mem = NULL; |
163 | 0 | BIGNUM * x_bn = NULL, *a = NULL, *p_1 = NULL, *q = NULL, *g_new = NULL; |
164 | 0 | const BIGNUM *p, *g; |
165 | 0 | DH *static_key = NULL, *ephemeral_key = NULL; |
166 | |
|
167 | 0 | check((ctx && in && ctx->ka_ctx), "Invalid arguments"); |
168 | 0 | if (in->length < (size_t) EVP_CIPHER_key_length(ctx->ka_ctx->cipher) |
169 | 0 | || !ctx->static_key) |
170 | 0 | goto err; |
171 | | |
172 | 0 | BN_CTX_start(bn_ctx); |
173 | |
|
174 | 0 | static_key = EVP_PKEY_get1_DH(ctx->static_key); |
175 | 0 | if (!static_key) |
176 | 0 | goto err; |
177 | | |
178 | | /* Initialize ephemeral parameters with parameters from the static key */ |
179 | 0 | ephemeral_key = DHparams_dup_with_q(static_key); |
180 | 0 | if (!ephemeral_key) |
181 | 0 | goto err; |
182 | 0 | DH_get0_pqg(ephemeral_key, &p, NULL, &g); |
183 | | |
184 | | /* Perform the actual mapping */ |
185 | 0 | x_mem = cipher_no_pad(ctx->ka_ctx, NULL, in, s, 1); |
186 | 0 | if (!x_mem) |
187 | 0 | goto err; |
188 | 0 | x_bn = BN_bin2bn((unsigned char *) x_mem->data, x_mem->length, x_bn); |
189 | 0 | a = BN_CTX_get(bn_ctx); |
190 | 0 | q = DH_get_q(static_key, bn_ctx); |
191 | 0 | p_1 = BN_dup(p); |
192 | 0 | g_new = BN_dup(g); |
193 | 0 | if (!x_bn || !a || !q || !p_1 || !g_new || |
194 | | /* p_1 = p-1 */ |
195 | 0 | !BN_sub_word(p_1, 1) || |
196 | | /* a = p-1 / q */ |
197 | 0 | !BN_div(a, NULL, p_1, q, bn_ctx) || |
198 | | /* g~ = x^a mod p */ |
199 | 0 | !BN_mod_exp(g_new, x_bn, a, p, bn_ctx)) |
200 | 0 | goto err; |
201 | | |
202 | | /* check if g~ != 1 */ |
203 | 0 | check((!BN_is_one(g_new)), "Bad DH generator"); |
204 | |
|
205 | 0 | DH_set0_pqg(ephemeral_key, BN_dup(p), q, g_new); |
206 | 0 | g_new = NULL; |
207 | 0 | q = NULL; |
208 | | |
209 | | /* Copy ephemeral key to context structure */ |
210 | 0 | if (!EVP_PKEY_set1_DH(ctx->ka_ctx->key, ephemeral_key)) |
211 | 0 | goto err; |
212 | | |
213 | 0 | ret = 1; |
214 | |
|
215 | 0 | err: |
216 | 0 | if (q) |
217 | 0 | BN_clear_free(q); |
218 | 0 | if (g_new) |
219 | 0 | BN_clear_free(g_new); |
220 | 0 | if (p_1) |
221 | 0 | BN_clear_free(p_1); |
222 | 0 | if (x_bn) |
223 | 0 | BN_clear_free(x_bn); |
224 | 0 | if (x_mem) |
225 | 0 | BUF_MEM_free(x_mem); |
226 | | /* Decrement reference count, keys are still available via PACE_CTX */ |
227 | 0 | if (static_key) |
228 | 0 | DH_free(static_key); |
229 | 0 | if (ephemeral_key) |
230 | 0 | DH_free(ephemeral_key); |
231 | 0 | BN_CTX_end(bn_ctx); |
232 | |
|
233 | 0 | return ret; |
234 | 0 | } |
235 | | |
236 | | BUF_MEM * |
237 | | ecdh_gm_generate_key(const PACE_CTX * ctx, BN_CTX *bn_ctx) |
238 | 0 | { |
239 | 0 | check_return(ctx, "Invalid arguments"); |
240 | |
|
241 | 0 | return ecdh_generate_key(ctx->static_key, bn_ctx); |
242 | 0 | } |
243 | | |
244 | | int |
245 | | ecdh_gm_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, |
246 | | BN_CTX *bn_ctx) |
247 | 0 | { |
248 | 0 | int ret = 0; |
249 | 0 | BUF_MEM * mem_h = NULL; |
250 | 0 | BIGNUM * bn_s = NULL, *order = NULL, *cofactor = NULL; |
251 | 0 | EC_POINT * ecp_h = NULL, *ecp_g = NULL; |
252 | 0 | EC_GROUP *group = NULL; |
253 | 0 | EC_KEY *static_key = NULL, *ephemeral_key = NULL; |
254 | 0 | #ifdef HAVE_EC_KEY_METHOD |
255 | 0 | const EC_KEY_METHOD *default_method; |
256 | | #else |
257 | | const ECDH_METHOD *default_method; |
258 | | #endif |
259 | |
|
260 | 0 | BN_CTX_start(bn_ctx); |
261 | |
|
262 | 0 | check((ctx && ctx->static_key && s && ctx->ka_ctx), "Invalid arguments"); |
263 | |
|
264 | 0 | static_key = EVP_PKEY_get1_EC_KEY(ctx->static_key); |
265 | 0 | check(static_key, "could not get key object"); |
266 | | |
267 | | /* Extract group parameters */ |
268 | 0 | group = EC_GROUP_dup(EC_KEY_get0_group(static_key)); |
269 | 0 | order = BN_CTX_get(bn_ctx); |
270 | 0 | cofactor = BN_CTX_get(bn_ctx); |
271 | 0 | check(group && cofactor, "internal error"); |
272 | 0 | if (!EC_GROUP_get_order(group, order, bn_ctx) |
273 | 0 | || !EC_GROUP_get_cofactor(group, cofactor, bn_ctx)) |
274 | 0 | goto err; |
275 | | |
276 | | /* Convert nonce to BIGNUM */ |
277 | 0 | bn_s = BN_bin2bn((unsigned char *) s->data, s->length, bn_s); |
278 | 0 | if (!bn_s) |
279 | 0 | goto err; |
280 | | |
281 | 0 | #ifdef HAVE_EC_KEY_METHOD |
282 | 0 | default_method = EC_KEY_get_method(static_key); |
283 | 0 | if (!EC_KEY_set_method(static_key, EC_KEY_OpenSSL_Point())) |
284 | 0 | goto err; |
285 | | /* complete the ECDH and get the resulting point h */ |
286 | 0 | mem_h = ecdh_compute_key(ctx->static_key, in, bn_ctx); |
287 | 0 | EC_KEY_set_method(static_key, default_method); |
288 | | #else |
289 | | default_method = ECDH_get_default_method(); |
290 | | ECDH_set_default_method(ECDH_OpenSSL_Point()); |
291 | | /* complete the ECDH and get the resulting point h */ |
292 | | mem_h = ecdh_compute_key(ctx->static_key, in, bn_ctx); |
293 | | ECDH_set_default_method(default_method); |
294 | | #endif |
295 | 0 | ecp_h = EC_POINT_new(group); |
296 | 0 | if (!mem_h || !ecp_h || !EC_POINT_oct2point(group, ecp_h, |
297 | 0 | (unsigned char *) mem_h->data, mem_h->length, bn_ctx)) |
298 | 0 | goto err; |
299 | | |
300 | | /* map to new generator */ |
301 | 0 | ecp_g = EC_POINT_new(group); |
302 | | /* g' = g*s + h*1 */ |
303 | 0 | if (!EC_POINT_mul(group, ecp_g, bn_s, ecp_h, BN_value_one(), bn_ctx)) |
304 | 0 | goto err; |
305 | | |
306 | | /* Initialize ephemeral parameters with parameters from the static key */ |
307 | 0 | ephemeral_key = EC_KEY_dup(static_key); |
308 | 0 | if (!ephemeral_key) |
309 | 0 | goto err; |
310 | 0 | EVP_PKEY_set1_EC_KEY(ctx->ka_ctx->key, ephemeral_key); |
311 | | |
312 | | /* configure the new EC_KEY */ |
313 | 0 | if (!EC_GROUP_set_generator(group, ecp_g, order, cofactor) |
314 | 0 | || !EC_GROUP_check(group, bn_ctx) |
315 | 0 | || !EC_KEY_set_group(ephemeral_key, group)) |
316 | 0 | goto err; |
317 | | |
318 | 0 | ret = 1; |
319 | |
|
320 | 0 | err: |
321 | 0 | if (ecp_g) |
322 | 0 | EC_POINT_clear_free(ecp_g); |
323 | 0 | if (ecp_h) |
324 | 0 | EC_POINT_clear_free(ecp_h); |
325 | 0 | if (mem_h) |
326 | 0 | BUF_MEM_free(mem_h); |
327 | 0 | if (bn_s) |
328 | 0 | BN_clear_free(bn_s); |
329 | 0 | BN_CTX_end(bn_ctx); |
330 | | /* Decrement reference count, keys are still available via PACE_CTX */ |
331 | 0 | if (static_key) |
332 | 0 | EC_KEY_free(static_key); |
333 | 0 | if (ephemeral_key) |
334 | 0 | EC_KEY_free(ephemeral_key); |
335 | 0 | if (group) |
336 | 0 | EC_GROUP_clear_free(group); |
337 | |
|
338 | 0 | return ret; |
339 | 0 | } |
340 | | |
341 | | BUF_MEM * |
342 | | ecdh_im_generate_key(const PACE_CTX * ctx, BN_CTX *bn_ctx) |
343 | 0 | { |
344 | 0 | check_return((ctx && ctx->ka_ctx), "Invalid arguments"); |
345 | |
|
346 | 0 | return randb(EVP_CIPHER_key_length(ctx->ka_ctx->cipher)); |
347 | 0 | } |
348 | | |
349 | | int |
350 | | ecdh_im_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, |
351 | | BN_CTX *bn_ctx) |
352 | 0 | { |
353 | 0 | int ret = 0; |
354 | 0 | BUF_MEM * x_mem = NULL; |
355 | 0 | BIGNUM * a = NULL, *b = NULL, *p = NULL; |
356 | 0 | BIGNUM * x = NULL, *y = NULL, *v = NULL, *u = NULL; |
357 | 0 | BIGNUM * tmp = NULL, *tmp2 = NULL, *bn_inv = NULL; |
358 | 0 | BIGNUM * two = NULL, *three = NULL, *four = NULL, *six = NULL; |
359 | 0 | BIGNUM * twentyseven = NULL; |
360 | 0 | EC_KEY *static_key = NULL, *ephemeral_key = NULL; |
361 | 0 | EC_POINT *g = NULL; |
362 | |
|
363 | 0 | BN_CTX_start(bn_ctx); |
364 | |
|
365 | 0 | check((ctx && ctx->static_key && s && ctx->ka_ctx), "Invalid arguments"); |
366 | |
|
367 | 0 | static_key = EVP_PKEY_get1_EC_KEY(ctx->static_key); |
368 | 0 | if (!static_key) |
369 | 0 | goto err; |
370 | | |
371 | | /* Setup all the variables*/ |
372 | 0 | a = BN_CTX_get(bn_ctx); |
373 | 0 | b = BN_CTX_get(bn_ctx); |
374 | 0 | p = BN_CTX_get(bn_ctx); |
375 | 0 | x = BN_CTX_get(bn_ctx); |
376 | 0 | y = BN_CTX_get(bn_ctx); |
377 | 0 | v = BN_CTX_get(bn_ctx); |
378 | 0 | two = BN_CTX_get(bn_ctx); |
379 | 0 | three = BN_CTX_get(bn_ctx); |
380 | 0 | four = BN_CTX_get(bn_ctx); |
381 | 0 | six = BN_CTX_get(bn_ctx); |
382 | 0 | twentyseven = BN_CTX_get(bn_ctx); |
383 | 0 | tmp = BN_CTX_get(bn_ctx); |
384 | 0 | tmp2 = BN_CTX_get(bn_ctx); |
385 | 0 | bn_inv = BN_CTX_get(bn_ctx); |
386 | 0 | if (!bn_inv) |
387 | 0 | goto err; |
388 | | |
389 | | /* Encrypt the Nonce using the symmetric key in */ |
390 | 0 | x_mem = cipher_no_pad(ctx->ka_ctx, NULL, in, s, 1); |
391 | 0 | if (!x_mem) |
392 | 0 | goto err; |
393 | | |
394 | | /* Fetch the curve parameters */ |
395 | 0 | if (!EC_GROUP_get_curve_GFp(EC_KEY_get0_group(static_key), p, a, b, bn_ctx)) |
396 | 0 | goto err; |
397 | | |
398 | | /* Assign constants */ |
399 | 0 | if ( !BN_set_word(two,2)|| |
400 | 0 | !BN_set_word(three,3)|| |
401 | 0 | !BN_set_word(four,4)|| |
402 | 0 | !BN_set_word(six,6)|| |
403 | 0 | !BN_set_word(twentyseven,27) |
404 | 0 | ) goto err; |
405 | | |
406 | | /* Check prerequisites for curve parameters */ |
407 | 0 | check( |
408 | | /* p > 3;*/ |
409 | 0 | (BN_cmp(p, three) == 1) && |
410 | | /* p mod 3 = 2; (p has the form p=q^n, q prime) */ |
411 | 0 | BN_nnmod(tmp, p, three, bn_ctx) && |
412 | 0 | (BN_cmp(tmp, two) == 0), |
413 | 0 | "Unsuited curve"); |
414 | | |
415 | | /* Convert encrypted nonce to BIGNUM */ |
416 | 0 | u = BN_bin2bn((unsigned char *) x_mem->data, x_mem->length, u); |
417 | 0 | if (!u) |
418 | 0 | goto err; |
419 | | |
420 | 0 | if ( /* v = (3a - u^4) / 6u mod p */ |
421 | 0 | !BN_mod_mul(tmp, three, a, p, bn_ctx) || |
422 | 0 | !BN_mod_exp(tmp2, u, four, p, bn_ctx) || |
423 | 0 | !BN_mod_sub(v, tmp, tmp2, p, bn_ctx) || |
424 | 0 | !BN_mod_mul(tmp, u, six, p, bn_ctx) || |
425 | | /* For division within a galois field we need to compute |
426 | | * the multiplicative inverse of a number */ |
427 | 0 | !BN_mod_inverse(bn_inv, tmp, p, bn_ctx) || |
428 | 0 | !BN_mod_mul(v, v, bn_inv, p, bn_ctx) || |
429 | | |
430 | | /* x = (v^2 - b - ((u^6)/27)) */ |
431 | 0 | !BN_mod_sqr(tmp, v, p, bn_ctx) || |
432 | 0 | !BN_mod_sub(tmp2, tmp, b, p, bn_ctx) || |
433 | 0 | !BN_mod_exp(tmp, u, six, p, bn_ctx) || |
434 | 0 | !BN_mod_inverse(bn_inv, twentyseven, p, bn_ctx) || |
435 | 0 | !BN_mod_mul(tmp, tmp, bn_inv, p, bn_ctx) || |
436 | 0 | !BN_mod_sub(x, tmp2, tmp, p, bn_ctx) || |
437 | | |
438 | | /* x -> x^(1/3) = x^((2p^n -1)/3) */ |
439 | 0 | !BN_mul(tmp, two, p, bn_ctx) || |
440 | 0 | !BN_sub(tmp, tmp, BN_value_one()) || |
441 | | |
442 | | /* Division is defined, because p^n = 2 mod 3 */ |
443 | 0 | !BN_div(tmp, y, tmp, three, bn_ctx) || |
444 | 0 | !BN_mod_exp(tmp2, x, tmp, p, bn_ctx) || |
445 | 0 | !BN_copy(x, tmp2) || |
446 | | |
447 | | /* x += (u^2)/3 */ |
448 | 0 | !BN_mod_sqr(tmp, u, p, bn_ctx) || |
449 | 0 | !BN_mod_inverse(bn_inv, three, p, bn_ctx) || |
450 | 0 | !BN_mod_mul(tmp2, tmp, bn_inv, p, bn_ctx) || |
451 | 0 | !BN_mod_add(tmp, x, tmp2, p, bn_ctx) || |
452 | 0 | !BN_copy(x, tmp) || |
453 | | |
454 | | /* y = ux + v */ |
455 | 0 | !BN_mod_mul(y, u, x, p, bn_ctx) || |
456 | 0 | !BN_mod_add(tmp, y, v, p, bn_ctx) || |
457 | 0 | !BN_copy(y, tmp) |
458 | 0 | ) |
459 | 0 | goto err; |
460 | | |
461 | | /* Initialize ephemeral parameters with parameters from the static key */ |
462 | 0 | ephemeral_key = EC_KEY_dup(static_key); |
463 | 0 | if (!ephemeral_key) |
464 | 0 | goto err; |
465 | 0 | EVP_PKEY_set1_EC_KEY(ctx->ka_ctx->key, ephemeral_key); |
466 | | |
467 | | /* configure the new EC_KEY */ |
468 | 0 | g = EC_POINT_new(EC_KEY_get0_group(ephemeral_key)); |
469 | 0 | if (!g) |
470 | 0 | goto err; |
471 | 0 | if (!EC_POINT_set_affine_coordinates(EC_KEY_get0_group(ephemeral_key), g, |
472 | 0 | x, y, bn_ctx)) |
473 | 0 | goto err; |
474 | | |
475 | 0 | ret = 1; |
476 | |
|
477 | 0 | err: |
478 | 0 | if (x_mem) |
479 | 0 | BUF_MEM_free(x_mem); |
480 | 0 | if (u) |
481 | 0 | BN_free(u); |
482 | 0 | BN_CTX_end(bn_ctx); |
483 | 0 | if (g) |
484 | 0 | EC_POINT_clear_free(g); |
485 | | /* Decrement reference count, keys are still available via PACE_CTX */ |
486 | 0 | if (static_key) |
487 | 0 | EC_KEY_free(static_key); |
488 | 0 | if (ephemeral_key) |
489 | 0 | EC_KEY_free(ephemeral_key); |
490 | |
|
491 | 0 | return ret; |
492 | 0 | } |