]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
CMP: add support for genm with rootCaCert and genp with rootCaKeyUpdate
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Sat, 17 Sep 2022 08:56:21 +0000 (10:56 +0200)
committerPauli <pauli@openssl.org>
Sun, 16 Jul 2023 22:48:36 +0000 (08:48 +1000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21129)

22 files changed:
apps/cmp.c
apps/include/cmp_mock_srv.h
apps/lib/cmp_mock_srv.c
crypto/cmp/cmp_asn.c
crypto/cmp/cmp_err.c
crypto/cmp/cmp_genm.c
crypto/cmp/cmp_local.h
crypto/err/openssl.txt
doc/internal/man3/ossl_cmp_mock_srv_new.pod
doc/man1/openssl-cmp.pod.in
doc/man3/OSSL_CMP_ITAV_new_caCerts.pod
doc/man3/OSSL_CMP_exec_certreq.pod
include/openssl/cmp.h.in
include/openssl/cmperr.h
test/recipes/80-test_cmp_http.t
test/recipes/80-test_cmp_http_data/Mock/newWithNew.pem [new file with mode: 0644]
test/recipes/80-test_cmp_http_data/Mock/newWithOld.pem [new file with mode: 0644]
test/recipes/80-test_cmp_http_data/Mock/oldWithNew.pem [new file with mode: 0644]
test/recipes/80-test_cmp_http_data/Mock/oldWithOld.pem [new file with mode: 0644]
test/recipes/80-test_cmp_http_data/Mock/server.cnf
test/recipes/80-test_cmp_http_data/test_commands.csv
util/libcrypto.num

index d56a5e451cba0e0399aeeddaf38c272a5a420252..dbc609a2e00375ad2cedf87ae390aa626d3a913a 100644 (file)
@@ -89,6 +89,10 @@ static int opt_unprotected_errors = 0;
 static char *opt_srvcertout = NULL;
 static char *opt_extracertsout = NULL;
 static char *opt_cacertsout = NULL;
 static char *opt_srvcertout = NULL;
 static char *opt_extracertsout = NULL;
 static char *opt_cacertsout = NULL;
+static char *opt_oldwithold = NULL;
+static char *opt_newwithnew = NULL;
+static char *opt_newwithold = NULL;
+static char *opt_oldwithnew = NULL;
 
 /* client authentication */
 static char *opt_ref = NULL;
 
 /* client authentication */
 static char *opt_ref = NULL;
@@ -181,6 +185,10 @@ static char *opt_ref_cert = NULL;
 static char *opt_rsp_cert = NULL;
 static char *opt_rsp_extracerts = NULL;
 static char *opt_rsp_capubs = NULL;
 static char *opt_rsp_cert = NULL;
 static char *opt_rsp_extracerts = NULL;
 static char *opt_rsp_capubs = NULL;
+static char *opt_rsp_newwithnew = NULL;
+static char *opt_rsp_newwithold = NULL;
+static char *opt_rsp_oldwithnew = NULL;
+
 static int opt_poll_count = 0;
 static int opt_check_after = 1;
 static int opt_grant_implicitconf = 0;
 static int opt_poll_count = 0;
 static int opt_check_after = 1;
 static int opt_grant_implicitconf = 0;
@@ -224,6 +232,7 @@ typedef enum OPTION_choice {
     OPT_EXPECT_SENDER,
     OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS,
     OPT_SRVCERTOUT, OPT_EXTRACERTSOUT, OPT_CACERTSOUT,
     OPT_EXPECT_SENDER,
     OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS,
     OPT_SRVCERTOUT, OPT_EXTRACERTSOUT, OPT_CACERTSOUT,
+    OPT_OLDWITHOLD, OPT_NEWWITHNEW, OPT_NEWWITHOLD, OPT_OLDWITHNEW,
 
     OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS,
     OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
 
     OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS,
     OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
@@ -254,6 +263,7 @@ typedef enum OPTION_choice {
     OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS,
     OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED,
     OPT_REF_CERT, OPT_RSP_CERT, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
     OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS,
     OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED,
     OPT_REF_CERT, OPT_RSP_CERT, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
+    OPT_RSP_NEWWITHNEW, OPT_RSP_NEWWITHOLD, OPT_RSP_OLDWITHNEW,
     OPT_POLL_COUNT, OPT_CHECK_AFTER,
     OPT_GRANT_IMPLICITCONF,
     OPT_PKISTATUS, OPT_FAILURE,
     OPT_POLL_COUNT, OPT_CHECK_AFTER,
     OPT_GRANT_IMPLICITCONF,
     OPT_PKISTATUS, OPT_FAILURE,
@@ -278,7 +288,9 @@ const OPTIONS cmp_options[] = {
     OPT_SECTION("Generic message"),
     {"cmd", OPT_CMD, 's', "CMP request to send: ir/cr/kur/p10cr/rr/genm"},
     {"infotype", OPT_INFOTYPE, 's',
     OPT_SECTION("Generic message"),
     {"cmd", OPT_CMD, 's', "CMP request to send: ir/cr/kur/p10cr/rr/genm"},
     {"infotype", OPT_INFOTYPE, 's',
-     "InfoType name for requesting specific info in genm, e.g. 'caCerts'"},
+     "InfoType name for requesting specific info in genm, with specific support"},
+    {OPT_MORE_STR, 0, 0,
+     "for 'caCerts' and 'rootCaCert'"},
     {"geninfo", OPT_GENINFO, 's',
      "generalInfo integer values to place in request PKIHeader with given OID"},
     {OPT_MORE_STR, 0, 0,
     {"geninfo", OPT_GENINFO, 's',
      "generalInfo integer values to place in request PKIHeader with given OID"},
     {OPT_MORE_STR, 0, 0,
@@ -399,6 +411,14 @@ const OPTIONS cmp_options[] = {
      "File to save extra certificates received in the extraCerts field"},
     {"cacertsout", OPT_CACERTSOUT, 's',
      "File to save CA certs received in caPubs field or genp with id-it-caCerts"},
      "File to save extra certificates received in the extraCerts field"},
     {"cacertsout", OPT_CACERTSOUT, 's',
      "File to save CA certs received in caPubs field or genp with id-it-caCerts"},
+    { "oldwithold", OPT_OLDWITHOLD, 's',
+      "Root CA certificate to request update for in genm of type rootCaCert"},
+    { "newwithnew", OPT_NEWWITHNEW, 's',
+      "File to save NewWithNew cert received in genp of type rootCaKeyUpdate"},
+    { "newwithold", OPT_NEWWITHOLD, 's',
+      "File to save NewWithOld cert received in genp of type rootCaKeyUpdate"},
+    { "oldwithnew", OPT_OLDWITHNEW, 's',
+      "File to save OldWithNew cert received in genp of type rootCaKeyUpdate"},
 
     OPT_SECTION("Client authentication"),
     {"ref", OPT_REF, 's',
 
     OPT_SECTION("Client authentication"),
     {"ref", OPT_REF, 's',
@@ -517,6 +537,12 @@ const OPTIONS cmp_options[] = {
      "Extra certificates to be included in mock certification responses"},
     {"rsp_capubs", OPT_RSP_CAPUBS, 's',
      "CA certificates to be included in mock ip response"},
      "Extra certificates to be included in mock certification responses"},
     {"rsp_capubs", OPT_RSP_CAPUBS, 's',
      "CA certificates to be included in mock ip response"},
+    {"rsp_newwithnew", OPT_RSP_NEWWITHNEW, 's',
+     "New root CA certificate to include in genp of type rootCaKeyUpdate"},
+    {"rsp_newwithold", OPT_RSP_NEWWITHOLD, 's',
+     "NewWithOld transition cert to include in genp of type rootCaKeyUpdate"},
+    {"rsp_oldwithnew", OPT_RSP_OLDWITHNEW, 's',
+     "OldWithNew transition cert to include in genp of type rootCaKeyUpdate"},
     {"poll_count", OPT_POLL_COUNT, 'N',
      "Number of times the client must poll before receiving a certificate"},
     {"check_after", OPT_CHECK_AFTER, 'N',
     {"poll_count", OPT_POLL_COUNT, 'N',
      "Number of times the client must poll before receiving a certificate"},
     {"check_after", OPT_CHECK_AFTER, 'N',
@@ -584,6 +610,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {&opt_expect_sender},
     {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors},
     {&opt_srvcertout}, {&opt_extracertsout}, {&opt_cacertsout},
     {&opt_expect_sender},
     {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors},
     {&opt_srvcertout}, {&opt_extracertsout}, {&opt_cacertsout},
+    {&opt_oldwithold}, {&opt_newwithnew}, {&opt_newwithold}, {&opt_oldwithnew},
 
     {&opt_ref}, {&opt_secret},
     {&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
 
     {&opt_ref}, {&opt_secret},
     {&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
@@ -614,6 +641,8 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {&opt_srv_cert}, {&opt_srv_key}, {&opt_srv_keypass},
     {&opt_srv_trusted}, {&opt_srv_untrusted},
     {&opt_ref_cert}, {&opt_rsp_cert}, {&opt_rsp_extracerts}, {&opt_rsp_capubs},
     {&opt_srv_cert}, {&opt_srv_key}, {&opt_srv_keypass},
     {&opt_srv_trusted}, {&opt_srv_untrusted},
     {&opt_ref_cert}, {&opt_rsp_cert}, {&opt_rsp_extracerts}, {&opt_rsp_capubs},
+    {&opt_rsp_newwithnew}, {&opt_rsp_newwithold}, {&opt_rsp_oldwithnew},
+
     {(char **)&opt_poll_count}, {(char **)&opt_check_after},
     {(char **)&opt_grant_implicitconf},
     {(char **)&opt_pkistatus}, {(char **)&opt_failure},
     {(char **)&opt_poll_count}, {(char **)&opt_check_after},
     {(char **)&opt_grant_implicitconf},
     {(char **)&opt_pkistatus}, {(char **)&opt_failure},
@@ -929,8 +958,23 @@ static X509_STORE *load_trusted(char *input, int for_new_cert, const char *desc)
     return NULL;
 }
 
     return NULL;
 }
 
-typedef int (*add_X509_stack_fn_t)(void *ctx, const STACK_OF(X509) *certs);
+typedef int (*add_X509_fn_t)(void *ctx, const X509 *cert);
+static int setup_cert(void *ctx, const char *file, const char *pass,
+                      const char *desc, add_X509_fn_t set1_fn)
+{
+    X509 *cert;
+    int ok;
+
+    if (file == NULL)
+        return 1;
+    if ((cert = load_cert_pwd(file, pass, desc)) == NULL)
+        return 0;
+    ok = (*set1_fn)(ctx, cert);
+    X509_free(cert);
+    return ok;
+}
 
 
+typedef int (*add_X509_stack_fn_t)(void *ctx, const STACK_OF(X509) *certs);
 static int setup_certs(char *files, const char *desc, void *ctx,
                        add_X509_stack_fn_t set1_fn)
 {
 static int setup_certs(char *files, const char *desc, void *ctx,
                        add_X509_stack_fn_t set1_fn)
 {
@@ -1043,16 +1087,10 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
         CMP_err("must give both -srv_cert and -srv_key options or neither");
         goto err;
     }
         CMP_err("must give both -srv_cert and -srv_key options or neither");
         goto err;
     }
-    if (opt_srv_cert != NULL) {
-        X509 *srv_cert = load_cert_pwd(opt_srv_cert, opt_srv_keypass,
-                                       "certificate of the mock server");
-
-        if (srv_cert == NULL || !OSSL_CMP_CTX_set1_cert(ctx, srv_cert)) {
-            X509_free(srv_cert);
-            goto err;
-        }
-        X509_free(srv_cert);
-    }
+    if (!setup_cert(ctx, opt_srv_cert, opt_srv_keypass,
+                    "signer certificate of the mock server",
+                    (add_X509_fn_t)OSSL_CMP_CTX_set1_cert))
+        goto err;
     if (opt_srv_key != NULL) {
         EVP_PKEY *pkey = load_key_pwd(opt_srv_key, opt_keyform,
                                       opt_srv_keypass,
     if (opt_srv_key != NULL) {
         EVP_PKEY *pkey = load_key_pwd(opt_srv_key, opt_keyform,
                                       opt_srv_keypass,
@@ -1082,31 +1120,17 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
                      (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted))
         goto err;
 
                      (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted))
         goto err;
 
-    if (opt_ref_cert != NULL) {
-        X509 *cert = load_cert_pwd(opt_ref_cert, opt_keypass,
-                                   "reference cert to be expected by the mock server");
-
-        if (cert == NULL)
-            goto err;
-        if (!ossl_cmp_mock_srv_set1_refCert(srv_ctx, cert)) {
-            X509_free(cert);
+    if (!setup_cert(srv_ctx, opt_ref_cert, opt_otherpass,
+                    "reference cert to be expected by the mock server",
+                    (add_X509_fn_t)ossl_cmp_mock_srv_set1_refCert))
             goto err;
             goto err;
-        }
-        X509_free(cert);
-    }
     if (opt_rsp_cert == NULL) {
         CMP_warn("no -rsp_cert given for mock server");
     } else {
     if (opt_rsp_cert == NULL) {
         CMP_warn("no -rsp_cert given for mock server");
     } else {
-        X509 *cert = load_cert_pwd(opt_rsp_cert, opt_keypass,
-                                   "cert to be returned by the mock server");
-
-        if (cert == NULL)
-            goto err;
-        if (!ossl_cmp_mock_srv_set1_certOut(srv_ctx, cert)) {
-            X509_free(cert);
+        if (!setup_cert(srv_ctx, opt_rsp_cert, opt_keypass,
+                        "cert the mock server returns on certificate requests",
+                        (add_X509_fn_t)ossl_cmp_mock_srv_set1_certOut))
             goto err;
             goto err;
-        }
-        X509_free(cert);
     }
     if (!setup_certs(opt_rsp_extracerts,
                      "CMP extra certificates for mock server", srv_ctx,
     }
     if (!setup_certs(opt_rsp_extracerts,
                      "CMP extra certificates for mock server", srv_ctx,
@@ -1115,6 +1139,16 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
     if (!setup_certs(opt_rsp_capubs, "caPubs for mock server", srv_ctx,
                      (add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_caPubsOut))
         goto err;
     if (!setup_certs(opt_rsp_capubs, "caPubs for mock server", srv_ctx,
                      (add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_caPubsOut))
         goto err;
+    if (!setup_cert(srv_ctx, opt_rsp_newwithnew, opt_otherpass,
+                    "NewWithNew cert the mock server returns in rootCaKeyUpdate",
+                    (add_X509_fn_t)ossl_cmp_mock_srv_set1_newWithNew)
+        || !setup_cert(srv_ctx, opt_rsp_newwithold, opt_otherpass,
+                       "NewWithOld cert the mock server returns in rootCaKeyUpdate",
+                       (add_X509_fn_t)ossl_cmp_mock_srv_set1_newWithOld)
+        || !setup_cert(srv_ctx, opt_rsp_oldwithnew, opt_otherpass,
+                       "OldWithNew cert the mock server returns in rootCaKeyUpdate",
+                       (add_X509_fn_t)ossl_cmp_mock_srv_set1_oldWithNew))
+        goto err;
     (void)ossl_cmp_mock_srv_set_pollCount(srv_ctx, opt_poll_count);
     (void)ossl_cmp_mock_srv_set_checkAfterTime(srv_ctx, opt_check_after);
     if (opt_grant_implicitconf)
     (void)ossl_cmp_mock_srv_set_pollCount(srv_ctx, opt_poll_count);
     (void)ossl_cmp_mock_srv_set_checkAfterTime(srv_ctx, opt_check_after);
     if (opt_grant_implicitconf)
@@ -1171,10 +1205,6 @@ static int setup_verification_ctx(OSSL_CMP_CTX *ctx)
         return 0;
 
     if (opt_srvcert != NULL || opt_trusted != NULL) {
         return 0;
 
     if (opt_srvcert != NULL || opt_trusted != NULL) {
-        X509 *srvcert;
-        X509_STORE *ts;
-        int ok;
-
         if (opt_srvcert != NULL) {
             if (opt_trusted != NULL) {
                 CMP_warn("-trusted option is ignored since -srvcert option is present");
         if (opt_srvcert != NULL) {
             if (opt_trusted != NULL) {
                 CMP_warn("-trusted option is ignored since -srvcert option is present");
@@ -1184,14 +1214,14 @@ static int setup_verification_ctx(OSSL_CMP_CTX *ctx)
                 CMP_warn("-recipient option is ignored since -srvcert option is present");
                 opt_recipient = NULL;
             }
                 CMP_warn("-recipient option is ignored since -srvcert option is present");
                 opt_recipient = NULL;
             }
-            srvcert = load_cert_pwd(opt_srvcert, opt_otherpass,
-                                    "directly trusted CMP server certificate");
-            ok = srvcert != NULL && OSSL_CMP_CTX_set1_srvCert(ctx, srvcert);
-            X509_free(srvcert);
-            if (!ok)
+            if (!setup_cert(ctx, opt_srvcert, opt_otherpass,
+                            "directly trusted CMP server certificate",
+                            (add_X509_fn_t)OSSL_CMP_CTX_set1_srvCert))
                 return 0;
         }
         if (opt_trusted != NULL) {
                 return 0;
         }
         if (opt_trusted != NULL) {
+            X509_STORE *ts;
+
             /*
              * the 0 arg below clears any expected host/ip/email address;
              * opt_expect_sender is used instead
             /*
              * the 0 arg below clears any expected host/ip/email address;
              * opt_expect_sender is used instead
@@ -1408,7 +1438,7 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
         CMP_err("must give -ref if no -cert and no -subject given");
         return 0;
     }
         CMP_err("must give -ref if no -cert and no -subject given");
         return 0;
     }
-    if (!opt_secret && ((opt_cert == NULL) != (opt_key == NULL))) {
+    if (opt_secret == NULL && ((opt_cert == NULL) != (opt_key == NULL))) {
         CMP_err("must give both -cert and -key options or neither");
         return 0;
     }
         CMP_err("must give both -cert and -key options or neither");
         return 0;
     }
@@ -1786,22 +1816,13 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
         if (opt_cmd == CMP_GENM) {
             CMP_warn("-oldcert option is ignored for 'genm' command");
         } else {
         if (opt_cmd == CMP_GENM) {
             CMP_warn("-oldcert option is ignored for 'genm' command");
         } else {
-            X509 *oldcert = load_cert_pwd(opt_oldcert, opt_keypass,
-                                          opt_cmd == CMP_KUR ?
-                                          "certificate to be updated" :
-                                          opt_cmd == CMP_RR ?
-                                          "certificate to be revoked" :
-                                          "reference certificate (oldcert)");
-            /* opt_keypass needed if opt_oldcert is an encrypted PKCS#12 file */
-
-            if (oldcert == NULL)
-                return 0;
-            if (!OSSL_CMP_CTX_set1_oldCert(ctx, oldcert)) {
-                X509_free(oldcert);
-                CMP_err("out of memory");
+            if (!setup_cert(ctx, opt_oldcert, opt_keypass,
+                            /* needed if opt_oldcert is encrypted PKCS12 file */
+                            opt_cmd == CMP_KUR ? "certificate to be updated" :
+                            opt_cmd == CMP_RR ? "certificate to be revoked" :
+                            "reference certificate (oldcert)",
+                            (add_X509_fn_t)OSSL_CMP_CTX_set1_oldCert))
                 return 0;
                 return 0;
-            }
-            X509_free(oldcert);
         }
     }
     cleanse(opt_keypass);
         }
     }
     cleanse(opt_keypass);
@@ -1969,6 +1990,18 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
             goto err;
         }
     }
             goto err;
         }
     }
+    if (opt_cmd != CMP_GENM || opt_infotype != NID_id_it_rootCaCert) {
+        const char *msg = "option is ignored unless -cmd 'genm' and -infotype rootCaCert is given";
+
+        if (opt_oldwithold != NULL)
+            CMP_warn1("-oldwithold %s", msg);
+        if (opt_newwithnew != NULL)
+            CMP_warn1("-newwithnew %s", msg);
+        if (opt_newwithold != NULL)
+            CMP_warn1("-newwithold %s", msg);
+        if (opt_oldwithnew != NULL)
+            CMP_warn1("-oldwithnew %s", msg);
+    }
 
     if (!setup_verification_ctx(ctx))
         goto err;
 
     if (!setup_verification_ctx(ctx))
         goto err;
@@ -2549,6 +2582,18 @@ static int get_opts(int argc, char **argv)
         case OPT_CACERTSOUT:
             opt_cacertsout = opt_str();
             break;
         case OPT_CACERTSOUT:
             opt_cacertsout = opt_str();
             break;
+        case OPT_OLDWITHOLD:
+            opt_oldwithold = opt_str();
+            break;
+        case OPT_NEWWITHNEW:
+            opt_newwithnew = opt_str();
+            break;
+        case OPT_NEWWITHOLD:
+            opt_newwithold = opt_str();
+            break;
+        case OPT_OLDWITHNEW:
+            opt_oldwithnew = opt_str();
+            break;
 
         case OPT_V_CASES:
             if (!opt_verify(o, vpm))
 
         case OPT_V_CASES:
             if (!opt_verify(o, vpm))
@@ -2727,6 +2772,15 @@ static int get_opts(int argc, char **argv)
         case OPT_RSP_CAPUBS:
             opt_rsp_capubs = opt_str();
             break;
         case OPT_RSP_CAPUBS:
             opt_rsp_capubs = opt_str();
             break;
+        case OPT_RSP_NEWWITHNEW:
+            opt_rsp_newwithnew = opt_str();
+            break;
+        case OPT_RSP_NEWWITHOLD:
+            opt_rsp_newwithold = opt_str();
+            break;
+        case OPT_RSP_OLDWITHNEW:
+            opt_rsp_oldwithnew = opt_str();
+            break;
         case OPT_POLL_COUNT:
             opt_poll_count = opt_int_arg();
             break;
         case OPT_POLL_COUNT:
             opt_poll_count = opt_int_arg();
             break;
@@ -2905,6 +2959,49 @@ static int do_genm(OSSL_CMP_CTX *ctx)
             return 0;
         }
         return 1;
             return 0;
         }
         return 1;
+    } else if (opt_infotype == NID_id_it_rootCaCert) {
+        X509 *oldwithold = NULL;
+        X509 *newwithnew = NULL;
+        X509 *newwithold = NULL;
+        X509 *oldwithnew = NULL;
+        int res = 0;
+
+        if (opt_newwithnew == NULL) {
+            CMP_err("Missing -newwithnew option for -infotype rootCaCert");
+            return 0;
+        }
+        if (opt_oldwithold == NULL) {
+            CMP_warn("No -oldwithold given, will use all certs given with -trusted as trust anchors for verifying the newWithNew cert");
+        } else {
+            oldwithold = load_cert_pwd(opt_oldwithold, opt_otherpass,
+                                       "OldWithOld cert for genm with -infotype rootCaCert");
+            if (oldwithold == NULL)
+                goto end_upd;
+        }
+        if (!OSSL_CMP_get1_rootCaKeyUpdate(ctx, oldwithold, &newwithnew,
+                                           &newwithold, &oldwithnew))
+            goto end_upd;
+        /* At this point might check authorization of response sender/origin */
+
+        if (newwithnew == NULL)
+            CMP_info("no root CA certificate update available");
+        else if (oldwithold == NULL && oldwithnew != NULL)
+            CMP_warn("oldWithNew certificate received in genp for verifying oldWithOld, but oldWithOld was not provided");
+
+        if (save_cert_or_delete(newwithnew, opt_newwithnew,
+                                "NewWithNew cert from genp")
+            && save_cert_or_delete(newwithold, opt_newwithold,
+                                   "NewWithOld cert from genp")
+            && save_cert_or_delete(oldwithnew, opt_oldwithnew,
+                                   "OldWithNew cert from genp"))
+            res = 1;
+
+        X509_free(newwithnew);
+        X509_free(newwithold);
+        X509_free(oldwithnew);
+    end_upd:
+        X509_free(oldwithold);
+        return res;
     } else {
         OSSL_CMP_ITAV *req;
         STACK_OF(OSSL_CMP_ITAV) *itavs;
     } else {
         OSSL_CMP_ITAV *req;
         STACK_OF(OSSL_CMP_ITAV) *itavs;
index 68a83568570d662ec83a30ff38dab73c6628990d..6308ab93dac31b47084cfdf213034c00f3ba4c80 100644 (file)
@@ -26,6 +26,9 @@ int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
                                     STACK_OF(X509) *chain);
 int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
                                      STACK_OF(X509) *caPubs);
                                     STACK_OF(X509) *chain);
 int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
                                      STACK_OF(X509) *caPubs);
+int ossl_cmp_mock_srv_set1_newWithNew(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
+int ossl_cmp_mock_srv_set1_newWithOld(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
+int ossl_cmp_mock_srv_set1_oldWithNew(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
 int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
                                      int fail_info, const char *text);
 int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype);
 int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
                                      int fail_info, const char *text);
 int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype);
index e4c30e4438be1af6947e6bac58ba1eb3370f8b1c..f0ef2317db8a4c5f001033f8355c20400877f156 100644 (file)
@@ -22,6 +22,9 @@ typedef struct
     X509 *certOut;             /* certificate to be returned in cp/ip/kup msg */
     STACK_OF(X509) *chainOut;  /* chain of certOut to add to extraCerts field */
     STACK_OF(X509) *caPubsOut; /* used in caPubs of ip and in caCerts of genp */
     X509 *certOut;             /* certificate to be returned in cp/ip/kup msg */
     STACK_OF(X509) *chainOut;  /* chain of certOut to add to extraCerts field */
     STACK_OF(X509) *caPubsOut; /* used in caPubs of ip and in caCerts of genp */
+    X509 *newWithNew;          /* to return in newWithNew of rootKeyUpdate */
+    X509 *newWithOld;          /* to return in newWithOld of rootKeyUpdate */
+    X509 *oldWithNew;          /* to return in oldWithNew of rootKeyUpdate */
     OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */
     int sendError;             /* send error response on given request type */
     OSSL_CMP_MSG *certReq;     /* ir/cr/p10cr/kur remembered while polling */
     OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */
     int sendError;             /* send error response on given request type */
     OSSL_CMP_MSG *certReq;     /* ir/cr/p10cr/kur remembered while polling */
@@ -63,37 +66,26 @@ static mock_srv_ctx *mock_srv_ctx_new(void)
     return NULL;
 }
 
     return NULL;
 }
 
-int ossl_cmp_mock_srv_set1_refCert(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert)
-{
-    mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
-
-    if (ctx == NULL) {
-        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
-        return 0;
-    }
-    if (cert == NULL || X509_up_ref(cert)) {
-        X509_free(ctx->refCert);
-        ctx->refCert = cert;
-        return 1;
+#define DEFINE_OSSL_SET1_CERT(FIELD) \
+    int ossl_cmp_mock_srv_set1_##FIELD(OSSL_CMP_SRV_CTX *srv_ctx, \
+                                       X509 *cert) \
+    { \
+        mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); \
+ \
+        if (ctx == NULL) { \
+            ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+            return 0; \
+        } \
+        if (cert == NULL || X509_up_ref(cert)) { \
+            X509_free(ctx->FIELD); \
+            ctx->FIELD = cert; \
+            return 1; \
+        } \
+        return 0; \
     }
     }
-    return 0;
-}
 
 
-int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert)
-{
-    mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
-
-    if (ctx == NULL) {
-        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
-        return 0;
-    }
-    if (cert == NULL || X509_up_ref(cert)) {
-        X509_free(ctx->certOut);
-        ctx->certOut = cert;
-        return 1;
-    }
-    return 0;
-}
+DEFINE_OSSL_SET1_CERT(refCert)
+DEFINE_OSSL_SET1_CERT(certOut)
 
 int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
                                     STACK_OF(X509) *chain)
 
 int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
                                     STACK_OF(X509) *chain)
@@ -129,6 +121,10 @@ int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
     return 1;
 }
 
     return 1;
 }
 
+DEFINE_OSSL_SET1_CERT(newWithNew)
+DEFINE_OSSL_SET1_CERT(newWithOld)
+DEFINE_OSSL_SET1_CERT(oldWithNew)
+
 int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
                                      int fail_info, const char *text)
 {
 int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
                                      int fail_info, const char *text)
 {
@@ -212,6 +208,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
                                             STACK_OF(X509) **caPubs)
 {
     mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
                                             STACK_OF(X509) **caPubs)
 {
     mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+    int bodytype;
     OSSL_CMP_PKISI *si = NULL;
 
     if (ctx == NULL || cert_req == NULL
     OSSL_CMP_PKISI *si = NULL;
 
     if (ctx == NULL || cert_req == NULL
@@ -219,8 +216,8 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
         ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
         return NULL;
     }
         ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
         return NULL;
     }
-    if (ctx->sendError == 1
-            || ctx->sendError == OSSL_CMP_MSG_get_bodytype(cert_req)) {
+    bodytype = OSSL_CMP_MSG_get_bodytype(cert_req);
+    if (ctx->sendError == 1 || ctx->sendError == bodytype) {
         ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
         return NULL;
     }
         ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
         return NULL;
     }
@@ -245,7 +242,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
         ctx->curr_pollCount = 0;
 
     /* accept cert update request only for the reference cert, if given */
         ctx->curr_pollCount = 0;
 
     /* accept cert update request only for the reference cert, if given */
-    if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_KUR
+    if (bodytype == OSSL_CMP_KUR
             && crm != NULL /* thus not p10cr */ && ctx->refCert != NULL) {
         const OSSL_CRMF_CERTID *cid = OSSL_CRMF_MSG_get0_regCtrl_oldCertID(crm);
 
             && crm != NULL /* thus not p10cr */ && ctx->refCert != NULL) {
         const OSSL_CRMF_CERTID *cid = OSSL_CRMF_MSG_get0_regCtrl_oldCertID(crm);
 
@@ -268,7 +265,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
     if (ctx->chainOut != NULL
             && (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL)
         goto err;
     if (ctx->chainOut != NULL
             && (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL)
         goto err;
-    if (ctx->caPubsOut != NULL
+    if (ctx->caPubsOut != NULL /* OSSL_CMP_PKIBODY_IP not visible here */
             && (*caPubs = X509_chain_up_ref(ctx->caPubsOut)) == NULL)
         goto err;
     if (ctx->statusOut != NULL
             && (*caPubs = X509_chain_up_ref(ctx->caPubsOut)) == NULL)
         goto err;
     if (ctx->statusOut != NULL
@@ -314,6 +311,26 @@ static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
     return OSSL_CMP_PKISI_dup(ctx->statusOut);
 }
 
     return OSSL_CMP_PKISI_dup(ctx->statusOut);
 }
 
+static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
+                                        const OSSL_CMP_ITAV *req)
+{
+    OSSL_CMP_ITAV *rsp;
+
+    switch (req_nid) {
+    case NID_id_it_caCerts:
+        rsp = OSSL_CMP_ITAV_new_caCerts(ctx->caPubsOut);
+        break;
+    case NID_id_it_rootCaCert:
+        rsp = OSSL_CMP_ITAV_new_rootCaKeyUpdate(ctx->newWithNew,
+                                                ctx->newWithOld,
+                                                ctx->oldWithNew);
+        break;
+    default:
+        rsp = OSSL_CMP_ITAV_dup(req);
+    }
+    return rsp;
+}
+
 static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
                         const OSSL_CMP_MSG *genm,
                         const STACK_OF(OSSL_CMP_ITAV) *in,
 static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
                         const OSSL_CMP_MSG *genm,
                         const STACK_OF(OSSL_CMP_ITAV) *in,
@@ -335,16 +352,13 @@ static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
         OSSL_CMP_ITAV *req = sk_OSSL_CMP_ITAV_value(in, 0), *rsp;
         ASN1_OBJECT *obj = OSSL_CMP_ITAV_get0_type(req);
 
         OSSL_CMP_ITAV *req = sk_OSSL_CMP_ITAV_value(in, 0), *rsp;
         ASN1_OBJECT *obj = OSSL_CMP_ITAV_get0_type(req);
 
-        if (OBJ_obj2nid(obj) == NID_id_it_caCerts) {
-            if ((*out = sk_OSSL_CMP_ITAV_new_reserve(NULL, 1)) == NULL)
-                return 0;
-            if ((rsp = OSSL_CMP_ITAV_new_caCerts(ctx->caPubsOut)) == NULL) {
-                sk_OSSL_CMP_ITAV_free(*out);
-                return 0;
-            }
-            (void)sk_OSSL_CMP_ITAV_push(*out, rsp);
+        if ((*out = sk_OSSL_CMP_ITAV_new_reserve(NULL, 1)) == NULL)
+            return 0;
+        rsp = process_genm_itav(ctx, OBJ_obj2nid(obj), req);
+        if (rsp != NULL && sk_OSSL_CMP_ITAV_push(*out, rsp))
             return 1;
             return 1;
-        }
+        sk_OSSL_CMP_ITAV_free(*out);
+        return 0;
     }
 
     *out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup,
     }
 
     *out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup,
index b97c8323ff6f52ca58567edfa332e36e3bb0d7f0..73bc6363e0215bf8d0feade7f34a7a2f47dfc9c3 100644 (file)
@@ -116,6 +116,11 @@ ASN1_ADB(OSSL_CMP_ITAV) = {
                                    ASN1_UTF8STRING)),
     ADB_ENTRY(NID_id_it_caCerts,
               ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.caCerts, X509)),
                                    ASN1_UTF8STRING)),
     ADB_ENTRY(NID_id_it_caCerts,
               ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.caCerts, X509)),
+    ADB_ENTRY(NID_id_it_rootCaCert,
+              ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaCert, X509)),
+    ADB_ENTRY(NID_id_it_rootCaKeyUpdate,
+              ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaKeyUpdate,
+                       OSSL_CMP_ROOTCAKEYUPDATE)),
 } ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0,
                &infotypeandvalue_default_tt, NULL);
 
 } ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0,
                &infotypeandvalue_default_tt, NULL);
 
@@ -126,6 +131,14 @@ ASN1_SEQUENCE(OSSL_CMP_ITAV) = {
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ITAV)
 IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
 
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ITAV)
 IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
 
+ASN1_SEQUENCE(OSSL_CMP_ROOTCAKEYUPDATE) = {
+    /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+    ASN1_SIMPLE(OSSL_CMP_ROOTCAKEYUPDATE, newWithNew, X509),
+    ASN1_EXP_OPT(OSSL_CMP_ROOTCAKEYUPDATE, newWithOld, X509, 0),
+    ASN1_EXP_OPT(OSSL_CMP_ROOTCAKEYUPDATE, oldWithNew, X509, 1)
+} ASN1_SEQUENCE_END(OSSL_CMP_ROOTCAKEYUPDATE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
+
 OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value)
 {
     OSSL_CMP_ITAV *itav;
 OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value)
 {
     OSSL_CMP_ITAV *itav;
@@ -215,6 +228,84 @@ int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out)
     return 1;
 }
 
     return 1;
 }
 
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaCert(const X509 *rootCaCert)
+{
+    OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_new();
+
+    if (itav == NULL)
+        return NULL;
+    if (rootCaCert != NULL
+            && (itav->infoValue.rootCaCert = X509_dup(rootCaCert)) == NULL) {
+        OSSL_CMP_ITAV_free(itav);
+        return NULL;
+    }
+    itav->infoType = OBJ_nid2obj(NID_id_it_rootCaCert);
+    return itav;
+}
+
+int OSSL_CMP_ITAV_get0_rootCaCert(const OSSL_CMP_ITAV *itav, X509 **out)
+{
+    if (itav == NULL || out == NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    if (OBJ_obj2nid(itav->infoType) != NID_id_it_rootCaCert) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+    *out = itav->infoValue.rootCaCert;
+    return 1;
+}
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaKeyUpdate(const X509 *newWithNew,
+                                                 const X509 *newWithOld,
+                                                 const X509 *oldWithNew)
+{
+    OSSL_CMP_ITAV *itav;
+    OSSL_CMP_ROOTCAKEYUPDATE *upd = OSSL_CMP_ROOTCAKEYUPDATE_new();
+
+    if (upd == NULL)
+        return NULL;
+    if (newWithNew != NULL && (upd->newWithNew = X509_dup(newWithNew)) == NULL)
+        goto err;
+    if (newWithOld != NULL && (upd->newWithOld = X509_dup(newWithOld)) == NULL)
+        goto err;
+    if (oldWithNew != NULL && (upd->oldWithNew = X509_dup(oldWithNew)) == NULL)
+        goto err;
+    if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+        goto err;
+    itav->infoType = OBJ_nid2obj(NID_id_it_rootCaKeyUpdate);
+    itav->infoValue.rootCaKeyUpdate = upd;
+    return itav;
+
+    err:
+    OSSL_CMP_ROOTCAKEYUPDATE_free(upd);
+    return NULL;
+}
+
+int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const OSSL_CMP_ITAV *itav,
+                                       X509 **newWithNew,
+                                       X509 **newWithOld,
+                                       X509 **oldWithNew)
+{
+    OSSL_CMP_ROOTCAKEYUPDATE *upd;
+
+    if (itav == NULL || newWithNew == NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    if (OBJ_obj2nid(itav->infoType) != NID_id_it_rootCaKeyUpdate) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+    upd = itav->infoValue.rootCaKeyUpdate;
+    *newWithNew = upd->newWithNew;
+    if (newWithOld != NULL)
+        *newWithOld = upd->newWithOld;
+    if (oldWithNew != NULL)
+        *oldWithNew = upd->oldWithNew;
+    return 1;
+}
+
 /* get ASN.1 encoded integer, return -1 on error */
 int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
 {
 /* get ASN.1 encoded integer, return -1 on error */
 int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
 {
index 9d0e9680329f01e46c987007e94940a08f18756c..3853e52605969a23e4a64f87d422104a9f83cf84 100644 (file)
@@ -88,6 +88,8 @@ 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_INVALID_GENP), "invalid genp"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_GENP), "invalid genp"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ROOTCAKEYUPDATE),
+     "invalid rootcakeyupdate"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_CERTID), "missing certid"},
     {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_CERTID), "missing certid"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION),
     "missing key input for creating protection"},
index 2faeaf0d282a6b63842b96cf8455861106162075..74ac1d4b05198176fe4ab5aabac4a4239bf1e048 100644 (file)
@@ -177,3 +177,170 @@ int OSSL_CMP_get1_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out)
     OSSL_CMP_ITAV_free(itav);
     return ret;
 }
     OSSL_CMP_ITAV_free(itav);
     return ret;
 }
+
+static int selfsigned_verify_cb(int ok, X509_STORE_CTX *store_ctx)
+{
+    if (ok == 0 && store_ctx != NULL
+            && X509_STORE_CTX_get_error_depth(store_ctx) == 0
+            && X509_STORE_CTX_get_error(store_ctx)
+            == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) {
+        /* in this case, custom chain building */
+        int i;
+        STACK_OF(X509) *trust;
+        STACK_OF(X509) *chain = X509_STORE_CTX_get0_chain(store_ctx);
+        STACK_OF(X509) *untrusted = X509_STORE_CTX_get0_untrusted(store_ctx);
+        X509_STORE_CTX_check_issued_fn check_issued =
+            X509_STORE_CTX_get_check_issued(store_ctx);
+        X509 *cert = sk_X509_value(chain, 0); /* target cert */
+        X509 *issuer;
+
+        for (i = 0; i < sk_X509_num(untrusted); i++) {
+            cert = sk_X509_value(untrusted, i);
+            if (!X509_add_cert(chain, cert, X509_ADD_FLAG_UP_REF))
+                return 0;
+        }
+
+        trust = X509_STORE_get1_all_certs(X509_STORE_CTX_get0_store(store_ctx));
+        for (i = 0; i < sk_X509_num(trust); i++) {
+            issuer = sk_X509_value(trust, i);
+            if ((*check_issued)(store_ctx, cert, issuer)) {
+                if (X509_add_cert(chain, cert, X509_ADD_FLAG_UP_REF))
+                    ok = 1;
+                break;
+            }
+        }
+        sk_X509_pop_free(trust, X509_free);
+        return ok;
+    } else {
+        X509_STORE *ts = X509_STORE_CTX_get0_store(store_ctx);
+        X509_STORE_CTX_verify_cb verify_cb;
+
+        if (ts == NULL || (verify_cb = X509_STORE_get_verify_cb(ts)) == NULL)
+            return ok;
+        return (*verify_cb)(ok, store_ctx);
+    }
+}
+
+/* vanilla X509_verify_cert() does not support self-signed certs as target */
+static int verify_ss_cert(OSSL_LIB_CTX *libctx, const char *propq,
+                          X509_STORE *ts, STACK_OF(X509) *untrusted,
+                          X509 *target)
+{
+    X509_STORE_CTX *csc = NULL;
+    int ok = 0;
+
+    if (ts == NULL || target == NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    if ((csc = X509_STORE_CTX_new_ex(libctx, propq)) == NULL
+            || !X509_STORE_CTX_init(csc, ts, target, untrusted))
+        goto err;
+    X509_STORE_CTX_set_verify_cb(csc, selfsigned_verify_cb);
+    ok = X509_verify_cert(csc) > 0;
+
+ err:
+    X509_STORE_CTX_free(csc);
+    return ok;
+}
+
+static int
+verify_ss_cert_trans(OSSL_CMP_CTX *ctx, X509 *trusted /* may be NULL */,
+                     X509 *trans /* the only untrusted cert, may be NULL */,
+                     X509 *target, const char *desc)
+{
+    X509_STORE *ts = OSSL_CMP_CTX_get0_trusted(ctx);
+    STACK_OF(X509) *untrusted = NULL;
+    int res = 0;
+
+    if (trusted != NULL) {
+        X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts);
+
+        if ((ts = X509_STORE_new()) == NULL)
+            return 0;
+        if (!X509_STORE_set1_param(ts, vpm)
+            || !X509_STORE_add_cert(ts, trusted))
+            goto err;
+    }
+
+    if (trans != NULL
+            && !ossl_x509_add_cert_new(&untrusted, trans, X509_ADD_FLAG_UP_REF))
+        goto err;
+
+    res = verify_ss_cert(OSSL_CMP_CTX_get0_libctx(ctx),
+                         OSSL_CMP_CTX_get0_propq(ctx),
+                         ts, untrusted, target);
+    if (!res)
+        ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_ROOTCAKEYUPDATE,
+                       "failed to validate %s certificate received in genp %s",
+                       desc, trusted == NULL ? "using trust store"
+                       : "with given certificate as trust anchor");
+
+ err:
+    sk_X509_pop_free(untrusted, X509_free);
+    if (trusted != NULL)
+        X509_STORE_free(ts);
+    return res;
+}
+
+int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
+                                  const X509 *oldWithOld, X509 **newWithNew,
+                                  X509 **newWithOld, X509 **oldWithNew)
+{
+    X509 *oldWithOld_copy = NULL, *my_newWithOld, *my_oldWithNew;
+    OSSL_CMP_ITAV *req, *itav;
+    int res = 0;
+
+    if (newWithNew == NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    *newWithNew = NULL;
+
+    if ((req = OSSL_CMP_ITAV_new_rootCaCert(oldWithOld)) == NULL)
+        return 0;
+    itav = get_genm_itav(ctx, req, NID_id_it_rootCaKeyUpdate, "rootCaKeyUpdate");
+    if (itav == NULL)
+        return 0;
+
+    if (!OSSL_CMP_ITAV_get0_rootCaKeyUpdate(itav, newWithNew,
+                                            &my_newWithOld, &my_oldWithNew))
+        goto end;
+
+    if (*newWithNew == NULL) /* no root CA cert update available */
+        goto end;
+    if ((oldWithOld_copy = X509_dup(oldWithOld)) == NULL && oldWithOld != NULL)
+        goto end;
+    if (!verify_ss_cert_trans(ctx, oldWithOld_copy, my_newWithOld,
+                              *newWithNew, "newWithNew")) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ROOTCAKEYUPDATE);
+        goto end;
+    }
+    if (oldWithOld != NULL && my_oldWithNew != NULL
+        && !verify_ss_cert_trans(ctx, *newWithNew, my_oldWithNew,
+                                 oldWithOld_copy, "oldWithOld")) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_INVALID_ROOTCAKEYUPDATE);
+        goto end;
+    }
+
+    if (!X509_up_ref(*newWithNew))
+        goto end;
+    if (newWithOld != NULL &&
+        (*newWithOld = my_newWithOld) != NULL && !X509_up_ref(*newWithOld))
+        goto free;
+    if (oldWithNew == NULL ||
+        (*oldWithNew = my_oldWithNew) == NULL || X509_up_ref(*oldWithNew)) {
+        res = 1;
+        goto end;
+    }
+    if (newWithOld != NULL)
+        X509_free(*newWithOld);
+ free:
+    X509_free(*newWithNew);
+
+ end:
+    OSSL_CMP_ITAV_free(itav);
+    X509_free(oldWithOld_copy);
+    return res;
+}
index 18401ddb6070761180f10c5b728fdbde5871d68b..d1035c2da965a5180c80e90a5c3e2ec00da5ccde 100644 (file)
@@ -205,6 +205,9 @@ typedef struct ossl_cmp_cakeyupdanncontent_st {
 } OSSL_CMP_CAKEYUPDANNCONTENT;
 DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT)
 
 } OSSL_CMP_CAKEYUPDANNCONTENT;
 DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT)
 
+typedef struct ossl_cmp_rootcakeyupdate_st OSSL_CMP_ROOTCAKEYUPDATE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
+
 /*-
  * declared already here as it will be used in OSSL_CMP_MSG (nested) and
  * infoType and infoValue
 /*-
  * declared already here as it will be used in OSSL_CMP_MSG (nested) and
  * infoType and infoValue
@@ -252,6 +255,10 @@ struct ossl_cmp_itav_st {
         STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue;
         /* NID_id_it_caCerts - CA Certificates */
         STACK_OF(X509) *caCerts;
         STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue;
         /* NID_id_it_caCerts - CA Certificates */
         STACK_OF(X509) *caCerts;
+        /* NID_id_it_rootCaCert - Root CA Certificate */
+        X509 *rootCaCert;
+        /* NID_id_it_rootCaKeyUpdate - Root CA Certificate Update */
+        OSSL_CMP_ROOTCAKEYUPDATE *rootCaKeyUpdate;
         /* this is to be used for so far undeclared objects */
         ASN1_TYPE *other;
     } infoValue;
         /* this is to be used for so far undeclared objects */
         ASN1_TYPE *other;
     } infoValue;
@@ -738,6 +745,21 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PROTECTEDPART)
  *   }
  */
 
  *   }
  */
 
+/*
+ * RootCaKeyUpdateContent ::= SEQUENCE {
+ *      newWithNew       CMPCertificate,
+ *      newWithOld   [0] CMPCertificate OPTIONAL,
+ *      oldWithNew   [1] CMPCertificate OPTIONAL
+ * }
+ */
+
+struct ossl_cmp_rootcakeyupdate_st {
+    X509 *newWithNew;
+    X509 *newWithOld;
+    X509 *oldWithNew;
+} /* OSSL_CMP_ROOTCAKEYUPDATE */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
+
 /* from cmp_asn.c */
 int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
 
 /* from cmp_asn.c */
 int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
 
index cbb32969428352504bef059c894918d8dca4a8a5..4b86dac55725bf4ba61207e5b9475b093606ad82 100644 (file)
@@ -235,6 +235,7 @@ CMP_R_GETTING_GENP:192:getting genp
 CMP_R_INVALID_ARGS:100:invalid args
 CMP_R_INVALID_GENP:193:invalid genp
 CMP_R_INVALID_OPTION:174:invalid option
 CMP_R_INVALID_ARGS:100:invalid args
 CMP_R_INVALID_GENP:193:invalid genp
 CMP_R_INVALID_OPTION:174:invalid option
+CMP_R_INVALID_ROOTCAKEYUPDATE:195:invalid rootcakeyupdate
 CMP_R_MISSING_CERTID:165:missing certid
 CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION:130:\
        missing key input for creating protection
 CMP_R_MISSING_CERTID:165:missing certid
 CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION:130:\
        missing key input for creating protection
index 59568c65fcf9f823275641dd2cc51c881514932f..1789fad2754c82e40c5c808eaff98caacb7d5074 100644 (file)
@@ -8,6 +8,9 @@ ossl_cmp_mock_srv_set1_refCert,
 ossl_cmp_mock_srv_set1_certOut,
 ossl_cmp_mock_srv_set1_chainOut,
 ossl_cmp_mock_srv_set1_caPubsOut,
 ossl_cmp_mock_srv_set1_certOut,
 ossl_cmp_mock_srv_set1_chainOut,
 ossl_cmp_mock_srv_set1_caPubsOut,
+ossl_cmp_mock_srv_set1_newWithNew,
+ossl_cmp_mock_srv_set1_newWithOld,
+ossl_cmp_mock_srv_set1_oldWithNew,
 ossl_cmp_mock_srv_set_statusInfo,
 ossl_cmp_mock_srv_set_sendError,
 ossl_cmp_mock_srv_set_pollCount,
 ossl_cmp_mock_srv_set_statusInfo,
 ossl_cmp_mock_srv_set_sendError,
 ossl_cmp_mock_srv_set_pollCount,
@@ -21,12 +24,15 @@ ossl_cmp_mock_srv_set_checkAfterTime
  OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq);
  void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);
 
  OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq);
  void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);
 
- int ossl_cmp_mock_srv_set1_refCert(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
- int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
+ int ossl_cmp_mock_srv_set1_refCert(OSSL_CMP_SRV_CTX *ctx, const X509 *cert);
+ int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *ctx, const X509 *cert);
  int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
  int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
-                                     STACK_OF(X509) *chain);
+                                     const STACK_OF(X509) *chain);
  int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
  int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
-                                      STACK_OF(X509) *caPubs);
+                                      const STACK_OF(X509) *caPubs);
+ int ossl_cmp_mock_srv_set1_newWithNew(OSSL_CMP_SRV_CTX *ctx, const X509 *cert);
+ int ossl_cmp_mock_srv_set1_newWithOld(OSSL_CMP_SRV_CTX *ctx, const X509 *cert);
+ int ossl_cmp_mock_srv_set1_oldWithNew(OSSL_CMP_SRV_CTX *ctx, const X509 *cert);
  int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
                                       int fail_info, const char *text);
  int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype);
  int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
                                       int fail_info, const char *text);
  int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype);
@@ -41,21 +47,30 @@ I<propq>, both of which may be NULL to select the defaults.
 
 ossl_cmp_mock_srv_free() deallocates the contexts for the CMP mock server.
 
 
 ossl_cmp_mock_srv_free() deallocates the contexts for the CMP mock server.
 
-ossl_cmp_mock_srv_set1_refCert() sets the reference certificate to be expected
-for rr messages and for any oldCertID included in kur messages.
+ossl_cmp_mock_srv_set1_refCert() sets the reference certificate (or NULL)
+to be expected for rr messages and for any oldCertID included in kur messages.
 
 
-ossl_cmp_mock_srv_set1_certOut() sets the certificate to be returned in
-cp/ip/kup messages.
+ossl_cmp_mock_srv_set1_certOut() sets the certificate (or NULL)
+to be returned in cp/ip/kup messages.
 Note that on each certificate request the mock server does not produce
 a fresh certificate but just returns the same pre-existing certificate.
 
 Note that on each certificate request the mock server does not produce
 a fresh certificate but just returns the same pre-existing certificate.
 
-ossl_cmp_mock_srv_set1_chainOut() sets the certificate chain to be added to
-the extraCerts in a cp/ip/kup message.
+ossl_cmp_mock_srv_set1_chainOut() sets the certificate chain (or NULL)
+to be added to the extraCerts in a cp/ip/kup message.
 It should be useful for the validation of the certificate given via
 ossl_cmp_mock_srv_set1_certOut().
 
 It should be useful for the validation of the certificate given via
 ossl_cmp_mock_srv_set1_certOut().
 
-ossl_cmp_mock_srv_set1_caPubsOut() sets the caPubs to be returned in an ip msg
-and the list of certificates to be returned in a genp of infoType caCerts.
+ossl_cmp_mock_srv_set1_caPubsOut() sets list of certificates (or NULL) to be
+returned in the caPubs field an ip message and in a genp of infoType caCerts.
+
+ossl_cmp_mock_srv_set1_newWithNew() sets the value (which may be NULL)
+of the newWithNew field to be returned in a genp of infoType rootCaKeyUpdate.
+
+ossl_cmp_mock_srv_set1_newWithOld() sets the value (which may be NULL)
+of the newWithOld field to be returned in a genp of infoType rootCaKeyUpdate.
+
+ossl_cmp_mock_srv_set1_oldWithNew() sets the value (which may be NULL)
+of the oldWithNew field to be returned in a genp of infoType rootCaKeyUpdate.
 
 ossl_cmp_mock_srv_set_statusInfo() sets the status info to be returned.
 
 
 ossl_cmp_mock_srv_set_statusInfo() sets the status info to be returned.
 
index 4d077175537cf6fa096f75ba71418525fd000a35..7c68385f4b768929a18a1bb7257ec65c49b91afb 100644 (file)
@@ -68,6 +68,10 @@ Server authentication options:
 [B<-srvcertout> I<filename>]
 [B<-extracertsout> I<filename>]
 [B<-cacertsout> I<filename>]
 [B<-srvcertout> I<filename>]
 [B<-extracertsout> I<filename>]
 [B<-cacertsout> I<filename>]
+[B<-oldwithold> I<filename>]
+[B<-newwithnew> I<filename>]
+[B<-newwithold> I<filename>]
+[B<-oldwithnew> I<filename>]
 
 Client authentication and protection options:
 
 
 Client authentication and protection options:
 
@@ -129,6 +133,9 @@ Mock server options:
 [B<-rsp_cert> I<filename>|I<uri>]
 [B<-rsp_extracerts> I<filenames>|I<uris>]
 [B<-rsp_capubs> I<filenames>|I<uris>]
 [B<-rsp_cert> I<filename>|I<uri>]
 [B<-rsp_extracerts> I<filenames>|I<uris>]
 [B<-rsp_capubs> I<filenames>|I<uris>]
+[B<-rsp_newwithnew> I<filename>|I<uri>]
+[B<-rsp_newwithold> I<filename>|I<uri>]
+[B<-rsp_oldwithnew> I<filename>|I<uri>]
 [B<-poll_count> I<number>]
 [B<-check_after> I<number>]
 [B<-grant_implicitconf>]
 [B<-poll_count> I<number>]
 [B<-check_after> I<number>]
 [B<-grant_implicitconf>]
@@ -237,7 +244,7 @@ ITAV B<infoType>s is printed to stdout.
 
 Set InfoType name to use for requesting specific info in B<genm>,
 e.g., C<signKeyPairTypes>.
 
 Set InfoType name to use for requesting specific info in B<genm>,
 e.g., C<signKeyPairTypes>.
-So far, there is specific support for C<caCerts>.
+So far, there is specific support for C<caCerts> and C<rootCaCert>.
 
 =item B<-geninfo> I<OID:int:N>
 
 
 =item B<-geninfo> I<OID:int:N>
 
@@ -669,6 +676,43 @@ The file where to save the list of CA certificates contained in the caPubs field
 if a positive certificate response (i.e., IP, CP, or KUP) message was received
 or contained in a general response (genp) message with infoType C<caCerts>.
 
 if a positive certificate response (i.e., IP, CP, or KUP) message was received
 or contained in a general response (genp) message with infoType C<caCerts>.
 
+=item B<-oldwithold> I<filename>
+
+The root CA certificate to include in a genm request of infoType C<rootCaCert>.
+If present and the optional oldWithNew certificate is received,
+it is verified using the newWithNew certificate as the (only) trust anchor.
+
+=item B<-newwithnew> I<filename>
+
+This option must be provided when B<-infotype> I<rootCaCert> is given.
+It specifies the file to save the newWithNew certificate
+received in a genp message of type C<rootCaKeyUpdate>.
+If on success no such cert was received, this file (if present) is deleted
+to indicate that the requested root CA certificate update is not available.
+
+Any received newWithNew certificate is verified
+using any received newWithOld certificate as untrusted intermediate certificate
+and the certificate provided with B<-oldwithold> as the (only) trust anchor,
+or if not provided, using the certificates given with the B<-trusted> option.
+
+B<WARNING:>
+The newWithNew certificate is meant to be a certificate that will be trusted.
+The trust placed in it cannot be stronger than the trust placed in
+the B<-oldwithold> certificate if present, otherwise it cannot be stronger than
+the weakest trust placed in any of the B<-trusted> certificates.
+
+=item B<-newwithold> I<filename>
+
+The file to save any newWithOld certificate
+received in a genp message of infoType C<rootCaKeyUpdate>.
+If on success no such cert was received, this is indicated by deleting the file.
+
+=item B<-oldwithnew> I<filename>
+
+The file to save any oldWithNew certificate
+received in a genp message of infoType C<rootCaKeyUpdate>.
+If on success no such cert was received, this is indicated by deleting the file.
+
 =back
 
 =head2 Client authentication options
 =back
 
 =head2 Client authentication options
@@ -803,7 +847,9 @@ See L<openssl(1)/Format Options> for details.
 
 Pass phrase source for certificate given with the B<-trusted>, B<-untrusted>,
 B<-own_trusted>, B<-srvcert>, B<-out_trusted>, B<-extracerts>,
 
 Pass phrase source for certificate given with the B<-trusted>, B<-untrusted>,
 B<-own_trusted>, B<-srvcert>, B<-out_trusted>, B<-extracerts>,
-B<-srv_trusted>, B<-srv_untrusted>, B<-rsp_extracerts>, B<-rsp_capubs>,
+B<-srv_trusted>, B<-srv_untrusted>, B<-ref_cert>, B<-rsp_cert>,
+B<-rsp_extracerts>, B<-rsp_capubs>,
+B<-rsp_newwithnew>, B<-rsp_newwithold>, B<-rsp_oldwithnew>,
 B<-tls_extra>, and B<-tls_trusted> options.
 If not given here, the password will be prompted for if needed.
 
 B<-tls_extra>, and B<-tls_trusted> options.
 If not given here, the password will be prompted for if needed.
 
@@ -1054,6 +1100,18 @@ Extra certificates to be included in mock certification responses.
 
 CA certificates to be included in mock Initialization Response (IP) message.
 
 
 CA certificates to be included in mock Initialization Response (IP) message.
 
+=item B<-rsp_newwithnew> I<filename>|I<uri>
+
+Certificate to be returned in newWithNew field of genp of type rootCaKeyUpdate.
+
+=item B<-rsp_newwithold> I<filename>|I<uri>
+
+Certificate to be returned in newWithOld field of genp of type rootCaKeyUpdate.
+
+=item B<-rsp_oldwithnew> I<filename>|I<uri>
+
+Certificate to be returned in oldWithNew field of genp of type rootCaKeyUpdate.
+
 =item B<-poll_count> I<number>
 
 Number of times the client must poll before receiving a certificate.
 =item B<-poll_count> I<number>
 
 Number of times the client must poll before receiving a certificate.
@@ -1127,9 +1185,9 @@ only affect the certificate verification enabled via the B<-out_trusted> option.
 
 =head1 NOTES
 
 
 =head1 NOTES
 
-When a client obtains from a CMP server CA certificates that it is going to
+When a client obtains, from a CMP server, CA certificates that it is going to
 trust, for instance via the C<caPubs> field of a certificate response
 trust, for instance via the C<caPubs> field of a certificate response
-or using general messages with infoType C<caCerts>,
+or using general messages with infoType C<caCerts> or C<rootCaCert>,
 authentication of the CMP server is particularly critical.
 So special care must be taken setting up server authentication
 using B<-trusted> and related options for certificate-based authentication
 authentication of the CMP server is particularly critical.
 So special care must be taken setting up server authentication
 using B<-trusted> and related options for certificate-based authentication
index eb397388aa64d38f756bedf9e4a512db716650ea..882103f4c3b54adda5a2a0d81877753b50aa9056 100644 (file)
@@ -3,7 +3,11 @@
 =head1 NAME
 
 OSSL_CMP_ITAV_new_caCerts,
 =head1 NAME
 
 OSSL_CMP_ITAV_new_caCerts,
-OSSL_CMP_ITAV_get0_caCerts
+OSSL_CMP_ITAV_get0_caCerts,
+OSSL_CMP_ITAV_new_rootCaCert,
+OSSL_CMP_ITAV_get0_rootCaCert,
+OSSL_CMP_ITAV_new_rootCaKeyUpdate,
+OSSL_CMP_ITAV_get0_rootCaKeyUpdate
 - CMP utility functions for handling specific genm and genp messages
 
 =head1 SYNOPSIS
 - CMP utility functions for handling specific genm and genp messages
 
 =head1 SYNOPSIS
@@ -13,6 +17,16 @@ OSSL_CMP_ITAV_get0_caCerts
  OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts);
  int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out);
 
  OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts);
  int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out);
 
+ OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaCert(const X509 *rootCaCert);
+ int OSSL_CMP_ITAV_get0_rootCaCert(const OSSL_CMP_ITAV *itav, X509 **out);
+ OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaKeyUpdate(const X509 *newWithNew,
+                                                  const X509 *newWithOld,
+                                                  const X509 *oldWithNew);
+ int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const OSSL_CMP_ITAV *itav,
+                                        X509 **newWithNew,
+                                        X509 **newWithOld,
+                                        X509 **oldWithNew);
+
 =head1 DESCRIPTION
 
 ITAV is short for InfoTypeAndValue.
 =head1 DESCRIPTION
 
 ITAV is short for InfoTypeAndValue.
@@ -25,17 +39,41 @@ OSSL_CMP_ITAV_get0_caCerts() requires that I<itav> has type B<caCerts>.
 It assigns NULL to I<*out> if there are no CA certificates in I<itav>, otherwise
 the internal pointer of type B<STACK_OF(X509)> with the certificates present.
 
 It assigns NULL to I<*out> if there are no CA certificates in I<itav>, otherwise
 the internal pointer of type B<STACK_OF(X509)> with the certificates present.
 
+OSSL_CMP_ITAV_new_rootCaCert() creates a new B<OSSL_CMP_ITAV> structure
+of type B<rootCaCert> that includes the optionally given certificate.
+
+OSSL_CMP_ITAV_get0_rootCaCert() requires that I<itav> has type B<rootCaCert>.
+It assigns NULL to I<*out> if no certificate is included in I<itav>, otherwise
+the internal pointer to the certificate contained in the infoValue field.
+
+OSSL_CMP_ITAV_new_rootCaKeyUpdate() creates a new B<OSSL_CMP_ITAV> structure
+of type B<rootCaKeyUpdate> that includes an RootCaKeyUpdateContent structure
+with the optional I<newWithNew>, I<newWithOld>, and I<oldWithNew> certificates.
+
+OSSL_CMP_ITAV_get0_rootCaKeyUpdate() requires that I<itav> has infoType
+B<rootCaKeyUpdate>.
+If an update of a root CA certificate is included,
+it assigns to I<*newWithNew> the internal pointer
+to the certificate contained in the newWithNew infoValue sub-field of I<itav>.
+If I<newWithOld> is not NULL, it assigns to I<*newWithOld> the internal pointer
+to the certificate contained in the newWithOld infoValue sub-field of I<itav>.
+If I<oldWithNew> is not NULL, it assigns to I<*oldWithNew> the internal pointer
+to the certificate contained in the oldWithNew infoValue sub-field of I<itav>.
+Each of these pointers will be NULL if the respective sub-field is not set.
+
 =head1 NOTES
 
 CMP is defined in RFC 4210.
 
 =head1 RETURN VALUES
 
 =head1 NOTES
 
 CMP is defined in RFC 4210.
 
 =head1 RETURN VALUES
 
-OSSL_CMP_ITAV_new_caCerts()
-returns a pointer to the new ITAV structure on success, or NULL on error.
+OSSL_CMP_ITAV_new_caCerts(),
+OSSL_CMP_ITAV_new_rootCaCert(), and OSSL_CMP_ITAV_new_rootCaKeyUpdate()
+return a pointer to the new ITAV structure on success, or NULL on error.
 
 
-OSSL_CMP_ITAV_get0_caCerts()
-returns 1 on success, 0 on error.
+OSSL_CMP_ITAV_get0_caCerts(),
+OSSL_CMP_ITAV_get0_rootCaCert(), and OSSL_CMP_ITAV_get0_rootCaKeyUpdate()
+return 1 on success, 0 on error.
 
 =head1 SEE ALSO
 
 
 =head1 SEE ALSO
 
@@ -43,8 +81,9 @@ L<OSSL_CMP_ITAV_create(3)> and L<OSSL_CMP_ITAV_get0_type(3)>
 
 =head1 HISTORY
 
 
 =head1 HISTORY
 
-OSSL_CMP_ITAV_new_caCerts() and
-OSSL_CMP_ITAV_get0_rootCaCert()
+OSSL_CMP_ITAV_new_caCerts(), OSSL_CMP_ITAV_get0_caCerts(),
+OSSL_CMP_ITAV_new_rootCaCert(), OSSL_CMP_ITAV_get0_rootCaCert(),
+OSSL_CMP_ITAV_new_rootCaKeyUpdate(), and OSSL_CMP_ITAV_get0_rootCaKeyUpdate()
 were added in OpenSSL 3.2.
 
 =head1 COPYRIGHT
 were added in OpenSSL 3.2.
 
 =head1 COPYRIGHT
index fbf118c2b16ceab5af17034aacb61f66ff013750..e752b8e270697853944649c014efa09f551986d5 100644 (file)
@@ -14,7 +14,8 @@ OSSL_CMP_KUR,
 OSSL_CMP_try_certreq,
 OSSL_CMP_exec_RR_ses,
 OSSL_CMP_exec_GENM_ses,
 OSSL_CMP_try_certreq,
 OSSL_CMP_exec_RR_ses,
 OSSL_CMP_exec_GENM_ses,
-OSSL_CMP_get1_caCerts
+OSSL_CMP_get1_caCerts,
+OSSL_CMP_get1_rootCaKeyUpdate
 - functions implementing CMP client transactions
 
 =head1 SYNOPSIS
 - functions implementing CMP client transactions
 
 =head1 SYNOPSIS
@@ -37,6 +38,9 @@ OSSL_CMP_get1_caCerts
 
  STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
  int OSSL_CMP_get1_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out);
 
  STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
  int OSSL_CMP_get1_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out);
+ int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
+                                   const X509 *oldWithOld, X509 **newWithNew,
+                                   X509 **newWithOld, X509 **oldWithNew);
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
@@ -132,6 +136,23 @@ On success it assigns to I<*out> the list of certificates received,
 which must be freed by the caller.
 NULL output means that no CA certificates were provided by the server.
 
 which must be freed by the caller.
 NULL output means that no CA certificates were provided by the server.
 
+OSSL_CMP_get1_rootCaKeyUpdate() uses a genm request message
+with infoType rootCaCert to obtain from the CMP server referenced by I<ctx>
+in a genp response message with infoType rootCaKeyUpdate any update of the
+given root CA certificate I<oldWithOld> and verifies it as far as possible.
+See RFC 4210 section 4.4 for details.
+On success it assigns to I<*newWithNew> the root certificate received.
+When the I<newWithOld> and I<oldWithNew> output parameters are not NULL,
+it assigns to them the corresponding transition certificates.
+NULL means that the respective certificate was not provided by the server.
+All certificates obtained this way must be freed by the caller.
+
+B<WARNING:>
+The I<newWithNew> certificate is meant to be a certificate that will be trusted.
+The trust placed in it cannot be stronger than the trust placed in
+the I<oldwithold> certificate if present, otherwise it cannot be stronger than
+the weakest trust in any of the certificates in the trust store of I<ctx>.
+
 =head1 NOTES
 
 CMP is defined in RFC 4210 (and CRMF in RFC 4211).
 =head1 NOTES
 
 CMP is defined in RFC 4210 (and CRMF in RFC 4211).
@@ -140,8 +161,8 @@ The CMP client implementation is limited to one request per CMP message
 (and consequently to at most one response component per CMP message).
 
 When a client obtains from a CMP server CA certificates that it is going to
 (and consequently to at most one response component per CMP message).
 
 When a client obtains from a CMP server CA certificates that it is going to
-trust, for instance via the caPubs field of a certificate response
-or using functions like OSSL_CMP_get1_caCerts(),
+trust, for instance via the caPubs field of a certificate response or using
+functions like OSSL_CMP_get1_caCerts() and OSSL_CMP_get1_rootCaKeyUpdate(),
 authentication of the CMP server is particularly critical.
 So special care must be taken setting up server authentication in I<ctx>
 using functions such as
 authentication of the CMP server is particularly critical.
 So special care must be taken setting up server authentication in I<ctx>
 using functions such as
@@ -167,7 +188,8 @@ In the latter case L<OSSL_CMP_CTX_get0_newCert(3)> yields NULL
 and the output parameter I<checkAfter> has been used to
 assign the received value unless I<checkAfter> is NULL.
 
 and the output parameter I<checkAfter> has been used to
 assign the received value unless I<checkAfter> is NULL.
 
-OSSL_CMP_exec_RR_ses() and OSSL_CMP_get1_caCerts()
+OSSL_CMP_exec_RR_ses(), OSSL_CMP_get1_caCerts(),
+and OSSL_CMP_get1_rootCaKeyUpdate()
 return 1 on success, 0 on error.
 
 OSSL_CMP_exec_GENM_ses() returns NULL on error,
 return 1 on success, 0 on error.
 
 OSSL_CMP_exec_GENM_ses() returns NULL on error,
@@ -191,7 +213,8 @@ L<OSSL_CMP_MSG_http_perform(3)>
 
 The OpenSSL CMP support was added in OpenSSL 3.0.
 
 
 The OpenSSL CMP support was added in OpenSSL 3.0.
 
-OSSL_CMP_get1_caCerts() was added in OpenSSL 3.2.
+OSSL_CMP_get1_caCerts() and OSSL_CMP_get1_rootCaKeyUpdate()
+were added in OpenSSL 3.2.
 
 =head1 COPYRIGHT
 
 
 =head1 COPYRIGHT
 
index 0e49ee9d519ed2c6b8fd868a1afc6122bb1c7d64..d7f2354b3a9740d1235b512c5c9bebbf5c8c96fb 100644 (file)
@@ -264,6 +264,16 @@ void OSSL_CMP_ITAV_free(OSSL_CMP_ITAV *itav);
 OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts);
 int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out);
 
 OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts);
 int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out);
 
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaCert(const X509 *rootCaCert);
+int OSSL_CMP_ITAV_get0_rootCaCert(const OSSL_CMP_ITAV *itav, X509 **out);
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaKeyUpdate(const X509 *newWithNew,
+                                                 const X509 *newWithOld,
+                                                 const X509 *oldWithNew);
+int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const OSSL_CMP_ITAV *itav,
+                                       X509 **newWithNew,
+                                       X509 **newWithOld,
+                                       X509 **oldWithNew);
+
 void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
 
 /* from cmp_ctx.c */
 void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
 
 /* from cmp_ctx.c */
@@ -488,6 +498,9 @@ STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
 
 /* from cmp_genm.c */
 int OSSL_CMP_get1_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out);
 
 /* from cmp_genm.c */
 int OSSL_CMP_get1_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out);
+int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
+                                  const X509 *oldWithOld, X509 **newWithNew,
+                                  X509 **newWithOld, X509 **oldWithNew);
 
 #  ifdef  __cplusplus
 }
 
 #  ifdef  __cplusplus
 }
index f4435d825d08b41f9c229b247e1c19542f09f9bf..57a6effbe3fc2db148abe0c9bec7ddeb79e27dc3 100644 (file)
@@ -63,6 +63,7 @@
 #  define CMP_R_INVALID_ARGS                               100
 #  define CMP_R_INVALID_GENP                               193
 #  define CMP_R_INVALID_OPTION                             174
 #  define CMP_R_INVALID_ARGS                               100
 #  define CMP_R_INVALID_GENP                               193
 #  define CMP_R_INVALID_OPTION                             174
+#  define CMP_R_INVALID_ROOTCAKEYUPDATE                    195
 #  define CMP_R_MISSING_CERTID                             165
 #  define CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION  130
 #  define CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE         142
 #  define CMP_R_MISSING_CERTID                             165
 #  define CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION  130
 #  define CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE         142
index 4fd03e8b2d9e5b07b21b610cb0ea7e714a921775..2695c0f28f35b5900cab2a837b7965efec7882f7 100644 (file)
@@ -26,8 +26,8 @@ plan skip_all => "These tests are not supported in a fuzz build"
 
 plan skip_all => "These tests are not supported in a no-cmp build"
     if disabled("cmp");
 
 plan skip_all => "These tests are not supported in a no-cmp build"
     if disabled("cmp");
-plan skip_all => "These tests are not supported in a no-ec build"
-    if disabled("ec");
+plan skip_all => "These tests are not supported in a no-ecx build"
+    if disabled("ecx"); # EC and EDDSA test certs, e.g., in Mock/newWithNew.pem
 plan skip_all => "These tests are not supported in a no-sock build"
     if disabled("sock");
 plan skip_all => "These tests are not supported in a no-http build"
 plan skip_all => "These tests are not supported in a no-sock build"
     if disabled("sock");
 plan skip_all => "These tests are not supported in a no-http build"
diff --git a/test/recipes/80-test_cmp_http_data/Mock/newWithNew.pem b/test/recipes/80-test_cmp_http_data/Mock/newWithNew.pem
new file mode 100644 (file)
index 0000000..1a02d19
--- /dev/null
@@ -0,0 +1,11 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC
+-----END PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIBAzCBtqADAgECAgH+MAUGAytlcDASMRAwDgYDVQQDDAdSb290IENBMCAXDTIz
+MDYwNTIwMjMwMFoYDzIxMjMwNjA1MjAyMzAwWjASMRAwDgYDVQQDDAdSb290IENB
+MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuGjLzAt
+MAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFKKMwfhuWWDT4DrnXJYsl6jUSCk8MAUG
+AytlcANBAEG62N+3Go9h1ekWyQMf1hYFQMPQF/XVP2EH1euP7mVxJt0mquGpVsm+
+qLt/W4xBKiu08Jfcv4Gxi6CjgOekGww=
+-----END CERTIFICATE-----
diff --git a/test/recipes/80-test_cmp_http_data/Mock/newWithOld.pem b/test/recipes/80-test_cmp_http_data/Mock/newWithOld.pem
new file mode 100644 (file)
index 0000000..988496c
--- /dev/null
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIICCTCB8qADAgECAhR+y2i70DQe9ryvJ8uPJO8qOMfX+zANBgkqhkiG9w0BAQsF
+ADASMRAwDgYDVQQDDAdSb290IENBMCAXDTIzMDYwNTIwMjg1N1oYDzIxMjMwNjA1
+MjAyODU3WjASMRAwDgYDVQQDDAdSb290IENBMCowBQYDK2VwAyEAGb9ECWmEzf6F
+QbrBZ9w7lshQhqowtrbLDFw4rXAxZuGjUDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0O
+BBYEFKKMwfhuWWDT4DrnXJYsl6jUSCk8MB8GA1UdIwQYMBaAFHB/Lq6DaFmYBCMq
+zes+F80k3QFJMA0GCSqGSIb3DQEBCwUAA4IBAQB6Eg6lRxiUUXMGO8l7XYJ3d49x
+YDqwt+fvaQcnwVN3kJ1GAb/0lcB6k4mt8jHizT2HKw1ZMHK7CGbHYAMKvtxML3px
+GXqeEQO2IlWU23kEyPhX/yoOG0cp9QWm4tdTvr3xCr4E4rNZJUNbSqyOCdcAs39H
+4dDBHBQrL530/XquKdXmq4fAwyKIGxNW1WTohKq9Yzd3NK+0Ku11Ny86FIzB3iks
+a8NdsE88xfBQcQMo9omZZbPQBg7YMId4zRyDFplrLWZjhoNmStmTHTX/nOYUMGm3
+75iikSsNRJl4A/ZvnZrDA2am3ihvMghVIN4IVfXrk5tHiZ/XHZuu3vetK2jp
+-----END CERTIFICATE-----
diff --git a/test/recipes/80-test_cmp_http_data/Mock/oldWithNew.pem b/test/recipes/80-test_cmp_http_data/Mock/oldWithNew.pem
new file mode 100644 (file)
index 0000000..8fa15f8
--- /dev/null
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICMjCCAeSgAwIBAgIUcaAacl/D9rcbM5ytumMvdL3J+HIwBQYDK2VwMBIxEDAO
+BgNVBAMMB1Jvb3QgQ0EwIBcNMjMwNjA1MjAyOTI0WhgPMjEyMzA2MDUyMDI5MjRa
+MBIxEDAOBgNVBAMMB1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC/mhXWzc26ztIg2Duia7kDG54SAr3uaHk9TeGBmmWJIVoRKYvaosZ4/rT2
+hez/rxcNdVbi61QsI6MuHSen7lfLeLcZENeAFnvZAN7bdaqpCqpoGVBVWbVbEb5q
+ZG1kkRZ1IiyIUG2T7x0ESUeHZZAOEM5aocYdBqtCAk/EYH3sxGExKVtPArVPkoBY
+6WqLmYlbkvq82tDtOtr9hx4fvR9TR8lg5eEHEz3Y3APVttV30Y9gVKqt2tWPX1u+
+jrdezFl257HlAetGRapPnDmaAAdoSAKpatL/rir1NH1QTCsHySJlmDeT3+Kb7MHA
+RQtNm7SvygwSSmNtOVcua3wQwGrHAgMBAAGjUDBOMAwGA1UdEwQFMAMBAf8wHQYD
+VR0OBBYEFHB/Lq6DaFmYBCMqzes+F80k3QFJMB8GA1UdIwQYMBaAFKKMwfhuWWDT
+4DrnXJYsl6jUSCk8MAUGAytlcANBAHFKIp57/EisMF84ZvOFzxnS2o8/qKsRrrh5
+w1nBOmOvavZxbtFyO9batLEWikNV0LDFIHw9g3uYmgB1VUzhcw4=
+-----END CERTIFICATE-----
diff --git a/test/recipes/80-test_cmp_http_data/Mock/oldWithOld.pem b/test/recipes/80-test_cmp_http_data/Mock/oldWithOld.pem
new file mode 100644 (file)
index 0000000..7c6db11
--- /dev/null
@@ -0,0 +1,46 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC/mhXWzc26ztIg
+2Duia7kDG54SAr3uaHk9TeGBmmWJIVoRKYvaosZ4/rT2hez/rxcNdVbi61QsI6Mu
+HSen7lfLeLcZENeAFnvZAN7bdaqpCqpoGVBVWbVbEb5qZG1kkRZ1IiyIUG2T7x0E
+SUeHZZAOEM5aocYdBqtCAk/EYH3sxGExKVtPArVPkoBY6WqLmYlbkvq82tDtOtr9
+hx4fvR9TR8lg5eEHEz3Y3APVttV30Y9gVKqt2tWPX1u+jrdezFl257HlAetGRapP
+nDmaAAdoSAKpatL/rir1NH1QTCsHySJlmDeT3+Kb7MHARQtNm7SvygwSSmNtOVcu
+a3wQwGrHAgMBAAECggEBAL4rWle8JuCuHGNbGz1nO9d41tg7fnYdnZAaN6OiMfr8
+bl+wY84aV3GKJOS2InfYOcIy340UU5QHvxOq/kwwRVV/uAOZ8rqAFmZY9djOnhdv
+rZjq3xAHnPgJ0XvZt7XkR2z1AUw+v7Pf1WYGsYcSZ/t99MKB5Je0odA/aRqZRwLy
+YflbsnAJtxdJ6fsiVCSJcU76V8sxfiCimw6ppLMEp3zCjveQ5Lv0eVoL2zNYeh+l
+GiSwqTqaR+WJekkDiXRd9KYI19drf7OkTII1DtOd6bgvKX3zv2lNiere4J4k7cAP
+rW6fBFgtSq2oklTpWUlXRH7XQAgDtDvldXdlKaj96dkCgYEA8KPSu5ywg8pjCofE
+nLtJTfVyD2g9tgNLj9dI3kuSniZU51kOtk5rZZwL0S8piGczL908aV9DIWdXWsND
+5hlXquKUTSjxPYEzZvaN+tvf9e0AcY/D/UaK0mKPjEbh7vg6pS77aZZz2EL2inOs
+dam8famOOC9RUkxH5JWa3UV4UhsCgYEAy9T0wPQctjuvDkZQTqKEKsHrmrgY2PXT
+Re8DDGI8hxjYb8l+NoFQ7eiwTHir/DULupxQoBBUQtS+idQzUu02tzLMnGcjHNwh
+Tu+vZ4xlVnXxfgIRjDKkfQjiAC5SLzoNO9Jn8g4eS/1mEPXhQ0TXIsFonZDypp/n
+RMp21DkvdMUCgYAIMgwjR5rbYjEtUqJnlBlTBmD0FWDEqigQpgxdRcWgjT2nA2l0
+3AbcVwwv+6M2eg1MPASqsgvfP13CQZQ2afaKY10Zo6NTrOrLPupm+MYP4hp5w6Ox
+JI3lzGWHKYLYWKvmpEr7tZwMaXtsC7R77WP2A6hMUZA7dU2dg1ra3lrSsQKBgQDA
+sPIsUtmtwOBtqzUSEXrGfQqA+larDEGNVDVaiKfVwzwg+aeyWS+rqRS5Rj64L2GG
+KW3i020EvN/fplZap9vY9lIN7UZ5avSmDdqRFl1ajiccy1HRarKrbTFRoHibItMN
+4YvYfVZQ2h2aHQe2Myb6OULv6e4qbPIRyyDo4aKmTQKBgQCadq2JfICFIP9Q1aQn
+93oD7Z4WcYs+KsLYO+/uJxWMrn0/gv90cGrSfstJqDOHnRq4WKUcgK9ErxaE4LkW
+sD0mBhRM3SMxnRJZRO+6roRdehtjHkvzKu75KjcsuwefoMs2sFa4CLQ1YU2vO3Tx
+dgzpnKS2bH/i5yLwhelRfddZ6Q==
+-----END PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIC8TCCAdmgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
+IENBMCAXDTE2MDExNDIyMjkwNVoYDzIxMTYwMTE1MjIyOTA1WjASMRAwDgYDVQQD
+DAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv5oV1s3N
+us7SINg7omu5AxueEgK97mh5PU3hgZpliSFaESmL2qLGeP609oXs/68XDXVW4utU
+LCOjLh0np+5Xy3i3GRDXgBZ72QDe23WqqQqqaBlQVVm1WxG+amRtZJEWdSIsiFBt
+k+8dBElHh2WQDhDOWqHGHQarQgJPxGB97MRhMSlbTwK1T5KAWOlqi5mJW5L6vNrQ
+7Tra/YceH70fU0fJYOXhBxM92NwD1bbVd9GPYFSqrdrVj19bvo63XsxZduex5QHr
+RkWqT5w5mgAHaEgCqWrS/64q9TR9UEwrB8kiZZg3k9/im+zBwEULTZu0r8oMEkpj
+bTlXLmt8EMBqxwIDAQABo1AwTjAdBgNVHQ4EFgQUcH8uroNoWZgEIyrN6z4XzSTd
+AUkwHwYDVR0jBBgwFoAUcH8uroNoWZgEIyrN6z4XzSTdAUkwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAuiLq2lhcOJHrwUP0txbHk2vy6rmGTPxqmcCo
+CUQFZ3KrvUQM+rtRqqQ0+LzU4wSTFogBz9KSMfT03gPegY3b/7L2TOaMmUFRzTdd
+c9PNT0lP8V3pNQrxp0IjKir791QkGe2Ux45iMKf/SXpeTWASp4zeMiD6/LXFzzaK
+BfNS5IrIWRDev41lFasDzudK5/kmVaMvDOFyW51KkKkqb64VS4UA81JIEzClvz+3
+Vp3k1AXup5+XnTvhqu2nRhrLpJR5w8OXQpcn6qjKlVc2BXtb3xwci1/ibHlZy3CZ
+n70e2NYihU5yYKccReP+fjLgVFsuhsDs/0hRML1u9bLp9nUbYA==
+-----END CERTIFICATE-----
index 991c1cf525fdf3681be8317138f6f00ff0b469d5..04b612cde2d078bac945b0bf378770d766a65fd1 100644 (file)
@@ -11,7 +11,11 @@ srv_trusted = signer_root.crt
 
 ref_cert = signer_only.crt
 rsp_cert = signer_only.crt
 
 ref_cert = signer_only.crt
 rsp_cert = signer_only.crt
-rsp_capubs = signer_root.crt
+rsp_capubs = trusted.crt
 rsp_extracerts = signer_issuing.crt
 
 rsp_extracerts = signer_issuing.crt
 
+rsp_newwithnew = newWithNew.pem
+rsp_newwithold = newWithOld.pem
+rsp_oldwithnew = oldWithNew.pem
+
 verbosity = 7
 verbosity = 7
index dc2e922aaaf3fd5e2f4177c4b2f81ce655ced6de..5ab2ca3fd7a61696b1b235e81f1e9dbe3a49ef59 100644 (file)
@@ -56,8 +56,26 @@ expected,description, -section,val, -cmd,val,val2, -cacertsout,val,val2, -infoty
 0,genm with missing infotype value, -section,, -cmd,genm,,BLANK,,, -infotype,,,BLANK,,BLANK,
 0,genm with invalid infotype value, -section,, -cmd,genm,,BLANK,,, -infotype,asdf,,BLANK,,BLANK,
 1,genm with infotype signKeyPairTypes, -section,, -cmd,genm,,BLANK,,, -infotype,signKeyPairTypes,,BLANK,,BLANK,
 0,genm with missing infotype value, -section,, -cmd,genm,,BLANK,,, -infotype,,,BLANK,,BLANK,
 0,genm with invalid infotype value, -section,, -cmd,genm,,BLANK,,, -infotype,asdf,,BLANK,,BLANK,
 1,genm with infotype signKeyPairTypes, -section,, -cmd,genm,,BLANK,,, -infotype,signKeyPairTypes,,BLANK,,BLANK,
-0,genm with infotype caCerts but missing -cacertsout, -section,, -cmd,genm,,BLANK,,, -infotype,caCerts,,BLANK,,BLANK,
-1,genm with infotype caCerts, -section,, -cmd,genm,, -cacertsout,_RESULT_DIR/test.cacerts.pem,, -infotype,caCerts,,BLANK,,BLANK,
+,,,,,,,,,,,,,,,,,,,,,,
+1,genm caCerts                           , -section,, -cmd,genm,, -cacertsout,_RESULT_DIR/test.cacerts.pem,, -infotype,caCerts,,BLANK,,BLANK,
+0,genm caCerts missing cacertsout option , -section,, -cmd,genm,, BLANK      ,                            ,, -infotype,caCerts,,BLANK,,BLANK,
+0,genm caCerts missing cacertsout arg    , -section,, -cmd,genm,, -cacertsout,BLANK                       ,, -infotype,caCerts,,BLANK,,BLANK,
+0,genm caCerts extra cacertsout arg      , -section,, -cmd,genm,, -cacertsout,_RESULT_DIR/test.cacerts.pem,_RESULT_DIR/test.cacerts.pem, -infotype,caCerts,,BLANK,,BLANK,
+,,,,,,,,,,,,,,,,,,,,,,
+1,genm rootCaCert with oldwithold        , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew0.pem
+1,genm rootCaCert without oldwithold     , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, BLANK      ,               , -newwithnew, _RESULT_DIR/test.newwithnew.pem
+0,genm rootCaCert oldwithold missing arg , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold,               , -newwithnew, _RESULT_DIR/test.newwithnew.pem
+0,genm rootCaCert oldwithold empty file  , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, empty.txt     , -newwithnew, _RESULT_DIR/test.newwithnew.pem
+0,genm rootCaCert oldwithold random file , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, random.bin    , -newwithnew, _RESULT_DIR/test.newwithnew.pem
+0,genm rootCaCert oldwithold nonexistent , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, idontexist    , -newwithnew, _RESULT_DIR/test.newwithnew.pem
+0,genm rootCaCert oldwithold wrong       , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, signer.crt    , -newwithnew, _RESULT_DIR/test.newwithnew.pem
+0,genm rootCaCert missing newwithnew     , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, BLANK      ,,
+0,genm rootCaCert newwithnew missing arg , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew,,
+1,genm rootCaCert with oldwithnew        , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew1.pem, -oldwithnew, _RESULT_DIR/test.oldwithnew1.pem
+0,genm rootCaCert oldwithnew missing arg , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew.pem, -oldwithnew,,
+1,genm rootCaCert newwithnew oldwithnew newwithold  , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew2.pem, -oldwithnew, _RESULT_DIR/test.oldwithnew2.pem, -newwithold, _RESULT_DIR/test.newwithold1.pem
+0,genm rootCaCert newwithold missig arg  , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew.pem, -oldwithnew, _RESULT_DIR/test.oldwithnew.pem, -newwithold,,
+1,genm rootCaCert newwithnew newwithold  , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew3.pem, -newwithold, _RESULT_DIR/test.newwithold2.pem
 ,,,,,,,,,,,,,,,,,,,,,,
 1,geninfo, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int:987,BLANK,,BLANK,
 0,geninfo missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,,,,,
 ,,,,,,,,,,,,,,,,,,,,,,
 1,geninfo, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int:987,BLANK,,BLANK,
 0,geninfo missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,,,,,
index 24947c673f02a7f251b83325ac557e1203b3dab6..9871821a6f6bce6b00ab5e1ede8d3d680fbe94eb 100644 (file)
@@ -5448,6 +5448,11 @@ BIO_ADDR_dup                            ?        3_2_0   EXIST::FUNCTION:SOCK
 OSSL_CMP_ITAV_new_caCerts               ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_ITAV_get0_caCerts              ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_get1_caCerts                   ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_ITAV_new_caCerts               ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_ITAV_get0_caCerts              ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_get1_caCerts                   ?      3_2_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_new_rootCaCert            ?      3_2_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_get0_rootCaCert           ?      3_2_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_new_rootCaKeyUpdate       ?      3_2_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_get0_rootCaKeyUpdate      ?      3_2_0   EXIST::FUNCTION:CMP
+OSSL_CMP_get1_rootCaKeyUpdate           ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_CTX_get0_libctx                ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_CTX_get0_propq                 ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_CTX_reset_geninfo_ITAVs        ?      3_0_8   EXIST::FUNCTION:CMP
 OSSL_CMP_CTX_get0_libctx                ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_CTX_get0_propq                 ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_CTX_reset_geninfo_ITAVs        ?      3_0_8   EXIST::FUNCTION:CMP