soter_status_t soter_asym_cipher_decrypt(soter_asym_cipher_t* asym_cipher, const void* cipher_data, size_t cipher_data_length, void* plain_data, size_t* plain_data_length) { EVP_PKEY *pkey; RSA *rsa; int rsa_mod_size; size_t output_length; if ((!asym_cipher) || (!cipher_data) || (0 == cipher_data_length) || (!plain_data_length)) { return SOTER_INVALID_PARAMETER; } pkey = EVP_PKEY_CTX_get0_pkey(asym_cipher->pkey_ctx); if (!pkey) { return SOTER_INVALID_PARAMETER; } if (EVP_PKEY_RSA != EVP_PKEY_id(pkey)) { /* We can only do assymetric encryption with RSA algorithm */ return SOTER_INVALID_PARAMETER; } rsa = EVP_PKEY_get0(pkey); if (NULL == rsa) { return SOTER_FAIL; } rsa_mod_size = RSA_size(rsa); if (cipher_data_length < rsa_mod_size) { /* The cipherdata is too small for this key size */ return SOTER_INVALID_PARAMETER; } /* Currently we support only OAEP padding for RSA encryption */ /* TODO: should we support "no padding" or PKCS1.5 padding? */ if (!EVP_PKEY_decrypt_init(asym_cipher->pkey_ctx)) { return SOTER_FAIL; } /* TODO: This function automatically sets SHA1 as MGF digest for OAEP padding. Should we change it to SHA256? */ if (1 > EVP_PKEY_CTX_ctrl(asym_cipher->pkey_ctx, -1, -1, EVP_PKEY_CTRL_RSA_PADDING, RSA_PKCS1_OAEP_PADDING, NULL)) { return SOTER_FAIL; } /* We will check the size of the output buffer first */ if (EVP_PKEY_decrypt(asym_cipher->pkey_ctx, NULL, &output_length, (const unsigned char *)cipher_data, cipher_data_length)) { if (output_length > *plain_data_length) { *plain_data_length = output_length; return SOTER_BUFFER_TOO_SMALL; } } else { return SOTER_FAIL; } if (EVP_PKEY_decrypt(asym_cipher->pkey_ctx, (unsigned char *)plain_data, plain_data_length, (const unsigned char *)cipher_data, cipher_data_length)) { if (plain_data) { return SOTER_SUCCESS; } else { return SOTER_BUFFER_TOO_SMALL; } } else { return SOTER_FAIL; } }
/* EVP_PLEY_METHOD callback decrypt for * GOST R 34.10-94 cryptopro modification */ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len,const unsigned char *in, size_t in_len) { const unsigned char *p = in; GOST_KEY_TRANSPORT *gkt = NULL; unsigned char wrappedKey[44]; unsigned char sharedKey[32]; gost_ctx cctx; const struct gost_cipher_info *param=NULL; EVP_PKEY *eph_key=NULL, *peerkey=NULL; EVP_PKEY *priv= EVP_PKEY_CTX_get0_pkey(ctx); if (!key) { *key_len = 32; return 1; } gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, in_len); if (!gkt) { GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); return 0; } eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key); if (eph_key) { if (EVP_PKEY_derive_set_peer(ctx, eph_key) <= 0) { GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, GOST_R_INCOMPATIBLE_PEER_KEY); goto err; } } else { /* 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_DECRYPT, GOST_R_CTRL_CALL_FAILED); goto err; } } peerkey = EVP_PKEY_CTX_get0_peerkey(ctx); if (!peerkey) { GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, GOST_R_NO_PEER_KEY); goto err; } param = get_encryption_params(gkt->key_agreement_info->cipher); gost_init(&cctx,param->sblock); OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8); TINYCLR_SSL_MEMCPY(wrappedKey,gkt->key_agreement_info->eph_iv->data,8); OPENSSL_assert(gkt->key_info->encrypted_key->length==32); TINYCLR_SSL_MEMCPY(wrappedKey+8,gkt->key_info->encrypted_key->data,32); OPENSSL_assert(gkt->key_info->imit->length==4); TINYCLR_SSL_MEMCPY(wrappedKey+40,gkt->key_info->imit->data,4); make_cp_exchange_key(gost_get0_priv_key(priv),peerkey,sharedKey); if (!keyUnwrapCryptoPro(&cctx,sharedKey,wrappedKey,key)) { GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, GOST_R_ERROR_COMPUTING_SHARED_KEY); goto err; } EVP_PKEY_free(eph_key); GOST_KEY_TRANSPORT_free(gkt); return 1; err: EVP_PKEY_free(eph_key); GOST_KEY_TRANSPORT_free(gkt); 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; }
int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, uint64_t value) { return EVP_PKEY_CTX_ctrl(ctx, keytype, optype, cmd, 0, &value); }
static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) { EVP_PKEY_CTX *pctx = NULL; unsigned char *ek = NULL; size_t eklen; int ret = -1; pctx = EVP_PKEY_CTX_new(pkey, NULL); if (!pctx) return -1; if (EVP_PKEY_decrypt_init(pctx) <= 0) goto err; if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) { PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR); goto err; } if (EVP_PKEY_decrypt(pctx, NULL, &eklen, ri->enc_key->data, ri->enc_key->length) <= 0) goto err; ek = OPENSSL_malloc(eklen); if (ek == NULL) { PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_PKEY_decrypt(pctx, ek, &eklen, ri->enc_key->data, ri->enc_key->length) <= 0) { ret = 0; PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); goto err; } ret = 1; if (*pek) { OPENSSL_cleanse(*pek, *peklen); OPENSSL_free(*pek); } *pek = ek; *peklen = eklen; err: if (pctx) EVP_PKEY_CTX_free(pctx); if (!ret && ek) OPENSSL_free(ek); return ret; }
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0, (void *)md); }
/* * EVP_PKEY_METHOD callback decrypt * Implementation of GOST2001 key transport, cryptopo variation */ int pkey_GOST01cp_decrypt (EVP_PKEY_CTX * pctx, unsigned char *key, size_t * key_len, const unsigned char *in, size_t in_len) { const unsigned char *p = in; EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey (pctx); GOST_KEY_TRANSPORT *gkt = NULL; int ret = 0; unsigned char wrappedKey[44]; unsigned char sharedKey[32]; gost_ctx ctx; const struct gost_cipher_info *param = NULL; EVP_PKEY *eph_key = NULL, *peerkey = NULL; if (!key) { *key_len = 32; return 1; } gkt = d2i_GOST_KEY_TRANSPORT (NULL, (const unsigned char **) &p, in_len); if (!gkt) { GOSTerr (GOST_F_PKEY_GOST01CP_DECRYPT, GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); return -1; } /* If key transport structure contains public key, use it */ eph_key = X509_PUBKEY_get (gkt->key_agreement_info->ephem_key); if (eph_key) { if (EVP_PKEY_derive_set_peer (pctx, eph_key) <= 0) { GOSTerr (GOST_F_PKEY_GOST01CP_DECRYPT, GOST_R_INCOMPATIBLE_PEER_KEY); goto err; } } else { /* Set control "public key from client certificate used" */ if (EVP_PKEY_CTX_ctrl (pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) { GOSTerr (GOST_F_PKEY_GOST01CP_DECRYPT, GOST_R_CTRL_CALL_FAILED); goto err; } } peerkey = EVP_PKEY_CTX_get0_peerkey (pctx); if (!peerkey) { GOSTerr (GOST_F_PKEY_GOST01CP_DECRYPT, GOST_R_NO_PEER_KEY); goto err; } param = get_encryption_params (gkt->key_agreement_info->cipher); if (!param) { goto err; } gost_init (&ctx, param->sblock); OPENSSL_assert (gkt->key_agreement_info->eph_iv->length == 8); memcpy (wrappedKey, gkt->key_agreement_info->eph_iv->data, 8); OPENSSL_assert (gkt->key_info->encrypted_key->length == 32); memcpy (wrappedKey + 8, gkt->key_info->encrypted_key->data, 32); OPENSSL_assert (gkt->key_info->imit->length == 4); memcpy (wrappedKey + 40, gkt->key_info->imit->data, 4); VKO_compute_key (sharedKey, 32, EC_KEY_get0_public_key (EVP_PKEY_get0 (peerkey)), EVP_PKEY_get0 (priv), wrappedKey); if (!keyUnwrapCryptoPro (&ctx, sharedKey, wrappedKey, key)) { GOSTerr (GOST_F_PKEY_GOST01CP_DECRYPT, GOST_R_ERROR_COMPUTING_SHARED_KEY); goto err; } ret = 1; err: if (eph_key) EVP_PKEY_free (eph_key); if (gkt) GOST_KEY_TRANSPORT_free (gkt); return ret; }
int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX *ctx, int bits) { return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL); }
int EVP_PKEY_CTX_set_rsa_keygen_pubexp(EVP_PKEY_CTX *ctx, BIGNUM *e) { return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, e); }
int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int salt_len) { return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY), EVP_PKEY_CTRL_RSA_PSS_SALTLEN, salt_len, NULL); }
int EVP_PKEY_CTX_get_rsa_pss_saltlen(EVP_PKEY_CTX *ctx, int *out_salt_len) { return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY), EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, out_salt_len); }
int EVP_PKEY_CTX_get_rsa_padding(EVP_PKEY_CTX *ctx, int *out_padding) { return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, out_padding); }
int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding) { return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, padding, NULL); }
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) { EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED); #ifndef OPENSSL_NO_ENGINE /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts * so this context may already have an ENGINE! Try to avoid releasing * the previous handle, re-querying for an ENGINE, and having a * reinitialisation, when it may all be unecessary. */ if (ctx->engine && ctx->digest && (!type || (type && (type->type == ctx->digest->type)))) goto skip_to_init; if (type) { /* Ensure an ENGINE left lying around from last time is cleared * (the previous check attempted to avoid this if the same * ENGINE and EVP_MD could be used). */ if(ctx->engine) ENGINE_finish(ctx->engine); if(impl) { if (!ENGINE_init(impl)) { EVPerr(EVP_F_EVP_DIGESTINIT_EX,EVP_R_INITIALIZATION_ERROR); return 0; } } else /* Ask if an ENGINE is reserved for this job */ impl = ENGINE_get_digest_engine(type->type); if(impl) { /* There's an ENGINE for this job ... (apparently) */ const EVP_MD *d = ENGINE_get_digest(impl, type->type); if(!d) { /* Same comment from evp_enc.c */ EVPerr(EVP_F_EVP_DIGESTINIT_EX,EVP_R_INITIALIZATION_ERROR); ENGINE_finish(impl); return 0; } /* We'll use the ENGINE's private digest definition */ type = d; /* Store the ENGINE functional reference so we know * 'type' came from an ENGINE and we need to release * it when done. */ ctx->engine = impl; } else ctx->engine = NULL; } else if(!ctx->digest) { EVPerr(EVP_F_EVP_DIGESTINIT_EX,EVP_R_NO_DIGEST_SET); return 0; } #endif if (ctx->digest != type) { if (ctx->digest && ctx->digest->ctx_size) OPENSSL_free(ctx->md_data); ctx->digest=type; if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) { ctx->update = type->update; ctx->md_data=OPENSSL_malloc(type->ctx_size); if (ctx->md_data == NULL) { EVPerr(EVP_F_EVP_DIGESTINIT_EX, ERR_R_MALLOC_FAILURE); return 0; } } } #ifndef OPENSSL_NO_ENGINE skip_to_init: #endif if (ctx->pctx) { int r; r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_DIGESTINIT, 0, ctx); if (r <= 0 && (r != -2)) return 0; } if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) return 1; #ifdef OPENSSL_FIPS if (FIPS_mode()) { if (FIPS_digestinit(ctx, type)) return 1; OPENSSL_free(ctx->md_data); ctx->md_data = NULL; return 0; } #endif return ctx->digest->init(ctx); }
static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) { CMS_KeyTransRecipientInfo *ktri; CMS_EncryptedContentInfo *ec; EVP_PKEY_CTX *pctx; unsigned char *ek = NULL; size_t eklen; int ret = 0; if (ri->type != CMS_RECIPINFO_TRANS) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_NOT_KEY_TRANSPORT); return 0; } ktri = ri->d.ktri; ec = cms->d.envelopedData->encryptedContentInfo; pctx = ktri->pctx; if (pctx) { if (!cms_env_asn1_ctrl(ri, 0)) goto err; } else { pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); if (!pctx) return 0; if (EVP_PKEY_encrypt_init(pctx) <= 0) goto err; } if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR); goto err; } if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0) goto err; ek = OPENSSL_malloc(eklen); if (ek == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0) goto err; ASN1_STRING_set0(ktri->encryptedKey, ek, eklen); ek = NULL; ret = 1; err: EVP_PKEY_CTX_free(pctx); ktri->pctx = NULL; OPENSSL_free(ek); return ret; }
int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) { return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void*) out_md); }
static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) { CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; EVP_PKEY *pkey = ktri->pkey; unsigned char *ek = NULL; size_t eklen; int ret = 0; CMS_EncryptedContentInfo *ec; ec = cms->d.envelopedData->encryptedContentInfo; if (ktri->pkey == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_NO_PRIVATE_KEY); return 0; } ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL); if (!ktri->pctx) return 0; if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0) goto err; if (!cms_env_asn1_ctrl(ri, 1)) goto err; if (EVP_PKEY_CTX_ctrl(ktri->pctx, -1, EVP_PKEY_OP_DECRYPT, EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR); goto err; } if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen, ktri->encryptedKey->data, ktri->encryptedKey->length) <= 0) goto err; ek = OPENSSL_malloc(eklen); if (ek == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen, ktri->encryptedKey->data, ktri->encryptedKey->length) <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); goto err; } ret = 1; OPENSSL_clear_free(ec->key, ec->keylen); ec->key = ek; ec->keylen = eklen; err: EVP_PKEY_CTX_free(ktri->pctx); ktri->pctx = NULL; if (!ret) OPENSSL_free(ek); return ret; }
int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) { return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void*) out_md); }
int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) { return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_GET_MD, 0, (void *)out_md); }
int pkey_GOST01cp_encrypt (EVP_PKEY_CTX * pctx, unsigned char *out, size_t * out_len, const unsigned char *key, size_t key_len) { GOST_KEY_TRANSPORT *gkt = NULL; EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey (pctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data (pctx); const struct gost_cipher_info *param = get_encryption_params (NULL); unsigned char ukm[8], shared_key[32], crypted_key[44]; int ret = 0; int key_is_ephemeral = 1; gost_ctx cctx; EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey (pctx); if (data->shared_ukm) { memcpy (ukm, data->shared_ukm, 8); } else if (out) { if (RAND_bytes (ukm, 8) <= 0) { GOSTerr (GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_RANDOM_GENERATOR_FAILURE); return 0; } } /* Check for private key in the peer_key of context */ if (sec_key) { key_is_ephemeral = 0; if (!gost_get0_priv_key (sec_key)) { GOSTerr (GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); goto err; } } else { key_is_ephemeral = 1; if (out) { sec_key = EVP_PKEY_new (); EVP_PKEY_assign (sec_key, EVP_PKEY_base_id (pubk), EC_KEY_new ()); EVP_PKEY_copy_parameters (sec_key, pubk); if (!gost2001_keygen (EVP_PKEY_get0 (sec_key))) { goto err; } } } if (!get_gost_engine_param (GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list) { param = gost_cipher_list + 1; } if (out) { VKO_compute_key (shared_key, 32, EC_KEY_get0_public_key (EVP_PKEY_get0 (pubk)), EVP_PKEY_get0 (sec_key), ukm); gost_init (&cctx, param->sblock); keyWrapCryptoPro (&cctx, shared_key, ukm, key, crypted_key); } gkt = GOST_KEY_TRANSPORT_new (); if (!gkt) { goto err; } if (!ASN1_OCTET_STRING_set (gkt->key_agreement_info->eph_iv, ukm, 8)) { goto err; } if (!ASN1_OCTET_STRING_set (gkt->key_info->imit, crypted_key + 40, 4)) { goto err; } if (!ASN1_OCTET_STRING_set (gkt->key_info->encrypted_key, crypted_key + 8, 32)) { goto err; } if (key_is_ephemeral) { if (!X509_PUBKEY_set (&gkt->key_agreement_info->ephem_key, out ? sec_key : pubk)) { GOSTerr (GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; } } ASN1_OBJECT_free (gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj (param->nid); if (key_is_ephemeral && sec_key) EVP_PKEY_free (sec_key); if (!key_is_ephemeral) { /* Set control "public key from client certificate used" */ if (EVP_PKEY_CTX_ctrl (pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) { GOSTerr (GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_CTRL_CALL_FAILED); goto err; } } if ((*out_len = i2d_GOST_KEY_TRANSPORT (gkt, out ? &out : NULL)) > 0) ret = 1; GOST_KEY_TRANSPORT_free (gkt); return ret; err: if (key_is_ephemeral && sec_key) EVP_PKEY_free (sec_key); GOST_KEY_TRANSPORT_free (gkt); return -1; }