Commit 3986e51059 for openssl.org
commit 3986e51059db880b6795d42a9f4b0f9b2fb8fc90
Author: Bob Beck <beck@openssl.org>
Date: Fri Sep 4 14:34:14 2026 -0600
Remove the library context from X509_REQ
The X509_PUBKEY in a request holds the library context and property
query it needs to decode the public key, and the X509_REQ carried a
copy, just as X509 did. Worse, X509_REQ_new_ex() created the request
with ASN1_item_new() rather than ASN1_item_new_ex(), so only the copy
got the context and the public key was decoded in the default one.
Drop the copy, create the request with ASN1_item_new_ex() so the
X509_PUBKEY is seeded, and take the context from it in
X509_REQ_sign(), X509_REQ_digest() and d2i_X509_REQ_bio(). Remove
ossl_x509_req_set0_libctx(), which had no other callers.
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Merge-date: Mon Oct 26 19:04:41 2026
Merged-from: https://github.com/openssl/openssl/pull/32690
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index f102a74989..11ea028332 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -275,6 +275,8 @@ X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout)
int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
{
STACK_OF(X509_EXTENSION) *exts;
+ OSSL_LIB_CTX *libctx;
+ const char *propq;
int bad = 0;
if (x == NULL) {
@@ -287,9 +289,10 @@ int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
if (bad)
return 0;
x->req_info.enc.modified = 1;
+ ossl_x509_req_get0_libctx(x, &libctx, &propq);
return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL,
x->signature, &x->req_info, NULL,
- pkey, md, x->libctx, x->propq);
+ pkey, md, libctx, propq);
}
int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
@@ -470,10 +473,8 @@ X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req)
OSSL_LIB_CTX *libctx = NULL;
const char *propq = NULL;
- if (req != NULL && *req != NULL) {
- libctx = (*req)->libctx;
- propq = (*req)->propq;
- }
+ if (req != NULL && *req != NULL)
+ ossl_x509_req_get0_libctx(*req, &libctx, &propq);
return ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(X509_REQ), bp, req, libctx, propq);
}
@@ -809,8 +810,12 @@ int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
{
+ OSSL_LIB_CTX *libctx;
+ const char *propq;
+
+ ossl_x509_req_get0_libctx(data, &libctx, &propq);
return ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509_REQ), type, (char *)data,
- md, len, data->libctx, data->propq);
+ md, len, libctx, propq);
}
int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
diff --git a/crypto/x509/x_req.c b/crypto/x509/x_req.c
index 5137885a5b..5a70edda2f 100644
--- a/crypto/x509/x_req.c
+++ b/crypto/x509/x_req.c
@@ -60,13 +60,10 @@ static int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
case ASN1_OP_FREE_POST:
ASN1_OCTET_STRING_free(ret->distinguishing_id);
- OPENSSL_free(ret->propq);
break;
case ASN1_OP_DUP_POST: {
X509_REQ *old = exarg;
- if (!ossl_x509_req_set0_libctx(ret, old->libctx, old->propq))
- return 0;
if (old->req_info.pubkey != NULL) {
EVP_PKEY *pkey = X509_PUBKEY_get0(old->req_info.pubkey);
@@ -85,16 +82,12 @@ static int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
}
}
} break;
- case ASN1_OP_GET0_LIBCTX: {
- OSSL_LIB_CTX **libctx = exarg;
-
- *libctx = ret->libctx;
- } break;
- case ASN1_OP_GET0_PROPQ: {
- const char **propq = exarg;
-
- *propq = ret->propq;
- } break;
+ case ASN1_OP_GET0_LIBCTX:
+ ossl_x509_req_get0_libctx(ret, exarg, NULL);
+ break;
+ case ASN1_OP_GET0_PROPQ:
+ ossl_x509_req_get0_libctx(ret, NULL, exarg);
+ break;
}
return 1;
@@ -133,35 +126,18 @@ ASN1_OCTET_STRING *X509_REQ_get0_distinguishing_id(X509_REQ *x)
return x->distinguishing_id;
}
-/*
- * This should only be used if the X509_REQ object was embedded inside another
- * asn1 object and it needs a libctx to operate.
- * Use X509_REQ_new_ex() instead if possible.
- */
-int ossl_x509_req_set0_libctx(X509_REQ *x, OSSL_LIB_CTX *libctx,
- const char *propq)
+void ossl_x509_req_get0_libctx(const X509_REQ *x, OSSL_LIB_CTX **libctx,
+ const char **propq)
{
- if (x != NULL) {
- x->libctx = libctx;
- OPENSSL_free(x->propq);
- x->propq = NULL;
- if (propq != NULL) {
- x->propq = OPENSSL_strdup(propq);
- if (x->propq == NULL)
- return 0;
- }
- }
- return 1;
+ if (libctx != NULL)
+ *libctx = NULL;
+ if (propq != NULL)
+ *propq = NULL;
+ if (x->req_info.pubkey != NULL)
+ (void)ossl_x509_PUBKEY_get0_libctx(libctx, propq, x->req_info.pubkey);
}
X509_REQ *X509_REQ_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
{
- X509_REQ *req = NULL;
-
- req = (X509_REQ *)ASN1_item_new(ASN1_ITEM_rptr(X509_REQ));
- if (!ossl_x509_req_set0_libctx(req, libctx, propq)) {
- X509_REQ_free(req);
- req = NULL;
- }
- return req;
+ return (X509_REQ *)ASN1_item_new_ex(ASN1_ITEM_rptr(X509_REQ), libctx, propq);
}
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index f58bd9e90e..6343322ecd 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -99,8 +99,6 @@ struct X509_req_st {
/* Set on live certificates for authentication purposes */
ASN1_OCTET_STRING *distinguishing_id;
- OSSL_LIB_CTX *libctx;
- char *propq;
};
struct X509_crl_info_st {
@@ -450,8 +448,18 @@ void ossl_x509_get0_libctx(const X509 *x, OSSL_LIB_CTX **libctx,
const char **propq);
int ossl_x509_crl_set0_libctx(X509_CRL *x, OSSL_LIB_CTX *libctx,
const char *propq);
-int ossl_x509_req_set0_libctx(X509_REQ *x, OSSL_LIB_CTX *libctx,
- const char *propq);
+/**
+ * @brief Get the library context and property query of a request.
+ *
+ * As for ossl_x509_get0_libctx(): the request has none of its own; the
+ * one given to X509_REQ_new_ex() is kept by its X509_PUBKEY.
+ *
+ * @param x the certificate request
+ * @param libctx where to store the library context, may be NULL
+ * @param propq where to store the property query, may be NULL
+ */
+void ossl_x509_req_get0_libctx(const X509_REQ *x, OSSL_LIB_CTX **libctx,
+ const char **propq);
int ossl_asn1_item_digest_ex(const ASN1_ITEM *it, const EVP_MD *type,
void *data, unsigned char *md, unsigned int *len,
OSSL_LIB_CTX *libctx, const char *propq);