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