static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
	{
	EVP_PKEY_CTX *pctx;
	EVP_PKEY *pkey;
	EVP_CIPHER_CTX *ctx;
	int keylen;
	X509_ALGOR *talg, *wrap_alg = NULL;
	ASN1_OBJECT *aoid;
	ASN1_BIT_STRING *pubkey;
	ASN1_STRING *wrap_str;
	ASN1_OCTET_STRING *ukm;
	unsigned char *penc = NULL;
	int penclen;
	int rv = 0;
	int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
	const EVP_MD *kdf_md;
	pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
	if (!pctx)
		return 0;
	/* Get ephemeral key */
	pkey = EVP_PKEY_CTX_get0_pkey(pctx);
	if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
							NULL, NULL, NULL))
		goto err;
	X509_ALGOR_get0(&aoid, NULL, NULL, talg);
	/* Is everything uninitialised? */
	if (aoid == OBJ_nid2obj(NID_undef))
		{

		EC_KEY *eckey = pkey->pkey.ec;
		/* Set the key */
		unsigned char *p;

		penclen = i2o_ECPublicKey(eckey, NULL);
		if (penclen <= 0)
			goto err;
		penc = OPENSSL_malloc(penclen);
		if (!penc)
			goto err;
		p = penc;
		penclen = i2o_ECPublicKey(eckey, &p);
		if (penclen <= 0)
			goto err;
		ASN1_STRING_set0(pubkey, penc, penclen);
		pubkey->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
		pubkey->flags|=ASN1_STRING_FLAG_BITS_LEFT;

		penc = NULL;
		X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
							V_ASN1_UNDEF, NULL);
		}

	/* See if custom paraneters set */
	kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
	if (kdf_type <= 0)
		goto err;
	if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
		goto err;
	ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
	if (ecdh_nid < 0)
		goto err;
	else if (ecdh_nid == 0)
		ecdh_nid = NID_dh_std_kdf;
	else if (ecdh_nid == 1)
		ecdh_nid = NID_dh_cofactor_kdf;

	if (kdf_type == EVP_PKEY_ECDH_KDF_NONE)
		{
		kdf_type = EVP_PKEY_ECDH_KDF_X9_62;
		if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
			goto err;
		}
	else
		/* Uknown KDF */
		goto err;
	if (kdf_md == NULL)
		{
		/* Fixme later for better MD */
		kdf_md = EVP_sha1();
		if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
			goto err;
		}

	if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
		goto err;

	/* Lookup NID for KDF+cofactor+digest */

	if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
		goto err;
	/* Get wrap NID */
	ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
	wrap_nid = EVP_CIPHER_CTX_type(ctx);
	keylen = EVP_CIPHER_CTX_key_length(ctx);

	/* Package wrap algorithm in an AlgorithmIdentifier */

	wrap_alg = X509_ALGOR_new();
	if (!wrap_alg)
		goto err;
	wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
	wrap_alg->parameter = ASN1_TYPE_new();
	if (!wrap_alg->parameter)
		goto err;
	if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
		goto err;
	if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef)
		{
		ASN1_TYPE_free(wrap_alg->parameter);
		wrap_alg->parameter = NULL;
		}

	if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
		goto err;
	if (!ecdh_cms_set_ukm(pctx, wrap_alg, ukm, keylen))
		goto err;

	/* Now need to wrap encoding of wrap AlgorithmIdentifier into
	 * parameter of another AlgorithmIdentifier.
	 */
	penc = NULL;
	penclen = i2d_X509_ALGOR(wrap_alg, &penc);
	if (!penc || !penclen)
		goto err;
	wrap_str = ASN1_STRING_new();
	if (!wrap_str)
		goto err;
	ASN1_STRING_set0(wrap_str, penc, penclen);
	penc = NULL;
	X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);

	rv = 1;

	err:
	if (penc)
		OPENSSL_free(penc);
	if (wrap_alg)
		X509_ALGOR_free(wrap_alg);
	return rv;
	}