EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
	{
	EVP_PKEY *ret=NULL;
	const EVP_PKEY_ASN1_METHOD *meth;

	if (key == NULL) goto error;

	if (key->pkey != NULL)
		{
		CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
		return key->pkey;
		}

	if (key->public_key == NULL) goto error;

	if ((ret = EVP_PKEY_new()) == NULL)
		{
		X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);
		goto error;
		}

	meth = EVP_PKEY_ASN1_find(OBJ_obj2nid(key->algor->algorithm));

	if (meth)
		{
		if (meth->pub_decode)
			{
			if (!meth->pub_decode(ret, key))
				{
				X509err(X509_F_X509_PUBKEY_GET,
						X509_R_PUBLIC_KEY_DECODE_ERROR);
				goto error;
				}
			}
		else
			{
			X509err(X509_F_X509_PUBKEY_GET,
				X509_R_METHOD_NOT_SUPPORTED);
			goto error;
			}
		}
	else
		{
		X509err(X509_F_X509_PUBKEY_GET,X509_R_UNSUPPORTED_ALGORITHM);
		goto error;
		}

	key->pkey = ret;
	CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);

	return ret;

	error:
	if (ret != NULL)
		EVP_PKEY_free(ret);
	return(NULL);
	}