1 /* $OpenBSD: gostr341001_pmeth.c,v 1.11 2015/02/14 06:40:04 jsing 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 69 static ECDSA_SIG * 70 unpack_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 84 static int 85 pack_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 102 static ECDSA_SIG * 103 unpack_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 117 static int 118 pack_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 128 struct 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 137 static int 138 pkey_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 */ 157 static int 158 pkey_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 */ 174 static void 175 pkey_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 183 static int 184 pkey_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 213 done: 214 if (ret == 0) 215 GOST_KEY_free(gost); 216 EC_GROUP_free(group); 217 return ret; 218 } 219 220 static int 221 pkey_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 228 static int 229 pkey_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 280 static int 281 pkey_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 307 err: 308 BN_free(md); 309 ECDSA_SIG_free(s); 310 return ok; 311 } 312 313 static int 314 gost01_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 } 364 err: 365 BN_CTX_end(ctx); 366 BN_CTX_free(ctx); 367 return ret; 368 } 369 370 int 371 pkey_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; 446 err: 447 EVP_PKEY_free(eph_key); 448 GOST_KEY_TRANSPORT_free(gkt); 449 return ret; 450 } 451 452 int 453 pkey_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 481 int 482 pkey_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 574 err: 575 if (key_is_ephemeral) 576 EVP_PKEY_free(sec_key); 577 GOST_KEY_TRANSPORT_free(gkt); 578 return -1; 579 } 580 581 582 static int 583 pkey_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 656 static int 657 pkey_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 700 const 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 720