*Neil Horman*
+ * Added support for requesting CRL in CMP.
+
+ *Rajeev Ranjan, Siemens AG*
+
* Added `-set_issuer` and `-set_subject` options to `openssl x509` to
override the Issuer and Subject when creating a certificate. The `-subj`
option now is an alias for `-set_subject`.
static char *opt_newwithnew = NULL;
static char *opt_newwithold = NULL;
static char *opt_oldwithnew = NULL;
+static char *opt_crlcert = NULL;
+static char *opt_oldcrl = NULL;
+static char *opt_crlout = NULL;
/* client authentication */
static char *opt_ref = NULL;
/* credentials format */
static char *opt_certform_s = "PEM";
static int opt_certform = FORMAT_PEM;
+static char *opt_crlform_s = "DER";
+static int opt_crlform = FORMAT_ASN1;
static char *opt_keyform_s = NULL;
static int opt_keyform = FORMAT_UNDEF;
static char *opt_otherpass = NULL;
static char *opt_srv_untrusted = NULL;
static char *opt_ref_cert = NULL;
static char *opt_rsp_cert = NULL;
+static char *opt_rsp_crl = NULL;
static char *opt_rsp_extracerts = NULL;
static char *opt_rsp_capubs = NULL;
static char *opt_rsp_newwithnew = NULL;
OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, OPT_NO_CACHE_EXTRACERTS,
OPT_SRVCERTOUT, OPT_EXTRACERTSOUT, OPT_CACERTSOUT,
OPT_OLDWITHOLD, OPT_NEWWITHNEW, OPT_NEWWITHOLD, OPT_OLDWITHNEW,
+ OPT_CRLCERT, OPT_OLDCRL, OPT_CRLOUT,
OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS,
OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
OPT_UNPROTECTED_REQUESTS,
- OPT_CERTFORM, OPT_KEYFORM,
+ OPT_CERTFORM, OPT_CRLFORM, OPT_KEYFORM,
OPT_OTHERPASS,
#ifndef OPENSSL_NO_ENGINE
OPT_ENGINE,
OPT_SRV_REF, OPT_SRV_SECRET,
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_REF_CERT, OPT_RSP_CERT, OPT_RSP_CRL, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
OPT_RSP_NEWWITHNEW, OPT_RSP_NEWWITHOLD, OPT_RSP_OLDWITHNEW,
OPT_POLL_COUNT, OPT_CHECK_AFTER,
OPT_GRANT_IMPLICITCONF,
"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"},
+ { "crlcert", OPT_CRLCERT, 's',
+ "certificate to request a CRL for in genm of type crlStatusList"},
+ { "oldcrl", OPT_OLDCRL, 's',
+ "CRL to request update for in genm of type crlStatusList"},
+ { "crlout", OPT_CRLOUT, 's',
+ "File to save new CRL received in genp of type 'crls'"},
OPT_SECTION("Client authentication"),
{"ref", OPT_REF, 's',
OPT_SECTION("Credentials format"),
{"certform", OPT_CERTFORM, 's',
"Format (PEM or DER) to use when saving a certificate to a file. Default PEM"},
+ {"crlform", OPT_CRLFORM, 's',
+ "Format (PEM or DER) to use when saving a CRL to a file. Default DER"},
{"keyform", OPT_KEYFORM, 's',
"Format of the key input (ENGINE, other values ignored)"},
{"otherpass", OPT_OTHERPASS, 's',
"Certificate to be expected for rr and any oldCertID in kur messages"},
{"rsp_cert", OPT_RSP_CERT, 's',
"Certificate to be returned as mock enrollment result"},
+ {"rsp_crl", OPT_RSP_CRL, 's',
+ "CRL to be returned in genp of type crls"},
{"rsp_extracerts", OPT_RSP_EXTRACERTS, 's',
"Extra certificates to be included in mock certification responses"},
{"rsp_capubs", OPT_RSP_CAPUBS, 's',
{(char **)&opt_no_cache_extracerts},
{&opt_srvcertout}, {&opt_extracertsout}, {&opt_cacertsout},
{&opt_oldwithold}, {&opt_newwithnew}, {&opt_newwithold}, {&opt_oldwithnew},
+ {&opt_crlcert}, {&opt_oldcrl}, {&opt_crlout},
{&opt_ref}, {&opt_secret},
{&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
{&opt_digest}, {&opt_mac}, {&opt_extracerts},
{(char **)&opt_unprotected_requests},
- {&opt_certform_s}, {&opt_keyform_s},
+ {&opt_certform_s}, {&opt_crlform_s}, {&opt_keyform_s},
{&opt_otherpass},
#ifndef OPENSSL_NO_ENGINE
{&opt_engine},
{&opt_srv_ref}, {&opt_srv_secret},
{&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_ref_cert}, {&opt_rsp_cert}, {&opt_rsp_crl},
+ {&opt_rsp_extracerts}, {&opt_rsp_capubs},
{&opt_rsp_newwithnew}, {&opt_rsp_newwithold}, {&opt_rsp_oldwithnew},
{(char **)&opt_poll_count}, {(char **)&opt_check_after},
return ok;
}
+static int setup_mock_crlout(void *ctx, const char *file, const char *desc)
+{
+ X509_CRL *crl;
+ int ok;
+
+ if (file == NULL)
+ return 1;
+ if ((crl = load_crl(file, FORMAT_UNDEF, 0, desc)) == NULL)
+ return 0;
+ ok = ossl_cmp_mock_srv_set1_crlOut(ctx, crl);
+ X509_CRL_free(crl);
+ return ok;
+}
/*
* parse and transform some options, checking their syntax.
* Returns 1 on success, 0 on error
CMP_err("unknown option given for certificate storing format");
return 0;
}
+ if (opt_crlform_s != NULL
+ && !opt_format(opt_crlform_s, OPT_FMT_PEMDER, &opt_crlform)) {
+ CMP_err("unknown option given for CRL storing format");
+ return 0;
+ }
return 1;
}
(add_X509_fn_t)ossl_cmp_mock_srv_set1_certOut))
goto err;
}
+ if (!setup_mock_crlout(srv_ctx, opt_rsp_crl,
+ "CRL to be returned by the mock server"))
+ goto err;
if (!setup_certs(opt_rsp_extracerts,
"CMP extra certificates for mock server", srv_ctx,
(add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_chainOut))
return 0;
}
+static int write_crl(BIO *bio, X509_CRL *crl)
+{
+ if (opt_crlform != FORMAT_PEM && opt_crlform != FORMAT_ASN1) {
+ BIO_printf(bio_err, "error: unsupported type '%s' for writing CRLs\n",
+ opt_crlform_s);
+ return 0;
+ }
+
+ return opt_crlform == FORMAT_PEM ? PEM_write_bio_X509_CRL(bio, crl)
+ : i2d_X509_CRL_bio(bio, crl);
+}
+
/*
* If file != NULL writes out a stack of certs to the given file.
* If certs is NULL, the file is emptied.
return n;
}
+static int save_crl(X509_CRL *crl,
+ const char *file, const char *desc)
+{
+ BIO *bio = NULL;
+ int res = 0;
+
+ if (file == NULL)
+ return 1;
+ if (crl != NULL)
+ CMP_info2("received %s, saving to file '%s'", desc, file);
+
+ if ((bio = BIO_new(BIO_s_file())) == NULL
+ || !BIO_write_filename(bio, (char *)file)) {
+ CMP_err2("could not open file '%s' for writing %s",
+ file, desc);
+ goto end;
+ }
+
+ if (!write_crl(bio, crl)) {
+ CMP_err2("cannot write %s to file '%s'", desc, file);
+ goto end;
+ }
+ res = 1;
+
+ end:
+ BIO_free(bio);
+ return res;
+}
+
static int delete_file(const char *file, const char *desc)
{
if (file == NULL)
}
}
+static int save_crl_or_delete(X509_CRL *crl, const char *file, const char *desc)
+{
+ if (file == NULL)
+ return 1;
+ return (crl == NULL) ? delete_file(file, desc) : save_crl(crl, file, desc);
+}
+
static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
int i, ret = 1;
case OPT_OLDWITHNEW:
opt_oldwithnew = opt_str();
break;
+ case OPT_CRLCERT:
+ opt_crlcert = opt_str();
+ break;
+ case OPT_OLDCRL:
+ opt_oldcrl = opt_str();
+ break;
+ case OPT_CRLOUT:
+ opt_crlout = opt_str();
+ break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
case OPT_CERTFORM:
opt_certform_s = opt_str();
break;
+ case OPT_CRLFORM:
+ opt_crlform_s = opt_str();
+ break;
case OPT_KEYFORM:
opt_keyform_s = opt_str();
break;
case OPT_RSP_CERT:
opt_rsp_cert = opt_str();
break;
+ case OPT_RSP_CRL:
+ opt_rsp_crl = opt_str();
+ break;
case OPT_RSP_EXTRACERTS:
opt_rsp_extracerts = opt_str();
break;
end_upd:
X509_free(oldwithold);
return res;
+ } else if (opt_infotype == NID_id_it_crlStatusList) {
+ X509_CRL *oldcrl = NULL, *crl = NULL;
+ X509 *crlcert = NULL;
+ int res = 0;
+ const char *desc = "CRL from genp of type 'crls'";
+
+ if (opt_oldcrl == NULL && opt_crlcert == NULL) {
+ CMP_err("Missing -oldcrl and no -crlcert given for -infotype crlStatusList");
+ return 0;
+ }
+ if (opt_crlout == NULL) {
+ CMP_err("Missing -crlout for -infotype crlStatusList");
+ return 0;
+ }
+
+ if (opt_crlcert != NULL) {
+ crlcert = load_cert_pwd(opt_crlcert, opt_otherpass,
+ "Cert for genm with -infotype crlStatusList");
+ if (crlcert == NULL)
+ goto end_crlupd;
+ }
+
+ if (opt_oldcrl != NULL) {
+ oldcrl = load_crl(opt_oldcrl, FORMAT_UNDEF, 0,
+ "CRL for genm with -infotype crlStatusList");
+ if (oldcrl == NULL)
+ goto end_crlupd;
+ }
+
+ if (opt_oldcrl != NULL && opt_crlcert != NULL) {
+ if (X509_NAME_cmp(X509_CRL_get_issuer(oldcrl),
+ X509_get_issuer_name(crlcert))
+ != 0)
+ CMP_warn("-oldcrl and -crlcert have different issuer");
+ }
+
+ if (!OSSL_CMP_get1_crlUpdate(ctx, crlcert, oldcrl, &crl))
+ goto end_crlupd;
+
+ if (crl == NULL)
+ CMP_info("no CRL update available");
+ if (!save_crl_or_delete(crl, opt_crlout, desc))
+ goto end_crlupd;
+
+ res = 1;
+
+ end_crlupd:
+ X509_free(crlcert);
+ X509_CRL_free(oldcrl);
+ X509_CRL_free(crl);
+ return res;
+
} else {
OSSL_CMP_ITAV *req;
STACK_OF(OSSL_CMP_ITAV) *itavs;
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_crlOut(OSSL_CMP_SRV_CTX *srv_ctx, X509_CRL *crl);
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,
{
X509 *refCert; /* cert to expect for oldCertID in kur/rr msg */
X509 *certOut; /* certificate to be returned in cp/ip/kup msg */
+ X509_CRL *crlOut; /* CRL to be returned in genp for crls */
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 */
DEFINE_OSSL_SET1_CERT(refCert)
DEFINE_OSSL_SET1_CERT(certOut)
+int ossl_cmp_mock_srv_set1_crlOut(OSSL_CMP_SRV_CTX *srv_ctx,
+ X509_CRL *crl)
+{
+ 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 (crl != NULL && !X509_CRL_up_ref(crl))
+ return 0;
+ X509_CRL_free(ctx->crlOut);
+ ctx->crlOut = crl;
+ return 1;
+}
+
int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
STACK_OF(X509) *chain)
{
return OSSL_CMP_PKISI_dup(ctx->statusOut);
}
+/* return -1 for error, 0 for no update available */
+static int check_client_crl(const STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList,
+ const X509_CRL *crl)
+{
+ OSSL_CMP_CRLSTATUS *crlstatus;
+ DIST_POINT_NAME *dpn;
+ GENERAL_NAMES *issuer;
+ ASN1_TIME *thisupd = NULL;
+
+ if (sk_OSSL_CMP_CRLSTATUS_num(crlStatusList) != 1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CRLSTATUSLIST);
+ return -1;
+ }
+ if (crl == NULL)
+ return 0;
+
+ crlstatus = sk_OSSL_CMP_CRLSTATUS_value(crlStatusList, 0);
+ if (!OSSL_CMP_CRLSTATUS_get0(crlstatus, &dpn, &issuer, &thisupd))
+ return -1;
+
+ if (issuer != NULL) {
+ GENERAL_NAME *gn = sk_GENERAL_NAME_value(issuer, 0);
+
+ if (gn != NULL && gn->type == GEN_DIRNAME) {
+ X509_NAME *gen_name = gn->d.dirn;
+
+ if (X509_NAME_cmp(gen_name, X509_CRL_get_issuer(crl)) != 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CRL_ISSUER);
+ return -1;
+ }
+ } else {
+ ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
+ return -1; /* error according to RFC 9483 section 4.3.4 */
+ }
+ }
+
+ return thisupd == NULL
+ || ASN1_TIME_compare(thisupd, X509_CRL_get0_lastUpdate(crl)) < 0;
+}
+
static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
const OSSL_CMP_ITAV *req)
{
ctx->oldWithNew);
}
break;
+ case NID_id_it_crlStatusList:
+ {
+ STACK_OF(OSSL_CMP_CRLSTATUS) *crlstatuslist;
+ int res = 0;
+
+ if (!OSSL_CMP_ITAV_get0_crlStatusList(req, &crlstatuslist))
+ return NULL;
+
+ res = check_client_crl(crlstatuslist, ctx->crlOut);
+ if (res < 0)
+ rsp = NULL;
+ else
+ rsp = OSSL_CMP_ITAV_new_crls(res == 0 ? NULL : ctx->crlOut);
+ }
+ break;
default:
rsp = OSSL_CMP_ITAV_dup(req);
}
ADB_ENTRY(NID_id_it_certProfile,
ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.certProfile,
ASN1_UTF8STRING)),
+ ADB_ENTRY(NID_id_it_crlStatusList,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.crlStatusList,
+ OSSL_CMP_CRLSTATUS)),
+ ADB_ENTRY(NID_id_it_crls,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.crls, X509_CRL))
} ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0,
&infotypeandvalue_default_tt, NULL);
} ASN1_SEQUENCE_END(OSSL_CMP_ROOTCAKEYUPDATE)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
+ASN1_CHOICE(OSSL_CMP_CRLSOURCE) = {
+ ASN1_EXP(OSSL_CMP_CRLSOURCE, value.dpn, DIST_POINT_NAME, 0),
+ ASN1_EXP(OSSL_CMP_CRLSOURCE, value.issuer, GENERAL_NAMES, 1),
+} ASN1_CHOICE_END(OSSL_CMP_CRLSOURCE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CRLSOURCE)
+#define OSSL_CMP_CRLSOURCE_DPN 0
+#define OSSL_CMP_CRLSOURCE_ISSUER 1
+
+ASN1_SEQUENCE(OSSL_CMP_CRLSTATUS) = {
+ ASN1_SIMPLE(OSSL_CMP_CRLSTATUS, source, OSSL_CMP_CRLSOURCE),
+ ASN1_OPT(OSSL_CMP_CRLSTATUS, thisUpdate, ASN1_TIME)
+} ASN1_SEQUENCE_END(OSSL_CMP_CRLSTATUS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CRLSTATUS)
+
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_new0_crlStatusList(STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList)
+{
+ OSSL_CMP_ITAV *itav;
+
+ if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+ return NULL;
+ itav->infoType = OBJ_nid2obj(NID_id_it_crlStatusList);
+ itav->infoValue.crlStatusList = crlStatusList;
+ return itav;
+}
+
+int OSSL_CMP_ITAV_get0_crlStatusList(const OSSL_CMP_ITAV *itav,
+ STACK_OF(OSSL_CMP_CRLSTATUS) **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_crlStatusList) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ *out = itav->infoValue.crlStatusList;
+ return 1;
+}
+
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn,
+ const GENERAL_NAMES *issuer,
+ const ASN1_TIME *thisUpdate)
+{
+ OSSL_CMP_CRLSOURCE *crlsource;
+ OSSL_CMP_CRLSTATUS *crlstatus;
+
+ if (dpn == NULL && issuer == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (dpn != NULL && issuer != NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+
+ if ((crlstatus = OSSL_CMP_CRLSTATUS_new()) == NULL)
+ return NULL;
+ crlsource = crlstatus->source;
+
+ if (dpn != NULL) {
+ crlsource->type = OSSL_CMP_CRLSOURCE_DPN;
+ if ((crlsource->value.dpn = DIST_POINT_NAME_dup(dpn)) == NULL)
+ goto err;
+ } else {
+ crlsource->type = OSSL_CMP_CRLSOURCE_ISSUER;
+ if ((crlsource->value.issuer =
+ sk_GENERAL_NAME_deep_copy(issuer, GENERAL_NAME_dup,
+ GENERAL_NAME_free)) == NULL)
+ goto err;
+ }
+
+ if (thisUpdate != NULL
+ && (crlstatus->thisUpdate = ASN1_TIME_dup(thisUpdate)) == NULL)
+ goto err;
+ return crlstatus;
+
+ err:
+ OSSL_CMP_CRLSTATUS_free(crlstatus);
+ return NULL;
+}
+
+static GENERAL_NAMES *gennames_new(const X509_NAME *nm)
+{
+ GENERAL_NAMES *names;
+ GENERAL_NAME *name = NULL;
+
+ if ((names = sk_GENERAL_NAME_new_reserve(NULL, 1)) == NULL)
+ return NULL;
+ if (!GENERAL_NAME_set1_X509_NAME(&name, nm)) {
+ sk_GENERAL_NAME_free(names);
+ return NULL;
+ }
+ (void)sk_GENERAL_NAME_push(names, name); /* cannot fail */
+ return names;
+}
+
+static int gennames_allowed(GENERAL_NAMES *names, int only_DN)
+{
+ if (names == NULL)
+ return 0;
+ if (!only_DN)
+ return 1;
+ return sk_GENERAL_NAME_num(names) == 1
+ && sk_GENERAL_NAME_value(names, 0)->type == GEN_DIRNAME;
+}
+
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl,
+ const X509 *cert, int only_DN)
+{
+ STACK_OF(DIST_POINT) *crldps = NULL;
+ ISSUING_DIST_POINT *idp = NULL;
+ DIST_POINT_NAME *dpn = NULL;
+ AUTHORITY_KEYID *akid = NULL;
+ GENERAL_NAMES *issuers = NULL;
+ const GENERAL_NAMES *CRLissuer = NULL;
+ const ASN1_TIME *last = crl == NULL ? NULL : X509_CRL_get0_lastUpdate(crl);
+ OSSL_CMP_CRLSTATUS *status = NULL;
+ int i, NID_akid = NID_authority_key_identifier;
+
+ /*
+ * Note:
+ * X509{,_CRL}_get_ext_d2i(..., NID, ..., NULL) return the 1st extension with
+ * given NID that is available, if any. If there are more, this is an error.
+ */
+ if (cert != NULL) {
+ crldps = X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL);
+ /* if available, take the first suitable element */
+ for (i = 0; i < sk_DIST_POINT_num(crldps); i++) {
+ DIST_POINT *dp = sk_DIST_POINT_value(crldps, i);
+
+ if (dp == NULL)
+ continue;
+ if ((dpn = dp->distpoint) != NULL) {
+ CRLissuer = NULL;
+ break;
+ }
+ if (gennames_allowed(dp->CRLissuer, only_DN) && CRLissuer == NULL)
+ /* don't break because any dp->distpoint in list is preferred */
+ CRLissuer = dp->CRLissuer;
+ }
+ } else {
+ if (crl == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ idp = X509_CRL_get_ext_d2i(crl,
+ NID_issuing_distribution_point, NULL, NULL);
+ if (idp != NULL && idp->distpoint != NULL)
+ dpn = idp->distpoint;
+ }
+
+ if (dpn == NULL && CRLissuer == NULL) {
+ if (cert != NULL) {
+ akid = X509_get_ext_d2i(cert, NID_akid, NULL, NULL);
+ if (akid != NULL && gennames_allowed(akid->issuer, only_DN))
+ CRLissuer = akid->issuer;
+ else
+ CRLissuer = issuers = gennames_new(X509_get_issuer_name(cert));
+ }
+ if (CRLissuer == NULL && crl != NULL) {
+ akid = X509_CRL_get_ext_d2i(crl, NID_akid, NULL, NULL);
+ if (akid != NULL && gennames_allowed(akid->issuer, only_DN))
+ CRLissuer = akid->issuer;
+ else
+ CRLissuer = issuers = gennames_new(X509_CRL_get_issuer(crl));
+ }
+ if (CRLissuer == NULL)
+ goto end;
+ }
+
+ status = OSSL_CMP_CRLSTATUS_new1(dpn, CRLissuer, last);
+ end:
+ sk_DIST_POINT_pop_free(crldps, DIST_POINT_free);
+ ISSUING_DIST_POINT_free(idp);
+ AUTHORITY_KEYID_free(akid);
+ sk_GENERAL_NAME_pop_free(issuers, GENERAL_NAME_free);
+ return status;
+}
+
+int OSSL_CMP_CRLSTATUS_get0(const OSSL_CMP_CRLSTATUS *crlstatus,
+ DIST_POINT_NAME **dpn, GENERAL_NAMES **issuer,
+ ASN1_TIME **thisUpdate)
+{
+ OSSL_CMP_CRLSOURCE *crlsource;
+
+ if (crlstatus == NULL || dpn == NULL || issuer == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if ((crlsource = crlstatus->source) == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ if (crlsource->type == OSSL_CMP_CRLSOURCE_DPN) {
+ *dpn = crlsource->value.dpn;
+ *issuer = NULL;
+ } else if (crlsource->type == OSSL_CMP_CRLSOURCE_ISSUER) {
+ *dpn = NULL;
+ *issuer = crlsource->value.issuer;
+ } else {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ if (thisUpdate != NULL)
+ *thisUpdate = crlstatus->thisUpdate;
+ return 1;
+}
+
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crl)
+{
+ OSSL_CMP_ITAV *itav;
+ X509_CRL *crl_copy = NULL;
+ STACK_OF(X509_CRL) *crls = NULL;
+
+ if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+ return NULL;
+
+ if (crl != NULL) {
+ if ((crls = sk_X509_CRL_new_reserve(NULL, 1)) == NULL
+ || (crl_copy = X509_CRL_dup(crl)) == NULL)
+ goto err;
+ (void)sk_X509_CRL_push(crls, crl_copy); /* cannot fail */
+ }
+
+ itav->infoType = OBJ_nid2obj(NID_id_it_crls);
+ itav->infoValue.crls = crls;
+ return itav;
+
+ err:
+ sk_X509_CRL_free(crls);
+ OSSL_CMP_ITAV_free(itav);
+ return NULL;
+}
+
+int OSSL_CMP_ITAV_get0_crls(const OSSL_CMP_ITAV *itav, STACK_OF(X509_CRL) **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_crls) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ *out = itav->infoValue.crls;
+ return 1;
+}
+
/* get ASN.1 encoded integer, return -2 on error; -1 is valid for certReqId */
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
{
"failure obtaining random"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAIL_INFO_OUT_OF_RANGE),
"fail info out of range"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GENERATE_CRLSTATUS),
+ "error creating crlstatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GETTING_GENP), "getting genp"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GET_ITAV), "get itav"},
{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"},
+ "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_TRANSFER_ERROR), "transfer error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNCLEAN_CTX), "unclean ctx"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CERTPROFILE),
- "unexpected certprofile"},
+ "unexpected certprofile"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CRLSTATUSLIST),
+ "unexpected crlstatuslist"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
"unexpected pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
"unknown algorithm id"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CRL_ISSUER), "unknown crl issuer"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_PKISTATUS), "unknown pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_ALGORITHM),
"unsupported algorithm"},
X509_free(oldWithOld_copy);
return res;
}
+
+int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert,
+ const X509_CRL *last_crl,
+ X509_CRL **crl)
+{
+ OSSL_CMP_CRLSTATUS *status = NULL;
+ STACK_OF(OSSL_CMP_CRLSTATUS) *list = NULL;
+ OSSL_CMP_ITAV *req = NULL, *itav = NULL;
+ STACK_OF(X509_CRL) *crls;
+ int res = 0;
+
+ if (crl == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ *crl = NULL;
+
+ if ((status = OSSL_CMP_CRLSTATUS_create(last_crl, crlcert, 1)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_GENERATE_CRLSTATUS);
+ goto end;
+ }
+ if ((list = sk_OSSL_CMP_CRLSTATUS_new_reserve(NULL, 1)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_GENERATE_CRLSTATUS);
+ goto end;
+ }
+ (void)sk_OSSL_CMP_CRLSTATUS_push(list, status); /* cannot fail */
+
+ if ((req = OSSL_CMP_ITAV_new0_crlStatusList(list)) == NULL)
+ goto end;
+ status = NULL;
+ list = NULL;
+
+ if ((itav = get_genm_itav(ctx, req, NID_id_it_crls, "crl")) == NULL)
+ goto end;
+
+ if (!OSSL_CMP_ITAV_get0_crls(itav, &crls))
+ goto end;
+
+ if (crls == NULL) { /* no CRL update available */
+ res = 1;
+ goto end;
+ }
+ if (sk_X509_CRL_num(crls) != 1) {
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_GENP,
+ "Unexpected number of CRLs in genp: %d",
+ sk_X509_CRL_num(crls));
+ goto end;
+ }
+
+ if ((*crl = sk_X509_CRL_value(crls, 0)) == NULL || !X509_CRL_up_ref(*crl)) {
+ *crl = NULL;
+ goto end;
+ }
+ res = 1;
+ end:
+ OSSL_CMP_CRLSTATUS_free(status);
+ sk_OSSL_CMP_CRLSTATUS_free(list);
+ OSSL_CMP_ITAV_free(itav);
+ return res;
+}
|| (name->type == GEN_DIRNAME && IS_NULL_DN(name->d.directoryName));
}
-/* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */
-static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src)
-{
- GENERAL_NAME *name;
-
- if (!ossl_assert(tgt != NULL))
- return 0;
- if ((name = GENERAL_NAME_new()) == NULL)
- goto err;
- name->type = GEN_DIRNAME;
-
- if (src == NULL) { /* NULL-DN */
- if ((name->d.directoryName = X509_NAME_new()) == NULL)
- goto err;
- } else if (!X509_NAME_set(&name->d.directoryName, src)) {
- goto err;
- }
-
- GENERAL_NAME_free(*tgt);
- *tgt = name;
-
- return 1;
-
- err:
- GENERAL_NAME_free(name);
- return 0;
-}
-
/*
* Set the sender name in PKIHeader.
* when nm is NULL, sender is set to an empty string
{
if (!ossl_assert(hdr != NULL))
return 0;
- return set1_general_name(&hdr->sender, nm);
+ return GENERAL_NAME_set1_X509_NAME(&hdr->sender, nm);
}
int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm)
{
if (!ossl_assert(hdr != NULL))
return 0;
- return set1_general_name(&hdr->recipient, nm);
+ return GENERAL_NAME_set1_X509_NAME(&hdr->recipient, nm);
}
int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr)
typedef struct ossl_cmp_rootcakeyupdate_st OSSL_CMP_ROOTCAKEYUPDATE;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
+typedef struct ossl_cmp_certreqtemplate_st OSSL_CMP_CERTREQTEMPLATE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTREQTEMPLATE)
+
+/*-
+ * CRLSource ::= CHOICE {
+ * dpn [0] DistributionPointName,
+ * issuer [1] GeneralNames }
+ */
+
+typedef struct ossl_cmp_crlsource_st {
+ int type;
+ union {
+ DIST_POINT_NAME *dpn;
+ GENERAL_NAMES *issuer;
+ } value;
+} OSSL_CMP_CRLSOURCE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLSOURCE)
+
+/*
+ * CRLStatus ::= SEQUENCE {
+ * source CRLSource,
+ * thisUpdate Time OPTIONAL }
+ */
+
+struct ossl_cmp_crlstatus_st {
+ OSSL_CMP_CRLSOURCE *source;
+ ASN1_TIME *thisUpdate;
+}; /* OSSL_CMP_CRLSTATUS */
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLSTATUS)
+
/*-
* declared already here as it will be used in OSSL_CMP_MSG (nested) and
* infoType and infoValue
X509 *rootCaCert;
/* NID_id_it_rootCaKeyUpdate - Root CA Certificate Update */
OSSL_CMP_ROOTCAKEYUPDATE *rootCaKeyUpdate;
+ /* NID_id_it_crlStatusList - CRL Update Retrieval */
+ STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList;
+ /* NID_id_it_crls - Certificate Status Lists */
+ STACK_OF(X509_CRL) *crls;
+
/* this is to be used for so far undeclared objects */
ASN1_TYPE *other;
} infoValue;
CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
CMP_R_FAIL_INFO_OUT_OF_RANGE:129:fail info out of range
+CMP_R_GENERATE_CRLSTATUS:198:error creating crlstatus
CMP_R_GETTING_GENP:192:getting genp
+CMP_R_GET_ITAV:199:get itav
CMP_R_INVALID_ARGS:100:invalid args
CMP_R_INVALID_GENP:193:invalid genp
CMP_R_INVALID_OPTION:174:invalid option
CMP_R_TRANSFER_ERROR:159:transfer error
CMP_R_UNCLEAN_CTX:191:unclean ctx
CMP_R_UNEXPECTED_CERTPROFILE:196:unexpected certprofile
+CMP_R_UNEXPECTED_CRLSTATUSLIST:201:unexpected crlstatuslist
CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
CMP_R_UNEXPECTED_POLLREQ:105:unexpected pollreq
CMP_R_UNEXPECTED_SENDER:106:unexpected sender
CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
+CMP_R_UNKNOWN_CRL_ISSUER:200:unknown crl issuer
CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus
CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm
CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type
IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
+IMPLEMENT_ASN1_DUP_FUNCTION(DIST_POINT_NAME)
ASN1_SEQUENCE(DIST_POINT) = {
ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
(char *)a);
}
+int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src)
+{
+ GENERAL_NAME *name;
+
+ if (tgt == NULL){
+ ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if ((name = GENERAL_NAME_new()) == NULL)
+ return 0;
+ name->type = GEN_DIRNAME;
+
+ if (src == NULL) { /* NULL-DN */
+ if ((name->d.directoryName = X509_NAME_new()) == NULL)
+ goto err;
+ } else if (!X509_NAME_set(&name->d.directoryName, src)) {
+ goto err;
+ }
+
+ GENERAL_NAME_free(*tgt);
+ *tgt = name;
+ return 1;
+
+ err:
+ GENERAL_NAME_free(name);
+ return 0;
+}
+
static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
{
int res;
GENERATE[html/man3/EVP_whirlpool.html]=man3/EVP_whirlpool.pod
DEPEND[man/man3/EVP_whirlpool.3]=man3/EVP_whirlpool.pod
GENERATE[man/man3/EVP_whirlpool.3]=man3/EVP_whirlpool.pod
+DEPEND[html/man3/GENERAL_NAME.html]=man3/GENERAL_NAME.pod
+GENERATE[html/man3/GENERAL_NAME.html]=man3/GENERAL_NAME.pod
+DEPEND[man/man3/GENERAL_NAME.3]=man3/GENERAL_NAME.pod
+GENERATE[man/man3/GENERAL_NAME.3]=man3/GENERAL_NAME.pod
DEPEND[html/man3/HMAC.html]=man3/HMAC.pod
GENERATE[html/man3/HMAC.html]=man3/HMAC.pod
DEPEND[man/man3/HMAC.3]=man3/HMAC.pod
html/man3/EVP_sm3.html \
html/man3/EVP_sm4_cbc.html \
html/man3/EVP_whirlpool.html \
+html/man3/GENERAL_NAME.html \
html/man3/HMAC.html \
html/man3/MD5.html \
html/man3/MDC2_Init.html \
man/man3/EVP_sm3.3 \
man/man3/EVP_sm4_cbc.3 \
man/man3/EVP_whirlpool.3 \
+man/man3/GENERAL_NAME.3 \
man/man3/HMAC.3 \
man/man3/MD5.3 \
man/man3/MDC2_Init.3 \
[B<-newwithnew> I<filename>]
[B<-newwithold> I<filename>]
[B<-oldwithnew> I<filename>]
+[B<-crlcert> I<filename>]
+[B<-oldcrl> I<filename>]
+[B<-crlout> I<filename>]
Client authentication and protection options:
Credentials format options:
[B<-certform> I<PEM|DER>]
+[B<-crlform> I<PEM|DER>]
[B<-keyform> I<PEM|DER|P12|ENGINE>]
[B<-otherpass> I<arg>]
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
[B<-srv_untrusted> I<filenames>|I<uris>]
[B<-ref_cert> I<filename>|I<uri>]
[B<-rsp_cert> I<filename>|I<uri>]
+[B<-rsp_crl> 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>]
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> and C<rootCaCert>.
+So far, there is specific support for C<caCerts>, C<rootCaCert>
+and C<crlStatusList>.
=item B<-profile> I<name>
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<-crlcert> I<filename>
+
+Certificate used for specifying a CRL issuer when requesting a CRL
+in a genm message with infoType C<crlStatusList>.
+Any available distribution point name is preferred over issuer names.
+
+=item B<-oldcrl> I<filename>
+
+CRL used for specifying a CRL issuer when requesting a CRL
+in a genm message with infoType C<crlStatusList>.
+Any available distribution point name is preferred over issuer names.
+If also B<-crlcrt> is given, its data is preferred over data from B<-oldcrl>.
+
+=item B<-crlout> I<filename>
+
+The file to save CRL received in a genp message of infoType C<crls>.
+If on success no such CRL was received, this is indicated by deleting the file.
+
=back
=head2 Client authentication options
File format to use when saving a certificate to a file.
Default value is PEM.
+=item B<-crlform> I<PEM|DER>
+
+File format to use when saving a CRL to a file.
+Default value is DER.
+
=item B<-keyform> I<PEM|DER|P12|ENGINE>
The format of the key input; unspecified by default.
=item B<-otherpass> I<arg>
Pass phrase source for certificate given with the B<-trusted>, B<-untrusted>,
-B<-own_trusted>, B<-srvcert>, B<-out_trusted>, B<-extracerts>,
+B<-own_trusted>, B<-srvcert>, B<-crlcert>, B<-out_trusted>, B<-extracerts>,
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>,
Certificate to be returned as mock enrollment result.
+=item B<-rsp_crl> I<filename>|I<uri>
+
+CRL to be returned in genp of type C<crls>.
+
=item B<-rsp_extracerts> I<filenames>|I<uris>
Extra certificates to be included in mock certification responses.
The B<-engine> option was deprecated in OpenSSL 3.0.
-The B<-profile> option was added in OpenSSL 3.3.
+B<-profile>, B<-crlcert>, B<-oldcrl>, B<-crlout>, B<-crlform>
+and B<-rsp_crl> options were added in OpenSSL 3.3.
=head1 COPYRIGHT
--- /dev/null
+=pod
+
+=head1 NAME
+
+GENERAL_NAME,
+GENERAL_NAME_set1_X509_NAME
+- GENERAL_NAME method routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509v3.h>
+
+ typedef struct GENERAL_NAME_st GENERAL_NAME;
+
+ int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src);
+
+=head1 DESCRIPTION
+
+GENERAL_NAME_set1_X509_NAME() creates a new GENERAL_NAME of type GEN_DIRNAME
+and populates it based on provided X509_NAME I<src> which can be NULL.
+I<tgt> must not be NULL. If successful, I<*tgt> will be set to point
+to the newly created GENERAL_NAME.
+
+=head1 RETURN VALUES
+
+GENERAL_NAME_set1_X509_NAME() return 1 on success, 0 on error.
+
+=head1 HISTORY
+
+GENERAL_NAME_set1_X509_NAME() was added in OpenSSL 3.3.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
OSSL_CMP_ITAV_new_rootCaCert,
OSSL_CMP_ITAV_get0_rootCaCert,
OSSL_CMP_ITAV_new_rootCaKeyUpdate,
-OSSL_CMP_ITAV_get0_rootCaKeyUpdate
+OSSL_CMP_ITAV_get0_rootCaKeyUpdate,
+OSSL_CMP_CRLSTATUS_new1,
+OSSL_CMP_CRLSTATUS_create,
+OSSL_CMP_CRLSTATUS_get0,
+OSSL_CMP_ITAV_new0_crlStatusList,
+OSSL_CMP_ITAV_get0_crlStatusList,
+OSSL_CMP_ITAV_new_crls,
+OSSL_CMP_ITAV_get0_crls
- CMP utility functions for handling specific genm and genp messages
=head1 SYNOPSIS
X509 **newWithOld,
X509 **oldWithNew);
+ OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn,
+ const GENERAL_NAMES *issuer,
+ const ASN1_TIME *thisUpdate);
+ OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl,
+ const X509 *cert, int only_DN);
+ int OSSL_CMP_CRLSTATUS_get0(const OSSL_CMP_CRLSTATUS *crlstatus,
+ DIST_POINT_NAME **dpn, GENERAL_NAMES **issuer,
+ ASN1_TIME **thisUpdate);
+ OSSL_CMP_ITAV
+ *OSSL_CMP_ITAV_new0_crlStatusList(STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList);
+ int OSSL_CMP_ITAV_get0_crlStatusList(const OSSL_CMP_ITAV *itav,
+ STACK_OF(OSSL_CMP_CRLSTATUS) **out);
+ OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crl);
+ int OSSL_CMP_ITAV_get0_crls(const OSSL_CMP_ITAV *itav, STACK_OF(X509_CRL) **out);
+
=head1 DESCRIPTION
ITAV is short for InfoTypeAndValue.
Each of these pointers will be set to NULL if no root CA certificate update
is present or the respective sub-field is not included.
+OSSL_CMP_CRLSTATUS_new1() allocates a new B<OSSL_CMP_CRLSTATUS> structure
+that contains either a copy of the distribution point name I<dpn>
+or a copy of the certificate issuer I<issuer>, while giving both is an error.
+If given, a copy of the CRL issuance time I<thisUpdate> is also included.
+
+OSSL_CMP_CRLSTATUS_create() is a high-level variant of OSSL_CMP_CRLSTATUS_new1().
+It fills the thisUpdate field with a copy of the thisUpdate field of I<crl> if present.
+It fills the CRLSource field with a copy of the first data item found using the I<crl>
+and/or I<cert> parameters as follows.
+Any available distribution point name is preferred over issuer names.
+Data from I<cert>, if present, is preferred over data from I<crl>.
+If no distribution point names are available,
+candidate issuer names are taken from following sources, as far as present:
+
+=over 4
+
+=item the list of distribution points in the first cRLDistributionPoints
+extension of I<cert>,
+
+=item the issuer field of the authority key identifier of I<cert>,
+
+=item the issuer DN of I<cert>,
+
+=item the issuer field of the authority key identifier of I<crl>, and
+
+=item the issuer DN of I<crl>.
+
+=back
+
+If <only_DN> is set, a candidate issuer name of type B<GENERAL_NAMES> is
+accepted only if it contains exactly one general name of type directoryName.
+
+OSSL_CMP_CRLSTATUS_get0() reads the fields of I<crlstatus>
+and assigns them to I<*dpn>, I<*issuer>, and I<*thisUpdate>.
+I<*thisUpdate> is assigned only if the I<thisUpdate> argument is not NULL.
+Depending on the choice present, either I<*dpn> or I<*issuer> will be NULL.
+I<*thisUpdate> can also be NULL if the field is not present.
+
+OSSL_CMP_ITAV_new0_crlStatusList() creates a new B<OSSL_CMP_ITAV> structure of
+type B<crlStatusList> that includes the optionally given list of
+CRL status data, each of which is of type B<OSSL_CMP_CRLSTATUS>.
+
+OSSL_CMP_ITAV_get0_crlStatusList() on success assigns to I<*out> an internal
+pointer to the list of CRL status data in the infoValue field of I<itav>.
+The pointer may be NULL if no CRL status data is included.
+It is an error if the infoType of I<itav> is not B<crlStatusList>.
+
+OSSL_CMP_ITAV_new_crls() creates a new B<OSSL_CMP_ITAV> structure
+of type B<crls> including an empty list of CRLs if the I<crl> argument is NULL
+or including a singleton list a with copy of the provided CRL otherwise.
+
+OSSL_CMP_ITAV_get0_crls() on success assigns to I<*out> an internal pointer to
+the list of CRLs contained in the infoValue field of I<itav>.
+The pointer may be NULL if no CRL is included.
+It is an error if the infoType of I<itav> is not B<crls>.
+
=head1 NOTES
CMP is defined in RFC 4210.
=head1 RETURN VALUES
-OSSL_CMP_ITAV_new_caCerts(),
-OSSL_CMP_ITAV_new_rootCaCert(), and OSSL_CMP_ITAV_new_rootCaKeyUpdate()
+OSSL_CMP_ITAV_new_caCerts(), OSSL_CMP_ITAV_new_rootCaCert(),
+OSSL_CMP_ITAV_new_rootCaKeyUpdate(), OSSL_CMP_CRLSTATUS_new1(),
+OSSL_CMP_CRLSTATUS_create(), OSSL_CMP_ITAV_new0_crlStatusList()
+and OSSL_CMP_ITAV_new_crls()
return a pointer to the new ITAV structure on success, or NULL on error.
-OSSL_CMP_ITAV_get0_caCerts(),
-OSSL_CMP_ITAV_get0_rootCaCert(), and OSSL_CMP_ITAV_get0_rootCaKeyUpdate()
+OSSL_CMP_ITAV_get0_caCerts(), OSSL_CMP_ITAV_get0_rootCaCert(),
+OSSL_CMP_ITAV_get0_rootCaKeyUpdate(), OSSL_CMP_CRLSTATUS_get0(),
+OSSL_CMP_ITAV_get0_crlStatusList() and OSSL_CMP_ITAV_get0_crls()
return 1 on success, 0 on error.
=head1 SEE ALSO
OSSL_CMP_ITAV_new_rootCaKeyUpdate(), and OSSL_CMP_ITAV_get0_rootCaKeyUpdate()
were added in OpenSSL 3.2.
+OSSL_CMP_CRLSTATUS_new1(), OSSL_CMP_CRLSTATUS_create(),
+OSSL_CMP_CRLSTATUS_get0(), OSSL_CMP_ITAV_new0_crlStatusList(),
+OSSL_CMP_ITAV_get0_crlStatusList(), OSSL_CMP_ITAV_new_crls()
+and OSSL_CMP_ITAV_get0_crls() were added in OpenSSL 3.3.
+
=head1 COPYRIGHT
Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
OSSL_CMP_exec_RR_ses,
OSSL_CMP_exec_GENM_ses,
OSSL_CMP_get1_caCerts,
-OSSL_CMP_get1_rootCaKeyUpdate
+OSSL_CMP_get1_rootCaKeyUpdate,
+OSSL_CMP_get1_crlUpdate
- functions implementing CMP client transactions
=head1 SYNOPSIS
int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
const X509 *oldWithOld, X509 **newWithNew,
X509 **newWithOld, X509 **oldWithNew);
+ int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert,
+ const X509_CRL *last_crl,
+ X509_CRL **crl);
=head1 DESCRIPTION
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>.
+OSSL_CMP_get1_crlUpdate() uses a genm request message with infoType crlStatusList
+to obtain CRL from the CMP server referenced by I<ctx> in a genp response message
+with infoType crls. It uses I<last_crl> and I<crlcert> to create
+a request with a status field as described for L<OSSL_CMP_CRLSTATUS_create(3)>.
+On success it assigns to I<*crl> the CRL received.
+NULL means that no CRL was provided by the server.
+The CRL obtained this way must be freed by the caller.
+
=head1 NOTES
CMP is defined in RFC 4210 (and CRMF in RFC 4211).
assign the received value unless I<checkAfter> is NULL.
OSSL_CMP_exec_RR_ses(), OSSL_CMP_get1_caCerts(),
-and OSSL_CMP_get1_rootCaKeyUpdate()
+OSSL_CMP_get1_rootCaKeyUpdate() and OSSL_CMP_get1_crlUpdate()
return 1 on success, 0 on error.
OSSL_CMP_exec_GENM_ses() returns NULL on error,
L<OSSL_CMP_CTX_set1_subjectName(3)>, L<OSSL_CMP_CTX_set0_newPkey(3)>,
L<OSSL_CMP_CTX_set1_p10CSR(3)>, L<OSSL_CMP_CTX_set1_oldCert(3)>,
L<OSSL_CMP_CTX_get0_newCert(3)>, L<OSSL_CMP_CTX_push0_genm_ITAV(3)>,
-L<OSSL_CMP_MSG_http_perform(3)>
+L<OSSL_CMP_MSG_http_perform(3)>, L<OSSL_CMP_CRLSTATUS_create(3)>
=head1 HISTORY
OSSL_CMP_get1_caCerts() and OSSL_CMP_get1_rootCaKeyUpdate()
were added in OpenSSL 3.2.
-Support for delayed delivery of all types of response messages
-was added in OpenSSL 3.3.
+OSSL_CMP_get1_crlUpdate() and support for delayed delivery
+of all types of response messages was added in OpenSSL 3.3.
=head1 COPYRIGHT
DISPLAYTEXT_new,
DIST_POINT_NAME_free,
DIST_POINT_NAME_new,
+DIST_POINT_NAME_dup,
DIST_POINT_free,
DIST_POINT_new,
DSAparams_dup,
OCSP_SIGNATURE_new,
OCSP_SINGLERESP_free,
OCSP_SINGLERESP_new,
+OSSL_CMP_CRLSTATUS_free,
OSSL_CMP_ITAV_dup,
OSSL_CMP_ITAV_free,
OSSL_CMP_MSG_dup,
{-
generate_stack_macros("OSSL_CMP_ITAV");
-}
+
+typedef struct ossl_cmp_crlstatus_st OSSL_CMP_CRLSTATUS;
+{-
+ generate_stack_macros("OSSL_CMP_CRLSTATUS");
+-}
+
typedef struct ossl_cmp_revrepcontent_st OSSL_CMP_REVREPCONTENT;
typedef struct ossl_cmp_pkisi_st OSSL_CMP_PKISI;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
ASN1_TYPE *value);
ASN1_OBJECT *OSSL_CMP_ITAV_get0_type(const OSSL_CMP_ITAV *itav);
ASN1_TYPE *OSSL_CMP_ITAV_get0_value(const OSSL_CMP_ITAV *itav);
-int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
+int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **sk_p,
OSSL_CMP_ITAV *itav);
void OSSL_CMP_ITAV_free(OSSL_CMP_ITAV *itav);
X509 **newWithOld,
X509 **oldWithNew);
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl,
+ const X509 *cert, int only_DN);
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn,
+ const GENERAL_NAMES *issuer,
+ const ASN1_TIME *thisUpdate);
+int OSSL_CMP_CRLSTATUS_get0(const OSSL_CMP_CRLSTATUS *crlstatus,
+ DIST_POINT_NAME **dpn, GENERAL_NAMES **issuer,
+ ASN1_TIME **thisUpdate);
+void OSSL_CMP_CRLSTATUS_free(OSSL_CMP_CRLSTATUS *crlstatus);
+OSSL_CMP_ITAV
+*OSSL_CMP_ITAV_new0_crlStatusList(STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList);
+int OSSL_CMP_ITAV_get0_crlStatusList(const OSSL_CMP_ITAV *itav,
+ STACK_OF(OSSL_CMP_CRLSTATUS) **out);
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crls);
+int OSSL_CMP_ITAV_get0_crls(const OSSL_CMP_ITAV *it, STACK_OF(X509_CRL) **out);
+
void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
/* from cmp_ctx.c */
int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
const X509 *oldWithOld, X509 **newWithNew,
X509 **newWithOld, X509 **oldWithNew);
+int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert,
+ const X509_CRL *last_crl,
+ X509_CRL **crl);
# ifdef __cplusplus
}
# define CMP_R_FAILED_EXTRACTING_PUBKEY 141
# define CMP_R_FAILURE_OBTAINING_RANDOM 110
# define CMP_R_FAIL_INFO_OUT_OF_RANGE 129
+# define CMP_R_GENERATE_CRLSTATUS 198
# define CMP_R_GETTING_GENP 192
+# define CMP_R_GET_ITAV 199
# define CMP_R_INVALID_ARGS 100
# define CMP_R_INVALID_GENP 193
# define CMP_R_INVALID_OPTION 174
# define CMP_R_TRANSFER_ERROR 159
# define CMP_R_UNCLEAN_CTX 191
# define CMP_R_UNEXPECTED_CERTPROFILE 196
+# define CMP_R_UNEXPECTED_CRLSTATUSLIST 201
# define CMP_R_UNEXPECTED_PKIBODY 133
# define CMP_R_UNEXPECTED_PKISTATUS 185
# define CMP_R_UNEXPECTED_POLLREQ 105
# define CMP_R_UNEXPECTED_SENDER 106
# define CMP_R_UNKNOWN_ALGORITHM_ID 134
# define CMP_R_UNKNOWN_CERT_TYPE 135
+# define CMP_R_UNKNOWN_CRL_ISSUER 200
# define CMP_R_UNKNOWN_PKISTATUS 186
# define CMP_R_UNSUPPORTED_ALGORITHM 136
# define CMP_R_UNSUPPORTED_KEY_TYPE 137
GENERAL_NAME *location;
} ACCESS_DESCRIPTION;
+int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src);
+
{-
generate_stack_macros("ACCESS_DESCRIPTION")
.generate_stack_macros("GENERAL_NAME");
/* If relativename then this contains the full distribution point name */
X509_NAME *dpname;
} DIST_POINT_NAME;
+DECLARE_ASN1_DUP_FUNCTION(DIST_POINT_NAME)
/* All existing reasons */
# define CRLDP_ALL_REASONS 0x807f
--- /dev/null
+-----BEGIN X509 CRL-----
+MIIBtDCBnQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJBVTETMBEGA1UE
+CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk
+MRMwEQYDVQQDEwpzdWJpbnRlckNBFw0yNDAyMjMxNTQ3NTFaFw0zNzA5MTIxNTQ3
+NTFaoA8wDTALBgNVHRQEBAICEAcwDQYJKoZIhvcNAQELBQADggEBAFyUvxWlxjLA
+DjTq/N26EXH6GZxmDyr5tjPk1KQBRY/jPNWvxloXFIH7PAtzInJmEoF2PCDw290Z
+BRuftPaxVW1tcHAsZzL5QFSGa2wWSLGCHpZCg9twcLQbGrOq7+S2M2ZjOVxSMN1u
+ok/QLhuqniPieOUetzafqUNknYJahILnomLhPoQBzko9EdtBJkygOGdj/3T07iLy
+hicW0QlBA5B9oCIUmknnx4kCh6VlsSq9FJTs2HXZhJHF0VVFbAlbjHMFkwjTh31r
+Bc8u1D35T0kqwbTbVmtPghdpW2uJ+9LsWXdrlTGGlRJXA+3d13hKlFMFcQEavf4h
+wVlABZ6eEPo=
+-----END X509 CRL-----
--- /dev/null
+-----BEGIN X509 CRL-----
+MIIBtDCBnQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJBVTETMBEGA1UE
+CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk
+MRMwEQYDVQQDEwpzdWJpbnRlckNBFw0yNDAyMjMxNTQ3MzhaFw0zNDEyMTcxNTQ3
+MzhaoA8wDTALBgNVHRQEBAICEAYwDQYJKoZIhvcNAQELBQADggEBANfH339j7LXB
+9X+Vpk1xjTSRwoIQ7C/LZbOJ4tiVaNsBd+3rlOgJEnYPuB883ylAy3TOPn9taMXe
+kmPebHC4WDhESNbwm8kdFNz6Ghvvn4TuDcSgWV8xxtw5AHVfnCs8801KI8pcn7K6
+MwGdJ7CPvB38SFn5ssKQueLySRfL+bRWXpgB79hjFE7J1ukaUr2xg3q4YFQwexld
+xuaIR0AiFyTVKWTWLEdAKRzPiYTmx1ZMyYEdwh17l6nWh/UgfUEqmK9ub2Mqh20h
+g7/Nwf0iaQS7bui7DgzkW76dbXcmAmTkU8VLznOLIheus8uj6Kl2TewO5PvjVGeu
+Fgt7CED5epw=
+-----END X509 CRL-----
ref_cert = signer_only.crt
rsp_cert = signer_only.crt
+rsp_crl = newcrl.pem
rsp_capubs = trusted.crt
rsp_extracerts = signer_issuing.crt
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,genm crlStatusList with crlcert , -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, signer_only.crt,,,,, -crlout, _RESULT_DIR/test.crlout1.pem
+1,genm crlStatusList with old crl , -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -oldcrl, oldcrl.pem,,,,, -crlout, _RESULT_DIR/test.crlout2.pem
+1,genm crlStatusList with crlcert and old crl , -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, signer_only.crt, -oldcrl, oldcrl.pem,,, -crlout, _RESULT_DIR/test.crlout3.pem
+1,genm crlStatusList with latest crl , -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -oldcrl, _RESULT_DIR/test.crlout3.pem,,,,, -crlout, _RESULT_DIR/test.crlout4.pem
+0,genm crlStatusList with -oldcrl referring to nonexisting file due to empty CRL response message in previous test case, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -oldcrl, _RESULT_DIR/test.crlout4.pem,,,,, -crlout, _RESULT_DIR/test.crlout5.pem
+0,genm crlStatusList with -crlcert nonexistent, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, idontexist,,,,, -crlout, _RESULT_DIR/test.crlout.pem
+0,genm crlStatusList with wrong issuer, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, server.crt,,,,, -crlout, _RESULT_DIR/test.crlout.pem
+0,genm crlStatusList missing -crlcert & -oldcrl, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,,,,,,,, -crlout, _RESULT_DIR/test.crlout.pem
+0,genm crlStatusList with wrong cert and correct crl, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, server.crt, -oldcrl, oldcrl.pem,,, -crlout, _RESULT_DIR/test.crlout.pem
+,,,,,,,,,,,,,,,,,,,,,,
1,profile, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,profile1,BLANK,,BLANK,
0,profile wrong value, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,profile2,BLANK,,BLANK,
0,profile missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,,,,,
X509_STORE_CTX_set_current_reasons 5664 3_2_0 EXIST::FUNCTION:
OSSL_STORE_delete 5665 3_2_0 EXIST::FUNCTION:
BIO_ADDR_copy 5666 3_2_0 EXIST::FUNCTION:SOCK
+DIST_POINT_NAME_dup ? 3_3_0 EXIST::FUNCTION:
+GENERAL_NAME_set1_X509_NAME ? 3_3_0 EXIST::FUNCTION:
OSSL_CMP_CTX_get0_geninfo_ITAVs 5667 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_HDR_get0_geninfo_ITAVs 5668 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_ITAV_new0_certProfile 5669 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_ITAV_get0_certProfile 5670 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_MSG_get0_certreq_publickey 5671 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_SRV_CTX_init_trans 5672 3_3_0 EXIST::FUNCTION:CMP
+OSSL_CMP_CRLSTATUS_create ? 3_3_0 EXIST::FUNCTION:CMP
+OSSL_CMP_CRLSTATUS_free ? 3_3_0 EXIST::FUNCTION:CMP
+OSSL_CMP_CRLSTATUS_get0 ? 3_3_0 EXIST::FUNCTION:CMP
+OSSL_CMP_CRLSTATUS_new1 ? 3_3_0 EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_get0_crlStatusList ? 3_3_0 EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_get0_crls ? 3_3_0 EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_new0_crlStatusList ? 3_3_0 EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_new_crls ? 3_3_0 EXIST::FUNCTION:CMP
+OSSL_CMP_get1_crlUpdate ? 3_3_0 EXIST::FUNCTION:CMP
EVP_DigestSqueeze 5673 3_3_0 EXIST::FUNCTION:
ERR_pop 5674 3_3_0 EXIST::FUNCTION:
X509_STORE_get1_objects 5675 3_3_0 EXIST::FUNCTION:
EVP_RAND_CTX datatype
EVP_SIGNATURE datatype
GEN_SESSION_CB datatype
+GENERAL_NAME datatype
NAMING_AUTHORITY datatype
OPENSSL_Applink external
OSSL_ALGORITHM datatype