/* Generates Gost_R3410_94_cp key */ static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { DSA *dsa; if (!pkey_gost94_paramgen(ctx,pkey)) return 0; dsa = EVP_PKEY_get0(pkey); gost_sign_keygen(dsa); return 1; }
int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len ) { GOST_KEY_TRANSPORT *gkt=NULL; unsigned char shared_key[32], ukm[8],crypted_key[44]; const struct gost_cipher_info *param=get_encryption_params(NULL); EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx); struct gost_pmeth_data *data = (gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx); gost_ctx cctx; int key_is_ephemeral=1; EVP_PKEY *mykey = EVP_PKEY_CTX_get0_peerkey(ctx); /* Do not use vizir cipher parameters with cryptopro */ if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list) { param= gost_cipher_list+1; } if (mykey) { /* If key already set, it is not ephemeral */ key_is_ephemeral=0; if (!gost_get0_priv_key(mykey)) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); goto err; } } else { /* Otherwise generate ephemeral key */ key_is_ephemeral = 1; if (out) { mykey = EVP_PKEY_new(); EVP_PKEY_assign(mykey, EVP_PKEY_base_id(pubk),DSA_new()); EVP_PKEY_copy_parameters(mykey,pubk); if (!gost_sign_keygen((DSA*)EVP_PKEY_get0(mykey))) { goto err; } } } if (out) make_cp_exchange_key(gost_get0_priv_key(mykey),pubk,shared_key); if (data->shared_ukm) { TINYCLR_SSL_MEMCPY(ukm,data->shared_ukm,8); } else if (out) { if (RAND_bytes(ukm,8)<=0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_RANDOM_GENERATOR_FAILURE); goto err; } } if (out) { gost_init(&cctx,param->sblock); keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key); } gkt = GOST_KEY_TRANSPORT_new(); if (!gkt) { goto memerr; } if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm,8)) { goto memerr; } if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4)) { goto memerr; } if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32)) { goto memerr; } if (key_is_ephemeral) { if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,out?mykey:pubk)) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; } if (out) EVP_PKEY_free(mykey); } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); *outlen = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL); if (*outlen == 0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO); goto err; } if (!key_is_ephemeral) { /* Set control "public key from client certificate used" */ if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_CTRL_CALL_FAILED); goto err; } } GOST_KEY_TRANSPORT_free(gkt); return 1; memerr: if (key_is_ephemeral) { EVP_PKEY_free(mykey); } GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_MALLOC_FAILURE); err: GOST_KEY_TRANSPORT_free(gkt); return -1; }