diff options
Diffstat (limited to 'src/lib/libcrypto/gost/gostr341001_ameth.c')
-rw-r--r-- | src/lib/libcrypto/gost/gostr341001_ameth.c | 727 |
1 files changed, 0 insertions, 727 deletions
diff --git a/src/lib/libcrypto/gost/gostr341001_ameth.c b/src/lib/libcrypto/gost/gostr341001_ameth.c deleted file mode 100644 index e8e8c8aa82..0000000000 --- a/src/lib/libcrypto/gost/gostr341001_ameth.c +++ /dev/null | |||
@@ -1,727 +0,0 @@ | |||
1 | /* $OpenBSD: gostr341001_ameth.c,v 1.24 2024/01/04 17:01:26 tb Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | ||
4 | * Copyright (c) 2005-2006 Cryptocom LTD | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in | ||
15 | * the documentation and/or other materials provided with the | ||
16 | * distribution. | ||
17 | * | ||
18 | * 3. All advertising materials mentioning features or use of this | ||
19 | * software must display the following acknowledgment: | ||
20 | * "This product includes software developed by the OpenSSL Project | ||
21 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | ||
22 | * | ||
23 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | ||
24 | * endorse or promote products derived from this software without | ||
25 | * prior written permission. For written permission, please contact | ||
26 | * openssl-core@openssl.org. | ||
27 | * | ||
28 | * 5. Products derived from this software may not be called "OpenSSL" | ||
29 | * nor may "OpenSSL" appear in their names without prior written | ||
30 | * permission of the OpenSSL Project. | ||
31 | * | ||
32 | * 6. Redistributions of any form whatsoever must retain the following | ||
33 | * acknowledgment: | ||
34 | * "This product includes software developed by the OpenSSL Project | ||
35 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | ||
36 | * | ||
37 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | ||
38 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
39 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
40 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | ||
41 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
42 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
43 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
44 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
45 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
46 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
47 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
48 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
49 | * ==================================================================== | ||
50 | */ | ||
51 | |||
52 | #include <string.h> | ||
53 | |||
54 | #include <openssl/opensslconf.h> | ||
55 | |||
56 | #ifndef OPENSSL_NO_GOST | ||
57 | #include <openssl/bn.h> | ||
58 | #include <openssl/evp.h> | ||
59 | #include <openssl/ec.h> | ||
60 | #include <openssl/err.h> | ||
61 | #include <openssl/x509.h> | ||
62 | #include <openssl/gost.h> | ||
63 | |||
64 | |||
65 | #include "asn1_local.h" | ||
66 | #include "evp_local.h" | ||
67 | #include "gost_local.h" | ||
68 | #include "gost_asn1.h" | ||
69 | |||
70 | static void | ||
71 | pkey_free_gost01(EVP_PKEY *key) | ||
72 | { | ||
73 | GOST_KEY_free(key->pkey.gost); | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Parses GOST algorithm parameters from X509_ALGOR and | ||
78 | * modifies pkey setting NID and parameters | ||
79 | */ | ||
80 | static int | ||
81 | decode_gost01_algor_params(EVP_PKEY *pkey, const unsigned char **p, int len) | ||
82 | { | ||
83 | int param_nid = NID_undef, digest_nid = NID_undef; | ||
84 | GOST_KEY_PARAMS *gkp = NULL; | ||
85 | EC_GROUP *group; | ||
86 | GOST_KEY *ec; | ||
87 | |||
88 | gkp = d2i_GOST_KEY_PARAMS(NULL, p, len); | ||
89 | if (gkp == NULL) { | ||
90 | GOSTerror(GOST_R_BAD_PKEY_PARAMETERS_FORMAT); | ||
91 | return 0; | ||
92 | } | ||
93 | param_nid = OBJ_obj2nid(gkp->key_params); | ||
94 | digest_nid = OBJ_obj2nid(gkp->hash_params); | ||
95 | GOST_KEY_PARAMS_free(gkp); | ||
96 | |||
97 | ec = pkey->pkey.gost; | ||
98 | if (ec == NULL) { | ||
99 | ec = GOST_KEY_new(); | ||
100 | if (ec == NULL) { | ||
101 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
102 | return 0; | ||
103 | } | ||
104 | if (EVP_PKEY_assign_GOST(pkey, ec) == 0) { | ||
105 | GOST_KEY_free(ec); | ||
106 | return 0; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | group = EC_GROUP_new_by_curve_name(param_nid); | ||
111 | if (group == NULL) { | ||
112 | GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); | ||
113 | return 0; | ||
114 | } | ||
115 | EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); | ||
116 | if (GOST_KEY_set_group(ec, group) == 0) { | ||
117 | EC_GROUP_free(group); | ||
118 | return 0; | ||
119 | } | ||
120 | EC_GROUP_free(group); | ||
121 | if (GOST_KEY_set_digest(ec, digest_nid) == 0) | ||
122 | return 0; | ||
123 | return 1; | ||
124 | } | ||
125 | |||
126 | static ASN1_STRING * | ||
127 | encode_gost01_algor_params(const EVP_PKEY *key) | ||
128 | { | ||
129 | ASN1_STRING *params = ASN1_STRING_new(); | ||
130 | GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new(); | ||
131 | int pkey_param_nid = NID_undef; | ||
132 | |||
133 | if (params == NULL || gkp == NULL) { | ||
134 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
135 | ASN1_STRING_free(params); | ||
136 | params = NULL; | ||
137 | goto err; | ||
138 | } | ||
139 | |||
140 | pkey_param_nid = | ||
141 | EC_GROUP_get_curve_name(GOST_KEY_get0_group(key->pkey.gost)); | ||
142 | gkp->key_params = OBJ_nid2obj(pkey_param_nid); | ||
143 | gkp->hash_params = OBJ_nid2obj(GOST_KEY_get_digest(key->pkey.gost)); | ||
144 | /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */ | ||
145 | params->length = i2d_GOST_KEY_PARAMS(gkp, ¶ms->data); | ||
146 | if (params->length <= 0) { | ||
147 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
148 | ASN1_STRING_free(params); | ||
149 | params = NULL; | ||
150 | goto err; | ||
151 | } | ||
152 | params->type = V_ASN1_SEQUENCE; | ||
153 | err: | ||
154 | GOST_KEY_PARAMS_free(gkp); | ||
155 | return params; | ||
156 | } | ||
157 | |||
158 | static int | ||
159 | pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) | ||
160 | { | ||
161 | const GOST_KEY *ea = a->pkey.gost; | ||
162 | const GOST_KEY *eb = b->pkey.gost; | ||
163 | const EC_POINT *ka, *kb; | ||
164 | int ret = 0; | ||
165 | |||
166 | if (ea == NULL || eb == NULL) | ||
167 | return 0; | ||
168 | ka = GOST_KEY_get0_public_key(ea); | ||
169 | kb = GOST_KEY_get0_public_key(eb); | ||
170 | if (ka == NULL || kb == NULL) | ||
171 | return 0; | ||
172 | ret = (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea), ka, kb, NULL)); | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | static int | ||
177 | pkey_size_gost01(const EVP_PKEY *pk) | ||
178 | { | ||
179 | if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512) | ||
180 | return 128; | ||
181 | return 64; | ||
182 | } | ||
183 | |||
184 | static int | ||
185 | pkey_bits_gost01(const EVP_PKEY *pk) | ||
186 | { | ||
187 | if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512) | ||
188 | return 512; | ||
189 | return 256; | ||
190 | } | ||
191 | |||
192 | static int | ||
193 | pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub) | ||
194 | { | ||
195 | X509_ALGOR *palg = NULL; | ||
196 | const unsigned char *pubkey_buf = NULL; | ||
197 | const unsigned char *p; | ||
198 | ASN1_OBJECT *palgobj = NULL; | ||
199 | int pub_len; | ||
200 | BIGNUM *X, *Y; | ||
201 | ASN1_OCTET_STRING *octet = NULL; | ||
202 | int len; | ||
203 | int ret; | ||
204 | int ptype = V_ASN1_UNDEF; | ||
205 | ASN1_STRING *pval = NULL; | ||
206 | |||
207 | if (X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub) | ||
208 | == 0) | ||
209 | return 0; | ||
210 | /* Called for the side effect of freeing pk->pkey. */ | ||
211 | if (!EVP_PKEY_set_type(pk, EVP_PKEY_GOSTR01)) | ||
212 | return 0; | ||
213 | X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg); | ||
214 | if (ptype != V_ASN1_SEQUENCE) { | ||
215 | GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT); | ||
216 | return 0; | ||
217 | } | ||
218 | p = pval->data; | ||
219 | if (decode_gost01_algor_params(pk, &p, pval->length) == 0) { | ||
220 | GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT); | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len); | ||
225 | if (octet == NULL) { | ||
226 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
227 | return 0; | ||
228 | } | ||
229 | len = octet->length / 2; | ||
230 | |||
231 | X = GOST_le2bn(octet->data, len, NULL); | ||
232 | Y = GOST_le2bn(octet->data + len, len, NULL); | ||
233 | |||
234 | ASN1_OCTET_STRING_free(octet); | ||
235 | |||
236 | ret = GOST_KEY_set_public_key_affine_coordinates(pk->pkey.gost, X, Y); | ||
237 | if (ret == 0) | ||
238 | GOSTerror(ERR_R_EC_LIB); | ||
239 | |||
240 | BN_free(X); | ||
241 | BN_free(Y); | ||
242 | |||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | static int | ||
247 | pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk) | ||
248 | { | ||
249 | ASN1_OBJECT *algobj = NULL; | ||
250 | ASN1_OCTET_STRING *octet = NULL; | ||
251 | ASN1_STRING *params = NULL; | ||
252 | void *pval = NULL; | ||
253 | unsigned char *buf = NULL, *sptr; | ||
254 | int key_size, ret = 0; | ||
255 | const EC_POINT *pub_key; | ||
256 | BIGNUM *X = NULL, *Y = NULL; | ||
257 | const GOST_KEY *ec = pk->pkey.gost; | ||
258 | int ptype = V_ASN1_UNDEF; | ||
259 | |||
260 | algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec))); | ||
261 | if (pk->save_parameters) { | ||
262 | params = encode_gost01_algor_params(pk); | ||
263 | if (params == NULL) | ||
264 | return 0; | ||
265 | pval = params; | ||
266 | ptype = V_ASN1_SEQUENCE; | ||
267 | } | ||
268 | |||
269 | key_size = GOST_KEY_get_size(ec); | ||
270 | |||
271 | pub_key = GOST_KEY_get0_public_key(ec); | ||
272 | if (pub_key == NULL) { | ||
273 | GOSTerror(GOST_R_PUBLIC_KEY_UNDEFINED); | ||
274 | goto err; | ||
275 | } | ||
276 | |||
277 | octet = ASN1_OCTET_STRING_new(); | ||
278 | if (octet == NULL) { | ||
279 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
280 | goto err; | ||
281 | } | ||
282 | |||
283 | ret = ASN1_STRING_set(octet, NULL, 2 * key_size); | ||
284 | if (ret == 0) { | ||
285 | GOSTerror(ERR_R_INTERNAL_ERROR); | ||
286 | goto err; | ||
287 | } | ||
288 | |||
289 | sptr = ASN1_STRING_data(octet); | ||
290 | |||
291 | X = BN_new(); | ||
292 | Y = BN_new(); | ||
293 | if (X == NULL || Y == NULL) { | ||
294 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
295 | goto err; | ||
296 | } | ||
297 | |||
298 | if (EC_POINT_get_affine_coordinates(GOST_KEY_get0_group(ec), | ||
299 | pub_key, X, Y, NULL) == 0) { | ||
300 | GOSTerror(ERR_R_EC_LIB); | ||
301 | goto err; | ||
302 | } | ||
303 | |||
304 | GOST_bn2le(X, sptr, key_size); | ||
305 | GOST_bn2le(Y, sptr + key_size, key_size); | ||
306 | |||
307 | BN_free(Y); | ||
308 | BN_free(X); | ||
309 | |||
310 | ret = i2d_ASN1_OCTET_STRING(octet, &buf); | ||
311 | ASN1_BIT_STRING_free(octet); | ||
312 | if (ret < 0) | ||
313 | return 0; | ||
314 | |||
315 | return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret); | ||
316 | |||
317 | err: | ||
318 | BN_free(Y); | ||
319 | BN_free(X); | ||
320 | ASN1_BIT_STRING_free(octet); | ||
321 | ASN1_STRING_free(params); | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int | ||
326 | param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) | ||
327 | { | ||
328 | int param_nid = | ||
329 | EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost)); | ||
330 | |||
331 | if (BIO_indent(out, indent, 128) == 0) | ||
332 | return 0; | ||
333 | BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid)); | ||
334 | if (BIO_indent(out, indent, 128) == 0) | ||
335 | return 0; | ||
336 | BIO_printf(out, "Digest Algorithm: %s\n", | ||
337 | OBJ_nid2ln(GOST_KEY_get_digest(pkey->pkey.gost))); | ||
338 | return 1; | ||
339 | } | ||
340 | |||
341 | static int | ||
342 | pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) | ||
343 | { | ||
344 | BN_CTX *ctx = BN_CTX_new(); | ||
345 | BIGNUM *X, *Y; | ||
346 | const EC_POINT *pubkey; | ||
347 | const EC_GROUP *group; | ||
348 | |||
349 | if (ctx == NULL) { | ||
350 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
351 | return 0; | ||
352 | } | ||
353 | BN_CTX_start(ctx); | ||
354 | if ((X = BN_CTX_get(ctx)) == NULL) | ||
355 | goto err; | ||
356 | if ((Y = BN_CTX_get(ctx)) == NULL) | ||
357 | goto err; | ||
358 | pubkey = GOST_KEY_get0_public_key(pkey->pkey.gost); | ||
359 | group = GOST_KEY_get0_group(pkey->pkey.gost); | ||
360 | if (EC_POINT_get_affine_coordinates(group, pubkey, X, Y, ctx) == 0) { | ||
361 | GOSTerror(ERR_R_EC_LIB); | ||
362 | goto err; | ||
363 | } | ||
364 | if (BIO_indent(out, indent, 128) == 0) | ||
365 | goto err; | ||
366 | BIO_printf(out, "Public key:\n"); | ||
367 | if (BIO_indent(out, indent + 3, 128) == 0) | ||
368 | goto err; | ||
369 | BIO_printf(out, "X:"); | ||
370 | BN_print(out, X); | ||
371 | BIO_printf(out, "\n"); | ||
372 | if (BIO_indent(out, indent + 3, 128) == 0) | ||
373 | goto err; | ||
374 | BIO_printf(out, "Y:"); | ||
375 | BN_print(out, Y); | ||
376 | BIO_printf(out, "\n"); | ||
377 | |||
378 | BN_CTX_end(ctx); | ||
379 | BN_CTX_free(ctx); | ||
380 | |||
381 | return param_print_gost01(out, pkey, indent, pctx); | ||
382 | |||
383 | err: | ||
384 | BN_CTX_end(ctx); | ||
385 | BN_CTX_free(ctx); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static int | ||
390 | priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) | ||
391 | { | ||
392 | const BIGNUM *key; | ||
393 | |||
394 | if (BIO_indent(out, indent, 128) == 0) | ||
395 | return 0; | ||
396 | BIO_printf(out, "Private key: "); | ||
397 | key = GOST_KEY_get0_private_key(pkey->pkey.gost); | ||
398 | if (key == NULL) | ||
399 | BIO_printf(out, "<undefined)"); | ||
400 | else | ||
401 | BN_print(out, key); | ||
402 | BIO_printf(out, "\n"); | ||
403 | |||
404 | return pub_print_gost01(out, pkey, indent, pctx); | ||
405 | } | ||
406 | |||
407 | static int | ||
408 | priv_decode_gost01(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf) | ||
409 | { | ||
410 | const unsigned char *pkey_buf = NULL, *p = NULL; | ||
411 | int priv_len = 0; | ||
412 | BIGNUM *pk_num = NULL; | ||
413 | int ret = 0; | ||
414 | const X509_ALGOR *palg = NULL; | ||
415 | const ASN1_OBJECT *palg_obj = NULL; | ||
416 | ASN1_INTEGER *priv_key = NULL; | ||
417 | GOST_KEY *ec; | ||
418 | int ptype = V_ASN1_UNDEF; | ||
419 | ASN1_STRING *pval = NULL; | ||
420 | |||
421 | if (PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf) == 0) { | ||
422 | GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT); | ||
423 | return 0; | ||
424 | } | ||
425 | /* Called for the side effect of freeing pk->pkey. */ | ||
426 | if (!EVP_PKEY_set_type(pk, EVP_PKEY_GOSTR01)) | ||
427 | return 0; | ||
428 | X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg); | ||
429 | if (ptype != V_ASN1_SEQUENCE) { | ||
430 | GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT); | ||
431 | return 0; | ||
432 | } | ||
433 | p = pval->data; | ||
434 | if (decode_gost01_algor_params(pk, &p, pval->length) == 0) { | ||
435 | GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT); | ||
436 | return 0; | ||
437 | } | ||
438 | p = pkey_buf; | ||
439 | if (V_ASN1_OCTET_STRING == *p) { | ||
440 | /* New format - Little endian octet string */ | ||
441 | ASN1_OCTET_STRING *s = | ||
442 | d2i_ASN1_OCTET_STRING(NULL, &p, priv_len); | ||
443 | |||
444 | if (s == NULL) { | ||
445 | GOSTerror(EVP_R_DECODE_ERROR); | ||
446 | ASN1_STRING_free(s); | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | pk_num = GOST_le2bn(s->data, s->length, NULL); | ||
451 | ASN1_STRING_free(s); | ||
452 | } else { | ||
453 | priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len); | ||
454 | if (priv_key == NULL) | ||
455 | return 0; | ||
456 | ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL); | ||
457 | ASN1_INTEGER_free(priv_key); | ||
458 | if (ret == 0) { | ||
459 | GOSTerror(EVP_R_DECODE_ERROR); | ||
460 | return 0; | ||
461 | } | ||
462 | } | ||
463 | |||
464 | ec = pk->pkey.gost; | ||
465 | if (ec == NULL) { | ||
466 | ec = GOST_KEY_new(); | ||
467 | if (ec == NULL) { | ||
468 | BN_free(pk_num); | ||
469 | return 0; | ||
470 | } | ||
471 | if (EVP_PKEY_assign_GOST(pk, ec) == 0) { | ||
472 | BN_free(pk_num); | ||
473 | GOST_KEY_free(ec); | ||
474 | return 0; | ||
475 | } | ||
476 | } | ||
477 | if (GOST_KEY_set_private_key(ec, pk_num) == 0) { | ||
478 | BN_free(pk_num); | ||
479 | return 0; | ||
480 | } | ||
481 | ret = 0; | ||
482 | if (EVP_PKEY_missing_parameters(pk) == 0) | ||
483 | ret = gost2001_compute_public(ec) != 0; | ||
484 | BN_free(pk_num); | ||
485 | |||
486 | return ret; | ||
487 | } | ||
488 | |||
489 | static int | ||
490 | priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk) | ||
491 | { | ||
492 | ASN1_OBJECT *algobj = | ||
493 | OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost))); | ||
494 | ASN1_STRING *params = encode_gost01_algor_params(pk); | ||
495 | unsigned char *priv_buf = NULL; | ||
496 | int priv_len; | ||
497 | ASN1_INTEGER *asn1key = NULL; | ||
498 | |||
499 | if (params == NULL) | ||
500 | return 0; | ||
501 | |||
502 | asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost), | ||
503 | NULL); | ||
504 | if (asn1key == NULL) { | ||
505 | ASN1_STRING_free(params); | ||
506 | return 0; | ||
507 | } | ||
508 | priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf); | ||
509 | ASN1_INTEGER_free(asn1key); | ||
510 | return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf, | ||
511 | priv_len); | ||
512 | } | ||
513 | |||
514 | static int | ||
515 | param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder) | ||
516 | { | ||
517 | ASN1_STRING *params = encode_gost01_algor_params(pkey); | ||
518 | int len; | ||
519 | |||
520 | if (params == NULL) | ||
521 | return 0; | ||
522 | len = params->length; | ||
523 | if (pder != NULL) | ||
524 | memcpy(*pder, params->data, params->length); | ||
525 | ASN1_STRING_free(params); | ||
526 | return len; | ||
527 | } | ||
528 | |||
529 | static int | ||
530 | param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen) | ||
531 | { | ||
532 | ASN1_OBJECT *obj = NULL; | ||
533 | int nid; | ||
534 | GOST_KEY *ec; | ||
535 | EC_GROUP *group; | ||
536 | int ret; | ||
537 | |||
538 | /* New format */ | ||
539 | if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder) | ||
540 | return decode_gost01_algor_params(pkey, pder, derlen); | ||
541 | |||
542 | /* Compatibility */ | ||
543 | if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) { | ||
544 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
545 | return 0; | ||
546 | } | ||
547 | nid = OBJ_obj2nid(obj); | ||
548 | ASN1_OBJECT_free(obj); | ||
549 | |||
550 | ec = GOST_KEY_new(); | ||
551 | if (ec == NULL) { | ||
552 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
553 | return 0; | ||
554 | } | ||
555 | group = EC_GROUP_new_by_curve_name(nid); | ||
556 | if (group == NULL) { | ||
557 | GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); | ||
558 | GOST_KEY_free(ec); | ||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); | ||
563 | if (GOST_KEY_set_group(ec, group) == 0) { | ||
564 | GOSTerror(ERR_R_EC_LIB); | ||
565 | EC_GROUP_free(group); | ||
566 | GOST_KEY_free(ec); | ||
567 | return 0; | ||
568 | } | ||
569 | EC_GROUP_free(group); | ||
570 | if (GOST_KEY_set_digest(ec, | ||
571 | NID_id_GostR3411_94_CryptoProParamSet) == 0) { | ||
572 | GOSTerror(GOST_R_INVALID_DIGEST_TYPE); | ||
573 | GOST_KEY_free(ec); | ||
574 | return 0; | ||
575 | } | ||
576 | ret = EVP_PKEY_assign_GOST(pkey, ec); | ||
577 | if (ret == 0) | ||
578 | GOST_KEY_free(ec); | ||
579 | return ret; | ||
580 | } | ||
581 | |||
582 | static int | ||
583 | param_missing_gost01(const EVP_PKEY *pk) | ||
584 | { | ||
585 | const GOST_KEY *ec = pk->pkey.gost; | ||
586 | |||
587 | if (ec == NULL) | ||
588 | return 1; | ||
589 | if (GOST_KEY_get0_group(ec) == NULL) | ||
590 | return 1; | ||
591 | if (GOST_KEY_get_digest(ec) == NID_undef) | ||
592 | return 1; | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int | ||
597 | param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) | ||
598 | { | ||
599 | GOST_KEY *eto = to->pkey.gost; | ||
600 | const GOST_KEY *efrom = from->pkey.gost; | ||
601 | int ret = 1; | ||
602 | |||
603 | if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) { | ||
604 | GOSTerror(GOST_R_INCOMPATIBLE_ALGORITHMS); | ||
605 | return 0; | ||
606 | } | ||
607 | if (efrom == NULL) { | ||
608 | GOSTerror(GOST_R_KEY_PARAMETERS_MISSING); | ||
609 | return 0; | ||
610 | } | ||
611 | if (eto == NULL) { | ||
612 | eto = GOST_KEY_new(); | ||
613 | if (eto == NULL) { | ||
614 | GOSTerror(ERR_R_MALLOC_FAILURE); | ||
615 | return 0; | ||
616 | } | ||
617 | if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) { | ||
618 | GOST_KEY_free(eto); | ||
619 | return 0; | ||
620 | } | ||
621 | } | ||
622 | GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom)); | ||
623 | GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom)); | ||
624 | if (GOST_KEY_get0_private_key(eto) != NULL) | ||
625 | ret = gost2001_compute_public(eto); | ||
626 | |||
627 | return ret; | ||
628 | } | ||
629 | |||
630 | static int | ||
631 | param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) | ||
632 | { | ||
633 | if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) != | ||
634 | EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost))) | ||
635 | return 0; | ||
636 | |||
637 | if (GOST_KEY_get_digest(a->pkey.gost) != | ||
638 | GOST_KEY_get_digest(b->pkey.gost)) | ||
639 | return 0; | ||
640 | |||
641 | return 1; | ||
642 | } | ||
643 | |||
644 | static int | ||
645 | pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2) | ||
646 | { | ||
647 | X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL; | ||
648 | int digest = GOST_KEY_get_digest(pkey->pkey.gost); | ||
649 | |||
650 | switch (op) { | ||
651 | case ASN1_PKEY_CTRL_PKCS7_SIGN: | ||
652 | if (arg1 == 0) | ||
653 | PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); | ||
654 | break; | ||
655 | |||
656 | case ASN1_PKEY_CTRL_PKCS7_ENCRYPT: | ||
657 | if (arg1 == 0) | ||
658 | PKCS7_RECIP_INFO_get0_alg(arg2, &alg3); | ||
659 | break; | ||
660 | case ASN1_PKEY_CTRL_DEFAULT_MD_NID: | ||
661 | *(int *)arg2 = GostR3410_get_md_digest(digest); | ||
662 | return 2; | ||
663 | |||
664 | default: | ||
665 | return -2; | ||
666 | } | ||
667 | |||
668 | if (alg1) | ||
669 | X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0); | ||
670 | if (alg2) | ||
671 | X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0); | ||
672 | if (alg3) { | ||
673 | ASN1_STRING *params = encode_gost01_algor_params(pkey); | ||
674 | if (params == NULL) { | ||
675 | return -1; | ||
676 | } | ||
677 | X509_ALGOR_set0(alg3, | ||
678 | OBJ_nid2obj(GostR3410_get_pk_digest(digest)), | ||
679 | V_ASN1_SEQUENCE, params); | ||
680 | } | ||
681 | |||
682 | return 1; | ||
683 | } | ||
684 | |||
685 | const EVP_PKEY_ASN1_METHOD gostr01_asn1_meth = { | ||
686 | .base_method = &gostr01_asn1_meth, | ||
687 | .pkey_id = EVP_PKEY_GOSTR01, | ||
688 | .pkey_flags = ASN1_PKEY_SIGPARAM_NULL, | ||
689 | |||
690 | .pem_str = "GOST2001", | ||
691 | .info = "GOST R 34.10-2001", | ||
692 | |||
693 | .pkey_free = pkey_free_gost01, | ||
694 | .pkey_ctrl = pkey_ctrl_gost01, | ||
695 | |||
696 | .priv_decode = priv_decode_gost01, | ||
697 | .priv_encode = priv_encode_gost01, | ||
698 | .priv_print = priv_print_gost01, | ||
699 | |||
700 | .param_decode = param_decode_gost01, | ||
701 | .param_encode = param_encode_gost01, | ||
702 | .param_missing = param_missing_gost01, | ||
703 | .param_copy = param_copy_gost01, | ||
704 | .param_cmp = param_cmp_gost01, | ||
705 | .param_print = param_print_gost01, | ||
706 | |||
707 | .pub_decode = pub_decode_gost01, | ||
708 | .pub_encode = pub_encode_gost01, | ||
709 | .pub_cmp = pub_cmp_gost01, | ||
710 | .pub_print = pub_print_gost01, | ||
711 | .pkey_size = pkey_size_gost01, | ||
712 | .pkey_bits = pkey_bits_gost01, | ||
713 | }; | ||
714 | |||
715 | const EVP_PKEY_ASN1_METHOD gostr12_256_asn1_meth = { | ||
716 | .base_method = &gostr01_asn1_meth, | ||
717 | .pkey_id = EVP_PKEY_GOSTR12_256, | ||
718 | .pkey_flags = ASN1_PKEY_ALIAS, | ||
719 | }; | ||
720 | |||
721 | const EVP_PKEY_ASN1_METHOD gostr12_512_asn1_meth = { | ||
722 | .base_method = &gostr01_asn1_meth, | ||
723 | .pkey_id = EVP_PKEY_GOSTR12_512, | ||
724 | .pkey_flags = ASN1_PKEY_ALIAS, | ||
725 | }; | ||
726 | |||
727 | #endif | ||