OPENSSL_assert(EVP_CIPHER_iv_length(cipher) <= 16);
int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,			 ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,			 int en_de){	EVP_MD_CTX ctx;	unsigned char md_tmp[EVP_MAX_MD_SIZE];	unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];	int i;	PBEPARAM *pbe;	int saltlen, iter;	unsigned char *salt, *pbuf;	/* Extract useful info from parameter */	pbuf = param->value.sequence->data;	if (!param || (param->type != V_ASN1_SEQUENCE) ||	   !(pbe = d2i_PBEPARAM (NULL, &pbuf, param->value.sequence->length))) {		EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);		return 0;	}	if (!pbe->iter) iter = 1;	else iter = ASN1_INTEGER_get (pbe->iter);	salt = pbe->salt->data;	saltlen = pbe->salt->length;	if(!pass) passlen = 0;	else if(passlen == -1) passlen = strlen(pass);	EVP_MD_CTX_init(&ctx);	EVP_DigestInit_ex(&ctx, md, NULL);	EVP_DigestUpdate(&ctx, pass, passlen);	EVP_DigestUpdate(&ctx, salt, saltlen);	PBEPARAM_free(pbe);	EVP_DigestFinal_ex(&ctx, md_tmp, NULL);	for (i = 1; i < iter; i++) {		EVP_DigestInit_ex(&ctx, md, NULL);		EVP_DigestUpdate(&ctx, md_tmp, EVP_MD_size(md));		EVP_DigestFinal_ex (&ctx, md_tmp, NULL);	}	EVP_MD_CTX_cleanup(&ctx);	memcpy(key, md_tmp, EVP_CIPHER_key_length(cipher));	memcpy(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)),						 EVP_CIPHER_iv_length(cipher));	EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de);	memset(md_tmp, 0, EVP_MAX_MD_SIZE);	memset(key, 0, EVP_MAX_KEY_LENGTH);	memset(iv, 0, EVP_MAX_IV_LENGTH);	return 1;}