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;
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;
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_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_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,
"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',
"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',
{&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_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},
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)
{
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,
(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;
- }
- X509_free(cert);
- }
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;
- }
- X509_free(cert);
}
if (!setup_certs(opt_rsp_extracerts,
"CMP extra certificates for mock server", srv_ctx,
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)
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");
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) {
+ X509_STORE *ts;
+
/*
* the 0 arg below clears any expected host/ip/email address;
* opt_expect_sender is used instead
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;
}
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;
- }
- X509_free(oldcert);
}
}
cleanse(opt_keypass);
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;
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_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;
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;
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);
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 */
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)
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)
{
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
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;
}
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);
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
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,
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;
- }
+ sk_OSSL_CMP_ITAV_free(*out);
+ return 0;
}
*out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup,
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);
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;
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)
{
{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"},
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;
+}
} 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
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;
* }
*/
+/*
+ * 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);
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
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_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,
- STACK_OF(X509) *chain);
+ const STACK_OF(X509) *chain);
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);
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.
-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().
-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.
[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:
[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>]
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>
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
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.
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.
=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
-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
=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
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.
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
-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 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
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
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
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).
(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
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,
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
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 */
/* 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
}
# 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
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"
--- /dev/null
+-----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-----
--- /dev/null
+-----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-----
--- /dev/null
+-----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-----
--- /dev/null
+-----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-----
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_newwithnew = newWithNew.pem
+rsp_newwithold = newWithOld.pem
+rsp_oldwithnew = oldWithNew.pem
+
verbosity = 7
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,,,,,
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