Commit 2e976c3a38 for openssl.org

commit 2e976c3a3850f32ff13af59b2920585426d6571a
Author: Chris Baudouin, Jr. <cjb5326@rit.edu>
Date:   Sat Mar 21 18:08:01 2026 +0000

    Adds NULL checks for EVP_MD_CTX_get_pkey_ctx() return values

    Guard against potential NULL pointer dereferences when
    EVP_MD_CTX_get_pkey_ctx() is called and its result is used
    without validation. Store the return value in a local variable,
    check for NULL before passing it to subsequent functions, and
    remove redundant repeated calls.

    Fixes #27735

    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    MergeDate: Fri Mar 27 16:39:04 2026
    (Merged from https://github.com/openssl/openssl/pull/30522)

diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c
index 1088e20967..d83efa2816 100644
--- a/crypto/asn1/a_sign.c
+++ b/crypto/asn1/a_sign.c
@@ -163,6 +163,7 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
     const void *data, EVP_MD_CTX *ctx)
 {
     const EVP_MD *md;
+    EVP_PKEY_CTX *pctx;
     EVP_PKEY *pkey;
     unsigned char *buf_in = NULL, *buf_out = NULL;
     size_t inl = 0, outl = 0, outll = 0;
@@ -170,7 +171,14 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
     int rv, pkey_id;

     md = EVP_MD_CTX_get0_md(ctx);
-    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
+    pctx = EVP_MD_CTX_get_pkey_ctx(ctx);
+
+    if (pctx == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
+        goto err;
+    }
+
+    pkey = EVP_PKEY_CTX_get0_pkey(pctx);

     if (pkey == NULL) {
         ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
@@ -178,13 +186,11 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
     }

     if (pkey->ameth == NULL) {
-        EVP_PKEY_CTX *pctx = EVP_MD_CTX_get_pkey_ctx(ctx);
         OSSL_PARAM params[2];
         unsigned char aid[128];
         size_t aid_len = 0;

-        if (pctx == NULL
-            || !EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx)) {
+        if (!EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx)) {
             ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
             goto err;
         }
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c
index 3772939e74..5dae9e9c75 100644
--- a/crypto/asn1/a_verify.c
+++ b/crypto/asn1/a_verify.c
@@ -90,6 +90,7 @@ static int item_verify(const ASN1_ITEM *it, const X509_ALGOR *alg,
     const ASN1_BIT_STRING *signature, const void *data,
     EVP_MD_CTX *ctx, OSSL_LIB_CTX *libctx, const char *propq)
 {
+    EVP_PKEY_CTX *pctx;
     EVP_PKEY *pkey;
     EVP_MD *type = NULL;
     unsigned char *buf_in = NULL;
@@ -97,7 +98,14 @@ static int item_verify(const ASN1_ITEM *it, const X509_ALGOR *alg,
     int mdnid, pknid;
     size_t inll = 0;

-    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
+    pctx = EVP_MD_CTX_get_pkey_ctx(ctx);
+
+    if (pctx == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
+        return -1;
+    }
+
+    pkey = EVP_PKEY_CTX_get0_pkey(pctx);

     if (pkey == NULL) {
         ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
diff --git a/crypto/ocsp/ocsp_srv.c b/crypto/ocsp/ocsp_srv.c
index cc6a5bea5f..beecad63a2 100644
--- a/crypto/ocsp/ocsp_srv.c
+++ b/crypto/ocsp/ocsp_srv.c
@@ -167,14 +167,15 @@ int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp,
     const STACK_OF(X509) *certs, unsigned long flags)
 {
     OCSP_RESPID *rid;
+    EVP_PKEY_CTX *pkctx;
     EVP_PKEY *pkey;

-    if (ctx == NULL || EVP_MD_CTX_get_pkey_ctx(ctx) == NULL) {
+    if (ctx == NULL || (pkctx = EVP_MD_CTX_get_pkey_ctx(ctx)) == NULL) {
         ERR_raise(ERR_LIB_OCSP, OCSP_R_NO_SIGNER_KEY);
         goto err;
     }

-    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
+    pkey = EVP_PKEY_CTX_get0_pkey(pkctx);
     if (pkey == NULL || !X509_check_private_key(signer, pkey)) {
         ERR_raise(ERR_LIB_OCSP, OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
         goto err;
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 87bbaf04e3..1eb4649481 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -653,6 +653,10 @@ static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, const void *asn,
     int pad_mode;
     EVP_PKEY_CTX *pkctx = EVP_MD_CTX_get_pkey_ctx(ctx);

+    if (pkctx == NULL) {
+        ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
     if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
         return 0;
     if (pad_mode == RSA_PKCS1_PADDING)
diff --git a/ssl/record/methods/tls1_meth.c b/ssl/record/methods/tls1_meth.c
index e6360d995c..f89c365d7f 100644
--- a/ssl/record/methods/tls1_meth.c
+++ b/ssl/record/methods/tls1_meth.c
@@ -414,6 +414,7 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *rec, unsigned char *md
     EVP_MD_CTX *hash;
     size_t md_size;
     EVP_MD_CTX *hmac = NULL, *mac_ctx;
+    EVP_PKEY_CTX *pkctx;
     unsigned char header[13];
     int t;
     int ret = 0;
@@ -466,8 +467,13 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *rec, unsigned char *md
             &rec->orig_len);
         *p++ = OSSL_PARAM_construct_end();

-        if (!EVP_PKEY_CTX_set_params(EVP_MD_CTX_get_pkey_ctx(mac_ctx),
-                tls_hmac_params))
+        pkctx = EVP_MD_CTX_get_pkey_ctx(mac_ctx);
+        if (pkctx == NULL) {
+            RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+            goto end;
+        }
+
+        if (!EVP_PKEY_CTX_set_params(pkctx, tls_hmac_params))
             goto end;
     }