summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/gost/gostr341001_pmeth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/gost/gostr341001_pmeth.c')
-rw-r--r--src/lib/libcrypto/gost/gostr341001_pmeth.c719
1 files changed, 0 insertions, 719 deletions
diff --git a/src/lib/libcrypto/gost/gostr341001_pmeth.c b/src/lib/libcrypto/gost/gostr341001_pmeth.c
deleted file mode 100644
index 1454f3f0a2..0000000000
--- a/src/lib/libcrypto/gost/gostr341001_pmeth.c
+++ /dev/null
@@ -1,719 +0,0 @@
1/* $OpenBSD: gostr341001_pmeth.c,v 1.12 2015/02/14 15:08:37 miod 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/err.h>
60#include <openssl/gost.h>
61#include <openssl/ec.h>
62#include <openssl/ecdsa.h>
63#include <openssl/x509.h>
64
65#include "evp_locl.h"
66#include "gost_locl.h"
67#include "gost_asn1.h"
68
69static ECDSA_SIG *
70unpack_signature_cp(const unsigned char *sig, size_t siglen)
71{
72 ECDSA_SIG *s;
73
74 s = ECDSA_SIG_new();
75 if (s == NULL) {
76 GOSTerr(GOST_F_UNPACK_SIGNATURE_CP, ERR_R_MALLOC_FAILURE);
77 return NULL;
78 }
79 BN_bin2bn(sig, siglen / 2, s->s);
80 BN_bin2bn(sig + siglen / 2, siglen / 2, s->r);
81 return s;
82}
83
84static int
85pack_signature_cp(ECDSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
86{
87 int r_len = BN_num_bytes(s->r);
88 int s_len = BN_num_bytes(s->s);
89
90 if (r_len > order || s_len > order)
91 return 0;
92
93 *siglen = 2 * order;
94
95 memset(sig, 0, *siglen);
96 BN_bn2bin(s->s, sig + order - s_len);
97 BN_bn2bin(s->r, sig + 2 * order - r_len);
98 ECDSA_SIG_free(s);
99 return 1;
100}
101
102static ECDSA_SIG *
103unpack_signature_le(const unsigned char *sig, size_t siglen)
104{
105 ECDSA_SIG *s;
106
107 s = ECDSA_SIG_new();
108 if (s == NULL) {
109 GOSTerr(GOST_F_UNPACK_SIGNATURE_LE, ERR_R_MALLOC_FAILURE);
110 return NULL;
111 }
112 GOST_le2bn(sig, siglen / 2, s->r);
113 GOST_le2bn(sig + siglen / 2, siglen / 2, s->s);
114 return s;
115}
116
117static int
118pack_signature_le(ECDSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
119{
120 *siglen = 2 * order;
121 memset(sig, 0, *siglen);
122 GOST_bn2le(s->r, sig, order);
123 GOST_bn2le(s->s, sig + order, order);
124 ECDSA_SIG_free(s);
125 return 1;
126}
127
128struct gost_pmeth_data {
129 int sign_param_nid; /* Should be set whenever parameters are filled */
130 int digest_nid;
131 EVP_MD *md;
132 unsigned char *shared_ukm;
133 int peer_key_used;
134 int sig_format;
135};
136
137static int
138pkey_gost01_init(EVP_PKEY_CTX *ctx)
139{
140 struct gost_pmeth_data *data;
141 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
142
143 data = calloc(1, sizeof(struct gost_pmeth_data));
144 if (data == NULL)
145 return 0;
146
147 if (pkey != NULL && pkey->pkey.gost != NULL) {
148 data->sign_param_nid =
149 EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost));
150 data->digest_nid = GOST_KEY_get_digest(pkey->pkey.gost);
151 }
152 EVP_PKEY_CTX_set_data(ctx, data);
153 return 1;
154}
155
156/* Copies contents of gost_pmeth_data structure */
157static int
158pkey_gost01_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
159{
160 struct gost_pmeth_data *dst_data, *src_data;
161
162 if (pkey_gost01_init(dst) == 0)
163 return 0;
164
165 src_data = EVP_PKEY_CTX_get_data(src);
166 dst_data = EVP_PKEY_CTX_get_data(dst);
167 *dst_data = *src_data;
168 if (src_data->shared_ukm != NULL)
169 dst_data->shared_ukm = NULL;
170 return 1;
171}
172
173/* Frees up gost_pmeth_data structure */
174static void
175pkey_gost01_cleanup(EVP_PKEY_CTX *ctx)
176{
177 struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
178
179 free(data->shared_ukm);
180 free(data);
181}
182
183static int
184pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
185{
186 struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
187 EC_GROUP *group = NULL;
188 GOST_KEY *gost = NULL;
189 int ret = 0;
190
191 if (data->sign_param_nid == NID_undef ||
192 data->digest_nid == NID_undef) {
193 GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
194 return 0;
195 }
196
197 group = EC_GROUP_new_by_curve_name(data->sign_param_nid);
198 if (group == NULL)
199 goto done;
200
201 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
202
203 gost = GOST_KEY_new();
204 if (gost == NULL)
205 goto done;
206
207 if (GOST_KEY_set_digest(gost, data->digest_nid) == 0)
208 goto done;
209
210 if (GOST_KEY_set_group(gost, group) != 0)
211 ret = EVP_PKEY_assign_GOST(pkey, gost);
212
213done:
214 if (ret == 0)
215 GOST_KEY_free(gost);
216 EC_GROUP_free(group);
217 return ret;
218}
219
220static int
221pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
222{
223 if (pkey_gost01_paramgen(ctx, pkey) == 0)
224 return 0;
225 return gost2001_keygen(pkey->pkey.gost) != 0;
226}
227
228static int
229pkey_gost01_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
230 const unsigned char *tbs, size_t tbs_len)
231{
232 ECDSA_SIG *unpacked_sig = NULL;
233 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
234 struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
235 BIGNUM *md;
236 size_t size;
237 int ret;
238
239 if (pkey == NULL || pkey->pkey.gost == NULL)
240 return 0;
241 size = GOST_KEY_get_size(pkey->pkey.gost);
242
243 if (siglen == NULL)
244 return 0;
245 if (sig == NULL) {
246 *siglen = 2 * size;
247 return 1;
248 } else if (*siglen < 2 * size) {
249 GOSTerr(GOST_F_PKEY_GOST01_SIGN, EC_R_BUFFER_TOO_SMALL);
250 return 0;
251 }
252 if (tbs_len != 32 && tbs_len != 64) {
253 GOSTerr(GOST_F_PKEY_GOST01_SIGN, EVP_R_BAD_BLOCK_LENGTH);
254 return 0;
255 }
256 md = GOST_le2bn(tbs, tbs_len, NULL);
257 if (md == NULL)
258 return 0;
259 unpacked_sig = gost2001_do_sign(md, pkey->pkey.gost);
260 BN_free(md);
261 if (unpacked_sig == NULL) {
262 return 0;
263 }
264 switch (pctx->sig_format) {
265 case GOST_SIG_FORMAT_SR_BE:
266 ret = pack_signature_cp(unpacked_sig, size, sig, siglen);
267 break;
268 case GOST_SIG_FORMAT_RS_LE:
269 ret = pack_signature_le(unpacked_sig, size, sig, siglen);
270 break;
271 default:
272 ret = -1;
273 break;
274 }
275 if (ret <= 0)
276 ECDSA_SIG_free(unpacked_sig);
277 return ret;
278}
279
280static int
281pkey_gost01_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
282 const unsigned char *tbs, size_t tbs_len)
283{
284 int ok = 0;
285 EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
286 struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
287 ECDSA_SIG *s = NULL;
288 BIGNUM *md;
289
290 if (pub_key == NULL)
291 return 0;
292 switch (pctx->sig_format) {
293 case GOST_SIG_FORMAT_SR_BE:
294 s = unpack_signature_cp(sig, siglen);
295 break;
296 case GOST_SIG_FORMAT_RS_LE:
297 s = unpack_signature_le(sig, siglen);
298 break;
299 }
300 if (s == NULL)
301 return 0;
302 md = GOST_le2bn(tbs, tbs_len, NULL);
303 if (md == NULL)
304 goto err;
305 ok = gost2001_do_verify(md, s, pub_key->pkey.gost);
306
307err:
308 BN_free(md);
309 ECDSA_SIG_free(s);
310 return ok;
311}
312
313static int
314gost01_VKO_key(EVP_PKEY *pub_key, EVP_PKEY *priv_key, const unsigned char *ukm,
315 unsigned char *key)
316{
317 unsigned char hashbuf[128];
318 int digest_nid;
319 int ret = 0;
320 BN_CTX *ctx = BN_CTX_new();
321 BIGNUM *UKM, *X, *Y;
322
323 if (ctx == NULL)
324 return 0;
325
326 BN_CTX_start(ctx);
327 if ((UKM = BN_CTX_get(ctx)) == NULL)
328 goto err;
329 if ((X = BN_CTX_get(ctx)) == NULL)
330 goto err;
331 if ((Y = BN_CTX_get(ctx)) == NULL)
332 goto err;
333
334 GOST_le2bn(ukm, 8, UKM);
335
336 digest_nid = GOST_KEY_get_digest(priv_key->pkey.gost);
337 if (VKO_compute_key(X, Y, pub_key->pkey.gost, priv_key->pkey.gost,
338 UKM) == 0)
339 goto err;
340
341 switch (digest_nid) {
342 case NID_id_GostR3411_94_CryptoProParamSet:
343 GOST_bn2le(X, hashbuf, 32);
344 GOST_bn2le(Y, hashbuf + 32, 32);
345 GOSTR341194(hashbuf, 64, key, digest_nid);
346 ret = 1;
347 break;
348 case NID_id_tc26_gost3411_2012_256:
349 GOST_bn2le(X, hashbuf, 32);
350 GOST_bn2le(Y, hashbuf + 32, 32);
351 STREEBOG256(hashbuf, 64, key);
352 ret = 1;
353 break;
354 case NID_id_tc26_gost3411_2012_512:
355 GOST_bn2le(X, hashbuf, 64);
356 GOST_bn2le(Y, hashbuf + 64, 64);
357 STREEBOG256(hashbuf, 128, key);
358 ret = 1;
359 break;
360 default:
361 ret = -2;
362 break;
363 }
364err:
365 BN_CTX_end(ctx);
366 BN_CTX_free(ctx);
367 return ret;
368}
369
370int
371pkey_gost01_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len,
372 const unsigned char *in, size_t in_len)
373{
374 const unsigned char *p = in;
375 EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx);
376 GOST_KEY_TRANSPORT *gkt = NULL;
377 int ret = 0;
378 unsigned char wrappedKey[44];
379 unsigned char sharedKey[32];
380 EVP_PKEY *eph_key = NULL, *peerkey = NULL;
381 int nid;
382
383 if (key == NULL) {
384 *key_len = 32;
385 return 1;
386 }
387 gkt = d2i_GOST_KEY_TRANSPORT(NULL, (const unsigned char **)&p, in_len);
388 if (gkt == NULL) {
389 GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
390 GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
391 return -1;
392 }
393
394 /* If key transport structure contains public key, use it */
395 eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
396 if (eph_key != NULL) {
397 if (EVP_PKEY_derive_set_peer(pctx, eph_key) <= 0) {
398 GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
399 GOST_R_INCOMPATIBLE_PEER_KEY);
400 goto err;
401 }
402 } else {
403 /* Set control "public key from client certificate used" */
404 if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
405 NULL) <= 0) {
406 GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
407 GOST_R_CTRL_CALL_FAILED);
408 goto err;
409 }
410 }
411 peerkey = EVP_PKEY_CTX_get0_peerkey(pctx);
412 if (peerkey == NULL) {
413 GOSTerr(GOST_F_PKEY_GOST01_DECRYPT, GOST_R_NO_PEER_KEY);
414 goto err;
415 }
416
417 nid = OBJ_obj2nid(gkt->key_agreement_info->cipher);
418
419 if (gkt->key_agreement_info->eph_iv->length != 8) {
420 GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
421 GOST_R_INVALID_IV_LENGTH);
422 goto err;
423 }
424 memcpy(wrappedKey, gkt->key_agreement_info->eph_iv->data, 8);
425 if (gkt->key_info->encrypted_key->length != 32) {
426 GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
427 EVP_R_BAD_KEY_LENGTH);
428 goto err;
429 }
430 memcpy(wrappedKey + 8, gkt->key_info->encrypted_key->data, 32);
431 if (gkt->key_info->imit->length != 4) {
432 GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
433 ERR_R_INTERNAL_ERROR);
434 goto err;
435 }
436 memcpy(wrappedKey + 40, gkt->key_info->imit->data, 4);
437 if (gost01_VKO_key(peerkey, priv, wrappedKey, sharedKey) <= 0)
438 goto err;
439 if (gost_key_unwrap_crypto_pro(nid, sharedKey, wrappedKey, key) == 0) {
440 GOSTerr(GOST_F_PKEY_GOST01_DECRYPT,
441 GOST_R_ERROR_COMPUTING_SHARED_KEY);
442 goto err;
443 }
444
445 ret = 1;
446err:
447 EVP_PKEY_free(eph_key);
448 GOST_KEY_TRANSPORT_free(gkt);
449 return ret;
450}
451
452int
453pkey_gost01_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
454{
455 /*
456 * Public key of peer in the ctx field peerkey
457 * Our private key in the ctx pkey
458 * ukm is in the algorithm specific context data
459 */
460 EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx);
461 EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx);
462 struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
463
464 if (data->shared_ukm == NULL) {
465 GOSTerr(GOST_F_PKEY_GOST01_DERIVE, GOST_R_UKM_NOT_SET);
466 return 0;
467 }
468
469 if (key == NULL) {
470 *keylen = 32;
471 return 32;
472 }
473
474 if (gost01_VKO_key(peer_key, my_key, data->shared_ukm, key) <= 0)
475 return 0;
476
477 *keylen = 32;
478 return 1;
479}
480
481int
482pkey_gost01_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len,
483 const unsigned char *key, size_t key_len)
484{
485 GOST_KEY_TRANSPORT *gkt = NULL;
486 EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
487 struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
488 unsigned char ukm[8], shared_key[32], crypted_key[44];
489 int ret = 0;
490 int key_is_ephemeral;
491 EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx);
492 int nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet;
493
494 if (data->shared_ukm != NULL) {
495 memcpy(ukm, data->shared_ukm, 8);
496 } else /* if (out != NULL) */ {
497 arc4random_buf(ukm, 8);
498 }
499 /* Check for private key in the peer_key of context */
500 if (sec_key) {
501 key_is_ephemeral = 0;
502 if (GOST_KEY_get0_private_key(sec_key->pkey.gost) == 0) {
503 GOSTerr(GOST_F_PKEY_GOST01_ENCRYPT,
504 GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR);
505 goto err;
506 }
507 } else {
508 key_is_ephemeral = 1;
509 if (out != NULL) {
510 GOST_KEY *tmp_key;
511
512 sec_key = EVP_PKEY_new();
513 if (sec_key == NULL)
514 goto err;
515 tmp_key = GOST_KEY_new();
516 if (tmp_key == NULL)
517 goto err;
518 if (EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk),
519 tmp_key) == 0) {
520 GOST_KEY_free(tmp_key);
521 goto err;
522 }
523 if (EVP_PKEY_copy_parameters(sec_key, pubk) == 0)
524 goto err;
525 if (gost2001_keygen(sec_key->pkey.gost) == 0) {
526 goto err;
527 }
528 }
529 }
530
531 if (out != NULL) {
532 if (gost01_VKO_key(pubk, sec_key, ukm, shared_key) <= 0)
533 goto err;
534 gost_key_wrap_crypto_pro(nid, shared_key, ukm, key,
535 crypted_key);
536 }
537 gkt = GOST_KEY_TRANSPORT_new();
538 if (gkt == NULL)
539 goto err;
540 if (ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm, 8) == 0)
541 goto err;
542 if (ASN1_OCTET_STRING_set(gkt->key_info->imit, crypted_key + 40,
543 4) == 0)
544 goto err;
545 if (ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key, crypted_key + 8,
546 32) == 0)
547 goto err;
548 if (key_is_ephemeral) {
549 if (X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,
550 out != NULL ? sec_key : pubk) == 0) {
551 GOSTerr(GOST_F_PKEY_GOST01_ENCRYPT,
552 GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
553 goto err;
554 }
555 }
556 ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
557 gkt->key_agreement_info->cipher = OBJ_nid2obj(nid);
558 if (key_is_ephemeral)
559 EVP_PKEY_free(sec_key);
560 else {
561 /* Set control "public key from client certificate used" */
562 if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
563 NULL) <= 0) {
564 GOSTerr(GOST_F_PKEY_GOST01_ENCRYPT,
565 GOST_R_CTRL_CALL_FAILED);
566 goto err;
567 }
568 }
569 if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL)) > 0)
570 ret = 1;
571 GOST_KEY_TRANSPORT_free(gkt);
572 return ret;
573
574err:
575 if (key_is_ephemeral)
576 EVP_PKEY_free(sec_key);
577 GOST_KEY_TRANSPORT_free(gkt);
578 return -1;
579}
580
581
582static int
583pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
584{
585 struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
586
587 switch (type) {
588 case EVP_PKEY_CTRL_MD:
589 if (EVP_MD_type(p2) !=
590 GostR3410_get_md_digest(pctx->digest_nid)) {
591 GOSTerr(GOST_F_PKEY_GOST01_CTRL,
592 GOST_R_INVALID_DIGEST_TYPE);
593 return 0;
594 }
595 pctx->md = p2;
596 return 1;
597 case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
598 case EVP_PKEY_CTRL_PKCS7_DECRYPT:
599 case EVP_PKEY_CTRL_PKCS7_SIGN:
600 case EVP_PKEY_CTRL_DIGESTINIT:
601#ifndef OPENSSL_NO_CMS
602 case EVP_PKEY_CTRL_CMS_ENCRYPT:
603 case EVP_PKEY_CTRL_CMS_DECRYPT:
604 case EVP_PKEY_CTRL_CMS_SIGN:
605#endif
606 return 1;
607
608 case EVP_PKEY_CTRL_GOST_PARAMSET:
609 pctx->sign_param_nid = (int)p1;
610 return 1;
611
612 case EVP_PKEY_CTRL_SET_IV:
613 {
614 char *ukm = malloc(p1);
615
616 if (ukm == NULL) {
617 GOSTerr(GOST_F_PKEY_GOST01_CTRL,
618 ERR_R_MALLOC_FAILURE);
619 return 0;
620 }
621 memcpy(ukm, p2, p1);
622 free(pctx->shared_ukm);
623 pctx->shared_ukm = ukm;
624 return 1;
625 }
626
627 case EVP_PKEY_CTRL_PEER_KEY:
628 if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */
629 return 1;
630 if (p1 == 2) /* TLS: peer key used? */
631 return pctx->peer_key_used;
632 if (p1 == 3) /* TLS: peer key used! */
633 return (pctx->peer_key_used = 1);
634 return -2;
635 case EVP_PKEY_CTRL_GOST_SIG_FORMAT:
636 switch (p1) {
637 case GOST_SIG_FORMAT_SR_BE:
638 case GOST_SIG_FORMAT_RS_LE:
639 pctx->sig_format = p1;
640 return 1;
641 default:
642 return 0;
643 }
644 break;
645 case EVP_PKEY_CTRL_GOST_SET_DIGEST:
646 pctx->digest_nid = (int)p1;
647 return 1;
648 case EVP_PKEY_CTRL_GOST_GET_DIGEST:
649 *(int *)p2 = pctx->digest_nid;
650 return 1;
651 default:
652 return -2;
653 }
654}
655
656static int
657pkey_gost01_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
658{
659 int param_nid = NID_undef;
660 int digest_nid = NID_undef;
661
662 if (strcmp(type, "paramset") == 0) {
663 if (value == NULL)
664 return 0;
665 if (pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_GET_DIGEST, 0,
666 &digest_nid) == 0)
667 return 0;
668 if (digest_nid == NID_id_tc26_gost3411_2012_512)
669 param_nid = GostR3410_512_param_id(value);
670 else
671 param_nid = GostR3410_256_param_id(value);
672 if (param_nid == NID_undef)
673 param_nid = OBJ_txt2nid(value);
674 if (param_nid == NID_undef)
675 return 0;
676
677 return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
678 param_nid, NULL);
679 }
680 if (strcmp(type, "dgst") == 0) {
681 if (value == NULL)
682 return 0;
683 else if (strcmp(value, "gost94") == 0 ||
684 strcmp(value, "md_gost94") == 0)
685 digest_nid = NID_id_GostR3411_94_CryptoProParamSet;
686 else if (strcmp(value, "streebog256") == 0)
687 digest_nid = NID_id_tc26_gost3411_2012_256;
688 else if (strcmp(value, "streebog512") == 0)
689 digest_nid = NID_id_tc26_gost3411_2012_512;
690
691 if (digest_nid == NID_undef)
692 return 0;
693
694 return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_SET_DIGEST,
695 digest_nid, NULL);
696 }
697 return -2;
698}
699
700const EVP_PKEY_METHOD gostr01_pkey_meth = {
701 .pkey_id = EVP_PKEY_GOSTR01,
702
703 .init = pkey_gost01_init,
704 .copy = pkey_gost01_copy,
705 .cleanup = pkey_gost01_cleanup,
706
707 .paramgen = pkey_gost01_paramgen,
708 .keygen = pkey_gost01_keygen,
709 .sign = pkey_gost01_sign,
710 .verify = pkey_gost01_verify,
711
712 .encrypt = pkey_gost01_encrypt,
713 .decrypt = pkey_gost01_decrypt,
714 .derive = pkey_gost01_derive,
715
716 .ctrl = pkey_gost01_ctrl,
717 .ctrl_str = pkey_gost01_ctrl_str,
718};
719#endif