gost_pmeth.c revision 306195
1/********************************************************************** 2 * gost_pmeth.c * 3 * Copyright (c) 2005-2006 Cryptocom LTD * 4 * This file is distributed under the same license as OpenSSL * 5 * * 6 * Implementation of RFC 4357 (GOST R 34.10) Publick key method * 7 * for OpenSSL * 8 * Requires OpenSSL 0.9.9 for compilation * 9 **********************************************************************/ 10#include <openssl/evp.h> 11#include <openssl/objects.h> 12#include <openssl/ec.h> 13#include <openssl/x509v3.h> /* For string_to_hex */ 14#include <stdlib.h> 15#include <string.h> 16#include <ctype.h> 17#include "gost_params.h" 18#include "gost_lcl.h" 19#include "e_gost_err.h" 20/* -----init, cleanup, copy - uniform for all algs ---------------*/ 21/* Allocates new gost_pmeth_data structure and assigns it as data */ 22static int pkey_gost_init(EVP_PKEY_CTX *ctx) 23{ 24 struct gost_pmeth_data *data; 25 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); 26 data = OPENSSL_malloc(sizeof(struct gost_pmeth_data)); 27 if (!data) 28 return 0; 29 memset(data, 0, sizeof(struct gost_pmeth_data)); 30 if (pkey && EVP_PKEY_get0(pkey)) { 31 switch (EVP_PKEY_base_id(pkey)) { 32 case NID_id_GostR3410_94: 33 data->sign_param_nid = gost94_nid_by_params(EVP_PKEY_get0(pkey)); 34 break; 35 case NID_id_GostR3410_2001: 36 data->sign_param_nid = 37 EC_GROUP_get_curve_name(EC_KEY_get0_group 38 (EVP_PKEY_get0((EVP_PKEY *)pkey))); 39 break; 40 default: 41 return 0; 42 } 43 } 44 EVP_PKEY_CTX_set_data(ctx, data); 45 return 1; 46} 47 48/* Copies contents of gost_pmeth_data structure */ 49static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 50{ 51 struct gost_pmeth_data *dst_data, *src_data; 52 if (!pkey_gost_init(dst)) { 53 return 0; 54 } 55 src_data = EVP_PKEY_CTX_get_data(src); 56 dst_data = EVP_PKEY_CTX_get_data(dst); 57 *dst_data = *src_data; 58 if (src_data->shared_ukm) { 59 dst_data->shared_ukm = NULL; 60 } 61 return 1; 62} 63 64/* Frees up gost_pmeth_data structure */ 65static void pkey_gost_cleanup(EVP_PKEY_CTX *ctx) 66{ 67 struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); 68 if (data->shared_ukm) 69 OPENSSL_free(data->shared_ukm); 70 OPENSSL_free(data); 71} 72 73/* --------------------- control functions ------------------------------*/ 74static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 75{ 76 struct gost_pmeth_data *pctx = 77 (struct gost_pmeth_data *)EVP_PKEY_CTX_get_data(ctx); 78 switch (type) { 79 case EVP_PKEY_CTRL_MD: 80 { 81 if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94) { 82 GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE); 83 return 0; 84 } 85 pctx->md = (EVP_MD *)p2; 86 return 1; 87 } 88 break; 89 90 case EVP_PKEY_CTRL_GET_MD: 91 *(const EVP_MD **)p2 = pctx->md; 92 return 1; 93 94 case EVP_PKEY_CTRL_PKCS7_ENCRYPT: 95 case EVP_PKEY_CTRL_PKCS7_DECRYPT: 96 case EVP_PKEY_CTRL_PKCS7_SIGN: 97 case EVP_PKEY_CTRL_DIGESTINIT: 98#ifndef OPENSSL_NO_CMS 99 case EVP_PKEY_CTRL_CMS_ENCRYPT: 100 case EVP_PKEY_CTRL_CMS_DECRYPT: 101 case EVP_PKEY_CTRL_CMS_SIGN: 102#endif 103 return 1; 104 105 case EVP_PKEY_CTRL_GOST_PARAMSET: 106 pctx->sign_param_nid = (int)p1; 107 return 1; 108 case EVP_PKEY_CTRL_SET_IV: 109 pctx->shared_ukm = OPENSSL_malloc((int)p1); 110 if (pctx->shared_ukm == NULL) 111 return 0; 112 memcpy(pctx->shared_ukm, p2, (int)p1); 113 return 1; 114 case EVP_PKEY_CTRL_PEER_KEY: 115 if (p1 == 0 || p1 == 1) /* call from EVP_PKEY_derive_set_peer */ 116 return 1; 117 if (p1 == 2) /* TLS: peer key used? */ 118 return pctx->peer_key_used; 119 if (p1 == 3) /* TLS: peer key used! */ 120 return (pctx->peer_key_used = 1); 121 return -2; 122 } 123 return -2; 124} 125 126static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx, 127 const char *type, const char *value) 128{ 129 int param_nid = 0; 130 if (!strcmp(type, param_ctrl_string)) { 131 if (!value) { 132 return 0; 133 } 134 if (strlen(value) == 1) { 135 switch (toupper((unsigned char)value[0])) { 136 case 'A': 137 param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet; 138 break; 139 case 'B': 140 param_nid = NID_id_GostR3410_94_CryptoPro_B_ParamSet; 141 break; 142 case 'C': 143 param_nid = NID_id_GostR3410_94_CryptoPro_C_ParamSet; 144 break; 145 case 'D': 146 param_nid = NID_id_GostR3410_94_CryptoPro_D_ParamSet; 147 break; 148 default: 149 return 0; 150 break; 151 } 152 } else if ((strlen(value) == 2) 153 && (toupper((unsigned char)value[0]) == 'X')) { 154 switch (toupper((unsigned char)value[1])) { 155 case 'A': 156 param_nid = NID_id_GostR3410_94_CryptoPro_XchA_ParamSet; 157 break; 158 case 'B': 159 param_nid = NID_id_GostR3410_94_CryptoPro_XchB_ParamSet; 160 break; 161 case 'C': 162 param_nid = NID_id_GostR3410_94_CryptoPro_XchC_ParamSet; 163 break; 164 default: 165 return 0; 166 break; 167 } 168 } else { 169 R3410_params *p = R3410_paramset; 170 param_nid = OBJ_txt2nid(value); 171 if (param_nid == NID_undef) { 172 return 0; 173 } 174 for (; p->nid != NID_undef; p++) { 175 if (p->nid == param_nid) 176 break; 177 } 178 if (p->nid == NID_undef) { 179 GOSTerr(GOST_F_PKEY_GOST_CTRL94_STR, GOST_R_INVALID_PARAMSET); 180 return 0; 181 } 182 } 183 184 return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, 185 param_nid, NULL); 186 } 187 return -2; 188} 189 190static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx, 191 const char *type, const char *value) 192{ 193 int param_nid = 0; 194 if (!strcmp(type, param_ctrl_string)) { 195 if (!value) { 196 return 0; 197 } 198 if (strlen(value) == 1) { 199 switch (toupper((unsigned char)value[0])) { 200 case 'A': 201 param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet; 202 break; 203 case 'B': 204 param_nid = NID_id_GostR3410_2001_CryptoPro_B_ParamSet; 205 break; 206 case 'C': 207 param_nid = NID_id_GostR3410_2001_CryptoPro_C_ParamSet; 208 break; 209 case '0': 210 param_nid = NID_id_GostR3410_2001_TestParamSet; 211 break; 212 default: 213 return 0; 214 break; 215 } 216 } else if ((strlen(value) == 2) 217 && (toupper((unsigned char)value[0]) == 'X')) { 218 switch (toupper((unsigned char)value[1])) { 219 case 'A': 220 param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet; 221 break; 222 case 'B': 223 param_nid = NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet; 224 break; 225 default: 226 return 0; 227 break; 228 } 229 } else { 230 R3410_2001_params *p = R3410_2001_paramset; 231 param_nid = OBJ_txt2nid(value); 232 if (param_nid == NID_undef) { 233 return 0; 234 } 235 for (; p->nid != NID_undef; p++) { 236 if (p->nid == param_nid) 237 break; 238 } 239 if (p->nid == NID_undef) { 240 GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR, GOST_R_INVALID_PARAMSET); 241 return 0; 242 } 243 } 244 245 return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, 246 param_nid, NULL); 247 } 248 return -2; 249} 250 251/* --------------------- key generation --------------------------------*/ 252 253static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx) 254{ 255 return 1; 256} 257 258static int pkey_gost94_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 259{ 260 struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); 261 DSA *dsa = NULL; 262 if (data->sign_param_nid == NID_undef) { 263 GOSTerr(GOST_F_PKEY_GOST94_PARAMGEN, GOST_R_NO_PARAMETERS_SET); 264 return 0; 265 } 266 dsa = DSA_new(); 267 if (!fill_GOST94_params(dsa, data->sign_param_nid)) { 268 DSA_free(dsa); 269 return 0; 270 } 271 EVP_PKEY_assign(pkey, NID_id_GostR3410_94, dsa); 272 return 1; 273} 274 275static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 276{ 277 struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); 278 EC_KEY *ec = NULL; 279 280 if (data->sign_param_nid == NID_undef) { 281 GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN, GOST_R_NO_PARAMETERS_SET); 282 return 0; 283 } 284 if (!ec) 285 ec = EC_KEY_new(); 286 if (!fill_GOST2001_params(ec, data->sign_param_nid)) { 287 EC_KEY_free(ec); 288 return 0; 289 } 290 EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec); 291 return 1; 292} 293 294/* Generates Gost_R3410_94_cp key */ 295static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 296{ 297 DSA *dsa; 298 if (!pkey_gost94_paramgen(ctx, pkey)) 299 return 0; 300 dsa = EVP_PKEY_get0(pkey); 301 gost_sign_keygen(dsa); 302 return 1; 303} 304 305/* Generates GOST_R3410 2001 key and assigns it using specified type */ 306static int pkey_gost01cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 307{ 308 EC_KEY *ec; 309 if (!pkey_gost01_paramgen(ctx, pkey)) 310 return 0; 311 ec = EVP_PKEY_get0(pkey); 312 gost2001_keygen(ec); 313 return 1; 314} 315 316/* ----------- sign callbacks --------------------------------------*/ 317 318static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, 319 size_t *siglen, const unsigned char *tbs, 320 size_t tbs_len) 321{ 322 DSA_SIG *unpacked_sig = NULL; 323 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); 324 if (!siglen) 325 return 0; 326 if (!sig) { 327 *siglen = 64; /* better to check size of pkey->pkey.dsa-q */ 328 return 1; 329 } 330 unpacked_sig = gost_do_sign(tbs, tbs_len, EVP_PKEY_get0(pkey)); 331 if (!unpacked_sig) { 332 return 0; 333 } 334 return pack_sign_cp(unpacked_sig, 32, sig, siglen); 335} 336 337static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, 338 size_t *siglen, const unsigned char *tbs, 339 size_t tbs_len) 340{ 341 DSA_SIG *unpacked_sig = NULL; 342 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); 343 if (!siglen) 344 return 0; 345 if (!sig) { 346 *siglen = 64; /* better to check size of curve order */ 347 return 1; 348 } 349 unpacked_sig = gost2001_do_sign(tbs, tbs_len, EVP_PKEY_get0(pkey)); 350 if (!unpacked_sig) { 351 return 0; 352 } 353 return pack_sign_cp(unpacked_sig, 32, sig, siglen); 354} 355 356/* ------------------- verify callbacks ---------------------------*/ 357 358static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, 359 size_t siglen, const unsigned char *tbs, 360 size_t tbs_len) 361{ 362 int ok = 0; 363 EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx); 364 DSA_SIG *s = unpack_cp_signature(sig, siglen); 365 if (!s) 366 return 0; 367 if (pub_key) 368 ok = gost_do_verify(tbs, tbs_len, s, EVP_PKEY_get0(pub_key)); 369 DSA_SIG_free(s); 370 return ok; 371} 372 373static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, 374 size_t siglen, const unsigned char *tbs, 375 size_t tbs_len) 376{ 377 int ok = 0; 378 EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx); 379 DSA_SIG *s = unpack_cp_signature(sig, siglen); 380 if (!s) 381 return 0; 382#ifdef DEBUG_SIGN 383 fprintf(stderr, "R="); 384 BN_print_fp(stderr, s->r); 385 fprintf(stderr, "\nS="); 386 BN_print_fp(stderr, s->s); 387 fprintf(stderr, "\n"); 388#endif 389 if (pub_key) 390 ok = gost2001_do_verify(tbs, tbs_len, s, EVP_PKEY_get0(pub_key)); 391 DSA_SIG_free(s); 392 return ok; 393} 394 395/* ------------- encrypt init -------------------------------------*/ 396/* Generates ephermeral key */ 397static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx) 398{ 399 return 1; 400} 401 402/* --------------- Derive init ------------------------------------*/ 403static int pkey_gost_derive_init(EVP_PKEY_CTX *ctx) 404{ 405 return 1; 406} 407 408/* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/ 409static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx) 410{ 411 struct gost_mac_pmeth_data *data; 412 data = OPENSSL_malloc(sizeof(struct gost_mac_pmeth_data)); 413 if (!data) 414 return 0; 415 memset(data, 0, sizeof(struct gost_mac_pmeth_data)); 416 EVP_PKEY_CTX_set_data(ctx, data); 417 return 1; 418} 419 420static void pkey_gost_mac_cleanup(EVP_PKEY_CTX *ctx) 421{ 422 struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); 423 OPENSSL_free(data); 424} 425 426static int pkey_gost_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 427{ 428 struct gost_mac_pmeth_data *dst_data, *src_data; 429 if (!pkey_gost_mac_init(dst)) { 430 return 0; 431 } 432 src_data = EVP_PKEY_CTX_get_data(src); 433 dst_data = EVP_PKEY_CTX_get_data(dst); 434 *dst_data = *src_data; 435 return 1; 436} 437 438static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 439{ 440 struct gost_mac_pmeth_data *data = 441 (struct gost_mac_pmeth_data *)EVP_PKEY_CTX_get_data(ctx); 442 443 switch (type) { 444 case EVP_PKEY_CTRL_MD: 445 { 446 if (EVP_MD_type((const EVP_MD *)p2) != NID_id_Gost28147_89_MAC) { 447 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, 448 GOST_R_INVALID_DIGEST_TYPE); 449 return 0; 450 } 451 data->md = (EVP_MD *)p2; 452 return 1; 453 } 454 break; 455 456 case EVP_PKEY_CTRL_GET_MD: 457 *(const EVP_MD **)p2 = data->md; 458 return 1; 459 460 case EVP_PKEY_CTRL_PKCS7_ENCRYPT: 461 case EVP_PKEY_CTRL_PKCS7_DECRYPT: 462 case EVP_PKEY_CTRL_PKCS7_SIGN: 463 return 1; 464 case EVP_PKEY_CTRL_SET_MAC_KEY: 465 if (p1 != 32) { 466 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH); 467 return 0; 468 } 469 470 memcpy(data->key, p2, 32); 471 data->key_set = 1; 472 return 1; 473 case EVP_PKEY_CTRL_DIGESTINIT: 474 { 475 EVP_MD_CTX *mctx = p2; 476 void *key; 477 if (!data->key_set) { 478 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); 479 if (!pkey) { 480 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, 481 GOST_R_MAC_KEY_NOT_SET); 482 return 0; 483 } 484 key = EVP_PKEY_get0(pkey); 485 if (!key) { 486 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL, 487 GOST_R_MAC_KEY_NOT_SET); 488 return 0; 489 } 490 } else { 491 key = &(data->key); 492 } 493 return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32, key); 494 } 495 } 496 return -2; 497} 498 499static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx, 500 const char *type, const char *value) 501{ 502 if (!strcmp(type, key_ctrl_string)) { 503 if (strlen(value) != 32) { 504 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, 505 GOST_R_INVALID_MAC_KEY_LENGTH); 506 return 0; 507 } 508 return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 509 32, (char *)value); 510 } 511 if (!strcmp(type, hexkey_ctrl_string)) { 512 long keylen; 513 int ret; 514 unsigned char *keybuf = string_to_hex(value, &keylen); 515 if (!keybuf || keylen != 32) { 516 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, 517 GOST_R_INVALID_MAC_KEY_LENGTH); 518 OPENSSL_free(keybuf); 519 return 0; 520 } 521 ret = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, 32, keybuf); 522 OPENSSL_free(keybuf); 523 return ret; 524 525 } 526 return -2; 527} 528 529static int pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 530{ 531 struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); 532 unsigned char *keydata; 533 if (!data->key_set) { 534 GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN, GOST_R_MAC_KEY_NOT_SET); 535 return 0; 536 } 537 keydata = OPENSSL_malloc(32); 538 if (keydata == NULL) 539 return 0; 540 memcpy(keydata, data->key, 32); 541 EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata); 542 return 1; 543} 544 545static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) 546{ 547 return 1; 548} 549 550static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, 551 size_t *siglen, EVP_MD_CTX *mctx) 552{ 553 unsigned int tmpsiglen = *siglen; /* for platforms where 554 * sizeof(int)!=sizeof(size_t) */ 555 int ret; 556 if (!sig) { 557 *siglen = 4; 558 return 1; 559 } 560 ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen); 561 *siglen = tmpsiglen; 562 return ret; 563} 564 565/* ----------------------------------------------------------------*/ 566int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags) 567{ 568 *pmeth = EVP_PKEY_meth_new(id, flags); 569 if (!*pmeth) 570 return 0; 571 572 switch (id) { 573 case NID_id_GostR3410_94: 574 EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_ctrl, pkey_gost_ctrl94_str); 575 EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost94cp_keygen); 576 EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cp_sign); 577 EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cp_verify); 578 EVP_PKEY_meth_set_encrypt(*pmeth, 579 pkey_gost_encrypt_init, 580 pkey_GOST94cp_encrypt); 581 EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cp_decrypt); 582 EVP_PKEY_meth_set_derive(*pmeth, 583 pkey_gost_derive_init, pkey_gost94_derive); 584 EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init, 585 pkey_gost94_paramgen); 586 break; 587 case NID_id_GostR3410_2001: 588 EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_ctrl, pkey_gost_ctrl01_str); 589 EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign); 590 EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify); 591 592 EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cp_keygen); 593 594 EVP_PKEY_meth_set_encrypt(*pmeth, 595 pkey_gost_encrypt_init, 596 pkey_GOST01cp_encrypt); 597 EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt); 598 EVP_PKEY_meth_set_derive(*pmeth, 599 pkey_gost_derive_init, pkey_gost2001_derive); 600 EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init, 601 pkey_gost01_paramgen); 602 break; 603 case NID_id_Gost28147_89_MAC: 604 EVP_PKEY_meth_set_ctrl(*pmeth, pkey_gost_mac_ctrl, 605 pkey_gost_mac_ctrl_str); 606 EVP_PKEY_meth_set_signctx(*pmeth, pkey_gost_mac_signctx_init, 607 pkey_gost_mac_signctx); 608 EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost_mac_keygen); 609 EVP_PKEY_meth_set_init(*pmeth, pkey_gost_mac_init); 610 EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_mac_cleanup); 611 EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_mac_copy); 612 return 1; 613 default: /* Unsupported method */ 614 return 0; 615 } 616 EVP_PKEY_meth_set_init(*pmeth, pkey_gost_init); 617 EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_cleanup); 618 619 EVP_PKEY_meth_set_copy(*pmeth, pkey_gost_copy); 620 /* 621 * FIXME derive etc... 622 */ 623 624 return 1; 625} 626