mirror of
https://github.com/QuasarApp/openssl.git
synced 2025-04-28 18:54:36 +00:00
X509: Add d2i_PUBKEY_ex(), which take a libctx and propq
Just like d2i_PrivateKey() / d2i_PrivateKey_ex(), there's a need to associate an EVP_PKEY extracted from a PUBKEY to a library context and a property query string. Without it, a provider-native EVP_PKEY can only fetch necessary internal algorithms from the default library context, even though an application specific context should be used. Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/12671)
This commit is contained in:
parent
3b1fd0b003
commit
22b814443e
@ -22,6 +22,7 @@
|
||||
#include <openssl/asn1t.h>
|
||||
#include "crypto/asn1.h"
|
||||
#include "crypto/evp.h"
|
||||
#include "crypto/x509.h"
|
||||
#include <openssl/core_names.h>
|
||||
#include "openssl/param_build.h"
|
||||
#include "ec_local.h"
|
||||
@ -161,12 +162,15 @@ static int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
|
||||
int ptype, pklen;
|
||||
EC_KEY *eckey = NULL;
|
||||
X509_ALGOR *palg;
|
||||
OPENSSL_CTX *libctx = NULL;
|
||||
const char *propq = NULL;
|
||||
|
||||
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
|
||||
if (!X509_PUBKEY_get0_libctx(&libctx, &propq, pubkey)
|
||||
|| !X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
|
||||
return 0;
|
||||
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
|
||||
|
||||
eckey = eckey_type2param(ptype, pval, NULL, NULL);
|
||||
eckey = eckey_type2param(ptype, pval, libctx, propq);
|
||||
|
||||
if (!eckey) {
|
||||
ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
|
||||
|
@ -28,6 +28,10 @@ struct X509_pubkey_st {
|
||||
X509_ALGOR *algor;
|
||||
ASN1_BIT_STRING *public_key;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
/* extra data for the callback, used by d2i_PUBKEY_ex */
|
||||
OPENSSL_CTX *libctx;
|
||||
const char *propq;
|
||||
};
|
||||
|
||||
static int x509_pubkey_decode(EVP_PKEY **pk, const X509_PUBKEY *key);
|
||||
@ -228,32 +232,57 @@ EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key)
|
||||
}
|
||||
|
||||
/*
|
||||
* Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or
|
||||
* decode as X509_PUBKEY
|
||||
* Now three pseudo ASN1 routines that take an EVP_PKEY structure and encode
|
||||
* or decode as X509_PUBKEY
|
||||
*/
|
||||
|
||||
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
|
||||
EVP_PKEY *d2i_PUBKEY_ex(EVP_PKEY **a, const unsigned char **pp, long length,
|
||||
OPENSSL_CTX *libctx, const char *propq)
|
||||
{
|
||||
X509_PUBKEY *xpk;
|
||||
EVP_PKEY *pktmp;
|
||||
X509_PUBKEY *xpk, *xpk2 = NULL, **pxpk = NULL;
|
||||
EVP_PKEY *pktmp = NULL;
|
||||
const unsigned char *q;
|
||||
|
||||
q = *pp;
|
||||
xpk = d2i_X509_PUBKEY(NULL, &q, length);
|
||||
|
||||
/*
|
||||
* If libctx or propq are non-NULL, we take advantage of the reuse
|
||||
* feature. It's not generally recommended, but is safe enough for
|
||||
* newly created structures.
|
||||
*/
|
||||
if (libctx != NULL || propq != NULL) {
|
||||
xpk2 = OPENSSL_zalloc(sizeof(*xpk2));
|
||||
if (xpk2 == NULL) {
|
||||
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
xpk2->libctx = libctx;
|
||||
xpk2->propq = propq;
|
||||
pxpk = &xpk2;
|
||||
}
|
||||
xpk = d2i_X509_PUBKEY(pxpk, &q, length);
|
||||
if (xpk == NULL)
|
||||
return NULL;
|
||||
goto end;
|
||||
pktmp = X509_PUBKEY_get(xpk);
|
||||
X509_PUBKEY_free(xpk);
|
||||
xpk2 = NULL; /* We know that xpk == xpk2 */
|
||||
if (pktmp == NULL)
|
||||
return NULL;
|
||||
goto end;
|
||||
*pp = q;
|
||||
if (a != NULL) {
|
||||
EVP_PKEY_free(*a);
|
||||
*a = pktmp;
|
||||
}
|
||||
end:
|
||||
X509_PUBKEY_free(xpk2);
|
||||
return pktmp;
|
||||
}
|
||||
|
||||
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
|
||||
{
|
||||
return d2i_PUBKEY_ex(a, pp, length, NULL, NULL);
|
||||
}
|
||||
|
||||
int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp)
|
||||
{
|
||||
int ret = -1;
|
||||
@ -493,3 +522,13 @@ int X509_PUBKEY_eq(const X509_PUBKEY *a, const X509_PUBKEY *b)
|
||||
return -2;
|
||||
return EVP_PKEY_eq(pA, pB);
|
||||
}
|
||||
|
||||
int X509_PUBKEY_get0_libctx(OPENSSL_CTX **plibctx, const char **ppropq,
|
||||
const X509_PUBKEY *key)
|
||||
{
|
||||
if (plibctx)
|
||||
*plibctx = key->libctx;
|
||||
if (ppropq)
|
||||
*ppropq = key->propq;
|
||||
return 1;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
X509_PUBKEY_new, X509_PUBKEY_free, X509_PUBKEY_dup,
|
||||
X509_PUBKEY_set, X509_PUBKEY_get0, X509_PUBKEY_get,
|
||||
d2i_PUBKEY, i2d_PUBKEY, d2i_PUBKEY_bio, d2i_PUBKEY_fp,
|
||||
d2i_PUBKEY_ex, d2i_PUBKEY, i2d_PUBKEY, d2i_PUBKEY_bio, d2i_PUBKEY_fp,
|
||||
i2d_PUBKEY_fp, i2d_PUBKEY_bio, X509_PUBKEY_set0_param, X509_PUBKEY_get0_param,
|
||||
X509_PUBKEY_eq - SubjectPublicKeyInfo public key functions
|
||||
|
||||
@ -20,6 +20,8 @@ X509_PUBKEY_eq - SubjectPublicKeyInfo public key functions
|
||||
EVP_PKEY *X509_PUBKEY_get0(const X509_PUBKEY *key);
|
||||
EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key);
|
||||
|
||||
EVP_PKEY *d2i_PUBKEY_ex(EVP_PKEY **a, const unsigned char **pp, long length,
|
||||
OPENSSL_CTX *libctx, const char *propq);
|
||||
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length);
|
||||
int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp);
|
||||
|
||||
@ -58,9 +60,15 @@ X509_PUBKEY_get() is similar to X509_PUBKEY_get0() except the reference
|
||||
count on the returned key is incremented so it B<MUST> be freed using
|
||||
EVP_PKEY_free() after use.
|
||||
|
||||
d2i_PUBKEY() and i2d_PUBKEY() decode and encode an B<EVP_PKEY> structure
|
||||
using B<SubjectPublicKeyInfo> format. They otherwise follow the conventions of
|
||||
other ASN.1 functions such as d2i_X509().
|
||||
d2i_PUBKEY_ex() decodes an B<EVP_PKEY> structure using B<SubjectPublicKeyInfo>
|
||||
format. Some public key decoding implementations may use cryptographic
|
||||
algorithms. In this case the supplied library context I<libctx> and property
|
||||
query string I<propq> are used.
|
||||
d2i_PUBKEY() does the same as d2i_PUBKEY_ex() except that the default
|
||||
library context and property query string are used.
|
||||
|
||||
i2d_PUBKEY() encodes an B<EVP_PKEY> structure using B<SubjectPublicKeyInfo>
|
||||
format.
|
||||
|
||||
d2i_PUBKEY_bio(), d2i_PUBKEY_fp(), i2d_PUBKEY_bio() and i2d_PUBKEY_fp() are
|
||||
similar to d2i_PUBKEY() and i2d_PUBKEY() except they decode or encode using a
|
||||
|
@ -306,3 +306,6 @@ int asn1_item_digest_with_libctx(const ASN1_ITEM *it, const EVP_MD *type,
|
||||
unsigned int *len, OPENSSL_CTX *libctx,
|
||||
const char *propq);
|
||||
int X509_add_cert_new(STACK_OF(X509) **sk, X509 *cert, int flags);
|
||||
|
||||
int X509_PUBKEY_get0_libctx(OPENSSL_CTX **plibctx, const char **ppropq,
|
||||
const X509_PUBKEY *key);
|
||||
|
@ -522,6 +522,8 @@ EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key);
|
||||
int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain);
|
||||
long X509_get_pathlen(X509 *x);
|
||||
DECLARE_ASN1_ENCODE_FUNCTIONS_only(EVP_PKEY, PUBKEY)
|
||||
EVP_PKEY *d2i_PUBKEY_ex(EVP_PKEY **a, const unsigned char **pp, long length,
|
||||
OPENSSL_CTX *libctx, const char *propq);
|
||||
# ifndef OPENSSL_NO_RSA
|
||||
DECLARE_ASN1_ENCODE_FUNCTIONS_only(RSA, RSA_PUBKEY)
|
||||
# endif
|
||||
|
@ -127,7 +127,7 @@ static int der2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
|
||||
libctx, NULL);
|
||||
if (pkey == NULL) {
|
||||
derp = der;
|
||||
pkey = d2i_PUBKEY(NULL, &derp, der_len);
|
||||
pkey = d2i_PUBKEY_ex(NULL, &derp, der_len, libctx, NULL);
|
||||
}
|
||||
|
||||
if (pkey == NULL) {
|
||||
@ -142,7 +142,7 @@ static int der2key_deserialize(void *vctx, OSSL_CORE_BIO *cin,
|
||||
*
|
||||
* TODO(3.0): The check should be done with EVP_PKEY_is_a(), but
|
||||
* as long as we still have #legacy internal keys, it's safer to
|
||||
* use the type numbers in side the provider.
|
||||
* use the type numbers inside the provider.
|
||||
*/
|
||||
if (EVP_PKEY_id(pkey) == ctx->desc->type)
|
||||
key = ctx->desc->extract_key(pkey);
|
||||
|
@ -5262,3 +5262,4 @@ EVP_SIGNATURE_gettable_ctx_params ? 3_0_0 EXIST::FUNCTION:
|
||||
EVP_SIGNATURE_settable_ctx_params ? 3_0_0 EXIST::FUNCTION:
|
||||
EVP_KEYEXCH_gettable_ctx_params ? 3_0_0 EXIST::FUNCTION:
|
||||
EVP_KEYEXCH_settable_ctx_params ? 3_0_0 EXIST::FUNCTION:
|
||||
d2i_PUBKEY_ex ? 3_0_0 EXIST::FUNCTION:
|
||||
|
Loading…
x
Reference in New Issue
Block a user