static EVP_PKEY *do_PVK_body(const unsigned char **in,
		unsigned int saltlen, unsigned int keylen,
		pem_password_cb *cb, void *u)
	{
	EVP_PKEY *ret = NULL;
	const unsigned char *p = *in;
	unsigned int magic;
	unsigned char *enctmp = NULL, *q;
	EVP_CIPHER_CTX cctx;
	EVP_CIPHER_CTX_init(&cctx);
	if (saltlen)
		{
		char psbuf[PEM_BUFSIZE];
		unsigned char keybuf[20];
		int enctmplen, inlen;
		if (cb)
			inlen=cb(psbuf,PEM_BUFSIZE,0,u);
		else
			inlen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u);
		if (inlen <= 0)
			{
			PEMerr(PEM_F_DO_PVK_BODY,PEM_R_BAD_PASSWORD_READ);
			return NULL;
			}
		enctmp = OPENSSL_malloc(keylen + 8);
		if (!enctmp)
			{
			PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
			return NULL;
			}
		if (!derive_pvk_key(keybuf, p, saltlen,
			    (unsigned char *)psbuf, inlen))
			return NULL;
		p += saltlen;
		memcpy(enctmp, p, 8);
		p += 8;
		inlen = keylen - 8;
		q = enctmp + 8;
		if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL))
			goto err;
		if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen))
			goto err;
		if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen))
			goto err;
		magic = read_ledword((const unsigned char **)&q);
		if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)
			{
			q = enctmp + 8;
			memset(keybuf + 5, 0, 11);
			if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf,
								NULL))
				goto err;
			OPENSSL_cleanse(keybuf, 20);
			if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen))
				goto err;
			if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen,
								&enctmplen))
				goto err;
			magic = read_ledword((const unsigned char **)&q);
			if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)
				{
				PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT);
				goto err;
				}
			}
		else
			OPENSSL_cleanse(keybuf, 20);
		p = enctmp;
		}
	ret = b2i_PrivateKey(&p, keylen);
	err:
	EVP_CIPHER_CTX_cleanup(&cctx);
	if (enctmp && saltlen)
		OPENSSL_free(enctmp);
	return ret;
	}
['EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)\n\t{\n\tunsigned char pvk_hdr[24], *buf = NULL;\n\tconst unsigned char *p;\n\tint buflen;\n\tEVP_PKEY *ret = NULL;\n\tunsigned int saltlen, keylen;\n\tif (BIO_read(in, pvk_hdr, 24) != 24)\n\t\t{\n\t\tPEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);\n\t\treturn NULL;\n\t\t}\n\tp = pvk_hdr;\n\tif (!do_PVK_header(&p, 24, 0, &saltlen, &keylen))\n\t\treturn 0;\n\tbuflen = (int) keylen + saltlen;\n\tbuf = OPENSSL_malloc(buflen);\n\tif (!buf)\n\t\t{\n\t\tPEMerr(PEM_F_B2I_PVK_BIO, ERR_R_MALLOC_FAILURE);\n\t\treturn 0;\n\t\t}\n\tp = buf;\n\tif (BIO_read(in, buf, buflen) != buflen)\n\t\t{\n\t\tPEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);\n\t\tgoto err;\n\t\t}\n\tret = do_PVK_body(&p, saltlen, keylen, cb, u);\n\terr:\n\tif (buf)\n\t\t{\n\t\tOPENSSL_cleanse(buf, buflen);\n\t\tOPENSSL_free(buf);\n\t\t}\n\treturn ret;\n\t}', 'static int do_PVK_header(const unsigned char **in, unsigned int length,\n\t\tint skip_magic,\n\t       \tunsigned int *psaltlen, unsigned int *pkeylen)\n\t{\n\tconst unsigned char *p = *in;\n\tunsigned int pvk_magic, keytype, is_encrypted;\n\tif (skip_magic)\n\t\t{\n\t\tif (length < 20)\n\t\t\t{\n\t\t\tPEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);\n\t\t\treturn 0;\n\t\t\t}\n\t\tlength -= 20;\n\t\t}\n\telse\n\t\t{\n\t\tif (length < 24)\n\t\t\t{\n\t\t\tPEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);\n\t\t\treturn 0;\n\t\t\t}\n\t\tlength -= 24;\n\t\tpvk_magic = read_ledword(&p);\n\t\tif (pvk_magic != MS_PVKMAGIC)\n\t\t\t{\n\t\t\tPEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER);\n\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\tp += 4;\n\tkeytype = read_ledword(&p);\n\tis_encrypted = read_ledword(&p);\n\t*psaltlen = read_ledword(&p);\n\t*pkeylen = read_ledword(&p);\n\tif (is_encrypted && !*psaltlen)\n\t\t{\n\t\tPEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER);\n\t\treturn 0;\n\t\t}\n\t*in = p;\n\treturn 1;\n\t}', 'static EVP_PKEY *do_PVK_body(const unsigned char **in,\n\t\tunsigned int saltlen, unsigned int keylen,\n\t\tpem_password_cb *cb, void *u)\n\t{\n\tEVP_PKEY *ret = NULL;\n\tconst unsigned char *p = *in;\n\tunsigned int magic;\n\tunsigned char *enctmp = NULL, *q;\n\tEVP_CIPHER_CTX cctx;\n\tEVP_CIPHER_CTX_init(&cctx);\n\tif (saltlen)\n\t\t{\n\t\tchar psbuf[PEM_BUFSIZE];\n\t\tunsigned char keybuf[20];\n\t\tint enctmplen, inlen;\n\t\tif (cb)\n\t\t\tinlen=cb(psbuf,PEM_BUFSIZE,0,u);\n\t\telse\n\t\t\tinlen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u);\n\t\tif (inlen <= 0)\n\t\t\t{\n\t\t\tPEMerr(PEM_F_DO_PVK_BODY,PEM_R_BAD_PASSWORD_READ);\n\t\t\treturn NULL;\n\t\t\t}\n\t\tenctmp = OPENSSL_malloc(keylen + 8);\n\t\tif (!enctmp)\n\t\t\t{\n\t\t\tPEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);\n\t\t\treturn NULL;\n\t\t\t}\n\t\tif (!derive_pvk_key(keybuf, p, saltlen,\n\t\t\t    (unsigned char *)psbuf, inlen))\n\t\t\treturn NULL;\n\t\tp += saltlen;\n\t\tmemcpy(enctmp, p, 8);\n\t\tp += 8;\n\t\tinlen = keylen - 8;\n\t\tq = enctmp + 8;\n\t\tif (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL))\n\t\t\tgoto err;\n\t\tif (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen))\n\t\t\tgoto err;\n\t\tif (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen))\n\t\t\tgoto err;\n\t\tmagic = read_ledword((const unsigned char **)&q);\n\t\tif (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)\n\t\t\t{\n\t\t\tq = enctmp + 8;\n\t\t\tmemset(keybuf + 5, 0, 11);\n\t\t\tif (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf,\n\t\t\t\t\t\t\t\tNULL))\n\t\t\t\tgoto err;\n\t\t\tOPENSSL_cleanse(keybuf, 20);\n\t\t\tif (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen))\n\t\t\t\tgoto err;\n\t\t\tif (!EVP_DecryptFinal_ex(&cctx, q + enctmplen,\n\t\t\t\t\t\t\t\t&enctmplen))\n\t\t\t\tgoto err;\n\t\t\tmagic = read_ledword((const unsigned char **)&q);\n\t\t\tif (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)\n\t\t\t\t{\n\t\t\t\tPEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT);\n\t\t\t\tgoto err;\n\t\t\t\t}\n\t\t\t}\n\t\telse\n\t\t\tOPENSSL_cleanse(keybuf, 20);\n\t\tp = enctmp;\n\t\t}\n\tret = b2i_PrivateKey(&p, keylen);\n\terr:\n\tEVP_CIPHER_CTX_cleanup(&cctx);\n\tif (enctmp && saltlen)\n\t\tOPENSSL_free(enctmp);\n\treturn ret;\n\t}']