[openssl] master update

dev at ddvo.net dev at ddvo.net
Mon Feb 17 06:53:52 UTC 2020


The branch master has been updated
       via  31b28ad96aa841ae39d4009ebb15d90f2a2afdab (commit)
       via  235595c402bd7815f07f1f3f3babe9fcc247a206 (commit)
       via  ebf3006917e0e968af4a5d5c2c6379c5b866f801 (commit)
       via  fcc25beb7b430fb0588accbb63bf369d914eacba (commit)
      from  a21314dbbc56cd30580123d74b3106a628540965 (commit)


- Log -----------------------------------------------------------------
commit 31b28ad96aa841ae39d4009ebb15d90f2a2afdab
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Sat Feb 15 14:57:32 2020 +0100

    chunk 7 of CMP contribution to OpenSSL
    
    add CMP message validation and related tests; while doing so:
    * add ERR_add_error_mem_bio() to crypto/err/err_prn.c
    * move ossl_cmp_add_error_txt() as ERR_add_error_txt() to crypto/err/err_prn.c
    * add X509_STORE_CTX_print_verify_cb() to crypto/x509/t_x509.c,
      adding internally x509_print_ex_brief(), print_certs(), and print_store_certs()
    * move {ossl_cmp_,}X509_STORE_get1_certs() to crypto/x509/x509_lu.c
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Bernd Edlinger <bernd.edlinger at hotmail.de>
    (Merged from https://github.com/openssl/openssl/pull/10620)

commit 235595c402bd7815f07f1f3f3babe9fcc247a206
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Fri Dec 13 20:07:08 2019 +0100

    fix various formatting nits in CMP contribution chunks 1-6 found by the new util/check-format.pl
    
    in addition:
    correct wording in doc, comments, and parameter names: self-signed -> self-issued where appropriate
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Bernd Edlinger <bernd.edlinger at hotmail.de>
    (Merged from https://github.com/openssl/openssl/pull/10620)

commit ebf3006917e0e968af4a5d5c2c6379c5b866f801
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Fri Dec 13 19:50:20 2019 +0100

    improve CMP logging according to comments on CMP chunk 7 preview
    
    in particular:
    consolidate documentation of CMP logging and error reporting functions
    fix compilation problem with clang on some platforms
    rename OSSL_CMP_log etc. to ossl_cmp_log etc. since these macros are CMP-internal
    move chopping of trailing separator to ossl_cmp_add_error_txt(), also fix handling of leading separator
    internalize X509_print_ex_brief() as x509_print_ex_brief()
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Bernd Edlinger <bernd.edlinger at hotmail.de>
    (Merged from https://github.com/openssl/openssl/pull/10620)

commit fcc25beb7b430fb0588accbb63bf369d914eacba
Author: Dr. David von Oheimb <David.von.Oheimb at siemens.com>
Date:   Fri Dec 13 18:54:15 2019 +0100

    add internal doc files actually belonging to CMP contribution chunk 6
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Bernd Edlinger <bernd.edlinger at hotmail.de>
    (Merged from https://github.com/openssl/openssl/pull/10620)

-----------------------------------------------------------------------

Summary of changes:
 crypto/cmp/build.info                              |   2 +-
 crypto/cmp/cmp_asn.c                               |   3 +-
 crypto/cmp/cmp_ctx.c                               |  61 +-
 crypto/cmp/cmp_err.c                               |  28 +
 crypto/cmp/cmp_local.h                             | 181 +++--
 crypto/cmp/cmp_msg.c                               |  12 +-
 crypto/cmp/cmp_protect.c                           |   2 +-
 crypto/cmp/cmp_status.c                            |   4 +-
 crypto/cmp/cmp_util.c                              | 199 ++----
 crypto/cmp/cmp_vfy.c                               | 754 +++++++++++++++++++++
 crypto/crmf/crmf_asn.c                             |  18 +-
 crypto/crmf/crmf_lib.c                             |  30 +-
 crypto/crmf/crmf_local.h                           |  32 +-
 crypto/crmf/crmf_pbm.c                             |   2 +-
 crypto/err/err_prn.c                               | 120 +++-
 crypto/err/openssl.txt                             |  21 +-
 crypto/x509/t_x509.c                               | 105 +++
 crypto/x509/x509_err.c                             |   2 +
 crypto/x509/x509_lu.c                              |  35 +
 .../man3/ossl_cmp_asn1_octet_string_set1.pod       |  42 --
 doc/internal/man3/ossl_cmp_certReq_new.pod         | 193 ++++++
 doc/internal/man3/ossl_cmp_msg_create.pod          |  81 +++
 doc/internal/man3/ossl_cmp_msg_protect.pod         |  53 ++
 doc/internal/man3/ossl_cmp_print_log.pod           | 108 +++
 doc/internal/man3/ossl_cmp_sk_X509_add1_cert.pod   |   8 +-
 doc/man3/ERR_put_error.pod                         |  31 +-
 doc/man3/OSSL_CMP_log_open.pod                     |  51 +-
 doc/man3/OSSL_CMP_validate_msg.pod                 |  86 +++
 doc/man3/X509_STORE_CTX_set_verify_cb.pod          |  14 +-
 doc/man3/X509_STORE_get0_param.pod                 |  12 +-
 include/crypto/x509.h                              |   1 +
 include/openssl/cmp.h                              |  11 +-
 include/openssl/cmp_util.h                         |  30 +-
 include/openssl/cmperr.h                           |  24 +-
 include/openssl/crmf.h                             |  16 +-
 include/openssl/crmferr.h                          |   6 +-
 include/openssl/err.h                              |   2 +
 include/openssl/x509_vfy.h                         |   4 +-
 include/openssl/x509err.h                          |   1 +
 test/build.info                                    |   6 +-
 test/cmp_ctx_test.c                                |  82 +--
 test/cmp_hdr_test.c                                | 116 ++--
 test/cmp_msg_test.c                                |  18 +-
 test/cmp_protect_test.c                            |  15 +-
 test/cmp_vfy_test.c                                | 636 +++++++++++++++++
 test/recipes/65-test_cmp_vfy.t                     |  36 +
 .../EndEntity1.crt                                 |   0
 .../EndEntity2.crt                                 |   0
 .../65-test_cmp_vfy_data/IP_waitingStatus_PBM.der  | Bin 0 -> 1801 bytes
 .../65-test_cmp_vfy_data/IP_waitingStatus_PBM.txt  |   2 +
 .../IR_protected.der                               | Bin
 .../IR_protected_0_extraCerts.der                  | Bin 0 -> 1087 bytes
 .../IR_protected_2_extraCerts.der                  | Bin 0 -> 2833 bytes
 .../65-test_cmp_vfy_data/IR_rmprotection.der       | Bin 0 -> 1098 bytes
 .../IR_unprotected.der                             | Bin
 .../Intermediate_CA.crt                            |   0
 .../Root_CA.crt                                    |   0
 test/recipes/65-test_cmp_vfy_data/chain.txt        |   4 +
 test/recipes/65-test_cmp_vfy_data/client.crt       |  17 +
 test/recipes/65-test_cmp_vfy_data/insta.cert.pem   |  25 +
 test/recipes/65-test_cmp_vfy_data/insta.priv.pem   |  27 +
 .../recipes/65-test_cmp_vfy_data/insta_ca.cert.pem |  22 +
 .../server.crt                                     |   0
 .../server.pem => 65-test_cmp_vfy_data/server.key} |   0
 util/libcrypto.num                                 |   7 +
 util/missingcrypto.txt                             |   1 -
 util/other.syms                                    |  10 -
 67 files changed, 2892 insertions(+), 517 deletions(-)
 create mode 100644 crypto/cmp/cmp_vfy.c
 create mode 100644 doc/internal/man3/ossl_cmp_certReq_new.pod
 create mode 100644 doc/internal/man3/ossl_cmp_msg_create.pod
 create mode 100644 doc/internal/man3/ossl_cmp_msg_protect.pod
 create mode 100644 doc/internal/man3/ossl_cmp_print_log.pod
 create mode 100644 doc/man3/OSSL_CMP_validate_msg.pod
 create mode 100644 test/cmp_vfy_test.c
 create mode 100644 test/recipes/65-test_cmp_vfy.t
 copy test/recipes/{65-test_cmp_protect_data => 65-test_cmp_vfy_data}/EndEntity1.crt (100%)
 copy test/recipes/{65-test_cmp_protect_data => 65-test_cmp_vfy_data}/EndEntity2.crt (100%)
 create mode 100644 test/recipes/65-test_cmp_vfy_data/IP_waitingStatus_PBM.der
 create mode 100644 test/recipes/65-test_cmp_vfy_data/IP_waitingStatus_PBM.txt
 copy test/recipes/{65-test_cmp_protect_data => 65-test_cmp_vfy_data}/IR_protected.der (100%)
 create mode 100755 test/recipes/65-test_cmp_vfy_data/IR_protected_0_extraCerts.der
 create mode 100755 test/recipes/65-test_cmp_vfy_data/IR_protected_2_extraCerts.der
 create mode 100644 test/recipes/65-test_cmp_vfy_data/IR_rmprotection.der
 copy test/recipes/{65-test_cmp_protect_data => 65-test_cmp_vfy_data}/IR_unprotected.der (100%)
 copy test/recipes/{65-test_cmp_protect_data => 65-test_cmp_vfy_data}/Intermediate_CA.crt (100%)
 copy test/recipes/{65-test_cmp_protect_data => 65-test_cmp_vfy_data}/Root_CA.crt (100%)
 create mode 100644 test/recipes/65-test_cmp_vfy_data/chain.txt
 create mode 100644 test/recipes/65-test_cmp_vfy_data/client.crt
 create mode 100755 test/recipes/65-test_cmp_vfy_data/insta.cert.pem
 create mode 100755 test/recipes/65-test_cmp_vfy_data/insta.priv.pem
 create mode 100755 test/recipes/65-test_cmp_vfy_data/insta_ca.cert.pem
 copy test/recipes/{65-test_cmp_msg_data => 65-test_cmp_vfy_data}/server.crt (100%)
 copy test/recipes/{65-test_cmp_protect_data/server.pem => 65-test_cmp_vfy_data/server.key} (100%)

diff --git a/crypto/cmp/build.info b/crypto/cmp/build.info
index 760c3423ad..41a5899319 100644
--- a/crypto/cmp/build.info
+++ b/crypto/cmp/build.info
@@ -1,3 +1,3 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]= cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \
-        cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c
+        cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c
diff --git a/crypto/cmp/cmp_asn.c b/crypto/cmp/cmp_asn.c
index ca121b068a..e02076bb12 100644
--- a/crypto/cmp/cmp_asn.c
+++ b/crypto/cmp/cmp_asn.c
@@ -73,7 +73,8 @@ ASN1_SEQUENCE(OSSL_CMP_ERRORMSGCONTENT) = {
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ERRORMSGCONTENT)
 
 ASN1_ADB_TEMPLATE(infotypeandvalue_default) = ASN1_OPT(OSSL_CMP_ITAV,
-        infoValue.other, ASN1_ANY);
+                                                       infoValue.other,
+                                                       ASN1_ANY);
 /* ITAV means InfoTypeAndValue */
 ASN1_ADB(OSSL_CMP_ITAV) = {
     /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c
index fc89ea6bc8..714157a964 100644
--- a/crypto/cmp/cmp_ctx.c
+++ b/crypto/cmp/cmp_ctx.c
@@ -80,7 +80,7 @@ int OSSL_CMP_CTX_set1_untrusted_certs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs)
     sk_X509_pop_free(ctx->untrusted_certs, X509_free);
     ctx->untrusted_certs = untrusted_certs;
     return 1;
-err:
+ err:
     sk_X509_pop_free(untrusted_certs, X509_free);
     return 0;
 }
@@ -301,7 +301,7 @@ static size_t ossl_cmp_log_trace_cb(const char *buf, size_t cnt,
                                     int category, int cmd, void *vdata)
 {
     OSSL_CMP_CTX *ctx = vdata;
-    const char *prefix_msg;
+    const char *msg;
     OSSL_CMP_severity level = -1;
     char *func = NULL;
     char *file = NULL;
@@ -312,14 +312,14 @@ static size_t ossl_cmp_log_trace_cb(const char *buf, size_t cnt,
     if (ctx->log_cb == NULL)
         return 1; /* silently drop message */
 
-    prefix_msg = ossl_cmp_log_parse_metadata(buf, &level, &func, &file, &line);
+    msg = ossl_cmp_log_parse_metadata(buf, &level, &func, &file, &line);
 
     if (level > ctx->log_verbosity) /* excludes the case level is unknown */
         goto end; /* suppress output since severity is not sufficient */
 
     if (!ctx->log_cb(func != NULL ? func : "(no func)",
                      file != NULL ? file : "(no file)",
-                     line, level, prefix_msg))
+                     line, level, msg))
         cnt = 0;
 
  end:
@@ -329,6 +329,57 @@ static size_t ossl_cmp_log_trace_cb(const char *buf, size_t cnt,
 }
 #endif
 
+/* Print CMP log messages (i.e., diagnostic info) via the log cb of the ctx */
+int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
+                       const char *func, const char *file, int line,
+                       const char *level_str, const char *format, ...)
+{
+    va_list args;
+    char hugebuf[1024 * 2];
+    int res = 0;
+
+    if (ctx == NULL || ctx->log_cb == NULL)
+        return 1; /* silently drop message */
+
+    if (level > ctx->log_verbosity) /* excludes the case level is unknown */
+        return 1; /* suppress output since severity is not sufficient */
+
+    if (format == NULL)
+        return 0;
+
+    va_start(args, format);
+
+    if (func == NULL)
+        func = "(unset function name)";
+    if (file == NULL)
+        file = "(unset file name)";
+    if (level_str == NULL)
+        level_str = "(unset level string)";
+
+#ifndef OPENSSL_NO_TRACE
+    if (OSSL_TRACE_ENABLED(CMP)) {
+        OSSL_TRACE_BEGIN(CMP) {
+            int printed =
+                BIO_snprintf(hugebuf, sizeof(hugebuf),
+                             "%s:%s:%d:" OSSL_CMP_LOG_PREFIX "%s: ",
+                             func, file, line, level_str);
+            if (printed > 0 && (size_t)printed < sizeof(hugebuf)) {
+                if (BIO_vsnprintf(hugebuf + printed,
+                                  sizeof(hugebuf) - printed, format, args) > 0)
+                    res = BIO_puts(trc_out, hugebuf) > 0;
+            }
+        } OSSL_TRACE_END(CMP);
+    }
+#else /* compensate for disabled trace API */
+    {
+        if (BIO_vsnprintf(hugebuf, sizeof(hugebuf), format, args) > 0)
+            res = ctx->log_cb(func, file, line, level, hugebuf);
+    }
+#endif
+    va_end(args);
+    return res;
+}
+
 /*
  * Set a callback function for error reporting and logging messages.
  * Returns 1 on success, 0 on error
@@ -768,7 +819,7 @@ int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
  * returns 1 on success, 0 on error
  */
 int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
-                            const ASN1_OCTET_STRING *nonce)
+                                 const ASN1_OCTET_STRING *nonce)
 {
     if (!ossl_assert(ctx != NULL))
         return 0;
diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c
index a6d59f9fc4..f82ef9e325 100644
--- a/crypto/cmp/cmp_err.c
+++ b/crypto/cmp/cmp_err.c
@@ -14,6 +14,8 @@
 #ifndef OPENSSL_NO_ERR
 
 static const ERR_STRING_DATA CMP_str_reasons[] = {
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ALGORITHM_NOT_SUPPORTED),
+    "algorithm not supported"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_REQUEST_ID), "bad request id"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTID_NOT_FOUND), "certid not found"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_FOUND),
@@ -50,6 +52,10 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     "error protecting message"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_SETTING_CERTHASH),
     "error setting certhash"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_PROTECTION),
+    "error validating protection"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY),
+    "failed extracting pubkey"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILURE_OBTAINING_RANDOM),
     "failure obtaining random"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAIL_INFO_OUT_OF_RANGE),
@@ -57,19 +63,38 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION),
     "missing key input for creating protection"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE),
+    "missing key usage digitalsignature"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PRIVATE_KEY),
     "missing private key"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_PROTECTION), "missing protection"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_SENDER_IDENTIFICATION),
     "missing sender identification"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_TRUST_STORE),
+    "missing trust store"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_SAN_SOURCES),
     "multiple san sources"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_STDIO), "no stdio"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_SUITABLE_SENDER_CERT),
+    "no suitable sender cert"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NULL_ARGUMENT), "null argument"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKIBODY_ERROR), "pkibody error"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKISTATUSINFO_NOT_FOUND),
     "pkistatusinfo not found"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE),
     "potentially invalid certificate"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECIPNONCE_UNMATCHED),
+    "recipnonce unmatched"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_NOT_ACCEPTED),
+    "request not accepted"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED),
+    "sender generalname type not supported"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG),
+    "srvcert does not validate msg"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSACTIONID_UNMATCHED),
+    "transactionid unmatched"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
     "unknown algorithm id"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"},
@@ -77,8 +102,11 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     "unsupported algorithm"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE),
     "unsupported key type"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC),
+    "unsupported protection alg dhbasedmac"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_ALGORITHM_OID),
     "wrong algorithm oid"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_PBM_VALUE), "wrong pbm value"},
     {0, NULL}
 };
 
diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h
index f705cb24be..015a3d4e67 100644
--- a/crypto/cmp/cmp_local.h
+++ b/crypto/cmp/cmp_local.h
@@ -48,16 +48,23 @@ struct ossl_cmp_ctx_st {
     void *http_cb_arg; /* allows to store optional argument to cb */
 
     /* server authentication */
-    int unprotectedErrors; /* accept neg. response with no/invalid protection */
-                           /* to cope with broken server */
+    /*
+     * unprotectedErrors may be set as workaround for broken server responses:
+     * accept missing or invalid protection of regular error messages, negative
+     * certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf
+     */
+    int unprotectedErrors;
     X509 *srvCert; /* certificate used to identify the server */
     X509 *validatedSrvCert; /* caches any already validated server cert */
     X509_NAME *expected_sender; /* expected sender in pkiheader of response */
     X509_STORE *trusted; /* trust store maybe w CRLs and cert verify callback */
     STACK_OF(X509) *untrusted_certs; /* untrusted (intermediate) certs */
     int ignore_keyusage; /* ignore key usage entry when validating certs */
-    int permitTAInExtraCertsForIR; /* allow use of root certs in extracerts */
-             /* when validating message protection; used for 3GPP-style E.7 */
+    /*
+     * permitTAInExtraCertsForIR allows use of root certs in extracerts
+     * when validating message protection; this is used for 3GPP-style E.7
+     */
+    int permitTAInExtraCertsForIR;
 
     /* client authentication */
     int unprotectedSend; /* send unprotected PKI messages */
@@ -536,68 +543,108 @@ typedef struct ossl_cmp_pkibody_st {
         OSSL_CMP_CERTREPMESSAGE *ip; /* 1 */
         OSSL_CRMF_MSGS *cr; /* 2 */
         OSSL_CMP_CERTREPMESSAGE *cp; /* 3 */
-        /* p10cr      [4]  CertificationRequest,     --imported from [PKCS10] */
-        /*
+        /*-
+         * p10cr      [4]  CertificationRequest,     --imported from [PKCS10]
+         *
          * PKCS10_CERTIFICATIONREQUEST is effectively X509_REQ
          * so it is used directly
          */
         X509_REQ *p10cr; /* 4 */
-        /* popdecc    [5]  POPODecKeyChallContent, --pop Challenge */
-        /* POPODecKeyChallContent ::= SEQUENCE OF Challenge */
+        /*-
+         * popdecc    [5]  POPODecKeyChallContent, --pop Challenge
+         *
+         * POPODecKeyChallContent ::= SEQUENCE OF Challenge
+         */
         OSSL_CMP_POPODECKEYCHALLCONTENT *popdecc; /* 5 */
-        /* popdecr    [6]  POPODecKeyRespContent,  --pop Response */
-        /* POPODecKeyRespContent ::= SEQUENCE OF INTEGER */
+        /*-
+         * popdecr    [6]  POPODecKeyRespContent,  --pop Response
+         *
+         * POPODecKeyRespContent ::= SEQUENCE OF INTEGER
+         */
         OSSL_CMP_POPODECKEYRESPCONTENT *popdecr; /* 6 */
         OSSL_CRMF_MSGS *kur; /* 7 */
         OSSL_CMP_CERTREPMESSAGE *kup; /* 8 */
         OSSL_CRMF_MSGS *krr; /* 9 */
 
-        /* krp        [10] KeyRecRepContent,         --Key Recovery Response */
+        /*-
+         * krp        [10] KeyRecRepContent,         --Key Recovery Response
+         */
         OSSL_CMP_KEYRECREPCONTENT *krp; /* 10 */
-        /* rr         [11] RevReqContent,            --Revocation Request */
+        /*-
+         * rr         [11] RevReqContent,            --Revocation Request
+         */
         OSSL_CMP_REVREQCONTENT *rr; /* 11 */
-        /* rp         [12] RevRepContent,            --Revocation Response */
+        /*-
+         * rp         [12] RevRepContent,            --Revocation Response
+         */
         OSSL_CMP_REVREPCONTENT *rp; /* 12 */
-        /* ccr        [13] CertReqMessages,          --Cross-Cert. Request */
+        /*-
+         * ccr        [13] CertReqMessages,          --Cross-Cert. Request
+         */
         OSSL_CRMF_MSGS *ccr; /* 13 */
-        /* ccp        [14] CertRepMessage,           --Cross-Cert. Response */
+        /*-
+         * ccp        [14] CertRepMessage,           --Cross-Cert. Response
+         */
         OSSL_CMP_CERTREPMESSAGE *ccp; /* 14 */
-        /* ckuann     [15] CAKeyUpdAnnContent,       --CA Key Update Ann. */
+        /*-
+         * ckuann     [15] CAKeyUpdAnnContent,       --CA Key Update Ann.
+         */
         OSSL_CMP_CAKEYUPDANNCONTENT *ckuann; /* 15 */
-        /* cann       [16] CertAnnContent,           --Certificate Ann. */
-        /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
-        X509 *cann;         /* 16 */
-        /* rann       [17] RevAnnContent,            --Revocation Ann. */
+        /*-
+         * cann       [16] CertAnnContent,           --Certificate Ann.
+         * OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly
+         */
+        X509 *cann; /* 16 */
+        /*-
+         * rann       [17] RevAnnContent,            --Revocation Ann.
+         */
         OSSL_CMP_REVANNCONTENT *rann; /* 17 */
-        /* crlann     [18] CRLAnnContent,            --CRL Announcement */
-        /* CRLAnnContent ::= SEQUENCE OF CertificateList */
-        OSSL_CMP_CRLANNCONTENT *crlann;
-        /* PKIConfirmContent ::= NULL */
-        /* pkiconf    [19] PKIConfirmContent,        --Confirmation */
-        /* OSSL_CMP_PKICONFIRMCONTENT would be only a typedef of ASN1_NULL */
-        /* OSSL_CMP_CONFIRMCONTENT *pkiconf; */
-        /*
+        /*-
+         * crlann     [18] CRLAnnContent,            --CRL Announcement
+         * CRLAnnContent ::= SEQUENCE OF CertificateList
+         */
+        OSSL_CMP_CRLANNCONTENT *crlann; /* 18 */
+        /*-
+         * PKIConfirmContent ::= NULL
+         * pkiconf    [19] PKIConfirmContent,        --Confirmation
+         * OSSL_CMP_PKICONFIRMCONTENT would be only a typedef of ASN1_NULL
+         * OSSL_CMP_CONFIRMCONTENT *pkiconf;
+         *
          * NOTE: this should ASN1_NULL according to the RFC
          * but there might be a struct in it when sent from faulty servers...
          */
         ASN1_TYPE *pkiconf; /* 19 */
-        /* nested     [20] NestedMessageContent,     --Nested Message */
-        /* NestedMessageContent ::= PKIMessages */
+        /*-
+         * nested     [20] NestedMessageContent,     --Nested Message
+         * NestedMessageContent ::= PKIMessages
+         */
         OSSL_CMP_MSGS *nested; /* 20 */
-        /* genm       [21] GenMsgContent,            --General Message */
-        /* GenMsgContent ::= SEQUENCE OF InfoTypeAndValue */
+        /*-
+         * genm       [21] GenMsgContent,            --General Message
+         * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+         */
         OSSL_CMP_GENMSGCONTENT *genm; /* 21 */
-        /* genp       [22] GenRepContent,            --General Response */
-        /* GenRepContent ::= SEQUENCE OF InfoTypeAndValue */
+        /*-
+         * genp       [22] GenRepContent,            --General Response
+         * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+         */
         OSSL_CMP_GENREPCONTENT *genp; /* 22 */
-        /* error      [23] ErrorMsgContent,          --Error Message */
+        /*-
+         * error      [23] ErrorMsgContent,          --Error Message
+         */
         OSSL_CMP_ERRORMSGCONTENT *error; /* 23 */
-        /* certConf [24] CertConfirmContent,     --Certificate confirm */
+        /*-
+         * certConf [24] CertConfirmContent,     --Certificate confirm
+         */
         OSSL_CMP_CERTCONFIRMCONTENT *certConf; /* 24 */
-        /* pollReq    [25] PollReqContent,           --Polling request */
-        OSSL_CMP_POLLREQCONTENT *pollReq;
-        /* pollRep    [26] PollRepContent            --Polling response */
-        OSSL_CMP_POLLREPCONTENT *pollRep;
+        /*-
+         * pollReq    [25] PollReqContent,           --Polling request
+         */
+        OSSL_CMP_POLLREQCONTENT *pollReq; /* 25 */
+        /*-
+         * pollRep    [26] PollRepContent            --Polling response
+         */
+        OSSL_CMP_POLLREPCONTENT *pollRep; /* 26 */
     } value;
 } OSSL_CMP_PKIBODY;
 DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKIBODY)
@@ -699,18 +746,15 @@ int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
 const char *ossl_cmp_log_parse_metadata(const char *buf,
                                         OSSL_CMP_severity *level, char **func,
                                         char **file, int *line);
-/* workaround for 4096 bytes limitation of ERR_print_errors_cb() */
-void ossl_cmp_add_error_txt(const char *separator, const char *txt);
-# define ossl_cmp_add_error_data(txt) ossl_cmp_add_error_txt(" : ", txt)
-# define ossl_cmp_add_error_line(txt) ossl_cmp_add_error_txt("\n", txt)
+# define ossl_cmp_add_error_data(txt) ERR_add_error_txt(" : ", txt)
+# define ossl_cmp_add_error_line(txt) ERR_add_error_txt("\n", txt)
 /* functions manipulating lists of certificates etc could be generally useful */
-int ossl_cmp_sk_X509_add1_cert (STACK_OF(X509) *sk, X509 *cert,
-                                int no_dup, int prepend);
+int ossl_cmp_sk_X509_add1_cert(STACK_OF(X509) *sk, X509 *cert,
+                               int no_dup, int prepend);
 int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
-                                int no_self_signed, int no_dups, int prepend);
+                                int no_self_issued, int no_dups, int prepend);
 int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
-                                   int only_self_signed);
-STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store);
+                                   int only_self_issued);
 int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
                                     const ASN1_OCTET_STRING *src);
 int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
@@ -718,6 +762,31 @@ int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
 STACK_OF(X509) *ossl_cmp_build_cert_chain(STACK_OF(X509) *certs, X509 *cert);
 
 /* from cmp_ctx.c */
+int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
+                       const char *func, const char *file, int line,
+                       const char *level_str, const char *format, ...);
+# define ossl_cmp_log(level, ctx, msg) \
+    ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+                       OPENSSL_LINE, #level, "%s", msg)
+# define ossl_cmp_log1(level, ctx, fmt, arg1) \
+    ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+                       OPENSSL_LINE, #level, fmt, arg1)
+# define ossl_cmp_log2(level, ctx, fmt, arg1, arg2) \
+    ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+                       OPENSSL_LINE, #level, fmt, arg1, arg2)
+# define ossl_cmp_log3(level, ctx, fmt, arg1, arg2, arg3) \
+    ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+                       OPENSSL_LINE, #level, fmt, arg1, arg2, arg3)
+# define ossl_cmp_log4(level, ctx, fmt, arg1, arg2, arg3, arg4)         \
+    ossl_cmp_print_log(OSSL_CMP_LOG_##level, ctx, OPENSSL_FUNC, OPENSSL_FILE, \
+                       OPENSSL_LINE, #level, fmt, arg1, arg2, arg3, arg4)
+# define OSSL_CMP_LOG_ERROR OSSL_CMP_LOG_ERR
+# define OSSL_CMP_LOG_WARN OSSL_CMP_LOG_WARNING
+# define ossl_cmp_alert(ctx, msg) ossl_cmp_log(ALERT, ctx, msg)
+# define ossl_cmp_err(ctx, msg)   ossl_cmp_log(ERROR, ctx, msg)
+# define ossl_cmp_warn(ctx, msg)  ossl_cmp_log(WARN,  ctx, msg)
+# define ossl_cmp_info(ctx, msg)  ossl_cmp_log(INFO,  ctx, msg)
+# define ossl_cmp_debug(ctx, msg) ossl_cmp_log(DEBUG, ctx, msg)
 int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert);
 int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status);
 int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
@@ -825,7 +894,7 @@ OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
 OSSL_CMP_PKISI *
 ossl_cmp_revrepcontent_get_pkistatusinfo(OSSL_CMP_REVREPCONTENT *rrep, int rsid);
 OSSL_CRMF_CERTID *ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep,
-                                               int rsid);
+                                                    int rsid);
 OSSL_CMP_POLLREP *
 ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
                                      int rid);
@@ -836,9 +905,9 @@ X509 *ossl_cmp_certresponse_get1_certificate(EVP_PKEY *privkey,
                                              const OSSL_CMP_CERTRESPONSE *crep);
 OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file);
 /* BIO definitions */
-#  define OSSL_d2i_CMP_MSG_bio(bp, p) \
+# define OSSL_d2i_CMP_MSG_bio(bp, p) \
     ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new, d2i_OSSL_CMP_MSG, bp, p)
-#  define OSSL_i2d_CMP_MSG_bio(bp, o) \
+# define OSSL_i2d_CMP_MSG_bio(bp, o) \
     ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bp, o)
 
 /* from cmp_protect.c */
@@ -848,4 +917,12 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_MSG *msg,
 int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
 int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
 
+/* from cmp_vfy.c */
+typedef int (*ossl_cmp_allow_unprotected_cb_t)(const OSSL_CMP_CTX *ctx,
+                                               const OSSL_CMP_MSG *msg,
+                                               int invalid_protection, int arg);
+int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+                                ossl_cmp_allow_unprotected_cb_t cb, int cb_arg);
+int ossl_cmp_verify_popo(const OSSL_CMP_MSG *msg, int accept_RAVerified);
+
 #endif /* !defined OSSL_CRYPTO_CMP_LOCAL_H */
diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c
index 00381932f3..c794dc98bb 100644
--- a/crypto/cmp/cmp_msg.c
+++ b/crypto/cmp/cmp_msg.c
@@ -232,7 +232,7 @@ static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype,
              */
             || !OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_MSG_get0_tmpl(crm), rkey,
                                             subject, ctx->issuer,
-                                            NULL/* serial */))
+                                            NULL /* serial */))
         goto err;
     if (ctx->days != 0) {
         time_t notBefore, notAfter;
@@ -442,8 +442,8 @@ OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx)
 
     /* Fill the template from the contents of the certificate to be revoked */
     if (!OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
-                                     NULL/* pubkey would be redundant */,
-                                     NULL/* subject would be redundant */,
+                                     NULL /* pubkey would be redundant */,
+                                     NULL /* subject would be redundant */,
                                      X509_get_issuer_name(ctx->oldCert),
                                      X509_get_serialNumber(ctx->oldCert)))
         goto err;
@@ -569,7 +569,7 @@ int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
         return 0;
 
     for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) {
-        if ((itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs,i))) == NULL)
+        if ((itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i))) == NULL)
             return 0;
         if (!ossl_cmp_msg_gen_push0_ITAV(msg, itav)) {
             OSSL_CMP_ITAV_free(itav);
@@ -643,8 +643,8 @@ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
     }
     if (errorDetails != NULL)
         if ((msg->body->value.error->errorDetails =
-            sk_ASN1_UTF8STRING_deep_copy(errorDetails, ASN1_STRING_dup,
-                                         ASN1_STRING_free)) == NULL)
+             sk_ASN1_UTF8STRING_deep_copy(errorDetails, ASN1_STRING_dup,
+                                          ASN1_STRING_free)) == NULL)
             goto err;
 
     if (!unprotected && !ossl_cmp_msg_protect(ctx, msg))
diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c
index 7db3440f32..c1b4b8584d 100644
--- a/crypto/cmp/cmp_protect.c
+++ b/crypto/cmp/cmp_protect.c
@@ -156,7 +156,7 @@ int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
             STACK_OF(X509) *chain =
                 ossl_cmp_build_cert_chain(ctx->untrusted_certs, ctx->clCert);
             int res = ossl_cmp_sk_X509_add1_certs(msg->extraCerts, chain,
-                                                  1 /* no self-signed */,
+                                                  1 /* no self-issued */,
                                                   1 /* no duplicates */, 0);
             sk_X509_pop_free(chain, X509_free);
             if (res == 0)
diff --git a/crypto/cmp/cmp_status.c b/crypto/cmp/cmp_status.c
index a5f6b29490..7ebc57d37b 100644
--- a/crypto/cmp/cmp_status.c
+++ b/crypto/cmp/cmp_status.c
@@ -61,7 +61,7 @@ const char *ossl_cmp_PKIStatus_to_string(int status)
             char buf[40];
             BIO_snprintf(buf, sizeof(buf), "PKIStatus: invalid=%d", status);
             CMPerr(0, CMP_R_ERROR_PARSING_PKISTATUS);
-            ossl_cmp_add_error_data(buf);
+            ERR_add_error_data(1, buf);
             return NULL;
         }
     }
@@ -195,7 +195,7 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
     int printed_chars;
     int failinfo_found = 0;
     int n_status_strings;
-    char* write_ptr = buf;
+    char *write_ptr = buf;
 
 #define ADVANCE_BUFFER                                         \
     if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \
diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c
index 0390c23e66..ad4ae66454 100644
--- a/crypto/cmp/cmp_util.c
+++ b/crypto/cmp/cmp_util.c
@@ -69,7 +69,8 @@ static OSSL_CMP_severity parse_level(const char *level)
 }
 
 const char *ossl_cmp_log_parse_metadata(const char *buf,
-                 OSSL_CMP_severity *level, char **func, char **file, int *line)
+                                        OSSL_CMP_severity *level,
+                                        char **func, char **file, int *line)
 {
     const char *p_func = buf;
     const char *p_file = buf == NULL ? NULL : strchr(buf, ':');
@@ -106,129 +107,75 @@ const char *ossl_cmp_log_parse_metadata(const char *buf,
     return msg;
 }
 
-
+#define UNKNOWN_FUNC "(unknown function)" /* the default for OPENSSL_FUNC */
 /*
- * auxiliary function for incrementally reporting texts via the error queue
+ * substitute fallback if component/function name is NULL or empty or contains
+ * just pseudo-information "(unknown function)" due to -pedantic and macros.h
  */
-static void put_error(int lib, const char *func, int reason,
-                      const char *file, int line)
+static const char *improve_location_name(const char *func, const char *fallback)
 {
-    ERR_new();
-    ERR_set_debug(file, line, func);
-    ERR_set_error(lib, reason, NULL /* no data here, so fmt is NULL */);
+    if (!ossl_assert(fallback != NULL))
+        return NULL;
+    return func == NULL || *func == '\0' || strcmp(func, UNKNOWN_FUNC) == 0
+        ? fallback : func;
 }
 
-#define ERR_print_errors_cb_LIMIT 4096 /* size of char buf[] variable there */
-#define TYPICAL_MAX_OUTPUT_BEFORE_DATA 100
-#define MAX_DATA_LEN (ERR_print_errors_cb_LIMIT-TYPICAL_MAX_OUTPUT_BEFORE_DATA)
-void ossl_cmp_add_error_txt(const char *separator, const char *txt)
+int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file,
+                          int line, OSSL_CMP_severity level, const char *msg)
 {
-    const char *file = NULL;
-    int line;
-    const char *func = NULL;
-    const char *data = NULL;
-    int flags;
-    unsigned long err = ERR_peek_last_error();
-
-    if (separator == NULL)
-        separator = "";
-    if (err == 0)
-        put_error(ERR_LIB_CMP, NULL, 0, "", 0);
-
-    do {
-        size_t available_len, data_len;
-        const char *curr = txt, *next = txt;
-        char *tmp;
-
-        ERR_peek_last_error_all(&file, &line, &func, &data, &flags);
-        if ((flags & ERR_TXT_STRING) == 0) {
-            data = "";
-            separator = "";
-        }
-        data_len = strlen(data);
-
-        /* workaround for limit of ERR_print_errors_cb() */
-        if (data_len >= MAX_DATA_LEN
-                || strlen(separator) >= (size_t)(MAX_DATA_LEN - data_len))
-            available_len = 0;
-        else
-            available_len = MAX_DATA_LEN - data_len - strlen(separator) - 1;
-        /* MAX_DATA_LEN > available_len >= 0 */
-
-        if (separator[0] == '\0') {
-            const size_t len_next = strlen(next);
-
-            if (len_next <= available_len) {
-                next += len_next;
-                curr = NULL; /* no need to split */
-            }
-            else {
-                next += available_len;
-                curr = next; /* will split at this point */
-            }
-        } else {
-            while (*next != '\0' && (size_t)(next - txt) <= available_len) {
-                curr = next;
-                next = strstr(curr, separator);
-                if (next != NULL)
-                    next += strlen(separator);
-                else
-                    next = curr + strlen(curr);
-            }
-            if ((size_t)(next - txt) <= available_len)
-                curr = NULL; /* the above loop implies *next == '\0' */
-        }
-        if (curr != NULL) {
-            /* split error msg at curr since error data would get too long */
-            if (curr != txt) {
-                tmp = OPENSSL_strndup(txt, curr - txt);
-                if (tmp == NULL)
-                    return;
-                ERR_add_error_data(2, separator, tmp);
-                OPENSSL_free(tmp);
-            }
-            put_error(ERR_LIB_CMP, func, err, file, line);
-            txt = curr;
-        } else {
-            ERR_add_error_data(2, separator, txt);
-            txt = next; /* finished */
-        }
-    } while (*txt != '\0');
+    const char *level_string =
+        level == OSSL_CMP_LOG_EMERG ? "EMERG" :
+        level == OSSL_CMP_LOG_ALERT ? "ALERT" :
+        level == OSSL_CMP_LOG_CRIT ? "CRIT" :
+        level == OSSL_CMP_LOG_ERR ? "error" :
+        level == OSSL_CMP_LOG_WARNING ? "warning" :
+        level == OSSL_CMP_LOG_NOTICE ? "NOTE" :
+        level == OSSL_CMP_LOG_INFO ? "info" :
+        level == OSSL_CMP_LOG_DEBUG ? "DEBUG" : "(unknown level)";
+
+#ifndef NDEBUG
+    if (BIO_printf(bio, "%s:%s:%d:", improve_location_name(component, "CMP"),
+                   file, line) < 0)
+        return 0;
+#endif
+    return BIO_printf(bio, OSSL_CMP_LOG_PREFIX"%s: %s\n",
+                      level_string, msg) >= 0;
 }
 
+#define ERR_PRINT_BUF_SIZE 4096
 /* this is similar to ERR_print_errors_cb, but uses the CMP-specific cb type */
 void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn)
 {
     unsigned long err;
-    char msg[ERR_print_errors_cb_LIMIT];
+    char msg[ERR_PRINT_BUF_SIZE];
     const char *file = NULL, *func = NULL, *data = NULL;
     int line, flags;
 
-    if (log_fn == NULL) {
-#ifndef OPENSSL_NO_STDIO
-        ERR_print_errors_fp(stderr);
-#else
-        /* CMPerr(0, CMP_R_NO_STDIO) makes no sense during error printing */
-#endif
-        return;
-    }
-
     while ((err = ERR_get_error_all(&file, &line, &func, &data, &flags)) != 0) {
-        char component[128];
-        const char *func_ = func != NULL && *func != '\0' ? func : "<unknown>";
+        const char *component =
+            improve_location_name(func, ERR_lib_error_string(err));
 
         if (!(flags & ERR_TXT_STRING))
             data = NULL;
-#ifdef OSSL_CMP_PRINT_LIBINFO
-        BIO_snprintf(component, sizeof(component), "OpenSSL:%s:%s",
-                     ERR_lib_error_string(err), func_);
+        BIO_snprintf(msg, sizeof(msg), "%s%s%s", ERR_reason_error_string(err),
+                     data == NULL || *data == '\0' ? "" : " : ",
+                     data == NULL ? "" : data);
+        if (log_fn == NULL) {
+#ifndef OPENSSL_NO_STDIO
+            BIO *bio = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+            if (bio != NULL) {
+                OSSL_CMP_print_to_bio(bio, component, file, line,
+                                      OSSL_CMP_LOG_ERR, msg);
+                BIO_free(bio);
+            }
 #else
-        BIO_snprintf(component, sizeof(component), "%s",func_);
+            /* CMPerr(0, CMP_R_NO_STDIO) makes no sense during error printing */
 #endif
-        BIO_snprintf(msg, sizeof(msg), "%s%s%s", ERR_reason_error_string(err),
-                     data == NULL ? "" : " : ", data == NULL ? "" : data);
-        if (log_fn(component, file, line, OSSL_CMP_LOG_ERR, msg) <= 0)
-            break;              /* abort outputting the error report */
+        } else {
+            if (log_fn(component, file, line, OSSL_CMP_LOG_ERR, msg) <= 0)
+                break; /* abort outputting the error report */
+        }
     }
 }
 
@@ -266,7 +213,7 @@ int ossl_cmp_sk_X509_add1_cert(STACK_OF(X509) *sk, X509 *cert,
 }
 
 int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
-                                int no_self_signed, int no_dups, int prepend)
+                                int no_self_issued, int no_dups, int prepend)
 /* compiler would allow 'const' for the list of certs, yet they are up-ref'ed */
 {
     int i;
@@ -278,7 +225,7 @@ int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
     for (i = 0; i < sk_X509_num(certs); i++) { /* certs may be NULL */
         X509 *cert = sk_X509_value(certs, i);
 
-        if (!no_self_signed || X509_check_issued(cert, cert) != X509_V_OK) {
+        if (!no_self_issued || X509_check_issued(cert, cert) != X509_V_OK) {
             if (!ossl_cmp_sk_X509_add1_cert(sk, cert, no_dups, prepend))
                 return 0;
         }
@@ -287,7 +234,7 @@ int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
 }
 
 int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
-                                   int only_self_signed)
+                                   int only_self_issued)
 {
     int i;
 
@@ -300,45 +247,13 @@ int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
     for (i = 0; i < sk_X509_num(certs); i++) {
         X509 *cert = sk_X509_value(certs, i);
 
-        if (!only_self_signed || X509_check_issued(cert, cert) == X509_V_OK)
+        if (!only_self_issued || X509_check_issued(cert, cert) == X509_V_OK)
             if (!X509_STORE_add_cert(store, cert)) /* ups cert ref counter */
                 return 0;
     }
     return 1;
 }
 
-STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store)
-{
-    int i;
-    STACK_OF(X509) *sk;
-    STACK_OF(X509_OBJECT) *objs;
-
-    if (store == NULL) {
-        CMPerr(0, CMP_R_NULL_ARGUMENT);
-        return 0;
-    }
-    if ((sk = sk_X509_new_null()) == NULL)
-        return NULL;
-    objs = X509_STORE_get0_objects(store);
-    for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
-        X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
-
-        if (cert != NULL) {
-            if (!sk_X509_push(sk, cert))
-                goto err;
-            if (!X509_up_ref(cert)) {
-                (void)sk_X509_pop(sk);
-                goto err;
-            }
-        }
-    }
-    return sk;
-
- err:
-    sk_X509_pop_free(sk, X509_free);
-    return NULL;
-}
-
 /*-
  * Builds up the certificate chain of certs as high up as possible using
  * the given list of certs containing all possible intermediate certificates and
@@ -390,10 +305,10 @@ STACK_OF(X509) *ossl_cmp_build_cert_chain(STACK_OF(X509) *certs, X509 *cert)
 
     chain = X509_STORE_CTX_get0_chain(csc);
 
-    /* result list to store the up_ref'ed not self-signed certificates */
+    /* result list to store the up_ref'ed not self-issued certificates */
     if ((result = sk_X509_new_null()) == NULL)
         goto err;
-    if (!ossl_cmp_sk_X509_add1_certs(result, chain, 1 /* no self-signed */,
+    if (!ossl_cmp_sk_X509_add1_certs(result, chain, 1 /* no self-issued */,
                                      1 /* no duplicates */, 0)) {
         sk_X509_free(result);
         result = NULL;
@@ -438,7 +353,7 @@ int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
         return 0;
     }
     if (bytes != NULL) {
-        if ((new =  ASN1_OCTET_STRING_new()) == NULL
+        if ((new = ASN1_OCTET_STRING_new()) == NULL
                 || !(ASN1_OCTET_STRING_set(new, bytes, len))) {
             ASN1_OCTET_STRING_free(new);
             return 0;
diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c
new file mode 100644
index 0000000000..437bc3298f
--- /dev/null
+++ b/crypto/cmp/cmp_vfy.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2020
+ * Copyright Siemens AG 2015-2020
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* CMP functions for PKIMessage checking */
+
+#include "cmp_local.h"
+#include <openssl/cmp_util.h>
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/asn1t.h>
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include "crypto/x509.h"
+
+/*
+ * Verify a message protected by signature according to section 5.1.3.3
+ * (sha1+RSA/DSA or any other algorithm supported by OpenSSL).
+ *
+ * Returns 1 on successful validation and 0 otherwise.
+ */
+static int verify_signature(const OSSL_CMP_CTX *cmp_ctx,
+                            const OSSL_CMP_MSG *msg, X509 *cert)
+{
+    EVP_MD_CTX *ctx = NULL;
+    CMP_PROTECTEDPART prot_part;
+    int digest_nid, pk_nid;
+    const EVP_MD *digest = NULL;
+    EVP_PKEY *pubkey = NULL;
+    int len;
+    size_t prot_part_der_len = 0;
+    unsigned char *prot_part_der = NULL;
+    BIO *bio = BIO_new(BIO_s_mem()); /* may be NULL */
+    int res = 0;
+
+    if (!ossl_assert(cmp_ctx != NULL && msg != NULL && cert != NULL))
+        return 0;
+
+    /* verify that keyUsage, if present, contains digitalSignature */
+    if (!cmp_ctx->ignore_keyusage
+            && (X509_get_key_usage(cert) & X509v3_KU_DIGITAL_SIGNATURE) == 0) {
+        CMPerr(0, CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE);
+        goto sig_err;
+    }
+
+    pubkey = X509_get_pubkey(cert);
+    if (pubkey == NULL) {
+        CMPerr(0, CMP_R_FAILED_EXTRACTING_PUBKEY);
+        goto sig_err;
+    }
+
+    /* create the DER representation of protected part */
+    prot_part.header = msg->header;
+    prot_part.body = msg->body;
+
+    len = i2d_CMP_PROTECTEDPART(&prot_part, &prot_part_der);
+    if (len < 0 || prot_part_der == NULL)
+        goto end;
+    prot_part_der_len = (size_t) len;
+
+    /* verify signature of protected part */
+    if (!OBJ_find_sigid_algs(OBJ_obj2nid(msg->header->protectionAlg->algorithm),
+                             &digest_nid, &pk_nid)
+            || digest_nid == NID_undef || pk_nid == NID_undef
+            || (digest = EVP_get_digestbynid(digest_nid)) == NULL) {
+        CMPerr(0, CMP_R_ALGORITHM_NOT_SUPPORTED);
+        goto sig_err;
+    }
+
+    /* check msg->header->protectionAlg is consistent with public key type */
+    if (EVP_PKEY_type(pk_nid) != EVP_PKEY_base_id(pubkey)) {
+        CMPerr(0, CMP_R_WRONG_ALGORITHM_OID);
+        goto sig_err;
+    }
+    if ((ctx = EVP_MD_CTX_new()) == NULL)
+        goto end;
+    if (EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pubkey)
+            && EVP_DigestVerify(ctx, msg->protection->data,
+                                msg->protection->length,
+                                prot_part_der, prot_part_der_len) == 1) {
+        res = 1;
+        goto end;
+    }
+
+ sig_err:
+    res = x509_print_ex_brief(bio, cert, X509_FLAG_NO_EXTENSIONS);
+    CMPerr(0, CMP_R_ERROR_VALIDATING_PROTECTION);
+    if (res)
+        ERR_add_error_mem_bio("\n", bio);
+    res = 0;
+
+ end:
+    EVP_MD_CTX_free(ctx);
+    OPENSSL_free(prot_part_der);
+    EVP_PKEY_free(pubkey);
+    BIO_free(bio);
+
+    return res;
+}
+
+/* Verify a message protected with PBMAC */
+static int verify_PBMAC(const OSSL_CMP_MSG *msg,
+                        const ASN1_OCTET_STRING *secret)
+{
+    ASN1_BIT_STRING *protection = NULL;
+    int valid = 0;
+
+    /* generate expected protection for the message */
+    if ((protection = ossl_cmp_calc_protection(msg, secret, NULL)) == NULL)
+        return 0; /* failed to generate protection string! */
+
+    valid = msg->protection != NULL && msg->protection->length >= 0
+            && msg->protection->type == protection->type
+            && msg->protection->length == protection->length
+            && CRYPTO_memcmp(msg->protection->data, protection->data,
+                             protection->length) == 0;
+    ASN1_BIT_STRING_free(protection);
+    if (!valid)
+        CMPerr(0, CMP_R_WRONG_PBM_VALUE);
+
+    return valid;
+}
+
+/*
+ * Attempt to validate certificate and path using any given store with trusted
+ * certs (possibly including CRLs and a cert verification callback function)
+ * and non-trusted intermediate certs from the given ctx.
+ *
+ * Returns 1 on successful validation and 0 otherwise.
+ */
+int OSSL_CMP_validate_cert_path(OSSL_CMP_CTX *ctx, X509_STORE *trusted_store,
+                                X509 *cert)
+{
+    int valid = 0;
+    X509_STORE_CTX *csc = NULL;
+    int err;
+
+    if (ctx == NULL || cert == NULL) {
+        CMPerr(0, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    if (trusted_store == NULL) {
+        CMPerr(0, CMP_R_MISSING_TRUST_STORE);
+        return 0;
+    }
+
+    if ((csc = X509_STORE_CTX_new()) == NULL
+            || !X509_STORE_CTX_init(csc, trusted_store,
+                                    cert, ctx->untrusted_certs))
+        goto err;
+
+    valid = X509_verify_cert(csc) > 0;
+
+    /* make sure suitable error is queued even if callback did not do */
+    err = ERR_peek_last_error();
+    if (!valid && ERR_GET_REASON(err) != CMP_R_POTENTIALLY_INVALID_CERTIFICATE)
+        CMPerr(0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE);
+
+ err:
+    X509_STORE_CTX_free(csc);
+    return valid;
+}
+
+/* Return 0 if expect_name != NULL and there is no matching actual_name */
+static int check_name(OSSL_CMP_CTX *ctx,
+                      const char *actual_desc, const X509_NAME *actual_name,
+                      const char *expect_desc, const X509_NAME *expect_name)
+{
+    char *str;
+
+    if (expect_name == NULL)
+        return 1; /* no expectation, thus trivially fulfilled */
+
+    /* make sure that a matching name is there */
+    if (actual_name == NULL) {
+        ossl_cmp_log1(WARN, ctx, "missing %s", actual_desc);
+        return 0;
+    }
+    if (X509_NAME_cmp(actual_name, expect_name) == 0)
+        return 1;
+
+    if ((str = X509_NAME_oneline(actual_name, NULL, 0)) != NULL)
+        ossl_cmp_log2(INFO, ctx, " actual name in %s = %s", actual_desc, str);
+    OPENSSL_free(str);
+    if ((str = X509_NAME_oneline(expect_name, NULL, 0)) != NULL)
+        ossl_cmp_log2(INFO, ctx, " does not match %s = %s", expect_desc, str);
+    OPENSSL_free(str);
+    return 0;
+}
+
+/* Return 0 if skid != NULL and there is no matching subject key ID in cert */
+static int check_kid(OSSL_CMP_CTX *ctx,
+                     X509 *cert, const ASN1_OCTET_STRING *skid)
+{
+    char *actual, *expect;
+    const ASN1_OCTET_STRING *ckid = X509_get0_subject_key_id(cert);
+
+    if (skid == NULL)
+        return 1; /* no expectation, thus trivially fulfilled */
+
+    /* make sure that the expected subject key identifier is there */
+    if (ckid == NULL) {
+        ossl_cmp_warn(ctx, "missing Subject Key Identifier in certificate");
+        return 0;
+    }
+    if (ASN1_OCTET_STRING_cmp(ckid, skid) == 0)
+        return 1;
+
+    if ((actual = OPENSSL_buf2hexstr(ckid->data, ckid->length)) != NULL)
+        ossl_cmp_log1(INFO, ctx, " cert Subject Key Identifier = %s", actual);
+    if ((expect = OPENSSL_buf2hexstr(skid->data, skid->length)) != NULL)
+        ossl_cmp_log1(INFO, ctx, " does not match senderKID    = %s", expect);
+    OPENSSL_free(expect);
+    OPENSSL_free(actual);
+    return 0;
+}
+
+static int already_checked(X509 *cert, const STACK_OF(X509) *already_checked)
+{
+    int i;
+
+    for (i = sk_X509_num(already_checked /* may be NULL */); i > 0; i--)
+        if (X509_cmp(sk_X509_value(already_checked, i - 1), cert) == 0)
+            return 1;
+    return 0;
+}
+
+/*
+ * Check if the given cert is acceptable as sender cert of the given message.
+ * The subject DN must match, the subject key ID as well if present in the msg,
+ * and the cert must be current (checked if ctx->trusted is not NULL).
+ * Note that cert revocation etc. is checked by OSSL_CMP_validate_cert_path().
+ *
+ * Returns 0 on error or not acceptable, else 1.
+ */
+static int cert_acceptable(OSSL_CMP_CTX *ctx,
+                           const char *desc1, const char *desc2, X509 *cert,
+                           const STACK_OF(X509) *already_checked1,
+                           const STACK_OF(X509) *already_checked2,
+                           const OSSL_CMP_MSG *msg)
+{
+    X509_STORE *ts = ctx->trusted;
+    char *sub, *iss;
+    X509_VERIFY_PARAM *vpm = ts != NULL ? X509_STORE_get0_param(ts) : NULL;
+    int time_cmp;
+
+    ossl_cmp_log2(INFO, ctx, " considering %s %s with..", desc1, desc2);
+    if ((sub = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL)
+        ossl_cmp_log1(INFO, ctx, "  subject = %s", sub);
+    if ((iss = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0)) != NULL)
+        ossl_cmp_log1(INFO, ctx, "  issuer  = %s", iss);
+    OPENSSL_free(iss);
+    OPENSSL_free(sub);
+
+    if (already_checked(cert, already_checked1)
+            || already_checked(cert, already_checked2)) {
+        ossl_cmp_info(ctx, " cert has already been checked");
+        return 0;
+    }
+
+    time_cmp = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
+                                  X509_get0_notAfter(cert));
+    if (time_cmp != 0) {
+        ossl_cmp_warn(ctx, time_cmp > 0 ? "cert has expired"
+                                        : "cert is not yet valid");
+        return 0;
+    }
+
+    if (!check_name(ctx,
+                    "cert subject", X509_get_subject_name(cert),
+                    "sender field", msg->header->sender->d.directoryName))
+        return 0;
+
+    if (!check_kid(ctx, cert, msg->header->senderKID))
+        return 0;
+    /* acceptable also if there is no senderKID in msg header */
+    ossl_cmp_info(ctx, " cert is acceptable");
+    return 1;
+}
+
+static int check_msg_valid_cert(OSSL_CMP_CTX *ctx, X509_STORE *store,
+                                X509 *scrt, const OSSL_CMP_MSG *msg)
+{
+    if (!verify_signature(ctx, msg, scrt)) {
+        ossl_cmp_warn(ctx, "msg signature verification failed");
+        return 0;
+    }
+    if (!OSSL_CMP_validate_cert_path(ctx, store, scrt)) {
+        ossl_cmp_warn(ctx, "cert path validation failed");
+        return 0;
+    }
+    return 1;
+}
+
+/*
+ * Exceptional handling for 3GPP TS 33.310 [3G/LTE Network Domain Security
+ * (NDS); Authentication Framework (AF)], only to use for IP and if the ctx
+ * option is explicitly set: use self-issued certificates from extraCerts as
+ * trust anchor to validate sender cert and msg -
+ * provided it also can validate the newly enrolled certificate
+ */
+static int check_msg_valid_cert_3gpp(OSSL_CMP_CTX *ctx, X509 *scrt,
+                                     const OSSL_CMP_MSG *msg)
+{
+    int valid = 0;
+    X509_STORE *store = X509_STORE_new();
+
+    if (store != NULL /* store does not include CRLs */
+            && ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts,
+                                              1 /* self-issued only */))
+        valid = check_msg_valid_cert(ctx, store, scrt, msg);
+    if (valid) {
+        /*
+         * verify that the newly enrolled certificate (which is assumed to have
+         * rid == 0) can also be validated with the same trusted store
+         */
+        EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
+        OSSL_CMP_CERTRESPONSE *crep =
+            ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip, 0);
+        X509 *newcrt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
+        /*
+         * maybe better use get_cert_status() from cmp_client.c, which catches
+         * errors
+         */
+        valid = OSSL_CMP_validate_cert_path(ctx, store, newcrt);
+        X509_free(newcrt);
+    }
+    X509_STORE_free(store);
+    return valid;
+}
+
+/*
+ * Try all certs in given list for verifying msg, normally or in 3GPP mode.
+ * If already_checked1 == NULL then certs are assumed to be the msg->extraCerts.
+ */
+static int check_msg_with_certs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs,
+                                const char *desc,
+                                const STACK_OF(X509) *already_checked1,
+                                const STACK_OF(X509) *already_checked2,
+                                const OSSL_CMP_MSG *msg, int mode_3gpp)
+{
+    int in_extraCerts = already_checked1 == NULL;
+    int n_acceptable_certs = 0;
+    int i;
+
+    if (sk_X509_num(certs) <= 0) {
+        ossl_cmp_log1(WARN, ctx, "no %s", desc);
+        return 0;
+    }
+
+    for (i = 0; i < sk_X509_num(certs); i++) { /* certs may be NULL */
+        X509 *cert = sk_X509_value(certs, i);
+
+        if (!ossl_assert(cert != NULL))
+            return 0;
+        if (!cert_acceptable(ctx, "cert from", desc, cert,
+                             already_checked1, already_checked2, msg))
+            continue;
+        n_acceptable_certs++;
+        if (mode_3gpp ? check_msg_valid_cert_3gpp(ctx, cert, msg)
+                      : check_msg_valid_cert(ctx, ctx->trusted, cert, msg)) {
+            /* store successful sender cert for further msgs in transaction */
+            if (!X509_up_ref(cert))
+                return 0;
+            if (!ossl_cmp_ctx_set0_validatedSrvCert(ctx, cert)) {
+                X509_free(cert);
+                return 0;
+            }
+            return 1;
+        }
+    }
+    if (in_extraCerts && n_acceptable_certs == 0)
+        ossl_cmp_warn(ctx, "no acceptable cert in extraCerts");
+    return 0;
+}
+
+/*
+ * Verify msg trying first ctx->untrusted_certs, which should include extraCerts
+ * at its front, then trying the trusted certs in truststore (if any) of ctx.
+ */
+static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+                               int mode_3gpp)
+{
+    int ret = 0;
+
+    ossl_cmp_info(ctx,
+                  mode_3gpp ? "failed; trying now 3GPP mode trusting extraCerts"
+                            : "trying first normal mode using trust store");
+    if (check_msg_with_certs(ctx, msg->extraCerts, "extraCerts",
+                             NULL, NULL, msg, mode_3gpp))
+        return 1;
+    if (check_msg_with_certs(ctx, ctx->untrusted_certs, "untrusted certs",
+                             msg->extraCerts, NULL, msg, mode_3gpp))
+        return 1;
+
+    if (ctx->trusted == NULL) {
+        ossl_cmp_warn(ctx, mode_3gpp ? "no self-issued extraCerts"
+                                     : "no trusted store");
+    } else {
+        STACK_OF(X509) *trusted = X509_STORE_get1_all_certs(ctx->trusted);
+        ret = check_msg_with_certs(ctx, trusted,
+                                   mode_3gpp ? "self-issued extraCerts"
+                                             : "certs in trusted store",
+                                   msg->extraCerts, ctx->untrusted_certs,
+                                   msg, mode_3gpp);
+        sk_X509_pop_free(trusted, X509_free);
+    }
+    return ret;
+}
+
+/* verify message signature with any acceptable and valid candidate cert */
+static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
+{
+    X509 *scrt = ctx->validatedSrvCert; /* previous successful sender cert */
+    GENERAL_NAME *sender = msg->header->sender;
+    char *sname = NULL;
+    char *skid_str = NULL;
+    const ASN1_OCTET_STRING *skid = msg->header->senderKID;
+    OSSL_cmp_log_cb_t backup_log_cb = ctx->log_cb;
+    int res = 0;
+
+    if (sender == NULL || msg->body == NULL)
+        return 0; /* other NULL cases already have been checked */
+    if (sender->type != GEN_DIRNAME) {
+        CMPerr(0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
+        return 0;
+    }
+
+    /*
+     * try first cached scrt, used successfully earlier in same transaction,
+     * for validating this and any further msgs where extraCerts may be left out
+     */
+    (void)ERR_set_mark();
+    if (scrt != NULL
+            && cert_acceptable(ctx, "previously validated", "sender cert", scrt,
+                               NULL, NULL, msg)
+            && (check_msg_valid_cert(ctx, ctx->trusted, scrt, msg)
+                    || check_msg_valid_cert_3gpp(ctx, scrt, msg))) {
+        (void)ERR_pop_to_mark();
+        return 1;
+    }
+    (void)ERR_pop_to_mark();
+
+    /* release any cached sender cert that proved no more successfully usable */
+    (void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL);
+
+    /* enable clearing irrelevant errors in attempts to validate sender certs */
+    (void)ERR_set_mark();
+    ctx->log_cb = NULL; /* temporarily disable logging diagnostic info */
+
+    if (check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */)
+            || check_msg_all_certs(ctx, msg, 1 /* 3gpp */)) {
+        /* discard any diagnostic info on trying to use certs */
+        ctx->log_cb = backup_log_cb; /* restore any logging */
+        (void)ERR_pop_to_mark();
+        res = 1;
+        goto end;
+    }
+    /* failed finding a sender cert that verifies the message signature */
+    ctx->log_cb = backup_log_cb; /* restore any logging */
+    (void)ERR_clear_last_mark();
+
+    sname = X509_NAME_oneline(sender->d.directoryName, NULL, 0);
+    skid_str = skid == NULL ? NULL
+                            : OPENSSL_buf2hexstr(skid->data, skid->length);
+    if (ctx->log_cb != NULL) {
+        ossl_cmp_info(ctx, "verifying msg signature with valid cert that..");
+        if (sname != NULL)
+            ossl_cmp_log1(INFO, ctx, "matches msg sender name = %s", sname);
+        if (skid_str != NULL)
+            ossl_cmp_log1(INFO, ctx, "matches msg senderKID   = %s", skid_str);
+        else
+            ossl_cmp_info(ctx, "while msg header does not contain senderKID");
+        /* re-do the above checks (just) for adding diagnostic information */
+        check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */);
+        check_msg_all_certs(ctx, msg, 1 /* 3gpp */);
+    }
+
+    CMPerr(0, CMP_R_NO_SUITABLE_SENDER_CERT);
+    if (sname != NULL) {
+        ERR_add_error_txt(NULL, "for msg sender name = ");
+        ERR_add_error_txt(NULL, sname);
+    }
+    if (skid_str != NULL) {
+        ERR_add_error_txt(" and ", "for msg senderKID = ");
+        ERR_add_error_txt(NULL, skid_str);
+    }
+
+ end:
+    OPENSSL_free(sname);
+    OPENSSL_free(skid_str);
+    return res;
+}
+
+/*
+ * Validate the protection of the given PKIMessage using either password-
+ * based mac (PBM) or a signature algorithm. In the case of signature algorithm,
+ * the sender certificate can have been pinned by providing it in ctx->srvCert,
+ * else it is searched in msg->extraCerts, ctx->untrusted_certs, in ctx->trusted
+ * (in this order) and is path is validated against ctx->trusted.
+ *
+ * If ctx->permitTAInExtraCertsForIR is true and when validating a CMP IP msg,
+ * the trust anchor for validating the IP msg may be taken from msg->extraCerts
+ * if a self-issued certificate is found there that can be used to
+ * validate the enrolled certificate returned in the IP.
+ * This is according to the need given in 3GPP TS 33.310.
+ *
+ * Returns 1 on success, 0 on error or validation failed.
+ */
+int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
+{
+    X509_ALGOR *alg;
+    int nid = NID_undef, pk_nid = NID_undef;
+    const ASN1_OBJECT *algorOID = NULL;
+    X509 *scrt;
+
+    if (ctx == NULL || msg == NULL
+            || msg->header == NULL || msg->body == NULL) {
+        CMPerr(0, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    if ((alg = msg->header->protectionAlg) == NULL /* unprotected message */
+            || msg->protection == NULL || msg->protection->data == NULL) {
+        CMPerr(0, CMP_R_MISSING_PROTECTION);
+        return 0;
+    }
+
+    /* determine the nid for the used protection algorithm */
+    X509_ALGOR_get0(&algorOID, NULL, NULL, alg);
+    nid = OBJ_obj2nid(algorOID);
+
+    switch (nid) {
+        /* 5.1.3.1.  Shared Secret Information */
+    case NID_id_PasswordBasedMAC:
+        if (verify_PBMAC(msg, ctx->secretValue)) {
+            /*
+             * RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is
+             * "shared secret information", then any certificate transported in
+             * the caPubs field may be directly trusted as a root CA
+             * certificate by the initiator.'
+             */
+            switch (ossl_cmp_msg_get_bodytype(msg)) {
+            case -1:
+                return 0;
+            case OSSL_CMP_PKIBODY_IP:
+            case OSSL_CMP_PKIBODY_CP:
+            case OSSL_CMP_PKIBODY_KUP:
+            case OSSL_CMP_PKIBODY_CCP:
+                if (ctx->trusted != NULL) {
+                    STACK_OF(X509) *certs = msg->body->value.ip->caPubs;
+                    /* value.ip is same for cp, kup, and ccp */
+
+                    if (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, certs, 0))
+                        /* adds both self-issued and not self-issued certs */
+                        return 0;
+                }
+                break;
+            default:
+                break;
+            }
+            return 1;
+        }
+        break;
+
+        /*
+         * 5.1.3.2 DH Key Pairs
+         * Not yet supported
+         */
+    case NID_id_DHBasedMac:
+        CMPerr(0, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC);
+        break;
+
+        /*
+         * 5.1.3.3.  Signature
+         */
+    default:
+        if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), NULL, &pk_nid)
+                || pk_nid == NID_undef) {
+            CMPerr(0, CMP_R_UNKNOWN_ALGORITHM_ID);
+            break;
+        }
+        /* validate sender name of received msg */
+        if (msg->header->sender->type != GEN_DIRNAME) {
+            CMPerr(0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
+            break; /* FR#42: support for more than X509_NAME */
+        }
+        /*
+         * Compare actual sender name of response with expected sender name.
+         * Expected name can be set explicitly or the subject of ctx->srvCert.
+         * Mitigates risk to accept misused certificate of an unauthorized
+         * entity of a trusted hierarchy.
+         */
+        if (!check_name(ctx, "sender DN field",
+                        msg->header->sender->d.directoryName,
+                        "expected sender", ctx->expected_sender))
+            break;
+        /* Note: if recipient was NULL-DN it could be learned here if needed */
+
+        scrt = ctx->srvCert;
+        if (scrt == NULL) {
+            if (check_msg_find_cert(ctx, msg))
+                return 1;
+        } else { /* use pinned sender cert */
+            /* use ctx->srvCert for signature check even if not acceptable */
+            if (verify_signature(ctx, msg, scrt))
+                return 1;
+            /* call cert_acceptable() for adding diagnostic information */
+            (void)cert_acceptable(ctx, "explicitly set", "sender cert", scrt,
+                                  NULL, NULL, msg);
+            ossl_cmp_warn(ctx, "msg signature verification failed");
+            CMPerr(0, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG);
+        }
+        break;
+    }
+    return 0;
+}
+
+
+/*-
+ * Check received message (i.e., response by server or request from client)
+ * Any msg->extraCerts are prepended to ctx->untrusted_certs
+ *
+ * Ensures that:
+ * it has a valid body type
+ * its protection is valid or absent (allowed only if callback function is
+ *    present and function yields non-zero result using also supplied argument)
+ * its transaction ID matches the previous transaction ID stored in ctx (if any)
+ * its recipNonce matches the previous senderNonce stored in the ctx (if any)
+ *
+ * If everything is fine:
+ * learns the senderNonce from the received message,
+ * learns the transaction ID if it is not yet in ctx.
+ *
+ * returns body type (which is >= 0) of the message on success, -1 on error
+ */
+int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+                                ossl_cmp_allow_unprotected_cb_t cb, int cb_arg)
+{
+    int rcvd_type;
+
+    if (!ossl_assert(ctx != NULL && msg != NULL))
+        return -1;
+
+    if (sk_X509_num(msg->extraCerts) > 10)
+        ossl_cmp_warn(ctx,
+                      "received CMP message contains more than 10 extraCerts");
+
+    /* validate message protection */
+    if (msg->header->protectionAlg != 0) {
+        /* detect explicitly permitted exceptions for invalid protection */
+        if (!OSSL_CMP_validate_msg(ctx, msg)
+                && (cb == NULL || !(*cb)(ctx, msg, 1, cb_arg))) {
+            CMPerr(0, CMP_R_ERROR_VALIDATING_PROTECTION);
+            return -1;
+        }
+    } else {
+        /* detect explicitly permitted exceptions for missing protection */
+        if (cb == NULL || !(*cb)(ctx, msg, 0, cb_arg)) {
+            CMPerr(0, CMP_R_MISSING_PROTECTION);
+            return -1;
+        }
+    }
+
+    /*
+     * Store any provided extraCerts in ctx for future use,
+     * such that they are available to ctx->certConf_cb and
+     * the peer does not need to send them again in the same transaction.
+     * For efficiency, the extraCerts are prepended so they get used first.
+     */
+    if (!ossl_cmp_sk_X509_add1_certs(ctx->untrusted_certs, msg->extraCerts,
+                                     0 /* this allows self-issued certs */,
+                                     1 /* no_dups */, 1 /* prepend */))
+        return -1;
+
+    /* check CMP version number in header */
+    if (ossl_cmp_hdr_get_pvno(OSSL_CMP_MSG_get0_header(msg)) != OSSL_CMP_PVNO) {
+        CMPerr(0, CMP_R_UNEXPECTED_PVNO);
+        return -1;
+    }
+
+    /* compare received transactionID with the expected one in previous msg */
+    if (ctx->transactionID != NULL
+            && (msg->header->transactionID == NULL
+                || ASN1_OCTET_STRING_cmp(ctx->transactionID,
+                                         msg->header->transactionID) != 0)) {
+        CMPerr(0, CMP_R_TRANSACTIONID_UNMATCHED);
+        return -1;
+    }
+
+    /* compare received nonce with the one we sent */
+    if (ctx->senderNonce != NULL
+            && (msg->header->recipNonce == NULL
+                || ASN1_OCTET_STRING_cmp(ctx->senderNonce,
+                                         msg->header->recipNonce) != 0)) {
+        CMPerr(0, CMP_R_RECIPNONCE_UNMATCHED);
+        return -1;
+    }
+
+    /*
+     * RFC 4210 section 5.1.1 states: the recipNonce is copied from
+     * the senderNonce of the previous message in the transaction.
+     * --> Store for setting in next message
+     */
+    if (!ossl_cmp_ctx_set1_recipNonce(ctx, msg->header->senderNonce))
+        return -1;
+
+    /* if not yet present, learn transactionID */
+    if (ctx->transactionID == NULL
+        && !OSSL_CMP_CTX_set1_transactionID(ctx, msg->header->transactionID))
+        return -1;
+
+    if ((rcvd_type = ossl_cmp_msg_get_bodytype(msg)) < 0) {
+        CMPerr(0, CMP_R_PKIBODY_ERROR);
+        return -1;
+    }
+    return rcvd_type;
+}
+
+int ossl_cmp_verify_popo(const OSSL_CMP_MSG *msg, int accept_RAVerified)
+{
+    if (!ossl_assert(msg != NULL && msg->body != NULL))
+        return 0;
+    switch (msg->body->type) {
+    case OSSL_CMP_PKIBODY_P10CR:
+        {
+            X509_REQ *req = msg->body->value.p10cr;
+
+            if (X509_REQ_verify(req, X509_REQ_get0_pubkey(req)) > 0)
+                return 1;
+            CMPerr(0, CMP_R_REQUEST_NOT_ACCEPTED);
+            return 0;
+        }
+    case OSSL_CMP_PKIBODY_IR:
+    case OSSL_CMP_PKIBODY_CR:
+    case OSSL_CMP_PKIBODY_KUR:
+        return OSSL_CRMF_MSGS_verify_popo(msg->body->value.ir,
+                                          OSSL_CMP_CERTREQID,
+                                          accept_RAVerified);
+    default:
+        CMPerr(0, CMP_R_PKIBODY_ERROR);
+        return 0;
+    }
+}
diff --git a/crypto/crmf/crmf_asn.c b/crypto/crmf/crmf_asn.c
index 8b6657f969..bd375c6f85 100644
--- a/crypto/crmf/crmf_asn.c
+++ b/crypto/crmf/crmf_asn.c
@@ -141,8 +141,8 @@ ASN1_CHOICE(OSSL_CRMF_POPO) = {
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPO)
 
 
-ASN1_ADB_TEMPLATE(attributetypeandvalue_default) = ASN1_OPT(
-        OSSL_CRMF_ATTRIBUTETYPEANDVALUE, value.other, ASN1_ANY);
+ASN1_ADB_TEMPLATE(attributetypeandvalue_default) =
+    ASN1_OPT(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, value.other, ASN1_ANY);
 ASN1_ADB(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = {
     ADB_ENTRY(NID_id_regCtrl_regToken,
               ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
@@ -187,7 +187,7 @@ IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_OPTIONALVALIDITY)
 
 
 ASN1_SEQUENCE(OSSL_CRMF_CERTTEMPLATE) = {
-    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, version,      ASN1_INTEGER, 0),
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, version, ASN1_INTEGER, 0),
     /*
      * serialNumber MUST be omitted. This field is assigned by the CA
      * during certificate creation.
@@ -197,16 +197,16 @@ ASN1_SEQUENCE(OSSL_CRMF_CERTTEMPLATE) = {
      * signingAlg MUST be omitted. This field is assigned by the CA
      * during certificate creation.
      */
-    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, signingAlg,   X509_ALGOR, 2),
-    ASN1_EXP_OPT(OSSL_CRMF_CERTTEMPLATE, issuer,       X509_NAME, 3),
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, signingAlg, X509_ALGOR, 2),
+    ASN1_EXP_OPT(OSSL_CRMF_CERTTEMPLATE, issuer, X509_NAME, 3),
     ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, validity,
                  OSSL_CRMF_OPTIONALVALIDITY, 4),
-    ASN1_EXP_OPT(OSSL_CRMF_CERTTEMPLATE, subject,      X509_NAME, 5),
-    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, publicKey,    X509_PUBKEY, 6),
+    ASN1_EXP_OPT(OSSL_CRMF_CERTTEMPLATE, subject, X509_NAME, 5),
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, publicKey, X509_PUBKEY, 6),
     /* issuerUID is deprecated in version 2 */
-    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, issuerUID,    ASN1_BIT_STRING, 7),
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, issuerUID, ASN1_BIT_STRING, 7),
     /* subjectUID is deprecated in version 2 */
-    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, subjectUID,   ASN1_BIT_STRING, 8),
+    ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, subjectUID, ASN1_BIT_STRING, 8),
     ASN1_IMP_SEQUENCE_OF_OPT(OSSL_CRMF_CERTTEMPLATE, extensions,
                              X509_EXTENSION, 9),
 } ASN1_SEQUENCE_END(OSSL_CRMF_CERTTEMPLATE)
diff --git a/crypto/crmf/crmf_lib.c b/crypto/crmf/crmf_lib.c
index 64dbf80978..4d81569299 100644
--- a/crypto/crmf/crmf_lib.c
+++ b/crypto/crmf/crmf_lib.c
@@ -47,7 +47,7 @@ int OSSL_CRMF_MSG_set1_##ctrlinf##_##atyp(OSSL_CRMF_MSG *msg,             \
 {                                                                         \
     OSSL_CRMF_ATTRIBUTETYPEANDVALUE *atav = NULL;                         \
                                                                           \
-    if (msg == NULL || in  == NULL)                                       \
+    if (msg == NULL || in == NULL)                                       \
         goto err;                                                         \
     if ((atav = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new()) == NULL)           \
         goto err;                                                         \
@@ -122,9 +122,9 @@ int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
     return 1;
 }
 
-int OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(
-                                 OSSL_CRMF_PKIPUBLICATIONINFO *pi,
-                                 OSSL_CRMF_SINGLEPUBINFO *spi)
+int
+OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+                                                     OSSL_CRMF_SINGLEPUBINFO *spi)
 {
     if (pi == NULL || spi == NULL) {
         CRMFerr(CRMF_F_OSSL_CRMF_MSG_PKIPUBLICATIONINFO_PUSH0_SINGLEPUBINFO,
@@ -139,8 +139,8 @@ int OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(
     return sk_OSSL_CRMF_SINGLEPUBINFO_push(pi->pubInfos, spi);
 }
 
-int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(
-                                 OSSL_CRMF_PKIPUBLICATIONINFO *pi, int action)
+int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+                                                int action)
 {
     if (pi == NULL
             || action < OSSL_CRMF_PUB_ACTION_DONTPUBLISH
@@ -457,7 +457,7 @@ int OSSL_CRMF_MSG_create_popo(OSSL_CRMF_MSG *crm, EVP_PKEY *pkey,
         {
             OSSL_CRMF_POPOSIGNINGKEY *ps = OSSL_CRMF_POPOSIGNINGKEY_new();
             if (ps == NULL
-                    || !CRMF_poposigningkey_init(ps, crm->certReq, pkey, dgst)){
+                    || !CRMF_poposigningkey_init(ps, crm->certReq, pkey, dgst)) {
                 OSSL_CRMF_POPOSIGNINGKEY_free(ps);
                 goto err;
             }
@@ -542,21 +542,23 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
              * the public key from the certificate template. This MUST be
              * exactly the same value as contained in the certificate template.
              */
+            const ASN1_ITEM *rptr = ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT);
+
             if (pubkey == NULL
                     || sig->poposkInput->publicKey == NULL
                     || X509_PUBKEY_cmp(pubkey, sig->poposkInput->publicKey)
-                    || ASN1_item_verify(
-                           ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT),
-                           sig->algorithmIdentifier, sig->signature,
-                           sig->poposkInput, X509_PUBKEY_get0(pubkey)) < 1)
+                    || ASN1_item_verify(rptr, sig->algorithmIdentifier,
+                                        sig->signature, sig->poposkInput,
+                                        X509_PUBKEY_get0(pubkey)) < 1)
                 break;
         } else {
             if (pubkey == NULL
                     || req->certReq->certTemplate->subject == NULL
                     || ASN1_item_verify(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST),
-                                    sig->algorithmIdentifier, sig->signature,
-                                    req->certReq,
-                                    X509_PUBKEY_get0(pubkey)) < 1)
+                                        sig->algorithmIdentifier,
+                                        sig->signature,
+                                        req->certReq,
+                                        X509_PUBKEY_get0(pubkey)) < 1)
                 break;
         }
         return 1;
diff --git a/crypto/crmf/crmf_local.h b/crypto/crmf/crmf_local.h
index 06b32b5378..3f3f75cf2f 100644
--- a/crypto/crmf/crmf_local.h
+++ b/crypto/crmf/crmf_local.h
@@ -185,9 +185,9 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PKMACVALUE)
 typedef struct ossl_crmf_popoprivkey_st {
     int type;
     union {
-        ASN1_BIT_STRING *thisMessage; /* 0 */     /* Deprecated */
+        ASN1_BIT_STRING *thisMessage; /* 0 */ /* Deprecated */
         ASN1_INTEGER *subsequentMessage; /* 1 */
-        ASN1_BIT_STRING *dhMAC; /* 2 */           /* Deprecated */
+        ASN1_BIT_STRING *dhMAC; /* 2 */ /* Deprecated */
         OSSL_CRMF_PKMACVALUE *agreeMAC; /* 3 */
         /*
          * TODO: This is not ASN1_NULL but CMS_ENVELOPEDDATA which should be
@@ -310,20 +310,20 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_OPTIONALVALIDITY)
  * }
  */
 struct ossl_crmf_certtemplate_st {
-    ASN1_INTEGER *version;           /* 0 */
-    ASN1_INTEGER *serialNumber;      /* 1 */ /* serialNumber MUST be omitted  */
-             /* This field is assigned by the CA during certificate creation  */
-    X509_ALGOR *signingAlg;          /* 2 */  /* signingAlg MUST be omitted   */
-             /* This field is assigned by the CA during certificate creation  */
-    X509_NAME *issuer;               /* 3 */
-    OSSL_CRMF_OPTIONALVALIDITY *validity; /* 4 */
-    X509_NAME *subject;              /* 5 */
-    X509_PUBKEY *publicKey;          /* 6 */
-    ASN1_BIT_STRING *issuerUID;      /* 7 */  /* deprecated in version 2      */
-                  /* According to rfc 3280: UniqueIdentifier  ::=  BIT STRING */
-    ASN1_BIT_STRING *subjectUID;     /* 8 */  /* deprecated in version 2      */
-                      /* Could be X509_EXTENSION*S*, but that's only cosmetic */
-    STACK_OF(X509_EXTENSION) *extensions; /* 9 */
+    ASN1_INTEGER *version;
+    ASN1_INTEGER *serialNumber; /* serialNumber MUST be omitted */
+    /* This field is assigned by the CA during certificate creation */
+    X509_ALGOR *signingAlg; /* signingAlg MUST be omitted */
+    /* This field is assigned by the CA during certificate creation */
+    X509_NAME *issuer;
+    OSSL_CRMF_OPTIONALVALIDITY *validity;
+    X509_NAME *subject;
+    X509_PUBKEY *publicKey;
+    ASN1_BIT_STRING *issuerUID; /* deprecated in version 2 */
+    /* According to rfc 3280: UniqueIdentifier ::= BIT STRING */
+    ASN1_BIT_STRING *subjectUID; /* deprecated in version 2 */
+    /* Could be X509_EXTENSION*S*, but that's only cosmetic */
+    STACK_OF(X509_EXTENSION) *extensions;
 } /* OSSL_CRMF_CERTTEMPLATE */;
 
 /*-
diff --git a/crypto/crmf/crmf_pbm.c b/crypto/crmf/crmf_pbm.c
index 2dfa84e49b..6c22bc29a0 100644
--- a/crypto/crmf/crmf_pbm.c
+++ b/crypto/crmf/crmf_pbm.c
@@ -71,7 +71,7 @@ OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(size_t slen, int owfnid,
     /*
      * iterationCount identifies the number of times the hash is applied
      * during the key computation process.  The iterationCount MUST be a
-     * minimum of 100.      Many people suggest using values as high as 1000
+     * minimum of 100. Many people suggest using values as high as 1000
      * iterations as the minimum value.  The trade off here is between
      * protection of the password from attacks and the time spent by the
      * server processing all of the different iterations in deriving
diff --git a/crypto/err/err_prn.c b/crypto/err/err_prn.c
index e0184b0771..9a5889829d 100644
--- a/crypto/err/err_prn.c
+++ b/crypto/err/err_prn.c
@@ -17,12 +17,13 @@
 #include <openssl/err.h>
 #include "err_local.h"
 
+#define ERR_PRINT_BUF_SIZE 4096
 void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u),
                          void *u)
 {
     CRYPTO_THREAD_ID tid = CRYPTO_THREAD_get_current_id();
     unsigned long l;
-    char buf[4096], *hex;
+    char buf[ERR_PRINT_BUF_SIZE], *hex;
     const char *lib, *reason;
     const char *file, *data, *func;
     int line, flags;
@@ -44,6 +45,123 @@ void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u),
     }
 }
 
+/* auxiliary function for incrementally reporting texts via the error queue */
+static void put_error(int lib, const char *func, int reason,
+                      const char *file, int line)
+{
+    ERR_new();
+    ERR_set_debug(file, line, func);
+    ERR_set_error(lib, reason, NULL /* no data here, so fmt is NULL */);
+}
+
+#define TYPICAL_MAX_OUTPUT_BEFORE_DATA 100
+#define MAX_DATA_LEN (ERR_PRINT_BUF_SIZE - TYPICAL_MAX_OUTPUT_BEFORE_DATA)
+void ERR_add_error_txt(const char *separator, const char *txt)
+{
+    const char *file = NULL;
+    int line;
+    const char *func = NULL;
+    const char *data = NULL;
+    int flags;
+    unsigned long err = ERR_peek_last_error();
+
+    if (separator == NULL)
+        separator = "";
+    if (err == 0)
+        put_error(ERR_LIB_CMP, NULL, 0, "", 0);
+
+    do {
+        size_t available_len, data_len;
+        const char *curr = txt, *next = txt;
+        const char *leading_separator = separator;
+        int trailing_separator = 0;
+        char *tmp;
+
+        ERR_peek_last_error_all(&file, &line, &func, &data, &flags);
+        if ((flags & ERR_TXT_STRING) == 0) {
+            data = "";
+            leading_separator = "";
+        }
+        data_len = strlen(data);
+
+        /* workaround for limit of ERR_print_errors_cb() */
+        if (data_len >= MAX_DATA_LEN
+                || strlen(separator) >= (size_t)(MAX_DATA_LEN - data_len))
+            available_len = 0;
+        else
+            available_len = MAX_DATA_LEN - data_len - strlen(separator) - 1;
+        /* MAX_DATA_LEN > available_len >= 0 */
+
+        if (*separator == '\0') {
+            const size_t len_next = strlen(next);
+
+            if (len_next <= available_len) {
+                next += len_next;
+                curr = NULL; /* no need to split */
+            } else {
+                next += available_len;
+                curr = next; /* will split at this point */
+            }
+        } else {
+            while (*next != '\0' && (size_t)(next - txt) <= available_len) {
+                curr = next;
+                next = strstr(curr, separator);
+                if (next != NULL) {
+                    next += strlen(separator);
+                    trailing_separator = *next == '\0';
+                } else {
+                    next = curr + strlen(curr);
+                }
+            }
+            if ((size_t)(next - txt) <= available_len)
+                curr = NULL; /* the above loop implies *next == '\0' */
+        }
+        if (curr != NULL) {
+            /* split error msg at curr since error data would get too long */
+            if (curr != txt) {
+                tmp = OPENSSL_strndup(txt, curr - txt);
+                if (tmp == NULL)
+                    return;
+                ERR_add_error_data(2, separator, tmp);
+                OPENSSL_free(tmp);
+            }
+            put_error(ERR_LIB_CMP, func, err, file, line);
+            txt = curr;
+        } else {
+            if (trailing_separator) {
+                tmp = OPENSSL_strndup(txt, next - strlen(separator) - txt);
+                if (tmp == NULL)
+                    return;
+                /* output txt without the trailing separator */
+                ERR_add_error_data(2, leading_separator, tmp);
+                OPENSSL_free(tmp);
+            } else {
+                ERR_add_error_data(2, leading_separator, txt);
+            }
+            txt = next; /* finished */
+        }
+    } while (*txt != '\0');
+}
+
+void ERR_add_error_mem_bio(const char *separator, BIO *bio)
+{
+    if (bio != NULL) {
+        char *str;
+        long len = BIO_get_mem_data(bio, &str);
+
+        if (len > 0) {
+            if (str[len - 1] != '\0') {
+                if (BIO_write(bio, "", 1) <= 0)
+                    return;
+
+                len = BIO_get_mem_data(bio, &str);
+            }
+            if (len > 1)
+                ERR_add_error_txt(separator, str);
+        }
+    }
+}
+
 static int print_bio(const char *str, size_t len, void *bp)
 {
     return BIO_write((BIO *)bp, str, len);
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 8920a77390..e6a45ac03a 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2067,6 +2067,7 @@ BN_R_PRIVATE_KEY_TOO_LARGE:117:private key too large
 BN_R_P_IS_NOT_PRIME:112:p is not prime
 BN_R_TOO_MANY_ITERATIONS:113:too many iterations
 BN_R_TOO_MANY_TEMPORARY_VARIABLES:109:too many temporary variables
+CMP_R_ALGORITHM_NOT_SUPPORTED:139:algorithm not supported
 CMP_R_BAD_REQUEST_ID:108:bad request id
 CMP_R_CERTID_NOT_FOUND:109:certid not found
 CMP_R_CERTIFICATE_NOT_FOUND:112:certificate not found
@@ -2087,24 +2088,41 @@ CMP_R_ERROR_CREATING_RR:126:error creating rr
 CMP_R_ERROR_PARSING_PKISTATUS:107:error parsing pkistatus
 CMP_R_ERROR_PROTECTING_MESSAGE:127:error protecting message
 CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash
+CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection
+CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
 CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
 CMP_R_FAIL_INFO_OUT_OF_RANGE:129:fail info out of range
 CMP_R_INVALID_ARGS:100:invalid args
 CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION:130:\
 	missing key input for creating protection
+CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE:142:missing key usage digitalsignature
 CMP_R_MISSING_PRIVATE_KEY:131:missing private key
+CMP_R_MISSING_PROTECTION:143:missing protection
 CMP_R_MISSING_SENDER_IDENTIFICATION:111:missing sender identification
+CMP_R_MISSING_TRUST_STORE:144:missing trust store
 CMP_R_MULTIPLE_SAN_SOURCES:102:multiple san sources
 CMP_R_NO_STDIO:194:no stdio
+CMP_R_NO_SUITABLE_SENDER_CERT:145:no suitable sender cert
 CMP_R_NULL_ARGUMENT:103:null argument
+CMP_R_PKIBODY_ERROR:146:pkibody error
 CMP_R_PKISTATUSINFO_NOT_FOUND:132:pkistatusinfo not found
-CMP_R_POTENTIALLY_INVALID_CERTIFICATE:139:potentially invalid certificate
+CMP_R_POTENTIALLY_INVALID_CERTIFICATE:147:potentially invalid certificate
+CMP_R_RECIPNONCE_UNMATCHED:148:recipnonce unmatched
+CMP_R_REQUEST_NOT_ACCEPTED:149:request not accepted
+CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED:150:\
+	sender generalname type not supported
+CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG:151:srvcert does not validate msg
+CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
 CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
+CMP_R_UNEXPECTED_PVNO:153:unexpected pvno
 CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
 CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
 CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm
 CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type
+CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\
+	unsupported protection alg dhbasedmac
 CMP_R_WRONG_ALGORITHM_OID:138:wrong algorithm oid
+CMP_R_WRONG_PBM_VALUE:155:wrong pbm value
 CMS_R_ADD_SIGNER_ERROR:99:add signer error
 CMS_R_ATTRIBUTE_ERROR:161:attribute error
 CMS_R_CERTIFICATE_ALREADY_PRESENT:175:certificate already present
@@ -3360,6 +3378,7 @@ X509_R_BAD_X509_FILETYPE:100:bad x509 filetype
 X509_R_BASE64_DECODE_ERROR:118:base64 decode error
 X509_R_CANT_CHECK_DH_KEY:114:cant check dh key
 X509_R_CERT_ALREADY_IN_HASH_TABLE:101:cert already in hash table
+X509_R_CERTIFICATE_VERIFICATION_FAILED:139:certificate verification failed
 X509_R_CRL_ALREADY_DELTA:127:crl already delta
 X509_R_CRL_VERIFY_FAILURE:131:crl verify failure
 X509_R_IDP_MISMATCH:128:idp mismatch
diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c
index 4969bb34bf..eac299c09a 100644
--- a/crypto/x509/t_x509.c
+++ b/crypto/x509/t_x509.c
@@ -15,6 +15,7 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 #include "crypto/asn1.h"
+#include "crypto/x509.h"
 
 #ifndef OPENSSL_NO_STDIO
 int X509_print_fp(FILE *fp, X509 *x)
@@ -380,3 +381,107 @@ int X509_aux_print(BIO *out, X509 *x, int indent)
     }
     return 1;
 }
+
+/*
+ * Helper functions for improving certificate verification error diagnostics
+ */
+
+int x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags)
+{
+    unsigned long flags = ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE |
+        XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN;
+
+    if (cert == NULL)
+        return BIO_printf(bio, "    (no certificate)\n") > 0;
+    if (BIO_printf(bio, "    certificate\n") <= 0
+            || !X509_print_ex(bio, cert, flags, ~X509_FLAG_NO_SUBJECT))
+        return 0;
+    if (X509_check_issued((X509 *)cert, cert) == X509_V_OK) {
+        if (BIO_printf(bio, "        self-issued\n") <= 0)
+            return 0;
+    } else {
+        if (BIO_printf(bio, " ") <= 0
+            || !X509_print_ex(bio, cert, flags, ~X509_FLAG_NO_ISSUER))
+            return 0;
+    }
+    if (!X509_print_ex(bio, cert, flags,
+                       ~(X509_FLAG_NO_SERIAL | X509_FLAG_NO_VALIDITY)))
+        return 0;
+    if (X509_cmp_current_time(X509_get0_notBefore(cert)) > 0)
+        if (BIO_printf(bio, "        not yet valid\n") <= 0)
+            return 0;
+    if (X509_cmp_current_time(X509_get0_notAfter(cert)) < 0)
+        if (BIO_printf(bio, "        no more valid\n") <= 0)
+            return 0;
+    return X509_print_ex(bio, cert, flags, ~(neg_cflags));
+}
+
+static int print_certs(BIO *bio, const STACK_OF(X509) *certs)
+{
+    int i;
+
+    if (certs == NULL || sk_X509_num(certs) <= 0)
+        return BIO_printf(bio, "    (no certificates)\n") >= 0;
+
+    for (i = 0; i < sk_X509_num(certs); i++) {
+        X509 *cert = sk_X509_value(certs, i);
+        if (cert != NULL && !x509_print_ex_brief(bio, cert, 0))
+            return 0;
+    }
+    return 1;
+}
+
+static int print_store_certs(BIO *bio, X509_STORE *store)
+{
+    if (store != NULL) {
+        STACK_OF(X509) *certs = X509_STORE_get1_all_certs(store);
+        int ret = print_certs(bio, certs);
+
+        sk_X509_pop_free(certs, X509_free);
+        return ret;
+    } else {
+        return BIO_printf(bio, "    (no trusted store)\n") >= 0;
+    }
+}
+
+/* Extend the error queue with details on a failed cert verification */
+int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+    if (ok == 0 && ctx != NULL) {
+        int cert_error = X509_STORE_CTX_get_error(ctx);
+        int depth = X509_STORE_CTX_get_error_depth(ctx);
+        X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
+        BIO *bio = BIO_new(BIO_s_mem()); /* may be NULL */
+
+        BIO_printf(bio, "%s at depth=%d error=%d (%s)\n",
+                   X509_STORE_CTX_get0_parent_ctx(ctx) != NULL
+                   ? "CRL path validation" : "certificate verification",
+                   depth, cert_error,
+                   X509_verify_cert_error_string(cert_error));
+        BIO_printf(bio, "failure for:\n");
+        x509_print_ex_brief(bio, cert, X509_FLAG_NO_EXTENSIONS);
+        if (cert_error == X509_V_ERR_CERT_UNTRUSTED
+                || cert_error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
+                || cert_error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
+                || cert_error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
+                || cert_error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
+                || cert_error == X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER
+                || cert_error == X509_V_ERR_STORE_LOOKUP) {
+            BIO_printf(bio, "non-trusted certs:\n");
+            print_certs(bio, X509_STORE_CTX_get0_untrusted(ctx));
+            BIO_printf(bio, "certs in trust store:\n");
+            print_store_certs(bio, X509_STORE_CTX_get0_store(ctx));
+        }
+        CMPerr(0, X509_R_CERTIFICATE_VERIFICATION_FAILED);
+        ERR_add_error_mem_bio("\n", bio);
+        BIO_free(bio);
+    }
+
+    /*
+     * TODO we could check policies here too, e.g.:
+     * if (cert_error == X509_V_OK && ok == 2)
+     *     policies_print(NULL, ctx);
+     */
+
+    return ok;
+}
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index 1b01fd0131..59ffbee6d8 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -22,6 +22,8 @@ static const ERR_STRING_DATA X509_str_reasons[] = {
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "cant check dh key"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE),
     "cert already in hash table"},
+    {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERTIFICATE_VERIFICATION_FAILED),
+    "certificate verification failed"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "crl already delta"},
     {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE),
     "crl verify failure"},
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index 016b4b304f..9018d6e114 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -532,6 +532,41 @@ STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v)
     return v->objs;
 }
 
+STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store)
+{
+    STACK_OF(X509) *sk;
+    STACK_OF(X509_OBJECT) *objs;
+    int i;
+
+    if (store == NULL) {
+        X509err(0, ERR_R_PASSED_NULL_PARAMETER);
+        return NULL;
+    }
+    if ((sk = sk_X509_new_null()) == NULL)
+        return NULL;
+    X509_STORE_lock(store);
+    objs = X509_STORE_get0_objects(store);
+    for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
+        X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
+
+        if (cert != NULL) {
+            if (!X509_up_ref(cert))
+                goto err;
+            if (!sk_X509_push(sk, cert)) {
+                X509_free(cert);
+                goto err;
+            }
+        }
+    }
+    X509_STORE_unlock(store);
+    return sk;
+
+ err:
+    X509_STORE_unlock(store);
+    sk_X509_pop_free(sk, X509_free);
+    return NULL;
+}
+
 STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
 {
     int i, idx, cnt;
diff --git a/doc/internal/man3/ossl_cmp_asn1_octet_string_set1.pod b/doc/internal/man3/ossl_cmp_asn1_octet_string_set1.pod
index 08941362fb..a239ca044a 100644
--- a/doc/internal/man3/ossl_cmp_asn1_octet_string_set1.pod
+++ b/doc/internal/man3/ossl_cmp_asn1_octet_string_set1.pod
@@ -2,10 +2,6 @@
 
 =head1 NAME
 
-ossl_cmp_log_parse_metadata,
-ossl_cmp_add_error_txt,
-ossl_cmp_add_error_data,
-ossl_cmp_add_error_line,
 ossl_cmp_asn1_octet_string_set1,
 ossl_cmp_asn1_octet_string_set1_bytes,
 ossl_cmp_build_cert_chain
@@ -15,14 +11,6 @@ ossl_cmp_build_cert_chain
 
  #include "cmp_local.h"
 
- const char *ossl_cmp_log_parse_metadata(const char *buf,
-                                         OSSL_CMP_severity *level, char **func,
-                                         char **file, int *line);
-
- void ossl_cmp_add_error_txt(const char *separator, const char *txt);
- #define ossl_cmp_add_error_data(txt)
- #define ossl_cmp_add_error_line(txt)
-
  int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
                                      const ASN1_OCTET_STRING *src);
  int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
@@ -32,27 +20,6 @@ ossl_cmp_build_cert_chain
 
 =head1 DESCRIPTION
 
-ossl_cmp_log_parse_metadata() parses the given message buffer I<buf> populated
-by L<OSSL_CMP_log(3)> etc.
-according to the pattern OSSL_CMP_LOG_START#level ": %s\n", filling in
-the variable pointed to by I<level> with the severity level or -1,
-the variable pointed to by I<func> with the function name string or NULL,
-the variable pointed to by I<file> with the filename string or NULL, and
-the variable pointed to by I<line> with the line number or -1.
-Any string returned via I<*func> and I<*file> must be freeed by the caller.
-
-ossl_cmp_add_error_txt() appends text to the extra data field of the last
-error message in the OpenSSL error queue, after adding the optional separator
-unless data has been empty so far. The text can be of arbitrary length,
-which is not possible when using L<ERR_add_error_data(3)> in conjunction with
-L<ERR_print_errors_cb(3)>.
-
-ossl_cmp_add_error_data() is a macro calling
-ossl_cmp_add_error_txt() with the separator being ":".
-
-ossl_cmp_add_error_line() is a macro calling
-ossl_cmp_add_error_txt() with the separator being "\n".
-
 ossl_cmp_asn1_octet_string_set1() frees any previous value of the variable
 referenced via the I<tgt> argument and assigns either a copy of
 the ASN1_OCTET_STRING given as the I<src> argument or NULL.
@@ -68,15 +35,6 @@ certificates and optionally the (possible) trust anchor(s).
 
 =head1 RETURN VALUES
 
-ossl_cmp_log_parse_metadata() returns the pointer to the actual message text
-after the OSSL_CMP_LOG_PREFIX and level and ':' if found in the buffer,
-else the beginning of the buffer.
-
-ossl_cmp_add_error_txt()
-ossl_cmp_add_error_data(), and
-ossl_cmp_add_error_line()
-do not return anything.
-
 ossl_cmp_build_cert_chain()
 returns NULL on error, else a pointer to a stack of (up_ref'ed) certificates
 containing the EE certificate given in the function arguments (cert)
diff --git a/doc/internal/man3/ossl_cmp_certReq_new.pod b/doc/internal/man3/ossl_cmp_certReq_new.pod
new file mode 100644
index 0000000000..f54c215fa4
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_certReq_new.pod
@@ -0,0 +1,193 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_certReq_new,
+ossl_cmp_certRep_new,
+ossl_cmp_rr_new,
+ossl_cmp_rp_new,
+ossl_cmp_certConf_new,
+ossl_cmp_pkiconf_new,
+ossl_cmp_pollReq_new,
+ossl_cmp_pollRep_new,
+ossl_cmp_genm_new,
+ossl_cmp_genp_new,
+ossl_cmp_error_new
+- functions for generating CMP messages
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+# define OSSL_CMP_PKIBODY_IR        0
+# define OSSL_CMP_PKIBODY_IP        1
+# define OSSL_CMP_PKIBODY_CR        2
+# define OSSL_CMP_PKIBODY_CP        3
+# define OSSL_CMP_PKIBODY_P10CR     4
+# define OSSL_CMP_PKIBODY_POPDECC   5
+# define OSSL_CMP_PKIBODY_POPDECR   6
+# define OSSL_CMP_PKIBODY_KUR       7
+# define OSSL_CMP_PKIBODY_KUP       8
+# define OSSL_CMP_PKIBODY_KRR       9
+# define OSSL_CMP_PKIBODY_KRP      10
+# define OSSL_CMP_PKIBODY_RR       11
+# define OSSL_CMP_PKIBODY_RP       12
+# define OSSL_CMP_PKIBODY_CCR      13
+# define OSSL_CMP_PKIBODY_CCP      14
+# define OSSL_CMP_PKIBODY_CKUANN   15
+# define OSSL_CMP_PKIBODY_CANN     16
+# define OSSL_CMP_PKIBODY_RANN     17
+# define OSSL_CMP_PKIBODY_CRLANN   18
+# define OSSL_CMP_PKIBODY_PKICONF  19
+# define OSSL_CMP_PKIBODY_NESTED   20
+# define OSSL_CMP_PKIBODY_GENM     21
+# define OSSL_CMP_PKIBODY_GENP     22
+# define OSSL_CMP_PKIBODY_ERROR    23
+# define OSSL_CMP_PKIBODY_CERTCONF 24
+# define OSSL_CMP_PKIBODY_POLLREQ  25
+# define OSSL_CMP_PKIBODY_POLLREP  26
+
+ OSSL_ossl_cmp_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int bodytype,
+                                         int err_code);
+ OSSL_CMP_MSG *ossl_cmp_certRep_new(OSSL_CMP_CTX *ctx, int bodytype,
+                                    int certReqId, OSSL_CMP_PKISI *si,
+                                    X509 *cert, STACK_OF(X509) *chain,
+                                    STACK_OF(X509) *caPubs,
+                                    int encrypted, int unprotectedErrors);
+ OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx);
+ OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
+                               OSSL_CRMF_CERTID *cid, int unprot_err);
+ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
+                                     const char *text);
+ OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx);
+ OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid);
+ OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid, int poll_after)
+ OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx);
+ OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx);
+ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
+                                  int errorCode,
+                                  OSSL_CMP_PKIFREETEXT *errorDetails,
+                                  int unprotected)
+
+=head1 DESCRIPTION
+
+This is the API for creating various CMP PKIMESSAGES. The
+functions allocate a new message, fill it with the relevant data derived from
+the given OSSL_CMP_CTX, and create the applicable protection.
+
+ossl_cmp_certReq_new() creates a PKIMessage for requesting a certificate,
+which can be either of IR/CR/KUR/P10CR, depending on the given B<bodytype>.
+The OpenSSL error reason code defined in err.h to use on error is given as
+B<err_code>.
+
+Available CMP certificate request PKIMessage B<bodytype>s are:
+
+=over 4
+
+=item * B<OSSL_CMP_PKIBODY_IR>    - Initialization Request
+
+=item * B<OSSL_CMP_PKIBODY_CR>    - Certification Request
+
+=item * B<OSSL_CMP_PKIBODY_P10CR> - PKCS#10 Certification Request
+
+=item * B<OSSL_CMP_PKIBODY_KUR>   - Key Update Request
+
+=back
+
+ossl_cmp_certrep_new() creates a PKIMessage for certificate response, which can
+be either of IP/CP/KUP, depending on the given B<bodytype>.
+
+Available CMP certificate response PKIMessage B<bodytype>s are:
+
+=over 4
+
+=item * B<OSSL_CMP_PKIBODY_IP>    - Initialization Response
+
+=item * B<OSSL_CMP_PKIBODY_CP>    - Certification Response
+
+=item * B<OSSL_CMP_PKIBODY_KUP>   - Key Update Response
+
+=back
+
+The list of all CMP PKIMessage B<bodytype>s is:
+
+ #define OSSL_CMP_PKIBODY_IR        0
+ #define OSSL_CMP_PKIBODY_IP        1
+ #define OSSL_CMP_PKIBODY_CR        2
+ #define OSSL_CMP_PKIBODY_CP        3
+ #define OSSL_CMP_PKIBODY_P10CR     4
+ #define OSSL_CMP_PKIBODY_POPDECC   5
+ #define OSSL_CMP_PKIBODY_POPDECR   6
+ #define OSSL_CMP_PKIBODY_KRR       9
+ #define OSSL_CMP_PKIBODY_KRP      10
+ #define OSSL_CMP_PKIBODY_RR       11
+ #define OSSL_CMP_PKIBODY_RP       12
+ #define OSSL_CMP_PKIBODY_CCR      13
+ #define OSSL_CMP_PKIBODY_CCP      14
+ #define OSSL_CMP_PKIBODY_CKUANN   15
+ #define OSSL_CMP_PKIBODY_CANN     16
+ #define OSSL_CMP_PKIBODY_RANN     17
+ #define OSSL_CMP_PKIBODY_CRLANN   18
+ #define OSSL_CMP_PKIBODY_PKICONF  19
+ #define OSSL_CMP_PKIBODY_NESTED   20
+ #define OSSL_CMP_PKIBODY_GENM     21
+ #define OSSL_CMP_PKIBODY_GENP     22
+ #define OSSL_CMP_PKIBODY_ERROR    23
+ #define OSSL_CMP_PKIBODY_CERTCONF 24
+ #define OSSL_CMP_PKIBODY_POLLREQ  25
+ #define OSSL_CMP_PKIBODY_POLLREP  26
+
+ossl_cmp_rr_new() creates a Revocation Request message from the
+information set via OSSL_CMP_CTX_set1_oldClCert().
+
+ossl_cmp_rp_new() creates a Revocation Response message with status set to
+B<si> and CertID set to B<cid>. Consumes B<cid>.
+Accepts unprotected errors if B<uprot_err> != 0.
+
+ossl_cmp_certConf_new() creates a Certificate Confirmation message for the last
+received certificate. PKIStatus defaults to B<accepted> if the B<fail_info> bit
+field is 0. Else it is taken as the failInfo of the PKIStatusInfo, PKIStatus is
+set to B<rejected>, and B<text> is copied to statusString unless it is NULL.
+
+ossl_cmp_pkiconf_new() creates a PKI Confirmation message.
+
+ossl_cmp_pollReq_new() creates a Polling Request message with certReqId set to
+B<crid>.
+
+ossl_cmp_pollRep_new() creates a Polling Response message with certReqId set to
+B<crid> and pollAfter to B<poll_after>.
+
+ossl_cmp_genm_new() creates a new General Message with an empty ITAV stack.
+
+ossl_cmp_genp_new() creates a new General Response with an empty ITAV stack.
+
+ossl_cmp_error_new() creates a new Error Message with the given contents,
+copying B<si> and B<errorDetails>.
+
+=head1 NOTES
+
+CMP is specified in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+All of the functions return a new OSSL_CMP_MSG structure containing
+the generated message on success, or NULL on error.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_new(3)>, L<ERR_load_strings(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_msg_create.pod b/doc/internal/man3/ossl_cmp_msg_create.pod
new file mode 100644
index 0000000000..7498a1d6fd
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_msg_create.pod
@@ -0,0 +1,81 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_bodytype_to_string,
+ossl_cmp_msg_get_bodytype,
+ossl_cmp_msg_set_bodytype,
+ossl_cmp_msg_create,
+ossl_cmp_msg_load,
+ossl_cmp_msg_gen_ITAV_push0,
+ossl_cmp_msg_gen_ITAVs_push1
+- functions manipulating CMP messages
+
+=head1 SYNOPSIS
+
+  #include "cmp_int.h"
+
+  const char *ossl_cmp_bodytype_to_string(int type);
+  int ossl_cmp_msg_get_bodytype(const OSSL_CMP_MSG *msg);
+  int ossl_cmp_msg_set_bodytype( OSSL_CMP_MSG *msg, int type);
+  OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype);
+  OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file);
+  int ossl_cmp_msg_gen_ITAV_push0(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav);
+  int ossl_cmp_msg_gen_ITAVs_push1(OSSL_CMP_MSG *msg,
+                                    STACK_OF(OSSL_CMP_ITAV) *itavs);
+
+=head1 DESCRIPTION
+
+ossl_cmp_bodytype_to_string() returns the name of the given body type as string,
+or "illegal body type" on error.
+
+ossl_cmp_msg_get_bodytype() returns the body type of the given PKIMessage,
+or -1 on error.
+
+ossl_cmp_msg_set_bodytype() sets the type of the message contained in
+the PKIMessage body field.
+Returns 1 on success, 0 on error.
+
+ossl_cmp_msg_create() creates and initializes a OSSL_CMP_MSG structure,
+using B<ctx> for the header and B<bodytype> for the body.
+Returns pointer to created OSSL_CMP_MSG on success, NULL on error.
+
+OSSL_CMP_MSG *ossl_cmp_msg_load() loads a OSSL_CMP_MSG from a B<file>.
+Returns pointer to created OSSL_CMP_MSG on success, NULL on error.
+
+ossl_cmp_msg_gen_ITAV_push0() pushes the B<itav> to the body of the
+PKIMessage B<msg> of GenMsg or GenRep type. Consumes the B<itavs> pointer.
+Returns 1 on success, 0 on error.
+
+ossl_cmp_msg_gen_ITAVs_push1() adds a copy of the B<itavs> stack to the body
+of the PKIMessage B<msg> of GenMsg or GenRep type.
+Does not consume the B<itavs> pointer nor its elements.
+Returns 1 on success, 0 on error.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+See the individual functions above.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_exec_IR_ses(3)>,
+L<OSSL_CMP_MSG_http_perform(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_msg_protect.pod b/doc/internal/man3/ossl_cmp_msg_protect.pod
new file mode 100644
index 0000000000..7fd4e82e0b
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_msg_protect.pod
@@ -0,0 +1,53 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_msg_protect,
+ossl_cmp_msg_add_extraCerts
+- functions for producing CMP message protection
+
+=head1 SYNOPSIS
+
+  #include "cmp_int.h"
+
+  int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+  int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+
+=head1 DESCRIPTION
+
+ossl_cmp_msg_protect() protects the given message B<msg> using an algorithm
+depending on the available context information given in the B<ctx>.
+If there is a secretValue it selects PBMAC. Else if there is a clCert
+it selects Signature and uses B<ossl_cmp_msg_add_extraCerts()>.
+It also sets the protectionAlg field in the message header accordingly.
+
+ossl_cmp_msg_add_extraCerts() adds elements to the extraCerts field in the given
+message B<msg>. It tries to build the certificate chain of the client cert in
+the B<ctx> if present by using certificates in ctx->untrusted_certs;
+if no untrusted certs are set, it will at least add the client certificate.
+In any case all the certificates explicitly specified to be sent out (i.e.,
+B<ctx->extraCertsOut>) are added. Note that it will NOT add the root certificate
+of the chain, i.e, the trust anchor (unless it is part of extraCertsOut).
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+All functions return 1 on success, 0 on error.
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_print_log.pod b/doc/internal/man3/ossl_cmp_print_log.pod
new file mode 100644
index 0000000000..47d4dd8efa
--- /dev/null
+++ b/doc/internal/man3/ossl_cmp_print_log.pod
@@ -0,0 +1,108 @@
+=pod
+
+=head1 NAME
+
+ossl_cmp_print_log,
+ossl_cmp_alert,
+ossl_cmp_err,
+ossl_cmp_warn,
+ossl_cmp_info,
+ossl_cmp_debug,
+ossl_cmp_log,
+ossl_cmp_log1,
+ossl_cmp_log2,
+ossl_cmp_log3,
+ossl_cmp_log4,
+ossl_cmp_log_parse_metadata,
+ossl_cmp_add_error_data,
+ossl_cmp_add_error_line
+- logging and error reporting support for CMP
+
+=head1 SYNOPSIS
+
+ #include "cmp_local.h"
+
+ int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
+                        const char *func, const char *file, int line,
+                        const char *level_str, const char *format, ...);
+ #define ossl_cmp_alert(ctx, msg)
+ #define ossl_cmp_err(ctx, msg)
+ #define ossl_cmp_warn(ctx, msg)
+ #define ossl_cmp_info(ctx, msg)
+ #define ossl_cmp_debug(ctx, (msg)
+ #define ossl_cmp_log(level, ctx, msg)
+ #define ossl_cmp_log1(level, ctx, fmt, arg1)
+ #define ossl_cmp_log2(level, ctx, fmt, arg1, arg2)
+ #define ossl_cmp_log3(level, ctx, fmt, arg1, arg2, arg3)
+ #define ossl_cmp_log4(level, ctx, fmt, arg1, arg2, arg3, arg4)
+ const char *ossl_cmp_log_parse_metadata(const char *buf,
+                                         OSSL_CMP_severity *level, char **func,
+                                         char **file, int *line);
+
+ #define ossl_cmp_add_error_data(txt)
+ #define ossl_cmp_add_error_line(txt)
+
+=head1 DESCRIPTION
+
+ossl_cmp_print_log() prints CMP log messages (i.e., diagnostic info) via the
+log callback of the B<ctx> if present and the severity level is sufficient.
+If the trace API if enabled the function uses it, prepending the function name,
+filename, line number, and severity information to the message being output.
+In any case the B<level>, B<func>, B<file>, and B<line> parameters
+and the message constructed using the given B<format> and variable further
+argument list are passed to the log callback function (unless it is NULL).
+The B<ctx>, B<func>, B<file>, and B<level_str> arguments may be NULL.
+
+ossl_cmp_alert(), ossl_cmp_err(), ossl_cmp_warn(), ossl_cmp_info(), and
+ossl_cmp_debug() output a simple alert/error/warning/info/debug message
+via ossl_cmp_print_log().
+
+ossl_cmp_log(), ossl_cmp_log1(), ossl_cmp_log2(), ossl_cmp_log3(), and
+ossl_cmp_log4() output a log message with the given severity,
+constructing the message text from the given format and arguments.
+
+ossl_cmp_log_parse_metadata() parses the given message buffer I<buf> populated
+by ossl_cmp_log() etc.
+according to the pattern OSSL_CMP_LOG_START#level ": %s\n", filling in
+the variable pointed to by I<level> with the severity level or -1,
+the variable pointed to by I<func> with the function name string or NULL,
+the variable pointed to by I<file> with the filename string or NULL, and
+the variable pointed to by I<line> with the line number or -1.
+Any string returned via I<*func> and I<*file> must be freeed by the caller.
+
+ossl_cmp_add_error_data() is a macro calling
+L<ERR_add_error_txt(3)> with the separator being ":".
+
+ossl_cmp_add_error_line() is a macro calling
+L<ERR_add_error_txt(3)> with the separator being "\n".
+
+=head1 RETURN VALUES
+
+ossl_cmp_log_parse_metadata() returns the pointer to the actual message text
+after the OSSL_CMP_LOG_PREFIX and level and ':' if found in the buffer,
+else the beginning of the buffer.
+
+ossl_cmp_add_error_data() and
+ossl_cmp_add_error_line()
+do not return anything.
+
+All other functions return 1 on success, 0 on error.
+
+=head1 SEE ALSO
+
+L<ERR_add_error_txt(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/internal/man3/ossl_cmp_sk_X509_add1_cert.pod b/doc/internal/man3/ossl_cmp_sk_X509_add1_cert.pod
index cb36855adf..4c647708f3 100644
--- a/doc/internal/man3/ossl_cmp_sk_X509_add1_cert.pod
+++ b/doc/internal/man3/ossl_cmp_sk_X509_add1_cert.pod
@@ -15,9 +15,9 @@ ossl_cmp_X509_STORE_get1_certs
   int ossl_cmp_sk_X509_add1_cert(STACK_OF(X509) *sk, X509 *cert,
                                  int no_dup, int prepend);
   int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
-                                  int no_self_signed, int no_dups, int prepend);
+                                  int no_self_issued, int no_dups, int prepend);
   int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
-                                     int only_self_signed);
+                                     int only_self_issued);
   STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store);
 
 =head1 DESCRIPTION
@@ -29,10 +29,10 @@ On success the reference count of the certificate is increased.
 
 ossl_cmp_sk_X509_add1_certs() appends or prepends (depending on the I<prepend>
 argument) a list of certificates to the given list,
-optionally only if not self-signed and optionally only if not already contained.
+optionally only if not self-issued and optionally only if not already contained.
 The reference counts of those certificates appended successfully are increased.
 
-ossl_cmp_X509_STORE_add1_certs() adds all or only self-signed certificates from
+ossl_cmp_X509_STORE_add1_certs() adds all or only self-issued certificates from
 the given stack to given store. The I<certs> parameter may be NULL.
 
 ossl_cmp_X509_STORE_get1_certs() retrieves a copy of all certificates in the
diff --git a/doc/man3/ERR_put_error.pod b/doc/man3/ERR_put_error.pod
index e3c19bfdf4..85538f718b 100644
--- a/doc/man3/ERR_put_error.pod
+++ b/doc/man3/ERR_put_error.pod
@@ -3,7 +3,8 @@
 =head1 NAME
 
 ERR_raise, ERR_raise_data,
-ERR_put_error, ERR_add_error_data, ERR_add_error_vdata
+ERR_put_error, ERR_add_error_data, ERR_add_error_vdata,
+ERR_add_error_txt, ERR_add_error_mem_bio
 - record an error
 
 =head1 SYNOPSIS
@@ -15,6 +16,8 @@ ERR_put_error, ERR_add_error_data, ERR_add_error_vdata
 
  void ERR_add_error_data(int num, ...);
  void ERR_add_error_vdata(int num, va_list arg);
+ void ERR_add_error_txt(const char *sep, const char *txt);
+ void ERR_add_error_mem_bio(const char *sep, BIO *bio);
 
 Deprecated since OpenSSL 3.0:
 
@@ -38,9 +41,23 @@ B<func> of library B<lib>, in line number B<line> of B<file>.
 This function is usually called by a macro.
 
 ERR_add_error_data() associates the concatenation of its B<num> string
-arguments with the error code added last.
+arguments as additional data with the error code added last.
 ERR_add_error_vdata() is similar except the argument is a B<va_list>.
 Multiple calls to these functions append to the current top of the error queue.
+The total length of the string data per error is limited to 4096 characters.
+
+ERR_add_error_txt() appends the given text string as additional data to the
+last error queue entry, after inserting the optional separator string if it is
+not NULL and the top error entry does not yet have additional data.
+In case the separator is at the end of the text it is not appended to the data.
+The B<sep> argument may be for instance "\n" to insert a line break when needed.
+If the associated data would become more than 4096 characters long
+(which is the limit given above)
+it is split over sufficiently many new copies of the last error queue entry.
+
+ERR_add_error_mem_bio() is the same as ERR_add_error_txt() except that
+the text string is taken from the given memory BIO.
+It appends '\0' to the BIO contents if not already NUL-terminated.
 
 L<ERR_load_strings(3)> can be used to register
 error strings so that the application can a generate human-readable
@@ -76,8 +93,10 @@ the ASN1err() macro.
 
 =head1 RETURN VALUES
 
-ERR_raise(), ERR_put_error(), ERR_add_error_data() and
-ERR_add_error_vdata() return no values.
+ERR_raise(), ERR_put_error(),
+ERR_add_error_data(), ERR_add_error_vdata()
+ERR_add_error_txt(), and ERR_add_error_mem_bio()
+return no values.
 
 =head1 NOTES
 
@@ -87,6 +106,10 @@ ERR_raise() and ERR_put_error() are implemented as macros.
 
 L<ERR_load_strings(3)>
 
+=head1 HISTORY
+
+B<ERR_add_error_txt> and B<ERR_add_error_mem_bio> were added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/OSSL_CMP_log_open.pod b/doc/man3/OSSL_CMP_log_open.pod
index 64399e2b72..9f204d6ec1 100644
--- a/doc/man3/OSSL_CMP_log_open.pod
+++ b/doc/man3/OSSL_CMP_log_open.pod
@@ -4,16 +4,6 @@
 
 OSSL_CMP_log_open,
 OSSL_CMP_log_close,
-OSSL_CMP_alert,
-OSSL_CMP_err,
-OSSL_CMP_warn,
-OSSL_CMP_info,
-OSSL_CMP_debug,
-OSSL_CMP_log,
-OSSL_CMP_log1,
-OSSL_CMP_log2,
-OSSL_CMP_log3,
-OSSL_CMP_log4,
 OSSL_CMP_severity,
 OSSL_CMP_LOG_EMERG,
 OSSL_CMP_LOG_ALERT,
@@ -24,6 +14,7 @@ OSSL_CMP_LOG_NOTICE,
 OSSL_CMP_LOG_INFO,
 OSSL_CMP_LOG_DEBUG,
 OSSL_cmp_log_cb_t,
+OSSL_CMP_print_to_bio,
 OSSL_CMP_print_errors_cb
 - functions for logging and error reporting
 
@@ -33,16 +24,6 @@ OSSL_CMP_print_errors_cb
 
  int  OSSL_CMP_log_open(void);
  void OSSL_CMP_log_close(void);
- #define OSSL_CMP_alert(msg)
- #define OSSL_CMP_err(msg)
- #define OSSL_CMP_warn(msg)
- #define OSSL_CMP_info(msg)
- #define OSSL_CMP_debug(msg)
- #define OSSL_CMP_log(level, msg)
- #define OSSL_CMP_log1(level, fmt, arg1)
- #define OSSL_CMP_log2(level, fmt, arg1, arg2)
- #define OSSL_CMP_log3(level, fmt, arg1, arg2, arg3)
- #define OSSL_CMP_log4(level, fmt, arg1, arg2, arg3, arg4)
 
  /* severity level declarations resemble those from syslog.h */
  typedef int OSSL_CMP_severity;
@@ -54,16 +35,18 @@ OSSL_CMP_print_errors_cb
  #define OSSL_CMP_LOG_NOTICE  5
  #define OSSL_CMP_LOG_INFO    6
  #define OSSL_CMP_LOG_DEBUG   7
+
  typedef int (*OSSL_cmp_log_cb_t)(const char *component,
                                   const char *file, int line,
                                   OSSL_CMP_severity level, const char *msg);
-
+ int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file,
+                           int line, OSSL_CMP_severity level, const char *msg);
  void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn);
 
 =head1 DESCRIPTION
 
 The logging and error reporting facility described here contains
-convenience functions for CMP-specific logging via the trace API,
+convenience functions for CMP-specific logging,
 including a string prefix mirroring the severity levels of syslog.h,
 and enhancements of the error queue mechanism needed for large diagnostic
 messages produced by the CMP library in case of certificate validation failures.
@@ -73,12 +56,12 @@ should be provided for user information, debugging, and auditing purposes.
 A CMP application can obtain this information by providing a callback function
 with the following type:
 
- typedef void (*OSSL_cmp_log_cb_t)(const char *component,
-                                   const char *file, int line,
-                                   OSSL_CMP_severity level, const char *msg);
+ typedef int (*OSSL_cmp_log_cb_t)(const char *component,
+                                  const char *file, int line,
+                                  OSSL_CMP_severity level, const char *msg);
 
 The parameters may provide
-a component identifier (which may be a library name or function name) or NULL,
+some component info (which may be a module name and/or function name) or NULL,
 a file pathname or NULL,
 a line number or 0 indicating the source code location,
 a severity level, and
@@ -105,19 +88,15 @@ OSSL_CMP_log_close() may be called when all activities are finished to flush
 any pending CMP-specific log output and deallocate related resources.
 It may be called multiple times. It does get called at OpenSSL stutdown.
 
-OSSL_CMP_alert() outputs a simple alert message via the trace API.
-OSSL_CMP_err() outputs a simple error message via the trace API.
-OSSL_CMP_warn() outputs a simple warning message via the trace API.
-OSSL_CMP_info() outputs a simple info message via the trace API.
-OSSL_CMP_debug() outputs a simple debug message via the trace API.
-
-Note that due to the design of the trace API used, the log functions have no
-effect unless the B<enable-trace> option is used during build configuration.
+OSSL_CMP_print_to_bio() prints the given component info, filename, line number,
+severity level, and log message or error queue message to the given B<bio>.
+B<component> usually is a function or module name.
+If it is NULL, empty, or "(unknown function)" then "CMP" is used as fallback.
 
 OSSL_CMP_print_errors_cb() outputs any entries in the OpenSSL error queue.
 It is similar to B<ERR_print_errors_cb()> but uses the CMP log callback function
-C<log_fn> for uniformity with CMP logging if not B<NULL>. Otherwise it uses
-B<ERR_print_errors(3)> to print to STDERR (unless OPENSSL_NO_STDIO is defined).
+C<log_fn> for uniformity with CMP logging if not B<NULL>. Otherwise it prints to
+STDERR using B<OSSL_CMP_print_to_bio(3)> (unless OPENSSL_NO_STDIO is defined).
 
 =head1 RETURN VALUES
 
diff --git a/doc/man3/OSSL_CMP_validate_msg.pod b/doc/man3/OSSL_CMP_validate_msg.pod
new file mode 100644
index 0000000000..acb17facde
--- /dev/null
+++ b/doc/man3/OSSL_CMP_validate_msg.pod
@@ -0,0 +1,86 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_validate_msg,
+OSSL_CMP_validate_cert_path
+- functions for verifying CMP message protection
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+ int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
+                                 X509_STORE *trusted_store, X509 *cert);
+
+=head1 DESCRIPTION
+
+This is the API for validating the protection of CMP messages,
+which includes validating CMP message sender certificates and their paths
+while optionally checking the revocation status of the certificates(s).
+
+OSSL_CMP_validate_msg() validates the protection of the given C<msg>
+using either password-based mac (PBM) or a signature algorithm.
+
+In case of signature algorithm, the certificate to use for the signature check
+is preferably the one provided by a call to L<OSSL_CMP_CTX_set1_srvCert(3)>.
+If no such sender cert has been pinned then candidate sender certificates are
+taken from the list of certificates received in the C<msg> extraCerts, then any
+certificates provided before via L<OSSL_CMP_CTX_set1_untrusted_certs(3)>, and
+then all trusted certificates provided via L<OSSL_CMP_CTX_set0_trustedStore(3)>,
+where a candidate is acceptable only if has not expired, its subject DN matches
+the C<msg> sender DN (as far as present), and its subject key identifier
+is present and matches the senderKID (as far as the latter present).
+Each acceptable cert is tried in the given order to see if the message
+signature check succeeds and the cert and its path can be verified
+using any trust store set via L<OSSL_CMP_CTX_set0_trustedStore(3)>.
+
+If the option OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR was set by calling
+L<OSSL_CMP_CTX_set_option(3)>, for an Initialization Response (IP) message
+any self-issued certificate from the C<msg> extraCerts field may also be used
+as trust anchor for the path verification of an acceptable cert if it can be
+used also to validate the issued certificate returned in the IP message. This is
+according to TS 33.310 [Network Domain Security (NDS); Authentication Framework
+(AF)] document specified by the The 3rd Generation Partnership Project (3GPP).
+
+Any cert that has been found as described above is cached and tried first when
+validating the signatures of subsequent messages in the same transaction.
+
+After successful validation of PBM-based protection of a certificate response
+the certificates in the caPubs field (if any) are added to the trusted
+certificates provided via L<OSSL_CMP_CTX_set0_trustedStore(3)>, such that
+they are available for validating subsequent messages in the same context.
+Those could apply to any Polling Response (pollRep), error, or PKI Confirmation
+(PKIConf) messages following in the same or future transactions.
+
+OSSL_CMP_validate_cert_path() attempts to validate the given certificate and its
+path using the given store of trusted certs (possibly including CRLs and a cert
+verification callback) and non-trusted intermediate certs from the B<ctx>.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+OSSL_CMP_validate_msg() and OSSL_CMP_validate_cert_path()
+return 1 on success, 0 on error or validation failed.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_exec_IR_ses(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/X509_STORE_CTX_set_verify_cb.pod b/doc/man3/X509_STORE_CTX_set_verify_cb.pod
index 64ccefa7ff..c53b14db36 100644
--- a/doc/man3/X509_STORE_CTX_set_verify_cb.pod
+++ b/doc/man3/X509_STORE_CTX_set_verify_cb.pod
@@ -14,14 +14,16 @@ X509_STORE_CTX_get_check_issued,
 X509_STORE_CTX_get_get_issuer,
 X509_STORE_CTX_get_verify_cb,
 X509_STORE_CTX_set_verify_cb,
-X509_STORE_CTX_verify_cb
-- get and set verification callback
+X509_STORE_CTX_verify_cb,
+X509_STORE_CTX_print_verify_cb
+- get and set X509_STORE_CTX components such as verification callback
 
 =head1 SYNOPSIS
 
  #include <openssl/x509_vfy.h>
 
  typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *);
+ int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx);
 
  X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx);
 
@@ -63,6 +65,12 @@ structure and receive additional information about the error, for example
 by calling X509_STORE_CTX_get_current_cert(). Additional application data can
 be passed to the callback via the B<ex_data> mechanism.
 
+X509_STORE_CTX_print_verify_cb() is a verification callback function that,
+when a certificate verification has failed, adds an entry to the error queue
+with code B<X509_R_CERTIFICATE_VERIFICATION_FAILED> and with diagnostic details,
+including the most relevant fields of the target certificate that failed to
+verify and, if appropriate, of the available untrusted and trusted certificates.
+
 X509_STORE_CTX_get_verify_cb() returns the value of the current callback
 for the specific B<ctx>.
 
@@ -200,6 +208,8 @@ X509_STORE_CTX_get_cert_crl(), X509_STORE_CTX_get_check_policy(),
 X509_STORE_CTX_get_lookup_certs(), X509_STORE_CTX_get_lookup_crls()
 and X509_STORE_CTX_get_cleanup() functions were added in OpenSSL 1.1.0.
 
+X509_STORE_CTX_print_verify_cb() was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2009-2016 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/X509_STORE_get0_param.pod b/doc/man3/X509_STORE_get0_param.pod
index 27fe786783..6db760ea51 100644
--- a/doc/man3/X509_STORE_get0_param.pod
+++ b/doc/man3/X509_STORE_get0_param.pod
@@ -3,7 +3,8 @@
 =head1 NAME
 
 X509_STORE_get0_param, X509_STORE_set1_param,
-X509_STORE_get0_objects - X509_STORE setter and getter functions
+X509_STORE_get0_objects, X509_STORE_get1_all_certs
+- X509_STORE setter and getter functions
 
 =head1 SYNOPSIS
 
@@ -12,6 +13,7 @@ X509_STORE_get0_objects - X509_STORE setter and getter functions
  X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx);
  int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
  STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *ctx);
+ STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *st);
 
 =head1 DESCRIPTION
 
@@ -22,10 +24,12 @@ X509_STORE_get0_param() retrieves an internal pointer to the verification
 parameters for B<ctx>. The returned pointer must not be freed by the
 calling application
 
-X509_STORE_get0_objects() retrieve an internal pointer to the store's
+X509_STORE_get0_objects() retrieves an internal pointer to the store's
 X509 object cache. The cache contains B<X509> and B<X509_CRL> objects. The
 returned pointer must not be freed by the calling application.
 
+X509_STORE_get1_all_certs() returns a list of all certificates in the store.
+The caller is responsible for freeing the returned list.
 
 =head1 RETURN VALUES
 
@@ -36,6 +40,9 @@ X509_STORE_set1_param() returns 1 for success and 0 for failure.
 
 X509_STORE_get0_objects() returns a pointer to a stack of B<X509_OBJECT>.
 
+X509_STORE_get1_all_certs() returns a pointer to a stack of the retrieved
+certificates on success, else NULL.
+
 =head1 SEE ALSO
 
 L<X509_STORE_new(3)>
@@ -44,6 +51,7 @@ L<X509_STORE_new(3)>
 
 B<X509_STORE_get0_param> and B<X509_STORE_get0_objects> were added in
 OpenSSL 1.1.0.
+B<X509_STORE_get1_certs> was added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index 11a776953b..602a72fd27 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -288,5 +288,6 @@ struct x509_object_st {
 
 int a2i_ipadd(unsigned char *ipout, const char *ipasc);
 int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm);
+int x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags);
 
 void x509_init_sig_info(X509 *x);
diff --git a/include/openssl/cmp.h b/include/openssl/cmp.h
index 78763248e0..43dcc69993 100644
--- a/include/openssl/cmp.h
+++ b/include/openssl/cmp.h
@@ -26,7 +26,7 @@
 #  include <openssl/x509.h>
 #  include <openssl/x509v3.h>
 
-#  ifdef  __cplusplus
+#  ifdef __cplusplus
 extern "C" {
 #  endif
 
@@ -128,9 +128,9 @@ extern "C" {
 #  define OSSL_CMP_PKIFAILUREINFO_duplicateCertReq 26
 #  define OSSL_CMP_PKIFAILUREINFO_MAX 26
 #  define OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN \
-    ( (1<<(OSSL_CMP_PKIFAILUREINFO_MAX+1)) - 1)
+    ((1 << (OSSL_CMP_PKIFAILUREINFO_MAX + 1)) - 1)
 #  if OSSL_CMP_PKIFAILUREINFO_MAX_BIT_PATTERN > INT_MAX
-#   error  CMP_PKIFAILUREINFO_MAX bit pattern does not fit in type int
+#   error CMP_PKIFAILUREINFO_MAX bit pattern does not fit in type int
 #  endif
 
 typedef ASN1_BIT_STRING OSSL_CMP_PKIFAILUREINFO;
@@ -348,6 +348,11 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr);
 /* support application-level CMP debugging in cmp.c: */
 OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
 
+/* from cmp_vfy.c */
+int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg);
+int OSSL_CMP_validate_cert_path(OSSL_CMP_CTX *ctx,
+                                X509_STORE *trusted_store, X509 *cert);
+
 #  ifdef  __cplusplus
 }
 #  endif
diff --git a/include/openssl/cmp_util.h b/include/openssl/cmp_util.h
index ee368afa60..56fb49e188 100644
--- a/include/openssl/cmp_util.h
+++ b/include/openssl/cmp_util.h
@@ -19,39 +19,13 @@
 #  include <openssl/trace.h>
 #  include <openssl/x509.h>
 
-#  ifdef  __cplusplus
+#  ifdef __cplusplus
 extern "C" {
 #  endif
 
-/*
- * convenience functions for CMP-specific logging via the trace API
- */
 int  OSSL_CMP_log_open(void);
 void OSSL_CMP_log_close(void);
 #  define OSSL_CMP_LOG_PREFIX "CMP "
-/* in OSSL_CMP_LOG_START, cannot use OPENSSL_FUNC when expands to __func__ */
-#  define OSSL_CMP_LOG_START "%s:" OPENSSL_FILE ":" \
-    OPENSSL_MSTR(OPENSSL_LINE) ":" OSSL_CMP_LOG_PREFIX
-#  define OSSL_CMP_alert(msg) OSSL_CMP_log(ALERT, msg)
-#  define OSSL_CMP_err(msg)   OSSL_CMP_log(ERROR, msg)
-#  define OSSL_CMP_warn(msg)  OSSL_CMP_log(WARN, msg)
-#  define OSSL_CMP_info(msg)  OSSL_CMP_log(INFO, msg)
-#  define OSSL_CMP_debug(msg) OSSL_CMP_log(DEBUG, msg)
-#  define OSSL_CMP_log(level, msg) \
-    OSSL_TRACEV(CMP, (trc_out, OSSL_CMP_LOG_START#level ": %s\n", \
-                      OPENSSL_FUNC, msg))
-#  define OSSL_CMP_log1(level, fmt, arg1) \
-    OSSL_TRACEV(CMP, (trc_out, OSSL_CMP_LOG_START#level ": " fmt "\n", \
-                      OPENSSL_FUNC, arg1))
-#  define OSSL_CMP_log2(level, fmt, arg1, arg2) \
-    OSSL_TRACEV(CMP, (trc_out, OSSL_CMP_LOG_START#level ": " fmt "\n", \
-                      OPENSSL_FUNC, arg1, arg2))
-#  define OSSL_CMP_log3(level, fmt, arg1, arg2, arg3) \
-    OSSL_TRACEV(CMP, (trc_out, OSSL_CMP_LOG_START#level ": " fmt "\n", \
-                      OPENSSL_FUNC, arg1, arg2, arg3))
-#  define OSSL_CMP_log4(level, fmt, arg1, arg2, arg3, arg4) \
-    OSSL_TRACEV(CMP, (trc_out, OSSL_CMP_LOG_START#level ": " fmt "\n", \
-                      OPENSSL_FUNC, arg1, arg2, arg3, arg4))
 
 /*
  * generalized logging/error callback mirroring the severity levels of syslog.h
@@ -68,6 +42,8 @@ typedef int OSSL_CMP_severity;
 typedef int (*OSSL_cmp_log_cb_t)(const char *func, const char *file, int line,
                                  OSSL_CMP_severity level, const char *msg);
 
+int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file,
+                          int line, OSSL_CMP_severity level, const char *msg);
 /* use of the logging callback for outputting error queue */
 void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn);
 
diff --git a/include/openssl/cmperr.h b/include/openssl/cmperr.h
index cd962fb5d1..51795a52ab 100644
--- a/include/openssl/cmperr.h
+++ b/include/openssl/cmperr.h
@@ -19,7 +19,7 @@
 
 # ifndef OPENSSL_NO_CMP
 
-#  ifdef  __cplusplus
+#  ifdef __cplusplus
 extern "C"
 #  endif
 int ERR_load_CMP_strings(void);
@@ -27,12 +27,13 @@ int ERR_load_CMP_strings(void);
 /*
  * CMP function codes.
  */
-# ifndef OPENSSL_NO_DEPRECATED_3_0
-# endif
+#  ifndef OPENSSL_NO_DEPRECATED_3_0
+#  endif
 
 /*
  * CMP reason codes.
  */
+#  define CMP_R_ALGORITHM_NOT_SUPPORTED                    139
 #  define CMP_R_BAD_REQUEST_ID                             108
 #  define CMP_R_CERTID_NOT_FOUND                           109
 #  define CMP_R_CERTIFICATE_NOT_FOUND                      112
@@ -53,23 +54,38 @@ int ERR_load_CMP_strings(void);
 #  define CMP_R_ERROR_PARSING_PKISTATUS                    107
 #  define CMP_R_ERROR_PROTECTING_MESSAGE                   127
 #  define CMP_R_ERROR_SETTING_CERTHASH                     128
+#  define CMP_R_ERROR_VALIDATING_PROTECTION                140
+#  define CMP_R_FAILED_EXTRACTING_PUBKEY                   141
 #  define CMP_R_FAILURE_OBTAINING_RANDOM                   110
 #  define CMP_R_FAIL_INFO_OUT_OF_RANGE                     129
 #  define CMP_R_INVALID_ARGS                               100
 #  define CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION  130
+#  define CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE         142
 #  define CMP_R_MISSING_PRIVATE_KEY                        131
+#  define CMP_R_MISSING_PROTECTION                         143
 #  define CMP_R_MISSING_SENDER_IDENTIFICATION              111
+#  define CMP_R_MISSING_TRUST_STORE                        144
 #  define CMP_R_MULTIPLE_SAN_SOURCES                       102
 #  define CMP_R_NO_STDIO                                   194
+#  define CMP_R_NO_SUITABLE_SENDER_CERT                    145
 #  define CMP_R_NULL_ARGUMENT                              103
+#  define CMP_R_PKIBODY_ERROR                              146
 #  define CMP_R_PKISTATUSINFO_NOT_FOUND                    132
-#  define CMP_R_POTENTIALLY_INVALID_CERTIFICATE            139
+#  define CMP_R_POTENTIALLY_INVALID_CERTIFICATE            147
+#  define CMP_R_RECIPNONCE_UNMATCHED                       148
+#  define CMP_R_REQUEST_NOT_ACCEPTED                       149
+#  define CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED      150
+#  define CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG              151
+#  define CMP_R_TRANSACTIONID_UNMATCHED                    152
 #  define CMP_R_UNEXPECTED_PKIBODY                         133
+#  define CMP_R_UNEXPECTED_PVNO                            153
 #  define CMP_R_UNKNOWN_ALGORITHM_ID                       134
 #  define CMP_R_UNKNOWN_CERT_TYPE                          135
 #  define CMP_R_UNSUPPORTED_ALGORITHM                      136
 #  define CMP_R_UNSUPPORTED_KEY_TYPE                       137
+#  define CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC      154
 #  define CMP_R_WRONG_ALGORITHM_OID                        138
+#  define CMP_R_WRONG_PBM_VALUE                            155
 
 # endif
 #endif
diff --git a/include/openssl/crmf.h b/include/openssl/crmf.h
index 160ad326b0..09b57f6bce 100644
--- a/include/openssl/crmf.h
+++ b/include/openssl/crmf.h
@@ -26,7 +26,7 @@
 #  include <openssl/types.h>
 #  include <openssl/x509.h>
 
-#  ifdef  __cplusplus
+#  ifdef __cplusplus
 extern "C" {
 #  endif
 
@@ -77,9 +77,9 @@ int OSSL_CRMF_MSG_set1_regCtrl_regToken(OSSL_CRMF_MSG *msg,
                                         const ASN1_UTF8STRING *tok);
 int OSSL_CRMF_MSG_set1_regCtrl_authenticator(OSSL_CRMF_MSG *msg,
                                              const ASN1_UTF8STRING *auth);
-int OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(
-                                               OSSL_CRMF_PKIPUBLICATIONINFO *pi,
-                                               OSSL_CRMF_SINGLEPUBINFO *spi);
+int
+OSSL_CRMF_MSG_PKIPublicationInfo_push0_SinglePubInfo(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+                                                     OSSL_CRMF_SINGLEPUBINFO *spi);
 #  define OSSL_CRMF_PUB_METHOD_DONTCARE 0
 #  define OSSL_CRMF_PUB_METHOD_X500     1
 #  define OSSL_CRMF_PUB_METHOD_WEB      2
@@ -88,10 +88,10 @@ int OSSL_CRMF_MSG_set0_SinglePubInfo(OSSL_CRMF_SINGLEPUBINFO *spi,
                                      int method, GENERAL_NAME *nm);
 #  define OSSL_CRMF_PUB_ACTION_DONTPUBLISH   0
 #  define OSSL_CRMF_PUB_ACTION_PLEASEPUBLISH 1
-int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(
-                                  OSSL_CRMF_PKIPUBLICATIONINFO *pi, int action);
+int OSSL_CRMF_MSG_set_PKIPublicationInfo_action(OSSL_CRMF_PKIPUBLICATIONINFO *pi,
+                                                int action);
 int OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo(OSSL_CRMF_MSG *msg,
-                                        const OSSL_CRMF_PKIPUBLICATIONINFO *pi);
+                                                  const OSSL_CRMF_PKIPUBLICATIONINFO *pi);
 int OSSL_CRMF_MSG_set1_regCtrl_protocolEncrKey(OSSL_CRMF_MSG *msg,
                                                const X509_PUBKEY *pubkey);
 int OSSL_CRMF_MSG_set1_regCtrl_oldCertID(OSSL_CRMF_MSG *msg,
@@ -110,7 +110,7 @@ int OSSL_CRMF_MSG_get_certReqId(OSSL_CRMF_MSG *crm);
 int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm, X509_EXTENSIONS *exts);
 
 int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm, X509_EXTENSION *ext);
-#  define OSSL_CRMF_POPO_NONE      -1
+#  define OSSL_CRMF_POPO_NONE       -1
 #  define OSSL_CRMF_POPO_RAVERIFIED 0
 #  define OSSL_CRMF_POPO_SIGNATURE  1
 #  define OSSL_CRMF_POPO_KEYENC     2
diff --git a/include/openssl/crmferr.h b/include/openssl/crmferr.h
index 97f5159b51..97a3028ce2 100644
--- a/include/openssl/crmferr.h
+++ b/include/openssl/crmferr.h
@@ -19,7 +19,7 @@
 
 # ifndef OPENSSL_NO_CRMF
 
-#  ifdef  __cplusplus
+#  ifdef __cplusplus
 extern "C"
 #  endif
 int ERR_load_CRMF_strings(void);
@@ -27,7 +27,7 @@ int ERR_load_CRMF_strings(void);
 /*
  * CRMF function codes.
  */
-# ifndef OPENSSL_NO_DEPRECATED_3_0
+#  ifndef OPENSSL_NO_DEPRECATED_3_0
 #   define CRMF_F_CRMF_POPOSIGNINGKEY_INIT                  0
 #   define CRMF_F_OSSL_CRMF_CERTID_GEN                      0
 #   define CRMF_F_OSSL_CRMF_CERTTEMPLATE_FILL               0
@@ -47,7 +47,7 @@ int ERR_load_CRMF_strings(void);
 #   define CRMF_F_OSSL_CRMF_MSG_SET_VALIDITY                0
 #   define CRMF_F_OSSL_CRMF_PBMP_NEW                        0
 #   define CRMF_F_OSSL_CRMF_PBM_NEW                         0
-# endif
+#  endif
 
 /*
  * CRMF reason codes.
diff --git a/include/openssl/err.h b/include/openssl/err.h
index 17a248ca8d..ef8e895c6e 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -333,6 +333,8 @@ void ERR_print_errors(BIO *bp);
 
 void ERR_add_error_data(int num, ...);
 void ERR_add_error_vdata(int num, va_list args);
+void ERR_add_error_txt(const char *sepr, const char *txt);
+void ERR_add_error_mem_bio(const char *sep, BIO *bio);
 
 int ERR_load_strings(int lib, ERR_STRING_DATA *str);
 int ERR_load_strings_const(const ERR_STRING_DATA *str);
diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h
index affdc67d80..75529b234e 100644
--- a/include/openssl/x509_vfy.h
+++ b/include/openssl/x509_vfy.h
@@ -67,6 +67,7 @@ DEFINE_STACK_OF(X509_VERIFY_PARAM)
 int X509_STORE_set_depth(X509_STORE *store, int depth);
 
 typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *);
+int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx);
 typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *);
 typedef int (*X509_STORE_CTX_get_issuer_fn)(X509 **issuer,
                                             X509_STORE_CTX *ctx, X509 *x);
@@ -287,8 +288,9 @@ void X509_STORE_free(X509_STORE *v);
 int X509_STORE_lock(X509_STORE *ctx);
 int X509_STORE_unlock(X509_STORE *ctx);
 int X509_STORE_up_ref(X509_STORE *v);
-STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v);
 
+STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v);
+STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *st);
 STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *st, X509_NAME *nm);
 STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *st, X509_NAME *nm);
 int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h
index 5b0a6b5eaa..2653870d29 100644
--- a/include/openssl/x509err.h
+++ b/include/openssl/x509err.h
@@ -107,6 +107,7 @@ int ERR_load_X509_strings(void);
 # define X509_R_BASE64_DECODE_ERROR                       118
 # define X509_R_CANT_CHECK_DH_KEY                         114
 # define X509_R_CERT_ALREADY_IN_HASH_TABLE                101
+# define X509_R_CERTIFICATE_VERIFICATION_FAILED           139
 # define X509_R_CRL_ALREADY_DELTA                         127
 # define X509_R_CRL_VERIFY_FAILURE                        131
 # define X509_R_IDP_MISMATCH                              128
diff --git a/test/build.info b/test/build.info
index c35bed086c..f964dec4ba 100644
--- a/test/build.info
+++ b/test/build.info
@@ -455,7 +455,7 @@ IF[{- !$disabled{tests} -}]
 
   IF[{- !$disabled{cmp} -}]
     PROGRAMS{noinst}=cmp_asn_test cmp_ctx_test cmp_status_test cmp_hdr_test \
-                     cmp_protect_test cmp_msg_test
+                     cmp_protect_test cmp_msg_test cmp_vfy_test
   ENDIF
 
   SOURCE[cmp_asn_test]=cmp_asn_test.c cmp_testlib.c
@@ -482,6 +482,10 @@ IF[{- !$disabled{tests} -}]
   INCLUDE[cmp_msg_test]=.. ../include ../apps/include
   DEPEND[cmp_msg_test]=../libcrypto.a libtestutil.a
 
+  SOURCE[cmp_vfy_test]=cmp_status_test.c cmp_testlib.c
+  INCLUDE[cmp_vfy_test]=.. ../include ../apps/include
+  DEPEND[cmp_vfy_test]=../libcrypto.a libtestutil.a
+
   # Internal test programs.  These are essentially a collection of internal
   # test routines.  Some of them need to reach internal symbols that aren't
   # available through the shared library (at least on Linux, Solaris, Windows
diff --git a/test/cmp_ctx_test.c b/test/cmp_ctx_test.c
index c007cfb35e..26c65778b9 100644
--- a/test/cmp_ctx_test.c
+++ b/test/cmp_ctx_test.c
@@ -169,7 +169,7 @@ static int execute_CTX_print_errors_test(OSSL_CMP_CTX_TEST_FIXTURE *fixture)
         base_err_msg_size = strlen("INVALID_ARGS") + strlen(" : ");
         expected_size = base_err_msg_size;
         while (expected_size < 4096) { /* force split */
-            ossl_cmp_add_error_txt(STR_SEP, max_str_literal);
+            ERR_add_error_txt(STR_SEP, max_str_literal);
             expected_size += strlen(STR_SEP) + strlen(max_str_literal);
         }
         expected_size += base_err_msg_size - 2 * strlen(STR_SEP);
@@ -190,12 +190,12 @@ static int test_CTX_print_errors(void)
 }
 #endif
 
-static int execute_CTX_reqExtensions_have_SAN_test(
-                                             OSSL_CMP_CTX_TEST_FIXTURE *fixture)
+static
+int execute_CTX_reqExtensions_have_SAN_test(OSSL_CMP_CTX_TEST_FIXTURE *fixture)
 {
     OSSL_CMP_CTX *ctx = fixture->ctx;
     const int len = 16;
-    unsigned char str[16 /* = len */ ];
+    unsigned char str[16 /* = len */];
     ASN1_OCTET_STRING *data = NULL;
     X509_EXTENSION *ext = NULL;
     X509_EXTENSIONS *exts = NULL;
@@ -234,29 +234,27 @@ static int test_CTX_reqExtensions_have_SAN(void)
     return result;
 }
 
-#ifndef OPENSSL_NO_TRACE
 static int test_log_line;
 static int test_log_cb_res = 0;
 static int test_log_cb(const char *func, const char *file, int line,
                        OSSL_CMP_severity level, const char *msg)
 {
     test_log_cb_res =
-# ifndef PEDANTIC
-        (strcmp(func, "execute_cmp_ctx_log_cb_test") == 0
-         || strcmp(func, "(unknown function)") == 0) &&
-# endif
-        (strcmp(file, OPENSSL_FILE) == 0 || strcmp(file, "(no file)") == 0)
-        && (line == test_log_line || line == 0)
-        && (level == OSSL_CMP_LOG_INFO || level == -1)
-        && strcmp(msg, "ok\n") == 0;
+#ifndef PEDANTIC
+        (TEST_str_eq(func, "execute_cmp_ctx_log_cb_test")
+         || TEST_str_eq(func, "(unknown function)")) &&
+#endif
+        (TEST_str_eq(file, OPENSSL_FILE)
+         || TEST_str_eq(file, "(no file)"))
+        && (TEST_int_eq(line, test_log_line) || TEST_int_eq(line, 0))
+        && (TEST_int_eq(level, OSSL_CMP_LOG_INFO) || TEST_int_eq(level, -1))
+        && TEST_str_eq(msg, "ok");
     return 1;
 }
-#endif
 
 static int execute_cmp_ctx_log_cb_test(OSSL_CMP_CTX_TEST_FIXTURE *fixture)
 {
     int res = 1;
-#if !defined OPENSSL_NO_TRACE && !defined OPENSSL_NO_STDIO
     OSSL_CMP_CTX *ctx = fixture->ctx;
 
     OSSL_TRACE(ALL, "this general trace message is not shown by default\n");
@@ -267,30 +265,29 @@ static int execute_cmp_ctx_log_cb_test(OSSL_CMP_CTX_TEST_FIXTURE *fixture)
     if (!TEST_true(OSSL_CMP_CTX_set_log_cb(ctx, NULL))) {
         res = 0;
     } else {
-        OSSL_CMP_err("this should be printed as CMP error message");
-        OSSL_CMP_warn("this should be printed as CMP warning message");
-        OSSL_CMP_debug("this should not be printed");
+        ossl_cmp_err(ctx, "this should be printed as CMP error message");
+        ossl_cmp_warn(ctx, "this should be printed as CMP warning message");
+        ossl_cmp_debug(ctx, "this should not be printed");
         TEST_true(OSSL_CMP_CTX_set_log_verbosity(ctx, OSSL_CMP_LOG_DEBUG));
-        OSSL_CMP_debug("this should be printed as CMP debug message");
+        ossl_cmp_debug(ctx, "this should be printed as CMP debug message");
         TEST_true(OSSL_CMP_CTX_set_log_verbosity(ctx, OSSL_CMP_LOG_INFO));
     }
     if (!TEST_true(OSSL_CMP_CTX_set_log_cb(ctx, test_log_cb))) {
         res = 0;
     } else {
         test_log_line = OPENSSL_LINE + 1;
-        OSSL_CMP_log2(INFO, "%s%c", "o", 'k');
+        ossl_cmp_log2(INFO, ctx, "%s%c", "o", 'k');
         if (!TEST_int_eq(test_log_cb_res, 1))
             res = 0;
         OSSL_CMP_CTX_set_log_verbosity(ctx, OSSL_CMP_LOG_ERR);
         test_log_cb_res = -1; /* callback should not be called at all */
         test_log_line = OPENSSL_LINE + 1;
-        OSSL_CMP_log2(INFO, "%s%c", "o", 'k');
+        ossl_cmp_log2(INFO, ctx, "%s%c", "o", 'k');
         if (!TEST_int_eq(test_log_cb_res, -1))
             res = 0;
     }
     OSSL_CMP_log_close();
     OSSL_CMP_log_close(); /* multiple calls should be harmless */
-#endif
     return res;
 }
 
@@ -330,13 +327,13 @@ typedef OSSL_CMP_CTX CMP_CTX; /* prevents rewriting type name by below macro */
 
 #define DEFINE_SET_GET_BASE_TEST(PREFIX, SETN, GETN, DUP, FIELD, TYPE, ERR, \
                                  DEFAULT, NEW, FREE) \
-static int execute_CTX_##SETN##_##GETN##_##FIELD( \
-    OSSL_CMP_CTX_TEST_FIXTURE *fixture) \
+static int \
+execute_CTX_##SETN##_##GETN##_##FIELD(OSSL_CMP_CTX_TEST_FIXTURE *fixture) \
 { \
     CMP_CTX *ctx = fixture->ctx; \
     int (*set_fn)(CMP_CTX *ctx, TYPE) = \
         (int (*)(CMP_CTX *ctx, TYPE))PREFIX##_##SETN##_##FIELD; \
-    /* need type cast in above assignment because TYPE arg sometimes is const */ \
+    /* need type cast in above assignment as TYPE arg sometimes is const */ \
     TYPE (*get_fn)(const CMP_CTX *ctx) = OSSL_CMP_CTX_##GETN##_##FIELD; \
     TYPE val1_to_free = NEW; \
     TYPE val1 = val1_to_free; \
@@ -440,7 +437,7 @@ static int execute_CTX_##SETN##_##GETN##_##FIELD( \
             TEST_error("third get gave different value"); \
             res = 0; \
         } \
-    } else  { \
+    } else { \
         if (DUP && val3_read == val2_read) { \
             TEST_error("third get did not create a new dup"); \
             res = 0; \
@@ -489,8 +486,8 @@ static X509_STORE *X509_STORE_new_1(void)
     return store;
 }
 
-#define DEFAULT_STORE(x) ((x) == NULL \
-    || X509_VERIFY_PARAM_get_flags(X509_STORE_get0_param(x)) == 0)
+#define DEFAULT_STORE(x) \
+    ((x) == NULL || X509_VERIFY_PARAM_get_flags(X509_STORE_get0_param(x)) == 0)
 
 #define IS_NEG(x) ((x) < 0)
 #define IS_0(x) ((x) == 0) /* for any type */
@@ -501,7 +498,7 @@ static X509_STORE *X509_STORE_new_1(void)
 
 #define DEFINE_SET_GET_TEST(OSSL_CMP, CTX, N, M, DUP, FIELD, TYPE) \
     DEFINE_SET_GET_BASE_TEST(OSSL_CMP##_##CTX, set##N, get##M, DUP, FIELD, \
-                             TYPE*, NULL, IS_0, TYPE##_new(), TYPE##_free)
+                             TYPE *, NULL, IS_0, TYPE##_new(), TYPE##_free)
 
 #define DEFINE_SET_GET_SK_TEST_DEFAULT(OSSL_CMP, CTX, N, M, FIELD, ELEM_TYPE, \
                                        DEFAULT, NEW, FREE) \
@@ -518,7 +515,7 @@ static X509_STORE *X509_STORE_new_1(void)
 #define DEFINE_SET_GET_TEST_DEFAULT(OSSL_CMP, CTX, N, M, DUP, FIELD, TYPE, \
                                     DEFAULT) \
     DEFINE_SET_GET_BASE_TEST(OSSL_CMP##_##CTX, set##N, get##M, DUP, FIELD, \
-                             TYPE*, NULL, DEFAULT, TYPE##_new(), TYPE##_free)
+                             TYPE *, NULL, DEFAULT, TYPE##_new(), TYPE##_free)
 #define DEFINE_SET_TEST_DEFAULT(OSSL_CMP, CTX, N, DUP, FIELD, TYPE, DEFAULT) \
     static TYPE *OSSL_CMP_CTX_get0_##FIELD(const CMP_CTX *ctx) \
     { \
@@ -549,7 +546,7 @@ typedef OSSL_HTTP_bio_cb_t OSSL_cmp_http_cb_t;
                              OSSL_cmp_##FIELD##_t, NULL, IS_0, \
                              test_##FIELD, DROP)
 #define DEFINE_SET_GET_P_VOID_TEST(FIELD) \
-    DEFINE_SET_GET_BASE_TEST(OSSL_CMP_CTX, set, get, 0, FIELD, void*, \
+    DEFINE_SET_GET_BASE_TEST(OSSL_CMP_CTX, set, get, 0, FIELD, void *, \
                              NULL, IS_0, ((void *)1), DROP)
 
 #define DEFINE_SET_GET_INT_TEST_DEFAULT(OSSL_CMP, CTX, FIELD, DEFAULT) \
@@ -579,7 +576,7 @@ typedef OSSL_HTTP_bio_cb_t OSSL_cmp_http_cb_t;
     static int OSSL_CMP_CTX_##SETN##_##FIELD##_str(CMP_CTX *ctx, char *val)\
     { \
         return OSSL_CMP_CTX_##SETN##_##FIELD(ctx, (unsigned char *)val, \
-                                            strlen(val)); \
+                                             strlen(val));              \
     } \
     \
     static char *OSSL_CMP_CTX_get1_##FIELD##_str(const CMP_CTX *ctx) \
@@ -684,7 +681,7 @@ static int execute_CTX_##PUSHN##_##ELEM(OSSL_CMP_CTX_TEST_FIXTURE *fixture) \
             res = 0; \
         } \
     } \
-    /* this does not check that all remaining fields and elems are untouched */\
+    /* this does not check if all remaining fields and elems are untouched */ \
     \
     if (!TEST_int_eq(ERR_peek_error(), 0)) \
         res = 0; \
@@ -702,7 +699,7 @@ static int test_CTX_##PUSHN##_##ELEM(void) \
 } \
 
 #define DEFINE_PUSH_TEST(N, DUP, FIELD, ELEM, TYPE) \
-    DEFINE_PUSH_BASE_TEST(push##N, DUP, FIELD, ELEM, TYPE*, TYPE, \
+    DEFINE_PUSH_BASE_TEST(push##N, DUP, FIELD, ELEM, TYPE *, TYPE, \
                           IS_0, TYPE##_new(), TYPE##_free)
 
 void cleanup_tests(void)
@@ -715,9 +712,7 @@ DEFINE_SET_GET_ARG_FN(set, get, option, 16, int)
 DEFINE_SET_GET_BASE_TEST(OSSL_CMP_CTX, set, get, 0, option_16, int, -1, IS_0, \
                          1 /* true */, DROP)
 
-#ifndef OPENSSL_NO_TRACE
 DEFINE_SET_CB_TEST(log_cb)
-#endif
 
 DEFINE_SET_TEST_DEFAULT(OSSL_CMP, CTX, 1, 1, serverPath, char, IS_0)
 DEFINE_SET_TEST(OSSL_CMP, CTX, 1, 1, serverName, char)
@@ -733,7 +728,7 @@ DEFINE_SET_TEST(OSSL_CMP, CTX, 1, 0, srvCert, X509)
 DEFINE_SET_TEST(ossl_cmp, ctx, 0, 0, validatedSrvCert, X509)
 DEFINE_SET_TEST(OSSL_CMP, CTX, 1, 1, expected_sender, X509_NAME)
 DEFINE_SET_GET_BASE_TEST(OSSL_CMP_CTX, set0, get0, 0, trustedStore,
-                         X509_STORE*, NULL,
+                         X509_STORE *, NULL,
                          DEFAULT_STORE, X509_STORE_new_1(), X509_STORE_free)
 DEFINE_SET_GET_SK_X509_TEST(OSSL_CMP, CTX, 1, 0, untrusted_certs)
 
@@ -743,9 +738,9 @@ DEFINE_SET_TEST(OSSL_CMP, CTX, 1, 0, pkey, EVP_PKEY)
 DEFINE_SET_TEST(OSSL_CMP, CTX, 1, 1, recipient, X509_NAME)
 DEFINE_PUSH_TEST(0, 0, geninfo_ITAVs, geninfo_ITAV, OSSL_CMP_ITAV)
 DEFINE_SET_SK_TEST(OSSL_CMP, CTX, 1, extraCertsOut, X509)
-DEFINE_SET_GET_ARG_FN(set0, get0, newPkey, 1, EVP_PKEY*) /* priv == 1 */
+DEFINE_SET_GET_ARG_FN(set0, get0, newPkey, 1, EVP_PKEY *) /* priv == 1 */
 DEFINE_SET_GET_TEST(OSSL_CMP, CTX, 0, 0, 0, newPkey_1, EVP_PKEY)
-DEFINE_SET_GET_ARG_FN(set0, get0, newPkey, 0, EVP_PKEY*) /* priv == 0 */
+DEFINE_SET_GET_ARG_FN(set0, get0, newPkey, 0, EVP_PKEY *) /* priv == 0 */
 DEFINE_SET_GET_TEST(OSSL_CMP, CTX, 0, 0, 0, newPkey_0, EVP_PKEY)
 DEFINE_SET_GET1_STR_FN(set1, referenceValue)
 DEFINE_SET_GET_TEST_DEFAULT(OSSL_CMP, CTX, 1, 1, 1, referenceValue_str, char,
@@ -788,21 +783,18 @@ int setup_tests(void)
     /* various CMP options: */
     ADD_TEST(test_CTX_set_get_option_16);
     /* CMP-specific callback for logging and outputting the error queue: */
-#ifndef OPENSSL_NO_TRACE
     ADD_TEST(test_CTX_set_get_log_cb);
-#endif
     /*
      * also tests OSSL_CMP_log_open(), OSSL_CMP_CTX_set_log_verbosity(),
-     * OSSL_CMP_err(), OSSL_CMP_warn(), * OSSL_CMP_debug(),
-     * OSSL_CMP_log2(), ossl_cmp_log_parse_metadata(), and OSSL_CMP_log_close()
+     * ossl_cmp_err(), ossl_cmp_warn(), * ossl_cmp_debug(),
+     * ossl_cmp_log2(), ossl_cmp_log_parse_metadata(), and OSSL_CMP_log_close()
      * with OSSL_CMP_severity OSSL_CMP_LOG_ERR/WARNING/DEBUG/INFO:
      */
     ADD_TEST(test_cmp_ctx_log_cb);
 #if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
     /*
      * also tests OSSL_CMP_CTX_set_log_cb(), OSSL_CMP_print_errors_cb(),
-     * ossl_cmp_add_error_txt(), and the macros
-     * ossl_cmp_add_error_data and ossl_cmp_add_error_line:
+     * and the macros ossl_cmp_add_error_data and ossl_cmp_add_error_line:
      */
     ADD_TEST(test_CTX_print_errors);
 #endif
diff --git a/test/cmp_hdr_test.c b/test/cmp_hdr_test.c
index a9b2aff79c..c12b72f29e 100644
--- a/test/cmp_hdr_test.c
+++ b/test/cmp_hdr_test.c
@@ -65,8 +65,9 @@ static int test_HDR_set_get_pvno(void)
     return result;
 }
 
-#define X509_NAME_ADD(n, rd, s) X509_NAME_add_entry_by_txt((n), (rd),          \
-                                MBSTRING_ASC, (unsigned char *)(s), -1, -1, 0)
+#define X509_NAME_ADD(n, rd, s) \
+    X509_NAME_add_entry_by_txt((n), (rd), MBSTRING_ASC, (unsigned char *)(s), \
+                               -1, -1, 0)
 
 static int execute_HDR_get0_senderNonce_test(CMP_HDR_TEST_FIXTURE *fixture)
 {
@@ -112,8 +113,8 @@ static int execute_HDR_set1_sender_test(CMP_HDR_TEST_FIXTURE *fixture)
     if (!TEST_int_eq(fixture->hdr->sender->type, GEN_DIRNAME))
         return 0;
 
-    if (!TEST_int_eq(
-            X509_NAME_cmp(fixture->hdr->sender->d.directoryName, x509name), 0))
+    if (!TEST_int_eq(X509_NAME_cmp(fixture->hdr->sender->d.directoryName,
+                                   x509name), 0))
         return 0;
 
     X509_NAME_free(x509name);
@@ -142,8 +143,8 @@ static int execute_HDR_set1_recipient_test(CMP_HDR_TEST_FIXTURE *fixture)
     if (!TEST_int_eq(fixture->hdr->recipient->type, GEN_DIRNAME))
         return 0;
 
-    if (!TEST_int_eq(
-            X509_NAME_cmp(fixture->hdr->recipient->d.directoryName, x509name),0))
+    if (!TEST_int_eq(X509_NAME_cmp(fixture->hdr->recipient->d.directoryName,
+                                   x509name), 0))
         return 0;
 
     X509_NAME_free(x509name);
@@ -188,7 +189,7 @@ static int test_HDR_update_messageTime(void)
 
 static int execute_HDR_set1_senderKID_test(CMP_HDR_TEST_FIXTURE *fixture)
 {
-    ASN1_OCTET_STRING* senderKID = ASN1_OCTET_STRING_new();
+    ASN1_OCTET_STRING *senderKID = ASN1_OCTET_STRING_new();
 
     if (!TEST_ptr(senderKID))
         return 0;
@@ -198,8 +199,8 @@ static int execute_HDR_set1_senderKID_test(CMP_HDR_TEST_FIXTURE *fixture)
         return 0;
     if (!TEST_int_eq(ossl_cmp_hdr_set1_senderKID(fixture->hdr, senderKID), 1))
         return 0;
-    if (!TEST_int_eq(
-            ASN1_OCTET_STRING_cmp(fixture->hdr->senderKID, senderKID), 0))
+    if (!TEST_int_eq(ASN1_OCTET_STRING_cmp(fixture->hdr->senderKID,
+                                           senderKID), 0))
         return 0;
 
     ASN1_OCTET_STRING_free(senderKID);
@@ -216,7 +217,7 @@ static int test_HDR_set1_senderKID(void)
 
 static int execute_HDR_push0_freeText_test(CMP_HDR_TEST_FIXTURE *fixture)
 {
-    ASN1_UTF8STRING* text = ASN1_UTF8STRING_new();
+    ASN1_UTF8STRING *text = ASN1_UTF8STRING_new();
 
     if (!TEST_ptr(text))
         return 0;
@@ -224,11 +225,10 @@ static int execute_HDR_push0_freeText_test(CMP_HDR_TEST_FIXTURE *fixture)
     if (!ASN1_STRING_set(text, "A free text", -1))
         return 0;
 
-    if (!TEST_int_eq(
-            ossl_cmp_hdr_push0_freeText(fixture->hdr, text), 1))
+    if (!TEST_int_eq(ossl_cmp_hdr_push0_freeText(fixture->hdr, text), 1))
         return 0;
-    if (!TEST_true(text == sk_ASN1_UTF8STRING_value(
-            fixture->hdr->freeText, 0)))
+
+    if (!TEST_true(text == sk_ASN1_UTF8STRING_value(fixture->hdr->freeText, 0)))
         return 0;
 
     return 1;
@@ -244,7 +244,8 @@ static int test_HDR_push0_freeText(void)
 
 static int execute_HDR_push1_freeText_test(CMP_HDR_TEST_FIXTURE *fixture)
 {
-    ASN1_UTF8STRING* text = ASN1_UTF8STRING_new();
+    ASN1_UTF8STRING *text = ASN1_UTF8STRING_new();
+    ASN1_UTF8STRING *pushed_text;
 
     if (!TEST_ptr(text))
         return 0;
@@ -252,11 +253,11 @@ static int execute_HDR_push1_freeText_test(CMP_HDR_TEST_FIXTURE *fixture)
     if (!ASN1_STRING_set(text, "A free text", -1))
         return 0;
 
-    if (!TEST_int_eq(
-            ossl_cmp_hdr_push1_freeText(fixture->hdr, text), 1))
+    if (!TEST_int_eq(ossl_cmp_hdr_push1_freeText(fixture->hdr, text), 1))
         return 0;
-    if (!TEST_int_eq(ASN1_STRING_cmp(
-            sk_ASN1_UTF8STRING_value(fixture->hdr->freeText, 0), text), 0))
+
+    pushed_text = sk_ASN1_UTF8STRING_value(fixture->hdr->freeText, 0);
+    if (!TEST_int_eq(ASN1_STRING_cmp(text, pushed_text), 0))
         return 0;
 
     ASN1_UTF8STRING_free(text);
@@ -279,11 +280,12 @@ execute_HDR_generalInfo_push0_item_test(CMP_HDR_TEST_FIXTURE *fixture)
     if (!TEST_ptr(itav))
         return 0;
 
-    if (!TEST_int_eq(
-            ossl_cmp_hdr_generalInfo_push0_item(fixture->hdr, itav), 1))
+    if (!TEST_int_eq(ossl_cmp_hdr_generalInfo_push0_item(fixture->hdr, itav),
+                     1))
         return 0;
-    if (!TEST_true(itav == sk_OSSL_CMP_ITAV_value(
-            fixture->hdr->generalInfo, 0)))
+
+    if (!TEST_true(itav == sk_OSSL_CMP_ITAV_value(fixture->hdr->generalInfo,
+                                                  0)))
         return 0;
 
     return 1;
@@ -302,10 +304,11 @@ execute_HDR_generalInfo_push1_items_test(CMP_HDR_TEST_FIXTURE *fixture)
 {
     const char oid[] = "1.2.3.4";
     char buf[20];
-    OSSL_CMP_ITAV *itav;
-    STACK_OF(OSSL_CMP_ITAV) *itavs = NULL;
+    OSSL_CMP_ITAV *itav, *pushed_itav;
+    STACK_OF(OSSL_CMP_ITAV) *itavs = NULL, *ginfo;
     ASN1_INTEGER *asn1int = ASN1_INTEGER_new();
     ASN1_TYPE *val = ASN1_TYPE_new();
+    ASN1_TYPE *pushed_val;
 
     if (!TEST_ptr(asn1int))
         return 0;
@@ -318,17 +321,17 @@ execute_HDR_generalInfo_push1_items_test(CMP_HDR_TEST_FIXTURE *fixture)
     itav = OSSL_CMP_ITAV_create(OBJ_txt2obj(oid, 1), val);
     OSSL_CMP_ITAV_push0_stack_item(&itavs, itav);
 
-    if (!TEST_int_eq(
-        ossl_cmp_hdr_generalInfo_push1_items(fixture->hdr, itavs), 1))
+    if (!TEST_int_eq(ossl_cmp_hdr_generalInfo_push1_items(fixture->hdr, itavs),
+                     1))
         return 0;
-    OBJ_obj2txt(buf, sizeof(buf), OSSL_CMP_ITAV_get0_type(
-            sk_OSSL_CMP_ITAV_value(fixture->hdr->generalInfo, 0)), 0);
+    ginfo = fixture->hdr->generalInfo;
+    pushed_itav = sk_OSSL_CMP_ITAV_value(ginfo, 0);
+    OBJ_obj2txt(buf, sizeof(buf), OSSL_CMP_ITAV_get0_type(pushed_itav), 0);
     if (!TEST_int_eq(memcmp(oid, buf, sizeof(oid)), 0))
         return 0;
 
-    if (!TEST_int_eq(ASN1_TYPE_cmp(itav->infoValue.other,
-                                   OSSL_CMP_ITAV_get0_value(
-            sk_OSSL_CMP_ITAV_value(fixture->hdr->generalInfo, 0))), 0))
+    pushed_val = OSSL_CMP_ITAV_get0_value(sk_OSSL_CMP_ITAV_value(ginfo, 0));
+    if (!TEST_int_eq(ASN1_TYPE_cmp(itav->infoValue.other, pushed_val), 0))
         return 0;
 
     sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
@@ -362,35 +365,36 @@ static int test_HDR_set_and_check_implicit_confirm(void)
 
 static int execute_HDR_init_test(CMP_HDR_TEST_FIXTURE *fixture)
 {
-    ASN1_OCTET_STRING *header_nonce = NULL;
-    ASN1_OCTET_STRING *ctx_nonce = NULL;
-    int res = 0;
+    ASN1_OCTET_STRING *header_nonce, *header_transactionID;
+    ASN1_OCTET_STRING *ctx_nonce;
 
     if (!TEST_int_eq(fixture->expected,
                      ossl_cmp_hdr_init(fixture->cmp_ctx, fixture->hdr)))
-        goto err;
-    if (fixture->expected != 0) {
-        if (!TEST_int_eq(ossl_cmp_hdr_get_pvno(fixture->hdr), OSSL_CMP_PVNO)
-                || !TEST_true(0 == ASN1_OCTET_STRING_cmp(
-                        ossl_cmp_hdr_get0_senderNonce(fixture->hdr),
-                        fixture->cmp_ctx->senderNonce))
-                || !TEST_true(0 == ASN1_OCTET_STRING_cmp(
-                            OSSL_CMP_HDR_get0_transactionID(fixture->hdr),
-                            fixture->cmp_ctx->transactionID)))
-            goto err;
-        header_nonce = OSSL_CMP_HDR_get0_recipNonce(fixture->hdr);
-        ctx_nonce = fixture->cmp_ctx->recipNonce;
-        if (ctx_nonce != NULL
-                && (!TEST_ptr(header_nonce)
-                || !TEST_int_eq(0, ASN1_OCTET_STRING_cmp(header_nonce,
-                                                         ctx_nonce))))
-            goto err;
-    }
+        return 0;
+    if (fixture->expected == 0)
+        return 1;
 
-    res = 1;
+    if (!TEST_int_eq(ossl_cmp_hdr_get_pvno(fixture->hdr), OSSL_CMP_PVNO))
+        return 0;
 
- err:
-    return res;
+    header_nonce = ossl_cmp_hdr_get0_senderNonce(fixture->hdr);
+    if (!TEST_int_eq(0, ASN1_OCTET_STRING_cmp(header_nonce,
+                                              fixture->cmp_ctx->senderNonce)))
+        return 0;
+    header_transactionID = OSSL_CMP_HDR_get0_transactionID(fixture->hdr);
+    if (!TEST_true(0 == ASN1_OCTET_STRING_cmp(header_transactionID,
+                                              fixture->cmp_ctx->transactionID)))
+        return 0;
+
+    header_nonce = OSSL_CMP_HDR_get0_recipNonce(fixture->hdr);
+    ctx_nonce = fixture->cmp_ctx->recipNonce;
+    if (ctx_nonce != NULL
+            && (!TEST_ptr(header_nonce)
+                    || !TEST_int_eq(0, ASN1_OCTET_STRING_cmp(header_nonce,
+                                                             ctx_nonce))))
+        return 0;
+
+    return 1;
 }
 
 static int test_HDR_init(void)
diff --git a/test/cmp_msg_test.c b/test/cmp_msg_test.c
index 7fa0619284..8f95865869 100644
--- a/test/cmp_msg_test.c
+++ b/test/cmp_msg_test.c
@@ -122,7 +122,7 @@ static int execute_pkimessage_create_test(CMP_MSG_TEST_FIXTURE *fixture)
                               (fixture->cmp_ctx, fixture->bodytype));
 }
 
-static int set1_newPkey(OSSL_CMP_CTX *ctx, EVP_PKEY* pkey)
+static int set1_newPkey(OSSL_CMP_CTX *ctx, EVP_PKEY *pkey)
 {
     if (!EVP_PKEY_up_ref(pkey))
         return 0;
@@ -321,7 +321,7 @@ static int test_cmp_create_error_msg(void)
                                           OSSL_CMP_PKIFAILUREINFO_systemFailure,
                                           NULL);
     fixture->err_code = -1;
-    fixture->expected = 1;      /* Expected: Message creation is successful */
+    fixture->expected = 1; /* expected: message creation is successful */
     if (!TEST_true(set1_newPkey(fixture->cmp_ctx, newkey))) {
         tear_down(fixture);
         fixture = NULL;
@@ -430,7 +430,7 @@ static int execute_rp_create(CMP_MSG_TEST_FIXTURE *fixture)
         goto err;
 
     if (!X509_NAME_add_entry_by_txt(issuer, "CN", MBSTRING_ASC,
-                                    (unsigned char*)"The Issuer", -1, -1, 0)
+                                    (unsigned char *)"The Issuer", -1, -1, 0)
             || !ASN1_INTEGER_set(serial, 99)
             || (cid = OSSL_CRMF_CERTID_gen(issuer, serial)) == NULL
             || (rpmsg = ossl_cmp_rp_new(fixture->cmp_ctx, si, cid, 1)) == NULL)
@@ -439,8 +439,8 @@ static int execute_rp_create(CMP_MSG_TEST_FIXTURE *fixture)
     if (!TEST_ptr(ossl_cmp_revrepcontent_get_CertId(rpmsg->body->value.rp, 0)))
         goto err;
 
-    if (!TEST_ptr(ossl_cmp_revrepcontent_get_pkistatusinfo(rpmsg->body->value.rp,
-                                                           0)))
+    if (!TEST_ptr(ossl_cmp_revrepcontent_get_pkistatusinfo(rpmsg->body->
+                                                           value.rp, 0)))
         goto err;
 
     res = 1;
@@ -468,11 +468,11 @@ static int execute_pollrep_create(CMP_MSG_TEST_FIXTURE *fixture)
     pollrep = ossl_cmp_pollRep_new(fixture->cmp_ctx, 77, 2000);
     if (!TEST_ptr(pollrep))
         return 0;
-    if (!TEST_ptr(ossl_cmp_pollrepcontent_get0_pollrep(
-            pollrep->body->value.pollRep, 77)))
+    if (!TEST_ptr(ossl_cmp_pollrepcontent_get0_pollrep(pollrep->body->
+                                                       value.pollRep, 77)))
         goto err;
-    if (!TEST_ptr_null(ossl_cmp_pollrepcontent_get0_pollrep(
-            pollrep->body->value.pollRep, 88)))
+    if (!TEST_ptr_null(ossl_cmp_pollrepcontent_get0_pollrep(pollrep->body->
+                                                            value.pollRep, 88)))
         goto err;
 
     res = 1;
diff --git a/test/cmp_protect_test.c b/test/cmp_protect_test.c
index 8425849835..5d5df89abd 100644
--- a/test/cmp_protect_test.c
+++ b/test/cmp_protect_test.c
@@ -20,7 +20,7 @@ typedef struct test_fixture {
     OSSL_CMP_CTX *cmp_ctx;
     /* for protection tests */
     OSSL_CMP_MSG *msg;
-    OSSL_CMP_PKISI *si;      /* for error and response messages */
+    OSSL_CMP_PKISI *si; /* for error and response messages */
     ASN1_OCTET_STRING *secret;
     EVP_PKEY *privkey;
     EVP_PKEY *pubkey;
@@ -86,7 +86,8 @@ static int execute_calc_protection_pbmac_test(CMP_PROTECT_TEST_FIXTURE *fixture)
     ASN1_BIT_STRING *protection =
         ossl_cmp_calc_protection(fixture->msg, fixture->secret, NULL);
     int res = TEST_ptr(protection)
-        && TEST_true(ASN1_STRING_cmp(protection, fixture->msg->protection) == 0);
+            && TEST_true(ASN1_STRING_cmp(protection,
+                                         fixture->msg->protection) == 0);
 
     ASN1_BIT_STRING_free(protection);
     return res;
@@ -386,7 +387,7 @@ static int execute_X509_STORE_test(CMP_PROTECT_TEST_FIXTURE *fixture)
                                                   fixture->certs,
                                                   fixture->callback_arg)))
         goto err;
-    sk = ossl_cmp_X509_STORE_get1_certs(store);
+    sk = X509_STORE_get1_all_certs(store);
     if (!TEST_int_eq(0, STACK_OF_X509_cmp(sk, fixture->chain)))
         goto err;
     res = 1;
@@ -400,7 +401,7 @@ static int execute_X509_STORE_test(CMP_PROTECT_TEST_FIXTURE *fixture)
 static int test_X509_STORE(void)
 {
     SETUP_TEST_FIXTURE(CMP_PROTECT_TEST_FIXTURE, set_up);
-    fixture->callback_arg = 0;  /* self-signed allowed */
+    fixture->callback_arg = 0; /* self-issued allowed */
     if (!TEST_ptr(fixture->certs = sk_X509_new_null())
             || !sk_X509_push(fixture->certs, endentity1)
             || !sk_X509_push(fixture->certs, endentity2)
@@ -414,12 +415,12 @@ static int test_X509_STORE(void)
     return result;
 }
 
-static int test_X509_STORE_only_self_signed(void)
+static int test_X509_STORE_only_self_issued(void)
 {
     SETUP_TEST_FIXTURE(CMP_PROTECT_TEST_FIXTURE, set_up);
     fixture->certs = sk_X509_new_null();
     fixture->chain = sk_X509_new_null();
-    fixture->callback_arg = 1;  /* only self-signed */
+    fixture->callback_arg = 1; /* only self-issued */
     if (!TEST_true(sk_X509_push(fixture->certs, endentity1))
             || !TEST_true(sk_X509_push(fixture->certs, endentity2))
             || !TEST_true(sk_X509_push(fixture->certs, root))
@@ -521,7 +522,7 @@ int setup_tests(void)
 #endif
 
     ADD_TEST(test_X509_STORE);
-    ADD_TEST(test_X509_STORE_only_self_signed);
+    ADD_TEST(test_X509_STORE_only_self_issued);
 
     return 1;
 }
diff --git a/test/cmp_vfy_test.c b/test/cmp_vfy_test.c
new file mode 100644
index 0000000000..41ddad86ba
--- /dev/null
+++ b/test/cmp_vfy_test.c
@@ -0,0 +1,636 @@
+/*
+ * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "cmp_testlib.h"
+#include "../crypto/crmf/crmf_local.h" /* for manipulating POPO signature */
+
+static const char *server_f;
+static const char *client_f;
+static const char *endentity1_f;
+static const char *endentity2_f;
+static const char *root_f;
+static const char *intermediate_f;
+static const char *ir_protected_f;
+static const char *ir_unprotected_f;
+static const char *ir_rmprotection_f;
+static const char *ip_waiting_f;
+static const char *instacert_f;
+static const char *instaca_f;
+static const char *ir_protected_0_extracerts;
+static const char *ir_protected_2_extracerts;
+
+typedef struct test_fixture {
+    const char *test_case_name;
+    int expected;
+    OSSL_CMP_CTX *cmp_ctx;
+    OSSL_CMP_MSG *msg;
+    X509 *cert;
+    ossl_cmp_allow_unprotected_cb_t allow_unprotected_cb;
+    int additional_arg;
+} CMP_VFY_TEST_FIXTURE;
+
+static void tear_down(CMP_VFY_TEST_FIXTURE *fixture)
+{
+    OSSL_CMP_MSG_free(fixture->msg);
+    OSSL_CMP_CTX_free(fixture->cmp_ctx);
+    OPENSSL_free(fixture);
+}
+
+static int print_to_bio_out(const char *func, const char *file, int line,
+                            OSSL_CMP_severity level, const char *msg)
+{
+    return OSSL_CMP_print_to_bio(bio_out, func, file, line, level, msg);
+}
+
+static time_t test_time_valid = 0, test_time_after_expiration = 0;
+
+static CMP_VFY_TEST_FIXTURE *set_up(const char *const test_case_name)
+{
+    X509_STORE *ts = X509_STORE_new();
+    CMP_VFY_TEST_FIXTURE *fixture;
+
+    if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture))))
+        return NULL;
+    fixture->test_case_name = test_case_name;
+    if (ts == NULL
+            || !TEST_ptr(fixture->cmp_ctx = OSSL_CMP_CTX_new())
+            || !OSSL_CMP_CTX_set0_trustedStore(fixture->cmp_ctx, ts)
+            || !OSSL_CMP_CTX_set_log_cb(fixture->cmp_ctx, print_to_bio_out)) {
+        tear_down(fixture);
+        X509_STORE_free(ts);
+        return NULL;
+    }
+    X509_VERIFY_PARAM_set_time(X509_STORE_get0_param(ts), test_time_valid);
+    X509_STORE_set_verify_cb(ts, OSSL_CMP_print_cert_verify_cb);
+    return fixture;
+}
+
+static X509 *srvcert = NULL;
+static X509 *clcert = NULL;
+/* chain */
+static X509 *endentity1 = NULL, *endentity2 = NULL,
+    *intermediate = NULL, *root = NULL;
+/* INSTA chain */
+static X509 *insta_cert = NULL, *instaca_cert = NULL;
+
+static unsigned char rand_data[OSSL_CMP_TRANSACTIONID_LENGTH];
+static OSSL_CMP_MSG *ir_unprotected, *ir_rmprotection;
+
+static int flip_bit(ASN1_BIT_STRING *bitstr)
+{
+    int bit_num = 7;
+    int bit = ASN1_BIT_STRING_get_bit(bitstr, bit_num);
+
+    return ASN1_BIT_STRING_set_bit(bitstr, bit_num, !bit);
+}
+
+static int execute_verify_popo_test(CMP_VFY_TEST_FIXTURE *fixture)
+{
+    if ((fixture->msg = load_pkimsg(ir_protected_f)) == NULL)
+        return 0;
+    if (fixture->expected == 0) {
+        const OSSL_CRMF_MSGS *reqs = fixture->msg->body->value.ir;
+        const OSSL_CRMF_MSG *req = sk_OSSL_CRMF_MSG_value(reqs, 0);
+        if (req == NULL || !flip_bit(req->popo->value.signature->signature))
+            return 0;
+    }
+    return TEST_int_eq(fixture->expected,
+                       ossl_cmp_verify_popo(fixture->msg,
+                                            fixture->additional_arg));
+}
+
+static int test_verify_popo(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = 1;
+    EXECUTE_TEST(execute_verify_popo_test, tear_down);
+    return result;
+}
+
+static int test_verify_popo_bad(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = 0;
+    EXECUTE_TEST(execute_verify_popo_test, tear_down);
+    return result;
+}
+
+static int execute_validate_msg_test(CMP_VFY_TEST_FIXTURE *fixture)
+{
+    return TEST_int_eq(fixture->expected,
+                       OSSL_CMP_validate_msg(fixture->cmp_ctx, fixture->msg));
+}
+
+static int execute_validate_cert_path_test(CMP_VFY_TEST_FIXTURE *fixture)
+{
+    X509_STORE *ts = OSSL_CMP_CTX_get0_trustedStore(fixture->cmp_ctx);
+    int res = TEST_int_eq(fixture->expected,
+                          OSSL_CMP_validate_cert_path(fixture->cmp_ctx,
+                                                      ts, fixture->cert));
+
+    OSSL_CMP_CTX_print_errors(fixture->cmp_ctx);
+    return res;
+}
+
+static int test_validate_msg_mac_alg_protection(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    /* secret value belonging to cmp-test/CMP_IP_waitingStatus_PBM.der */
+    const unsigned char sec_1[] = {
+        '9', 'p', 'p', '8', '-', 'b', '3', '5', 'i', '-', 'X', 'd', '3',
+        'Q', '-', 'u', 'd', 'N', 'R'
+    };
+
+    fixture->expected = 1;
+    if (!TEST_true(OSSL_CMP_CTX_set1_secretValue(fixture->cmp_ctx, sec_1,
+                                                 sizeof(sec_1)))
+            || !TEST_ptr(fixture->msg = load_pkimsg(ip_waiting_f))) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+static int test_validate_msg_mac_alg_protection_bad(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    const unsigned char sec_bad[] = {
+        '9', 'p', 'p', '8', '-', 'b', '3', '5', 'i', '-', 'X', 'd', '3',
+        'Q', '-', 'u', 'd', 'N', 'r'
+    };
+    fixture->expected = 0;
+
+    if (!TEST_true(OSSL_CMP_CTX_set1_secretValue(fixture->cmp_ctx, sec_bad,
+                                                 sizeof(sec_bad)))
+            || !TEST_ptr(fixture->msg = load_pkimsg(ip_waiting_f))) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+static int add_trusted(OSSL_CMP_CTX *ctx, X509 *cert)
+{
+    return X509_STORE_add_cert(OSSL_CMP_CTX_get0_trustedStore(ctx), cert);
+}
+
+static int add_untrusted(OSSL_CMP_CTX *ctx, X509 *cert)
+{
+    return ossl_cmp_sk_X509_add1_cert(OSSL_CMP_CTX_get0_untrusted_certs(ctx),
+                                      cert, 0, 0);
+}
+
+static int test_validate_msg_signature_partial_chain(int expired)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    X509_STORE *ts = OSSL_CMP_CTX_get0_trustedStore(fixture->cmp_ctx);
+
+    fixture->expected = !expired;
+    if (ts == NULL
+            || !TEST_ptr(fixture->msg = load_pkimsg(ir_protected_f))
+            || !add_trusted(fixture->cmp_ctx, srvcert)) {
+        tear_down(fixture);
+        fixture = NULL;
+    } else {
+        X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts);
+        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN);
+        if (expired)
+            X509_VERIFY_PARAM_set_time(vpm, test_time_after_expiration);
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+static int test_validate_msg_signature_trusted_ok(void)
+{
+    return test_validate_msg_signature_partial_chain(0);
+}
+
+static int test_validate_msg_signature_trusted_expired(void)
+{
+    return test_validate_msg_signature_partial_chain(1);
+}
+
+static int test_validate_msg_signature_srvcert_wrong(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = 0;
+    if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_f))
+        || !TEST_true(OSSL_CMP_CTX_set1_srvCert(fixture->cmp_ctx, clcert))) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+static int test_validate_msg_signature_srvcert(int bad_sig)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = !bad_sig;
+    if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_f))
+        || !TEST_true(OSSL_CMP_CTX_set1_srvCert(fixture->cmp_ctx, srvcert))
+        || (bad_sig && !flip_bit(fixture->msg->protection))) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+static int test_validate_msg_signature_bad(void)
+{
+    return test_validate_msg_signature_srvcert(1);
+}
+
+static int test_validate_msg_signature_sender_cert_srvcert(void)
+{
+    return test_validate_msg_signature_srvcert(0);
+}
+
+static int test_validate_msg_signature_sender_cert_untrusted(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = 1;
+    if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_0_extracerts))
+            || !add_trusted(fixture->cmp_ctx, instaca_cert)
+            || !add_untrusted(fixture->cmp_ctx, insta_cert)) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+static int test_validate_msg_signature_sender_cert_trusted(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = 1;
+    if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_0_extracerts))
+            || !add_trusted(fixture->cmp_ctx, instaca_cert)
+            || !add_trusted(fixture->cmp_ctx, insta_cert)) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+static int test_validate_msg_signature_sender_cert_extracert(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = 1;
+    if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_2_extracerts))
+            || !add_trusted(fixture->cmp_ctx, instaca_cert)) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+
+static int test_validate_msg_signature_sender_cert_absent(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = 0;
+    if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_0_extracerts))) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+
+static int test_validate_with_sender(X509_NAME *name, int expected)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = expected;
+    if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_f))
+        || !TEST_true(OSSL_CMP_CTX_set1_expected_sender(fixture->cmp_ctx, name))
+        || !TEST_true(OSSL_CMP_CTX_set1_srvCert(fixture->cmp_ctx, srvcert))) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+static int test_validate_msg_signature_expected_sender(void)
+{
+    return test_validate_with_sender(X509_get_subject_name(srvcert), 1);
+}
+
+static int test_validate_msg_signature_unexpected_sender(void)
+{
+    return test_validate_with_sender(X509_get_subject_name(root), 0);
+}
+
+static int test_validate_msg_unprotected_request(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    fixture->expected = 0;
+    if (!TEST_ptr(fixture->msg = load_pkimsg(ir_unprotected_f))) {
+        tear_down(fixture);
+        fixture = NULL;
+    }
+    EXECUTE_TEST(execute_validate_msg_test, tear_down);
+    return result;
+}
+
+static void setup_path(CMP_VFY_TEST_FIXTURE **fixture, X509 *wrong, int expired)
+{
+    (*fixture)->cert = endentity2;
+    (*fixture)->expected = wrong == NULL && !expired;
+    if (expired) {
+        X509_STORE *ts = OSSL_CMP_CTX_get0_trustedStore((*fixture)->cmp_ctx);
+        X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts);
+        X509_VERIFY_PARAM_set_time(vpm, test_time_after_expiration);
+    }
+    if (!add_trusted((*fixture)->cmp_ctx, wrong == NULL ? root : wrong)
+            || !add_untrusted((*fixture)->cmp_ctx, endentity1)
+            || !add_untrusted((*fixture)->cmp_ctx, intermediate)) {
+        tear_down((*fixture));
+        (*fixture) = NULL;
+    }
+}
+
+static int test_validate_cert_path_ok(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_path(&fixture, NULL, 0);
+    EXECUTE_TEST(execute_validate_cert_path_test, tear_down);
+    return result;
+}
+
+static int test_validate_cert_path_wrong_anchor(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_path(&fixture, srvcert /* wrong/non-root cert */, 0);
+    EXECUTE_TEST(execute_validate_cert_path_test, tear_down);
+    return result;
+}
+
+static int test_validate_cert_path_expired(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_path(&fixture, NULL, 1);
+    EXECUTE_TEST(execute_validate_cert_path_test, tear_down);
+    return result;
+}
+
+static int execute_MSG_check_received_test(CMP_VFY_TEST_FIXTURE *fixture)
+{
+    const OSSL_CMP_PKIHEADER *hdr = OSSL_CMP_MSG_get0_header(fixture->msg);
+    const ASN1_OCTET_STRING *tid = OSSL_CMP_HDR_get0_transactionID(hdr);
+
+    if (!TEST_int_eq(fixture->expected,
+                     ossl_cmp_msg_check_received(fixture->cmp_ctx,
+                                                 fixture->msg,
+                                                 fixture->allow_unprotected_cb,
+                                                 fixture->additional_arg)))
+        return 0;
+
+    if (fixture->expected < 0) /* error expected aready during above check */
+        return 1;
+    return
+        TEST_int_eq(0,
+                    ASN1_OCTET_STRING_cmp(ossl_cmp_hdr_get0_senderNonce(hdr),
+                                          fixture->cmp_ctx->recipNonce))
+        && TEST_int_eq(0,
+                       ASN1_OCTET_STRING_cmp(tid,
+                                             fixture->cmp_ctx->transactionID));
+}
+
+static int allow_unprotected(const OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+                             int invalid_protection, int allow)
+{
+    return allow;
+}
+
+static void setup_check_received(CMP_VFY_TEST_FIXTURE **fixture, int expected,
+                                 ossl_cmp_allow_unprotected_cb_t cb, int arg,
+                                 const unsigned char *trid_data,
+                                 const unsigned char *nonce_data)
+{
+    OSSL_CMP_CTX *ctx = (*fixture)->cmp_ctx;
+    int nonce_len = OSSL_CMP_SENDERNONCE_LENGTH;
+
+    (*fixture)->expected = expected;
+    (*fixture)->allow_unprotected_cb = cb;
+    (*fixture)->additional_arg = arg;
+    (*fixture)->msg = OSSL_CMP_MSG_dup(ir_rmprotection);
+    if ((*fixture)->msg == NULL
+        || (nonce_data != NULL
+            && !ossl_cmp_asn1_octet_string_set1_bytes(&ctx->senderNonce,
+                                                      nonce_data, nonce_len))) {
+        tear_down((*fixture));
+        (*fixture) = NULL;
+    }
+    else if (trid_data != NULL) {
+        ASN1_OCTET_STRING *trid = ASN1_OCTET_STRING_new();
+        if (trid == NULL
+            || !ASN1_OCTET_STRING_set(trid, trid_data,
+                                      OSSL_CMP_TRANSACTIONID_LENGTH)
+            || !OSSL_CMP_CTX_set1_transactionID(ctx, trid)) {
+            tear_down((*fixture));
+            (*fixture) = NULL;
+        }
+        ASN1_OCTET_STRING_free(trid);
+    }
+}
+
+static int test_MSG_check_received_no_protection_no_cb(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_check_received(&fixture, -1, NULL, 0, NULL, NULL);
+    EXECUTE_TEST(execute_MSG_check_received_test, tear_down);
+    return result;
+}
+
+static int test_MSG_check_received_no_protection_restrictive_cb(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_check_received(&fixture, -1, allow_unprotected, 0, NULL, NULL);
+    EXECUTE_TEST(execute_MSG_check_received_test, tear_down);
+    return result;
+}
+
+static int test_MSG_check_received_no_protection_permissive_cb(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_check_received(&fixture, OSSL_CMP_PKIBODY_IP, allow_unprotected, 1,
+                         NULL, NULL);
+    EXECUTE_TEST(execute_MSG_check_received_test, tear_down);
+    return result;
+}
+
+static int test_MSG_check_received_check_transaction_id(void)
+{
+    /* Transaction id belonging to CMP_IR_rmprotection.der */
+    const unsigned char trans_id[OSSL_CMP_TRANSACTIONID_LENGTH] = {
+        0x39, 0xB6, 0x90, 0x28, 0xC4, 0xBC, 0x7A, 0xF6,
+        0xBE, 0xC6, 0x4A, 0x88, 0x97, 0xA6, 0x95, 0x0B
+    };
+
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_check_received(&fixture, OSSL_CMP_PKIBODY_IP, allow_unprotected, 1,
+                         trans_id, NULL);
+    EXECUTE_TEST(execute_MSG_check_received_test, tear_down);
+    return result;
+}
+
+static int test_MSG_check_received_check_transaction_id_bad(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_check_received(&fixture, -1, allow_unprotected, 1, rand_data, NULL);
+    EXECUTE_TEST(execute_MSG_check_received_test, tear_down);
+    return result;
+}
+
+static int test_MSG_check_received_check_recipient_nonce(void)
+{
+    /* Recipient nonce belonging to CMP_IP_ir_rmprotection.der */
+    const unsigned char rec_nonce[OSSL_CMP_SENDERNONCE_LENGTH] = {
+        0x48, 0xF1, 0x71, 0x1F, 0xE5, 0xAF, 0x1C, 0x8B,
+        0x21, 0x97, 0x5C, 0x84, 0x74, 0x49, 0xBA, 0x32
+    };
+
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_check_received(&fixture, OSSL_CMP_PKIBODY_IP, allow_unprotected, 1,
+                         NULL, rec_nonce);
+    EXECUTE_TEST(execute_MSG_check_received_test, tear_down);
+    return result;
+}
+
+static int test_MSG_check_received_check_recipient_nonce_bad(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    setup_check_received(&fixture, -1, allow_unprotected, 1, NULL, rand_data);
+    EXECUTE_TEST(execute_MSG_check_received_test, tear_down);
+    return result;
+}
+
+void cleanup_tests(void)
+{
+    X509_free(srvcert);
+    X509_free(clcert);
+    X509_free(endentity1);
+    X509_free(endentity2);
+    X509_free(intermediate);
+    X509_free(root);
+    X509_free(insta_cert);
+    X509_free(instaca_cert);
+    OSSL_CMP_MSG_free(ir_unprotected);
+    OSSL_CMP_MSG_free(ir_rmprotection);
+    return;
+}
+
+int setup_tests(void)
+{
+    /* Set test time stamps */
+    struct tm ts = { 0 };
+
+    ts.tm_year = 2018 - 1900;      /* 2018 */
+    ts.tm_mon = 1;                 /* February */
+    ts.tm_mday = 18;               /* 18th */
+    test_time_valid = mktime(&ts); /* February 18th 2018 */
+    ts.tm_year += 10;              /* February 18th 2028 */
+    test_time_after_expiration = mktime(&ts);
+
+    RAND_bytes(rand_data, OSSL_CMP_TRANSACTIONID_LENGTH);
+    if (!TEST_ptr(server_f = test_get_argument(0))
+            || !TEST_ptr(client_f = test_get_argument(1))
+            || !TEST_ptr(endentity1_f = test_get_argument(2))
+            || !TEST_ptr(endentity2_f = test_get_argument(3))
+            || !TEST_ptr(root_f = test_get_argument(4))
+            || !TEST_ptr(intermediate_f = test_get_argument(5))
+            || !TEST_ptr(ir_protected_f = test_get_argument(6))
+            || !TEST_ptr(ir_unprotected_f = test_get_argument(7))
+            || !TEST_ptr(ip_waiting_f = test_get_argument(8))
+            || !TEST_ptr(ir_rmprotection_f = test_get_argument(9))
+            || !TEST_ptr(instacert_f = test_get_argument(10))
+            || !TEST_ptr(instaca_f = test_get_argument(11))
+            || !TEST_ptr(ir_protected_0_extracerts = test_get_argument(12))
+            || !TEST_ptr(ir_protected_2_extracerts = test_get_argument(13))) {
+        TEST_error("usage: cmp_vfy_test server.crt client.crt "
+                   "EndEntity1.crt EndEntity2.crt "
+                   "Root_CA.crt Intermediate_CA.crt "
+                   "CMP_IR_protected.der CMP_IR_unprotected.der "
+                   "IP_waitingStatus_PBM.der IR_rmprotection.der "
+                   "insta.cert.pem insta_ca.cert.pem "
+                   "IR_protected_0_extraCerts.der "
+                   "IR_protected_2_extraCerts.der\n");
+        return 0;
+    }
+
+    /* Load certificates for cert chain */
+    if (!TEST_ptr(endentity1 = load_pem_cert(endentity1_f))
+            || !TEST_ptr(endentity2 = load_pem_cert(endentity2_f))
+            || !TEST_ptr(root = load_pem_cert(root_f))
+            || !TEST_ptr(intermediate = load_pem_cert(intermediate_f)))
+        goto err;
+
+    if (!TEST_ptr(insta_cert = load_pem_cert(instacert_f))
+            || !TEST_ptr(instaca_cert = load_pem_cert(instaca_f)))
+        goto err;
+
+    /* Load certificates for message validation */
+    if (!TEST_ptr(srvcert = load_pem_cert(server_f))
+            || !TEST_ptr(clcert = load_pem_cert(client_f)))
+        goto err;
+    if (!TEST_int_eq(1, RAND_bytes(rand_data, OSSL_CMP_TRANSACTIONID_LENGTH)))
+        goto err;
+    if (!TEST_ptr(ir_unprotected = load_pkimsg(ir_unprotected_f))
+            || !TEST_ptr(ir_rmprotection = load_pkimsg(ir_rmprotection_f)))
+        goto err;
+
+    /* Message validation tests */
+    ADD_TEST(test_verify_popo);
+    ADD_TEST(test_verify_popo_bad);
+    ADD_TEST(test_validate_msg_signature_trusted_ok);
+    ADD_TEST(test_validate_msg_signature_trusted_expired);
+    ADD_TEST(test_validate_msg_signature_srvcert_wrong);
+    ADD_TEST(test_validate_msg_signature_bad);
+    ADD_TEST(test_validate_msg_signature_sender_cert_srvcert);
+    ADD_TEST(test_validate_msg_signature_sender_cert_untrusted);
+    ADD_TEST(test_validate_msg_signature_sender_cert_trusted);
+    ADD_TEST(test_validate_msg_signature_sender_cert_extracert);
+    ADD_TEST(test_validate_msg_signature_sender_cert_absent);
+    ADD_TEST(test_validate_msg_signature_expected_sender);
+    ADD_TEST(test_validate_msg_signature_unexpected_sender);
+    ADD_TEST(test_validate_msg_unprotected_request);
+    ADD_TEST(test_validate_msg_mac_alg_protection);
+    ADD_TEST(test_validate_msg_mac_alg_protection_bad);
+
+    /* Cert path validation tests */
+    ADD_TEST(test_validate_cert_path_ok);
+    ADD_TEST(test_validate_cert_path_expired);
+    ADD_TEST(test_validate_cert_path_wrong_anchor);
+
+    ADD_TEST(test_MSG_check_received_no_protection_no_cb);
+    ADD_TEST(test_MSG_check_received_no_protection_restrictive_cb);
+    ADD_TEST(test_MSG_check_received_no_protection_permissive_cb);
+    ADD_TEST(test_MSG_check_received_check_transaction_id);
+    ADD_TEST(test_MSG_check_received_check_transaction_id_bad);
+    ADD_TEST(test_MSG_check_received_check_recipient_nonce);
+    ADD_TEST(test_MSG_check_received_check_recipient_nonce_bad);
+
+    return 1;
+
+ err:
+    cleanup_tests();
+    return 0;
+
+}
diff --git a/test/recipes/65-test_cmp_vfy.t b/test/recipes/65-test_cmp_vfy.t
new file mode 100644
index 0000000000..c07e693f8a
--- /dev/null
+++ b/test/recipes/65-test_cmp_vfy.t
@@ -0,0 +1,36 @@
+#! /usr/bin/env perl
+# Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright Nokia 2007-2019
+# Copyright Siemens AG 2015-2019
+#
+# Licensed under the Apache License 2.0 (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use OpenSSL::Test qw/:DEFAULT data_file/;
+use OpenSSL::Test::Utils;
+
+setup("test_cmp_vfy");
+
+plan skip_all => "This test is not supported in a no-cmp build"
+    if disabled("cmp");
+
+plan skip_all => "This test is not supported in a no-ec build"
+    if disabled("ec");
+
+plan tests => 1;
+
+ok(run(test(["cmp_vfy_test",
+             data_file("server.crt"),     data_file("client.crt"),
+             data_file("EndEntity1.crt"), data_file("EndEntity2.crt"),
+             data_file("Root_CA.crt"),    data_file("Intermediate_CA.crt"),
+             data_file("IR_protected.der"),
+             data_file("IR_unprotected.der"),
+             data_file("IP_waitingStatus_PBM.der"),
+             data_file("IR_rmprotection.der"),
+             data_file("insta.cert.pem"),
+             data_file("insta_ca.cert.pem"),
+             data_file("IR_protected_0_extraCerts.der"),
+             data_file("IR_protected_2_extraCerts.der")])));
diff --git a/test/recipes/65-test_cmp_protect_data/EndEntity1.crt b/test/recipes/65-test_cmp_vfy_data/EndEntity1.crt
similarity index 100%
copy from test/recipes/65-test_cmp_protect_data/EndEntity1.crt
copy to test/recipes/65-test_cmp_vfy_data/EndEntity1.crt
diff --git a/test/recipes/65-test_cmp_protect_data/EndEntity2.crt b/test/recipes/65-test_cmp_vfy_data/EndEntity2.crt
similarity index 100%
copy from test/recipes/65-test_cmp_protect_data/EndEntity2.crt
copy to test/recipes/65-test_cmp_vfy_data/EndEntity2.crt
diff --git a/test/recipes/65-test_cmp_vfy_data/IP_waitingStatus_PBM.der b/test/recipes/65-test_cmp_vfy_data/IP_waitingStatus_PBM.der
new file mode 100644
index 0000000000..76888e84f7
Binary files /dev/null and b/test/recipes/65-test_cmp_vfy_data/IP_waitingStatus_PBM.der differ
diff --git a/test/recipes/65-test_cmp_vfy_data/IP_waitingStatus_PBM.txt b/test/recipes/65-test_cmp_vfy_data/IP_waitingStatus_PBM.txt
new file mode 100644
index 0000000000..89837972c9
--- /dev/null
+++ b/test/recipes/65-test_cmp_vfy_data/IP_waitingStatus_PBM.txt
@@ -0,0 +1,2 @@
+Reference#:   4787
+Secret Value: 9pp8-b35i-Xd3Q-udNR
diff --git a/test/recipes/65-test_cmp_protect_data/IR_protected.der b/test/recipes/65-test_cmp_vfy_data/IR_protected.der
similarity index 100%
copy from test/recipes/65-test_cmp_protect_data/IR_protected.der
copy to test/recipes/65-test_cmp_vfy_data/IR_protected.der
diff --git a/test/recipes/65-test_cmp_vfy_data/IR_protected_0_extraCerts.der b/test/recipes/65-test_cmp_vfy_data/IR_protected_0_extraCerts.der
new file mode 100755
index 0000000000..1c26028082
Binary files /dev/null and b/test/recipes/65-test_cmp_vfy_data/IR_protected_0_extraCerts.der differ
diff --git a/test/recipes/65-test_cmp_vfy_data/IR_protected_2_extraCerts.der b/test/recipes/65-test_cmp_vfy_data/IR_protected_2_extraCerts.der
new file mode 100755
index 0000000000..56faad4a0f
Binary files /dev/null and b/test/recipes/65-test_cmp_vfy_data/IR_protected_2_extraCerts.der differ
diff --git a/test/recipes/65-test_cmp_vfy_data/IR_rmprotection.der b/test/recipes/65-test_cmp_vfy_data/IR_rmprotection.der
new file mode 100644
index 0000000000..e84c64d8e0
Binary files /dev/null and b/test/recipes/65-test_cmp_vfy_data/IR_rmprotection.der differ
diff --git a/test/recipes/65-test_cmp_protect_data/IR_unprotected.der b/test/recipes/65-test_cmp_vfy_data/IR_unprotected.der
similarity index 100%
copy from test/recipes/65-test_cmp_protect_data/IR_unprotected.der
copy to test/recipes/65-test_cmp_vfy_data/IR_unprotected.der
diff --git a/test/recipes/65-test_cmp_protect_data/Intermediate_CA.crt b/test/recipes/65-test_cmp_vfy_data/Intermediate_CA.crt
similarity index 100%
copy from test/recipes/65-test_cmp_protect_data/Intermediate_CA.crt
copy to test/recipes/65-test_cmp_vfy_data/Intermediate_CA.crt
diff --git a/test/recipes/65-test_cmp_protect_data/Root_CA.crt b/test/recipes/65-test_cmp_vfy_data/Root_CA.crt
similarity index 100%
copy from test/recipes/65-test_cmp_protect_data/Root_CA.crt
copy to test/recipes/65-test_cmp_vfy_data/Root_CA.crt
diff --git a/test/recipes/65-test_cmp_vfy_data/chain.txt b/test/recipes/65-test_cmp_vfy_data/chain.txt
new file mode 100644
index 0000000000..1b55c25abb
--- /dev/null
+++ b/test/recipes/65-test_cmp_vfy_data/chain.txt
@@ -0,0 +1,4 @@
+1 - Root_CA (self-signed)
+1.1 - EndEntity1
+1.2 Intermediate_CA
+1.2.1 EndEntity2
diff --git a/test/recipes/65-test_cmp_vfy_data/client.crt b/test/recipes/65-test_cmp_vfy_data/client.crt
new file mode 100644
index 0000000000..fa6cdec436
--- /dev/null
+++ b/test/recipes/65-test_cmp_vfy_data/client.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICtTCCAZ2gAwIBAgIBATANBgkqhkiG9w0BAQUFADAeMRwwGgYDVQQKExNjbGll
+bnQgb3JnYW5pemF0aW9uMB4XDTE4MDIwNjEyNDYwMFoXDTE5MDIwNjEyNDYwMFow
+HjEcMBoGA1UEChMTY2xpZW50IG9yZ2FuaXphdGlvbjCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBALf0KDl07RlJlQVQcibB+JiUyXthFz4nzIkFVNISORCG
+JpTUMLLWxhF7Sc1li7gzvMAvx77SUThaNEOd0d2MJBbOXmZ9MtAOy8yHzRejBpw1
+mn9e0FKCI8rz3ttivspsGUIsRDhvMxuOol3lQ93QjfI593D7BOfBGdhsivD8m6+P
+EzF400iOSsbo3VPlArA+xTHiCyJ+E9p3yFGvzQrmK/MjM3lW3l3tARJmbXINIOio
+PnVmh4nsc9awqDGQdQTup/EjuY15AR4Vck7Zf9e+6U9t7Ow7aaZ5gX07FNnnqlVs
+48Lj/5a2Qgh482SQNvvRWAkPwTQNZ40ThKvOR/sB3iUCAwEAATANBgkqhkiG9w0B
+AQUFAAOCAQEAUSZBAR22ICoO7oPKMpfxwIHDAODv6jEHx2fSTpwxqodVqwF8ghAS
+PvJwQ4+7+yny4ieX9iVicRdXXT8kEOQL5/3/Q+cBj/BzYE0VGxo4YloHQwWNdSg0
+B1oQ/4dAnDntGnXHDJMSZCGq/jj4/56XSrPymzR2jgOQNqnEkMM9/SpW7MirixJA
+ZBR5Oc97vKaAH89ucsTu0neVMTXgywdBiy1W8bo4XxquK6VDRHlLj4gMLBpaG0mW
+r5ST1gs8j63nK/eZ7AuTV/tvI25reXT+2wOKAgPEcd02Fh61TO4IPD4GDidEHvAw
+6m66U9eFVezkxDvjE0X5voFnsBl4qTSZ/A==
+-----END CERTIFICATE-----
diff --git a/test/recipes/65-test_cmp_vfy_data/insta.cert.pem b/test/recipes/65-test_cmp_vfy_data/insta.cert.pem
new file mode 100755
index 0000000000..4a25699f05
--- /dev/null
+++ b/test/recipes/65-test_cmp_vfy_data/insta.cert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIEBtqJKDANBgkqhkiG9w0BAQsFADA6MQswCQYDVQQGEwJG
+STETMBEGA1UECgwKSW5zdGEgRGVtbzEWMBQGA1UEAwwNSW5zdGEgRGVtbyBDQTAe
+Fw0xODAxMzAxMDE0MjNaFw0xODA0MzAyMzU5NTlaMBAxDjAMBgNVBAMMBXRlc3Qx
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoiNNxo5pwk1lD1em3mad
+bpKz86GSYyGlQtd0ZhIX1tOUFo9lFex7n5Osv0A99pKb+7EKqB9Ghg6mJ29kIUUm
+LACnfZJ/q+U6s9T4zFrYyXweUNJvQgbA2ojDPyVoRp2T1ekahPh4DpxPWNKfYECD
+RbrxkHMM3WiIqYFLU8hYvEMGSWRHHbnS/vG7MTaVDkR8d0zixTOp0fST5c1UUTqp
+pYlThac/BG1kk3hyjIjz5o7lspfX3s/eAYgT9GhYHL6Uy4o4OqCleR39aVc0dMrr
+jb7hsmX6ecNwqJOE5AHHOG4Ti6CbweSOcdH5PRFzdpao5rlTErsFHlUSTca4mfVe
+WwIDAQABo4IBUzCCAU8wHwYDVR0jBBgwFoAUPHjduMGNV/UFKl5t4FhySvpEJWEw
+HQYDVR0OBBYEFD0oLwov3vSGa1f9bIKGzWoPP0A1MCcGA1UdEQQgMB6CBGFiLmOC
+BGRlLmaCBHRlc3SHBAECA/+HBAQFBgcweAYDVR0fBHEwbzBtoGugaYZnbGRhcDov
+L3BraS5jZXJ0aWZpY2F0ZS5maTozODkvQ049SW5zdGElMjBEZW1vJTIwQ0EsTz1J
+bnN0YSUyMERlbW8sQz1GST9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0O2JpbmFy
+eTBqBggrBgEFBQcBAQReMFwwWgYIKwYBBQUHMAKGTmxkYXA6Ly93d3cuY2VydGlm
+aWNhdGUuZmk6Mzg5L0NOPUluc3RhIERlbW8gQ0EsTz1JbnN0YSBEZW1vLEM9Rkk/
+Y2FDZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAQEAbIRfAbU0v2RWZg6lkjZg
+58fi4lT7Xk64sK4G/QLZ8TR/jg5UR0J5IvYt52YBjs/tjwJokkaW7+DyhVKkPrGs
+oexpdLRSnXBv33+Yj+MZbSfrIX1Ox7up+ovs8le4viSlUqIDWBuuUBfZ16BFMmnB
+UwDar8p/ci9ReKJH+FmvxlHbTHdMznZooSxTZm96HTutuiULL/SzZ2FpUsd7G5EE
+mRA6uRVV1tuysD15H+9paqVwd0RaKee8Z63cDi3NXOxUcCnpINHrjVsdcW47/73V
+IgfU4t39BKNiQNL0ADYpCyrpntTpsyZWrNmYzXMgLYEXxi4s6obusY0I3Qg+U31o
+Uw==
+-----END CERTIFICATE-----
diff --git a/test/recipes/65-test_cmp_vfy_data/insta.priv.pem b/test/recipes/65-test_cmp_vfy_data/insta.priv.pem
new file mode 100755
index 0000000000..8612994d15
--- /dev/null
+++ b/test/recipes/65-test_cmp_vfy_data/insta.priv.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAoiNNxo5pwk1lD1em3madbpKz86GSYyGlQtd0ZhIX1tOUFo9l
+Fex7n5Osv0A99pKb+7EKqB9Ghg6mJ29kIUUmLACnfZJ/q+U6s9T4zFrYyXweUNJv
+QgbA2ojDPyVoRp2T1ekahPh4DpxPWNKfYECDRbrxkHMM3WiIqYFLU8hYvEMGSWRH
+HbnS/vG7MTaVDkR8d0zixTOp0fST5c1UUTqppYlThac/BG1kk3hyjIjz5o7lspfX
+3s/eAYgT9GhYHL6Uy4o4OqCleR39aVc0dMrrjb7hsmX6ecNwqJOE5AHHOG4Ti6Cb
+weSOcdH5PRFzdpao5rlTErsFHlUSTca4mfVeWwIDAQABAoIBAQCUYAZevBjgbP8c
+qTPVtsY/WBVB0Qwrl7CqmIy2k7wpJfoRIyx4ga8n+3ZMlredm9EO5ZdA/04EhAdd
+czyIjcU+42JjMduQLPgpda4xJLnauLDteYXDQHbgBePXN55TcQTG7skMAm2rwTOD
+r0uWQ7Nd7pP9gqu1OmJF7EJI68D4llCU1FrOrliwSDzHWP3p4QmCW3M9PQJ68xw1
+gE7X1QflROGivcFoRgcgeoJDzpxveGvPbEn6Q+05/FMRVxjqWhpxdZ9/SL7iRz1e
+45T+P9a8OLgTyErT3Lp/f/vuHA1tlbAYumhSnxXsb+nHi80aDcImOrNQHAp076Ik
+bkZ1NpOxAoGBAM3Ulgi2hUPdoAMFtHZF8eBHRzn+4uTfY2s33wObiUJQ8VbGDeJY
+ifCfOwLThiAXAqktrs7ItwWDYmzd5xPYGQeWoKcBEoZ+dvaaOe8H7TCMnjB3R3i1
+ACSDHo/3c+NfFOnPJtXL85jeAqGYH50uOtYmYaBVe6xASTBgNvP7snYHAoGBAMmo
+ZBQqgIhoqMRapGh6n4OpzH0Nt9ruOTJoteAfbLdAu7X+wAaMuxEaAmZQRDYj0lzX
+Ty8DlKSy7vfvXtghxMBEv4+dsYpagXcUOeEZSPfu1c3e253dAov6C0MdREKWBT7P
++NwPBowPy0CP/yBeHaw7d/P7/SYIoPXLGraGl6ANAoGBAMmmce7LUjgw0mjjl+8f
+i14cts08x3FO4YnTTOut34VW43oNwuBzuYBBn4CfVpHtuS+hj9cKkTQXib/6jj7E
+wZDLo0y6Ijodf9MNOaDSdS/RM9Frqlu5iBA9XR3SYnjpWAXQas2eaGLlblJ+RMqq
+1f2j0JVR6j3RJWL9gBj8B9TVAoGBALYZrs4bF1iXEhfGNoL2gIdX1QX0VluIFfR0
+ZBDQr87H0Ppm4qbHfMHTt+kGgKJXNMaL08CDvj4AKxWPfhk0XUS2kDmzUDi8w/5x
+MFcaCy+A6Gdw4OcsRfl7QaJIknSCnpf7HCI0G1hthsB1iBCFjMwUI50ap54p2pg6
+4ZOD9PYdAoGAERi5Hlq7+rJeDi3VunKHySqV9mvbOPNclEUmAdKi1yuu3INF1Zgv
+Lf432ZI/Ufk2g888ed5ZGE1IMULc2tgSIAMzdX4ZYI4uGFLkHWzSOM6a7NCeZuVt
+W+NgUYa2qsqFEd9kqaoDbNry+nPvLM7fWXvBoE4oNkeJhHjOIabBPvw=
+-----END RSA PRIVATE KEY-----
diff --git a/test/recipes/65-test_cmp_vfy_data/insta_ca.cert.pem b/test/recipes/65-test_cmp_vfy_data/insta_ca.cert.pem
new file mode 100755
index 0000000000..4b7e31b86d
--- /dev/null
+++ b/test/recipes/65-test_cmp_vfy_data/insta_ca.cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDkDCCAnigAwIBAgIDCZU1MA0GCSqGSIb3DQEBBQUAMDoxCzAJBgNVBAYTAkZJ
+MRMwEQYDVQQKEwpJbnN0YSBEZW1vMRYwFAYDVQQDEw1JbnN0YSBEZW1vIENBMB4X
+DTA2MDEwMjA4NDgzOFoXDTI1MTIzMTA4NDgzOFowOjELMAkGA1UEBhMCRkkxEzAR
+BgNVBAoTCkluc3RhIERlbW8xFjAUBgNVBAMTDUluc3RhIERlbW8gQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDF57bSwj+hZnkgLyLtFsoNIN19qBv9
+GIoqFaCiPvw6VQgMXR15t+Z5sdYHdydGp875yJD4wDq2K7cjMoCXALxLeyp6dCY6
+WPC6Hk3QvZtMRuDAz8+0Nb5qaC4+O+7c7j1h/Gs8Jpj+TUuSkmtlCVIGPSWkWaQl
+FhLWeUnKRW8bj1CJQguV7igF19kGQKUZ/VZj+n5xIXKHc8njC1ZrS/s0IBFViQkZ
+63nTdNPLHQ4Xu8uKrbJbYEK1S4KVNH3L9yA4ut+brqX8n6OulTsKntvMdwNWZdor
+KoM15D3lmM7QUGDflJdSQ/qvBVTda+ccrT21sp4hdwwiU01vxQguT26JAgMBAAGj
+gZ4wgZswHwYDVR0jBBgwFoAUPHjduMGNV/UFKl5t4FhySvpEJWEwHQYDVR0OBBYE
+FDx43bjBjVf1BSpebeBYckr6RCVhMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8E
+CDAGAQH/AgEAMDUGCWCGSAGG+EIBDQQoFiZJbnN0YSBEZW1vIENBIC0gb25seSBm
+b3IgZGVtbyBwdXJwb3NlczANBgkqhkiG9w0BAQUFAAOCAQEAuVRmRimTxVTZMNXi
+3u4bRCq7GxJ4Lonx3mocxYiwBjCYwqn5dPAd4AHrA1HWYCEvIPo52FibpUNNljqH
+v7CSoEBg2f4If6cFtwudobqNvf8Z50CAnxlwpPy4k+EbXlh49/uZBtu8+Lc2Ss7L
+QaNHHiOeHxYeGX7pTcr6fnXQWAbbn4SLyqniW7ZTqjNJvC79Ym7KowMYzCbmozzv
+3xqElA+g/MLFfxn52c/vl/obOVk5eBf3f7V68qKL2IDEip3fyZyoelhfTypq944m
+sSJFQjoVzgd7ykgouEwOceOT8YMWWigNsWl/hsVJ03Ri7TxRX4+v8dMEbat+SsTL
+AqTTgQ==
+-----END CERTIFICATE-----
diff --git a/test/recipes/65-test_cmp_msg_data/server.crt b/test/recipes/65-test_cmp_vfy_data/server.crt
similarity index 100%
copy from test/recipes/65-test_cmp_msg_data/server.crt
copy to test/recipes/65-test_cmp_vfy_data/server.crt
diff --git a/test/recipes/65-test_cmp_protect_data/server.pem b/test/recipes/65-test_cmp_vfy_data/server.key
similarity index 100%
copy from test/recipes/65-test_cmp_protect_data/server.pem
copy to test/recipes/65-test_cmp_vfy_data/server.key
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 380a2d2916..9029688674 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4928,3 +4928,10 @@ OSSL_HTTP_get_asn1                      ?	3_0_0	EXIST::FUNCTION:SOCK
 OSSL_HTTP_post_asn1                     ?	3_0_0	EXIST::FUNCTION:SOCK
 OSSL_HTTP_transfer                      ?	3_0_0	EXIST::FUNCTION:SOCK
 OSSL_HTTP_proxy_connect                 ?	3_0_0	EXIST::FUNCTION:SOCK
+ERR_add_error_txt                       ?	3_0_0	EXIST::FUNCTION:
+ERR_add_error_mem_bio                   ?	3_0_0	EXIST::FUNCTION:
+X509_STORE_CTX_print_verify_cb          ?	3_0_0	EXIST::FUNCTION:
+X509_STORE_get1_all_certs               ?	3_0_0	EXIST::FUNCTION:
+OSSL_CMP_validate_msg                   ?	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CMP_validate_cert_path             ?	3_0_0	EXIST::FUNCTION:CMP
+OSSL_CMP_print_to_bio                   ?	3_0_0	EXIST::FUNCTION:CMP
diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt
index a1f0c3487e..95d300eda3 100644
--- a/util/missingcrypto.txt
+++ b/util/missingcrypto.txt
@@ -1567,7 +1567,6 @@ i2v_GENERAL_NAME(3)
 i2v_GENERAL_NAMES(3)
 o2i_ECPublicKey(3)
 openssl-core_numbers.h(7)
-ossl_cmp_certReq_new(3)
 provider-kdf(7)
 s2i_ASN1_IA5STRING(3)
 s2i_ASN1_INTEGER(3)
diff --git a/util/other.syms b/util/other.syms
index 378dda3659..27e9a92374 100644
--- a/util/other.syms
+++ b/util/other.syms
@@ -359,17 +359,7 @@ OSSL_CMP_LOG_NOTICE                     define
 OSSL_CMP_LOG_WARNING                    define
 OSSL_CMP_MSTR_HELPER                    define
 OSSL_CMP_MSTR                           define
-OSSL_CMP_alert                          define
-OSSL_CMP_debug                          define
-OSSL_CMP_err                            define
-OSSL_CMP_info                           define
-OSSL_CMP_log                            define
-OSSL_CMP_log1                           define
-OSSL_CMP_log2                           define
-OSSL_CMP_log3                           define
-OSSL_CMP_log4                           define
 OSSL_CMP_severity                       datatype
-OSSL_CMP_warn                           define
 OSSL_cmp_certConf_cb_t                  datatype
 OSSL_cmp_log_cb_t                       datatype
 OSSL_cmp_transfer_cb_t                  datatype


More information about the openssl-commits mailing list