]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
CMP: Optionally accept missing or non-matching transactionID or recipNonce values
authorDr. David von Oheimb <dev@ddvo.net>
Thu, 3 Apr 2025 06:53:58 +0000 (08:53 +0200)
committerDr. David von Oheimb <dev@ddvo.net>
Thu, 11 Jun 2026 14:56:35 +0000 (16:56 +0200)
This is done for error messages received if OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES
is set or the respective -nonmatched_error_nonces CLI option is given.

Can be helpful when the server (or other peer) cannot provide a proper error message header,
for instance if was unable to parse the ASN.1 encoding of a request message.

Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
MergeDate: Thu Jun 11 14:56:49 2026
(Merged from https://github.com/openssl/openssl/pull/29043)

CHANGES.md
apps/cmp.c
crypto/cmp/cmp_ctx.c
crypto/cmp/cmp_local.h
crypto/cmp/cmp_vfy.c
doc/man1/openssl-cmp.pod.in
doc/man3/OSSL_CMP_CTX_new.pod
include/openssl/cmp.h.in
test/cmp_vfy_test.c
test/recipes/65-test_cmp_vfy.t
test/recipes/65-test_cmp_vfy_data/error_protected.der [new file with mode: 0644]

index 4e33d004731b45c7ca265eed5bdf9c4f699104da..1bfdba4035ead1eb6ebb15498dbde861e9a02393 100644 (file)
@@ -155,6 +155,13 @@ OpenSSL Releases
 
    *Daniel Kubec*
 
+ * Added `OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES` option for `OSSL_CMP_CTX` and
+   a corresponding `-nonmatched_error_nonces` option for the `openssl cmp` command.
+
+   This work was sponsored by Siemens AG.
+
+   *David von Oheimb*
+
  * Added support for RFC 8701 GREASE (Generate Random Extensions And Sustain
    Extensibility). When `SSL_OP_GREASE` is set, the TLS client injects
    reserved GREASE values into cipher suites, supported versions, supported
index 8739e860d3b6907256626bb04346ae56824aae01..a5d5f0d9e624f5820f99e5e5f06cbd101e440695 100644 (file)
@@ -87,6 +87,7 @@ static char *opt_srvcert = NULL;
 static char *opt_expect_sender = NULL;
 static int opt_ignore_keyusage = 0;
 static int opt_unprotected_errors = 0;
+static int opt_nonmatched_error_nonces = 0;
 static int opt_ta_in_ip_extracerts = 0;
 static int opt_no_cache_extracerts = 0;
 static char *opt_srvcertout = NULL;
@@ -282,6 +283,7 @@ typedef enum OPTION_choice {
     OPT_EXPECT_SENDER,
     OPT_IGNORE_KEYUSAGE,
     OPT_UNPROTECTED_ERRORS,
+    OPT_NONMATCHED_ERROR_NONCES,
     OPT_TA_IN_IP_EXTRACERTS,
     OPT_NO_CACHE_EXTRACERTS,
     OPT_SRVCERTOUT,
@@ -511,6 +513,8 @@ const OPTIONS cmp_options[] = {
         "certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf" },
     { OPT_MORE_STR, 0, 0,
         "WARNING: This setting leads to behavior allowing violation of RFC 9810" },
+    { "nonmatched_error_nonces", OPT_NONMATCHED_ERROR_NONCES, '-',
+        "Accept missing or non-matching transactionID or recipNonce in error messages" },
     { "ta_in_ip_extracerts", OPT_TA_IN_IP_EXTRACERTS, '-',
         "Permit using self-issued certificates from the extraCerts in an IP message" },
     { OPT_MORE_STR, 0, 0,
@@ -735,6 +739,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     { &opt_trusted }, { &opt_untrusted }, { &opt_srvcert },
     { &opt_expect_sender },
     { (char **)&opt_ignore_keyusage }, { (char **)&opt_unprotected_errors },
+    { (char **)&opt_nonmatched_error_nonces },
     { (char **)&opt_ta_in_ip_extracerts },
     { (char **)&opt_no_cache_extracerts },
     { &opt_srvcertout }, { &opt_extracertsout }, { &opt_cacertsout },
@@ -1417,6 +1422,8 @@ static int setup_verification_ctx(OSSL_CMP_CTX *ctx)
 
     if (opt_unprotected_errors)
         (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1);
+    if (opt_nonmatched_error_nonces)
+        (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES, 1);
     if (opt_ta_in_ip_extracerts) {
         (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR, 1);
         CMP_warn("permitting non-authenticated trust anchors in IP extracerts according to 3GPP TS 33.310");
@@ -2989,6 +2996,9 @@ static int get_opts(int argc, char **argv)
         case OPT_UNPROTECTED_ERRORS:
             opt_unprotected_errors = 1;
             break;
+        case OPT_NONMATCHED_ERROR_NONCES:
+            opt_nonmatched_error_nonces = 1;
+            break;
         case OPT_TA_IN_IP_EXTRACERTS:
             opt_ta_in_ip_extracerts = 1;
             break;
index f2717de83fda345888f3c8d9f584f51f8a1fc98a..da8277f5feaa60166cd78801e1f790c6e5f8dc23 100644 (file)
@@ -925,6 +925,9 @@ DEFINE_set1_ASN1_OCTET_STRING(OSSL_CMP_CTX, transactionID)
     case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
         ctx->unprotectedErrors = val;
         break;
+    case OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES:
+        ctx->nonmatchedErrorNonces = val;
+        break;
     case OSSL_CMP_OPT_NO_CACHE_EXTRACERTS:
         ctx->noCacheExtraCerts = val;
         break;
@@ -1013,6 +1016,8 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
         return ctx->unprotectedSend;
     case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
         return ctx->unprotectedErrors;
+    case OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES:
+        return ctx->nonmatchedErrorNonces;
     case OSSL_CMP_OPT_NO_CACHE_EXTRACERTS:
         return ctx->noCacheExtraCerts;
     case OSSL_CMP_OPT_VALIDITY_DAYS:
index b96acf77ce69396be51827c1406c714b1947e257..e664a6ae221beeedd177b98467ce623c6e592532 100644 (file)
@@ -55,6 +55,7 @@ struct ossl_cmp_ctx_st {
      * certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf
      */
     int unprotectedErrors;
+    int nonmatchedErrorNonces; /* accept missing/wrong transactionID or recipNonce in error msgs */
     int noCacheExtraCerts;
     X509 *srvCert; /* certificate used to identify the server */
     X509 *validatedSrvCert; /* caches any already validated sender cert */
index 588649c8000eeb35e782f41f7e0e426daaa36ff2..48014295e33c68ebbd6035e0d1ef59539eecd174 100644 (file)
@@ -676,24 +676,35 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
     return 0;
 }
 
-static int check_transactionID_or_nonce(ASN1_OCTET_STRING *expected,
-    ASN1_OCTET_STRING *actual, int reason)
+static int check_transactionID_or_nonce(OSSL_CMP_CTX *ctx, const ASN1_OCTET_STRING *expected,
+    const ASN1_OCTET_STRING *actual, int bodytype, int reason)
 {
     if (expected != NULL
         && (actual == NULL || ASN1_OCTET_STRING_cmp(expected, actual) != 0)) {
 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-        char *expected_str, *actual_str;
+        char *expected_str, *actual_str, *expected_msg, *actual_msg;
+        const int strict = bodytype != OSSL_CMP_PKIBODY_ERROR || !ctx->nonmatchedErrorNonces;
+        int res = 0;
 
+        if (reason == 0) /* at end of polling, overall check is not yet complete */
+            return res;
         expected_str = i2s_ASN1_OCTET_STRING(NULL, expected);
+        expected_msg = expected_str == NULL ? "?" : expected_str;
         actual_str = actual == NULL ? NULL : i2s_ASN1_OCTET_STRING(NULL, actual);
-        ERR_raise_data(ERR_LIB_CMP, reason,
-            "expected = %s, actual = %s",
-            expected_str == NULL ? "?" : expected_str,
-            actual == NULL ? "(none)" : actual_str == NULL ? "?"
-                                                           : actual_str);
+        actual_msg = actual == NULL ? "(none)" : actual_str == NULL ? "?"
+                                                                    : actual_str;
+        if (strict) {
+            ERR_raise_data(ERR_LIB_CMP, reason, "expected = %s, actual = %s",
+                expected_msg, actual_msg);
+        } else {
+            ossl_cmp_log3(WARN, ctx, "ignoring missing or non-matching %s of error message, expected = %s, actual = %s",
+                reason == CMP_R_TRANSACTIONID_UNMATCHED ? "transactionID" : "recipNonce",
+                expected_msg, actual_msg);
+            res = 1;
+        }
         OPENSSL_free(expected_str);
         OPENSSL_free(actual_str);
-        return 0;
+        return res;
 #endif
     }
     return 1;
@@ -724,11 +735,13 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
 {
     OSSL_CMP_PKIHEADER *hdr;
     const X509_NAME *expected_sender;
+    int bodytype, end_of_polling;
     int num_untrusted, num_added, res;
 
     if (!ossl_assert(ctx != NULL && msg != NULL && msg->header != NULL))
         return 0;
     hdr = OSSL_CMP_MSG_get0_header(msg);
+    bodytype = OSSL_CMP_MSG_get_bodytype(msg);
 
     /* If expected_sender is given, validate sender name of received msg */
     expected_sender = ctx->expected_sender;
@@ -762,6 +775,8 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
             return 0;
         }
     }
+
+    /* Ignoring recipient */
     /* Note: if recipient was NULL-DN it could be learned here if needed */
 
     num_added = sk_X509_num(msg->extraCerts);
@@ -823,7 +838,7 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
 #endif
     }
 
-    if (OSSL_CMP_MSG_get_bodytype(msg) < 0) {
+    if (bodytype < 0) {
 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
         ERR_raise(ERR_LIB_CMP, CMP_R_PKIBODY_ERROR);
         return 0;
@@ -831,30 +846,25 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
     }
 
     /* compare received transactionID with the expected one in previous msg */
-    if (!check_transactionID_or_nonce(ctx->transactionID, hdr->transactionID,
-            CMP_R_TRANSACTIONID_UNMATCHED))
+    if (!check_transactionID_or_nonce(ctx, ctx->transactionID, hdr->transactionID,
+            bodytype, CMP_R_TRANSACTIONID_UNMATCHED))
         return 0;
 
     /*
-     * enable clearing irrelevant errors
-     * in attempts to validate recipient nonce in case of delayed delivery.
+     * Compare received nonce with the one we sent last.
+     * When we received the final response at the end of polling,
+     * we allow also the nonce that we sent earlier with the original request,
+     * as specified in RFC 9483 section 5.1.5.
      */
-    (void)ERR_set_mark();
-    /* compare received nonce with the one we sent */
-    if (!check_transactionID_or_nonce(ctx->senderNonce, hdr->recipNonce,
-            CMP_R_RECIPNONCE_UNMATCHED)) {
-        /* check if we are polling and received final response */
-        if (ctx->first_senderNonce == NULL
-            || OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_POLLREP
-            /* compare received nonce with our sender nonce at poll start */
-            || !check_transactionID_or_nonce(ctx->first_senderNonce,
-                hdr->recipNonce,
-                CMP_R_RECIPNONCE_UNMATCHED)) {
-            (void)ERR_clear_last_mark();
+    end_of_polling = ctx->first_senderNonce != NULL && bodytype != OSSL_CMP_PKIBODY_POLLREP;
+    if (!check_transactionID_or_nonce(ctx, ctx->senderNonce, hdr->recipNonce,
+            bodytype, end_of_polling ? 0 : CMP_R_RECIPNONCE_UNMATCHED)) {
+        if (!end_of_polling
+            /* otherwise, compare received nonce with our sender nonce at poll start: */
+            || !check_transactionID_or_nonce(ctx, ctx->first_senderNonce, hdr->recipNonce,
+                bodytype, CMP_R_RECIPNONCE_UNMATCHED))
             return 0;
-        }
     }
-    (void)ERR_pop_to_mark();
 
     /* if not yet present, learn transactionID */
     if (ctx->transactionID == NULL
@@ -876,7 +886,7 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
          * the caPubs field may be directly trusted as a root CA
          * certificate by the initiator.'
          */
-        switch (OSSL_CMP_MSG_get_bodytype(msg)) {
+        switch (bodytype) {
         case OSSL_CMP_PKIBODY_IP:
         case OSSL_CMP_PKIBODY_CP:
         case OSSL_CMP_PKIBODY_KUP:
index c3939292643a31c84f62ba96afcbfa39cac6e601..797414ea943a417ef06ec7d893677f237d49fdbf 100644 (file)
@@ -70,6 +70,7 @@ Server authentication options:
 [B<-expect_sender> I<name>]
 [B<-ignore_keyusage>]
 [B<-unprotected_errors>]
+[B<-nonmatched_error_nonces>]
 [B<-ta_in_ip_extracerts>]
 [B<-no_cache_extracerts>]
 [B<-srvcertout> I<filename>]
@@ -722,6 +723,12 @@ with a signature key."
 
 =back
 
+=item B<-nonmatched_error_nonces>
+
+Accept missing or non-matching transactionID or recipNonce values in error messages.
+This can be helpful in case the server cannot provide a proper error message,
+for instance if it was unable to parse the ASN.1 encoding of a request message.
+
 =item B<-ta_in_ip_extracerts>
 
 This is a quirk option added to support 3GPP TS 33.310.
@@ -1545,6 +1552,8 @@ The B<-ta_in_ip_extracerts> quirk option was added in OpenSSL 4.0.
 
 The B<-engine> option was removed in OpenSSL 4.0.
 
+The B<-nonmatched_error_nonces> option was added in OpenSSL 4.1.
+
 =head1 COPYRIGHT
 
 Copyright 2007-2026 The OpenSSL Project Authors. All Rights Reserved.
index 146bdbd0649bdce6a96db55b9e141d919d9f939e..ce8a0b7fc9dbaffe4b88e9885651c71e8eb01493 100644 (file)
@@ -335,6 +335,12 @@ B<WARNING:> This setting leads to unspecified behavior and it is meant
 exclusively to allow interoperability with server implementations violating
 RFC 9810.
 
+=item B<OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES>
+
+Accept missing or non-matching transactionID or recipNonce in error messages.
+This can be helpful in case the server cannot provide a proper error message,
+for instance if it was unable to parse the ASN.1 encoding of a request message.
+
 =item B<OSSL_CMP_OPT_IGNORE_KEYUSAGE>
 
 Ignore key usage restrictions in the signer's certificate when
@@ -894,8 +900,11 @@ OSSL_CMP_CTX_get0_geninfo_ITAVs() were added in OpenSSL 3.3.
 Support for central key generation, requested via B<OSSL_CRMF_POPO_NONE>,
 was added in OpenSSL 3.5.
 
+
 The B<OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR> option was added in OpenSSL 4.0.
 
+The B<OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES> option was added in OpenSSL 4.1.
+
 =head1 COPYRIGHT
 
 Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
index 639197eef38d3243c78fc836fdd0ab85db966088..6ae08e1872b3db8df238cd5d6a439569d32c5edc 100644 (file)
@@ -376,6 +376,7 @@ const char *OSSL_CMP_CTX_get0_propq(const OSSL_CMP_CTX *ctx);
 #define OSSL_CMP_OPT_IGNORE_KEYUSAGE 35
 #define OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR 36
 #define OSSL_CMP_OPT_NO_CACHE_EXTRACERTS 37
+#define OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES 38
 int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val);
 int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt);
 /* CMP-specific callback for logging and outputting the error queue: */
index 70d776c0f572ec2afdd48a3290c661c440f17493..ec7131a8613b8e6dc6e80e52903a50cc09da785c 100644 (file)
@@ -22,6 +22,7 @@ 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 *error_protected_f;
 static const char *instacert_f;
 static const char *instaca_f;
 static const char *ir_protected_0_extracerts;
@@ -81,7 +82,7 @@ static X509 *endentity1 = NULL, *endentity2 = NULL,
 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 OSSL_CMP_MSG *ir_unprotected, *ir_rmprotection, *error_protected;
 
 /* secret value used for IP_waitingStatus_PBM.der */
 static const unsigned char sec_1[] = {
@@ -452,9 +453,9 @@ static int execute_msg_check_test(CMP_VFY_TEST_FIXTURE *fixture)
 
     if (fixture->expected == 0) /* error expected already during above check */
         return 1;
-    return TEST_int_eq(0,
-               ASN1_OCTET_STRING_cmp(ossl_cmp_hdr_get0_senderNonce(hdr),
-                   fixture->cmp_ctx->recipNonce))
+    if (OSSL_CMP_CTX_get_option(fixture->cmp_ctx, OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES))
+        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));
@@ -468,6 +469,7 @@ static int allow_unprotected(const OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
 
 static void setup_check_update(CMP_VFY_TEST_FIXTURE **fixture, int expected,
     ossl_cmp_allow_unprotected_cb_t cb, int arg,
+    const OSSL_CMP_MSG *msg,
     const unsigned char *trid_data,
     const unsigned char *nonce_data)
 {
@@ -477,7 +479,7 @@ static void setup_check_update(CMP_VFY_TEST_FIXTURE **fixture, int expected,
     (*fixture)->expected = expected;
     (*fixture)->allow_unprotected_cb = cb;
     (*fixture)->additional_arg = arg;
-    (*fixture)->msg = OSSL_CMP_MSG_dup(ir_rmprotection);
+    (*fixture)->msg = OSSL_CMP_MSG_dup(msg);
     if ((*fixture)->msg == NULL
         || (nonce_data != NULL
             && !ossl_cmp_asn1_octet_string_set1_bytes(&ctx->senderNonce,
@@ -502,7 +504,7 @@ static void setup_check_update(CMP_VFY_TEST_FIXTURE **fixture, int expected,
 static int test_msg_check_no_protection_no_cb(void)
 {
     SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
-    setup_check_update(&fixture, 0, NULL, 0, NULL, NULL);
+    setup_check_update(&fixture, 0, NULL, 0, ir_rmprotection, NULL, NULL);
     EXECUTE_TEST(execute_msg_check_test, tear_down);
     return result;
 }
@@ -510,7 +512,7 @@ static int test_msg_check_no_protection_no_cb(void)
 static int test_msg_check_no_protection_restrictive_cb(void)
 {
     SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
-    setup_check_update(&fixture, 0, allow_unprotected, 0, NULL, NULL);
+    setup_check_update(&fixture, 0, allow_unprotected, 0, ir_rmprotection, NULL, NULL);
     EXECUTE_TEST(execute_msg_check_test, tear_down);
     return result;
 }
@@ -519,7 +521,7 @@ static int test_msg_check_no_protection_restrictive_cb(void)
 static int test_msg_check_no_protection_permissive_cb(void)
 {
     SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
-    setup_check_update(&fixture, 1, allow_unprotected, 1, NULL, NULL);
+    setup_check_update(&fixture, 1, allow_unprotected, 1, ir_rmprotection, NULL, NULL);
     EXECUTE_TEST(execute_msg_check_test, tear_down);
     return result;
 }
@@ -533,7 +535,7 @@ static int test_msg_check_transaction_id(void)
     };
 
     SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
-    setup_check_update(&fixture, 1, allow_unprotected, 1, trans_id, NULL);
+    setup_check_update(&fixture, 1, allow_unprotected, 1, ir_rmprotection, trans_id, NULL);
     EXECUTE_TEST(execute_msg_check_test, tear_down);
     return result;
 }
@@ -542,12 +544,22 @@ static int test_msg_check_transaction_id(void)
 static int test_msg_check_transaction_id_bad(void)
 {
     SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
-    setup_check_update(&fixture, 0, allow_unprotected, 1, rand_data, NULL);
+    setup_check_update(&fixture, 0, allow_unprotected, 1, ir_rmprotection, rand_data, NULL);
     EXECUTE_TEST(execute_msg_check_test, tear_down);
     return result;
 }
 #endif
 
+static int test_msg_check_transaction_id_error(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+
+    (void)OSSL_CMP_CTX_set_option(fixture->cmp_ctx, OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES, 1);
+    setup_check_update(&fixture, 1, allow_unprotected, 1, error_protected, rand_data, NULL);
+    EXECUTE_TEST(execute_msg_check_test, tear_down);
+    return result;
+}
+
 static int test_msg_check_recipient_nonce(void)
 {
     /* Recipient nonce belonging to CMP_IP_ir_rmprotection.der */
@@ -557,7 +569,7 @@ static int test_msg_check_recipient_nonce(void)
     };
 
     SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
-    setup_check_update(&fixture, 1, allow_unprotected, 1, NULL, rec_nonce);
+    setup_check_update(&fixture, 1, allow_unprotected, 1, ir_rmprotection, NULL, rec_nonce);
     EXECUTE_TEST(execute_msg_check_test, tear_down);
     return result;
 }
@@ -566,12 +578,23 @@ static int test_msg_check_recipient_nonce(void)
 static int test_msg_check_recipient_nonce_bad(void)
 {
     SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
-    setup_check_update(&fixture, 0, allow_unprotected, 1, NULL, rand_data);
+    setup_check_update(&fixture, 0, allow_unprotected, 1, ir_rmprotection, NULL, rand_data);
     EXECUTE_TEST(execute_msg_check_test, tear_down);
     return result;
 }
 #endif
 
+/* Transaction id belonging to error_protected.der not needed here: */
+/* 0x5D, 0x90, 0x14, 0xB4, 0xBA, 0xAD, 0x6F, 0xCC, 0x36, 0x7B, 0xB8, 0x09, 0xB6, 0x98, 0xBF, 0x21 */
+static int test_msg_check_recipient_nonce_error(void)
+{
+    SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up);
+    (void)OSSL_CMP_CTX_set_option(fixture->cmp_ctx, OSSL_CMP_OPT_NONMATCHED_ERROR_NONCES, 1);
+    setup_check_update(&fixture, 1, allow_unprotected, 1, error_protected, NULL, rand_data);
+    EXECUTE_TEST(execute_msg_check_test, tear_down);
+    return result;
+}
+
 void cleanup_tests(void)
 {
     X509_free(srvcert);
@@ -584,6 +607,7 @@ void cleanup_tests(void)
     X509_free(instaca_cert);
     OSSL_CMP_MSG_free(ir_unprotected);
     OSSL_CMP_MSG_free(ir_rmprotection);
+    OSSL_CMP_MSG_free(error_protected);
     OSSL_PROVIDER_unload(default_null_provider);
     OSSL_PROVIDER_unload(provider);
     OSSL_LIB_CTX_free(libctx);
@@ -595,6 +619,7 @@ void cleanup_tests(void)
               "Root_CA.crt Intermediate_CA.crt "              \
               "CMP_IR_protected.der CMP_IR_unprotected.der "  \
               "IP_waitingStatus_PBM.der IR_rmprotection.der " \
+              "error_protected.der "                          \
               "insta.cert.pem insta_ca.cert.pem "             \
               "IR_protected_0_extraCerts.der "                \
               "IR_protected_2_extraCerts.der module_name [module_conf_file]\n"
@@ -628,15 +653,16 @@ int setup_tests(void)
         || !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_ptr(error_protected_f = test_get_argument(10))
+        || !TEST_ptr(instacert_f = test_get_argument(11))
+        || !TEST_ptr(instaca_f = test_get_argument(12))
+        || !TEST_ptr(ir_protected_0_extracerts = test_get_argument(13))
+        || !TEST_ptr(ir_protected_2_extracerts = test_get_argument(14))) {
         TEST_error("usage: cmp_vfy_test %s", USAGE);
         return 0;
     }
 
-    if (!test_arg_libctx(&libctx, &default_null_provider, &provider, 14, USAGE))
+    if (!test_arg_libctx(&libctx, &default_null_provider, &provider, 15, USAGE))
         return 0;
 
     /* Load certificates for cert chain */
@@ -657,8 +683,8 @@ int setup_tests(void)
     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, libctx))
-        || !TEST_ptr(ir_rmprotection = load_pkimsg(ir_rmprotection_f,
-                         libctx)))
+        || !TEST_ptr(ir_rmprotection = load_pkimsg(ir_rmprotection_f, libctx))
+        || !TEST_ptr(error_protected = load_pkimsg(error_protected_f, libctx)))
         goto err;
 
     /* Message validation tests */
@@ -708,10 +734,12 @@ int setup_tests(void)
 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
     ADD_TEST(test_msg_check_transaction_id_bad);
 #endif
+    ADD_TEST(test_msg_check_transaction_id_error);
     ADD_TEST(test_msg_check_recipient_nonce);
 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
     ADD_TEST(test_msg_check_recipient_nonce_bad);
 #endif
+    ADD_TEST(test_msg_check_recipient_nonce_error);
 
     return 1;
 
index f722800e2765de392ed2a311c16180bf53792363..7cfeb4cc05cbd74236f1625567011fce2f2d56f3 100644 (file)
@@ -37,6 +37,7 @@ my @basic_cmd = ("cmp_vfy_test",
                  data_file("IR_unprotected.der"),
                  data_file("IP_waitingStatus_PBM.der"),
                  data_file("IR_rmprotection.der"),
+                 data_file("error_protected.der"),
                  data_file("insta.cert.pem"),
                  data_file("insta_ca.cert.pem"),
                  data_file("IR_protected_0_extraCerts.der"),
diff --git a/test/recipes/65-test_cmp_vfy_data/error_protected.der b/test/recipes/65-test_cmp_vfy_data/error_protected.der
new file mode 100644 (file)
index 0000000..26af9f0
Binary files /dev/null and b/test/recipes/65-test_cmp_vfy_data/error_protected.der differ