diff --git a/CHANGES.md b/CHANGES.md index d857bf846a5f60..098e40493aea81 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -67,6 +67,10 @@ OpenSSL 3.3 *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`. diff --git a/apps/cmp.c b/apps/cmp.c index a280cea7205975..bfb1f2aa0ae406 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -94,6 +94,9 @@ static char *opt_oldwithold = NULL; 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; @@ -143,6 +146,8 @@ static int opt_revreason = CRL_REASON_NONE; /* 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; @@ -187,6 +192,7 @@ static char *opt_srv_trusted = 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; @@ -237,12 +243,13 @@ typedef enum OPTION_choice { 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, @@ -267,7 +274,7 @@ typedef enum OPTION_choice { 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, @@ -428,6 +435,12 @@ const OPTIONS cmp_options[] = { "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', @@ -459,6 +472,8 @@ const OPTIONS cmp_options[] = { 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', @@ -544,6 +559,8 @@ const OPTIONS cmp_options[] = { "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', @@ -623,13 +640,14 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {(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}, @@ -652,7 +670,8 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {&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}, @@ -1010,6 +1029,19 @@ static int setup_certs(char *files, const char *desc, void *ctx, 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 @@ -1057,6 +1089,11 @@ static int transform_opts(void) 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; } @@ -1152,6 +1189,9 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine) (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)) @@ -2248,6 +2288,18 @@ static int write_cert(BIO *bio, X509 *cert) 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. @@ -2295,6 +2347,35 @@ static int save_free_certs(STACK_OF(X509) *certs, 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) @@ -2328,6 +2409,13 @@ static int save_cert_or_delete(X509 *cert, const char *file, const char *desc) } } +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; @@ -2727,6 +2815,15 @@ static int get_opts(int argc, char **argv) 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)) @@ -2822,6 +2919,9 @@ static int get_opts(int argc, char **argv) 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; @@ -2905,6 +3005,9 @@ static int get_opts(int argc, char **argv) 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; @@ -3141,6 +3244,58 @@ static int do_genm(OSSL_CMP_CTX *ctx) 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; diff --git a/apps/include/cmp_mock_srv.h b/apps/include/cmp_mock_srv.h index fcc1ef7bb4f0b3..6b4290460aa6cc 100644 --- a/apps/include/cmp_mock_srv.h +++ b/apps/include/cmp_mock_srv.h @@ -22,6 +22,7 @@ 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_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, diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c index 5fed3a9fd07a19..972ff4f9e2874e 100644 --- a/apps/lib/cmp_mock_srv.c +++ b/apps/lib/cmp_mock_srv.c @@ -20,6 +20,7 @@ typedef struct { 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 */ @@ -87,6 +88,22 @@ static mock_srv_ctx *mock_srv_ctx_new(void) 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) { @@ -391,6 +408,46 @@ static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, 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) { @@ -405,6 +462,21 @@ static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid, ctx->newWithOld, 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); } diff --git a/crypto/cmp/cmp_asn.c b/crypto/cmp/cmp_asn.c index 3049d4f0800817..ef167ad5745240 100644 --- a/crypto/cmp/cmp_asn.c +++ b/crypto/cmp/cmp_asn.c @@ -120,6 +120,11 @@ ASN1_ADB(OSSL_CMP_ITAV) = { 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); @@ -138,6 +143,20 @@ ASN1_SEQUENCE(OSSL_CMP_ROOTCAKEYUPDATE) = { } 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; @@ -332,6 +351,243 @@ int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const 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) { diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c index 30095aa7c52d33..689aa6a9520f71 100644 --- a/crypto/cmp/cmp_err.c +++ b/crypto/cmp/cmp_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-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 @@ -85,12 +85,15 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "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"}, @@ -146,7 +149,9 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { {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"}, @@ -156,6 +161,7 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { {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"}, diff --git a/crypto/cmp/cmp_genm.c b/crypto/cmp/cmp_genm.c index dad6ef1189713e..04077e7f787feb 100644 --- a/crypto/cmp/cmp_genm.c +++ b/crypto/cmp/cmp_genm.c @@ -344,3 +344,63 @@ int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx, 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; +} diff --git a/crypto/cmp/cmp_hdr.c b/crypto/cmp/cmp_hdr.c index 4358b38873f357..59205ef8c72e42 100644 --- a/crypto/cmp/cmp_hdr.c +++ b/crypto/cmp/cmp_hdr.c @@ -89,34 +89,6 @@ int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name) || (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 @@ -126,14 +98,14 @@ int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm) { 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) diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h index edec8808a78de5..b6148485ff78a0 100644 --- a/crypto/cmp/cmp_local.h +++ b/crypto/cmp/cmp_local.h @@ -211,6 +211,36 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT) 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 @@ -264,6 +294,11 @@ struct ossl_cmp_itav_st { 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; diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 22b5de9a7adb67..43377d4172ba1f 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -234,7 +234,9 @@ CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain 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 @@ -276,6 +278,7 @@ CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched 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 @@ -283,6 +286,7 @@ CMP_R_UNEXPECTED_PVNO:153:unexpected pvno 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 diff --git a/crypto/x509/v3_crld.c b/crypto/x509/v3_crld.c index e9f6e08e27a7cc..110c80ac01f445 100644 --- a/crypto/x509/v3_crld.c +++ b/crypto/x509/v3_crld.c @@ -327,6 +327,7 @@ ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = { 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), diff --git a/crypto/x509/v3_genn.c b/crypto/x509/v3_genn.c index 1f67bf2f63ab87..c71e5b91116d23 100644 --- a/crypto/x509/v3_genn.c +++ b/crypto/x509/v3_genn.c @@ -58,6 +58,35 @@ GENERAL_NAME *GENERAL_NAME_dup(const GENERAL_NAME *a) (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; diff --git a/doc/build.info b/doc/build.info index b4815fcf23a795..2135c962d804c6 100644 --- a/doc/build.info +++ b/doc/build.info @@ -1471,6 +1471,10 @@ DEPEND[html/man3/EVP_whirlpool.html]=man3/EVP_whirlpool.pod 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 @@ -3299,6 +3303,7 @@ html/man3/EVP_sha3_224.html \ 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 \ @@ -3944,6 +3949,7 @@ man/man3/EVP_sha3_224.3 \ 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 \ diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index d4228d8f84db58..5d63726b7cfdfe 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -74,6 +74,9 @@ Server authentication options: [B<-newwithnew> I] [B<-newwithold> I] [B<-oldwithnew> I] +[B<-crlcert> I] +[B<-oldcrl> I] +[B<-crlout> I] Client authentication and protection options: @@ -91,6 +94,7 @@ Client authentication and protection options: Credentials format options: [B<-certform> I] +[B<-crlform> I] [B<-keyform> I] [B<-otherpass> I] {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -} @@ -134,6 +138,7 @@ Mock server options: [B<-srv_untrusted> I|I] [B<-ref_cert> I|I] [B<-rsp_cert> I|I] +[B<-rsp_crl> I|I] [B<-rsp_extracerts> I|I] [B<-rsp_capubs> I|I] [B<-rsp_newwithnew> I|I] @@ -247,7 +252,8 @@ ITAV Bs is printed to stdout. Set InfoType name to use for requesting specific info in B, e.g., C. -So far, there is specific support for C and C. +So far, there is specific support for C, C +and C. =item B<-profile> I @@ -733,6 +739,24 @@ The file to save any oldWithNew certificate received in a genp message of infoType C. If on success no such cert was received, this is indicated by deleting the file. +=item B<-crlcert> I + +Certificate used for specifying a CRL issuer when requesting a CRL +in a genm message with infoType C. +Any available distribution point name is preferred over issuer names. + +=item B<-oldcrl> I + +CRL used for specifying a CRL issuer when requesting a CRL +in a genm message with infoType C. +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 + +The file to save CRL received in a genp message of infoType C. +If on success no such CRL was received, this is indicated by deleting the file. + =back =head2 Client authentication options @@ -858,6 +882,11 @@ Send request messages without CMP-level protection. File format to use when saving a certificate to a file. Default value is PEM. +=item B<-crlform> I + +File format to use when saving a CRL to a file. +Default value is DER. + =item B<-keyform> I The format of the key input; unspecified by default. @@ -866,7 +895,7 @@ See L for details. =item B<-otherpass> I 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>, @@ -1141,6 +1170,10 @@ Certificate to be expected for RR messages and any oldCertID in KUR messages. Certificate to be returned as mock enrollment result. +=item B<-rsp_crl> I|I + +CRL to be returned in genp of type C. + =item B<-rsp_extracerts> I|I Extra certificates to be included in mock certification responses. @@ -1438,7 +1471,8 @@ The B application was added in OpenSSL 3.0. 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 diff --git a/doc/man3/GENERAL_NAME.pod b/doc/man3/GENERAL_NAME.pod new file mode 100644 index 00000000000000..903a33944ebf6c --- /dev/null +++ b/doc/man3/GENERAL_NAME.pod @@ -0,0 +1,41 @@ +=pod + +=head1 NAME + +GENERAL_NAME, +GENERAL_NAME_set1_X509_NAME +- GENERAL_NAME method routines + +=head1 SYNOPSIS + + #include + + 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 which can be NULL. +I 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. + +=cut diff --git a/doc/man3/OSSL_CMP_ITAV_new_caCerts.pod b/doc/man3/OSSL_CMP_ITAV_new_caCerts.pod index 66f0ac90309d20..fada72c0ce1c8a 100644 --- a/doc/man3/OSSL_CMP_ITAV_new_caCerts.pod +++ b/doc/man3/OSSL_CMP_ITAV_new_caCerts.pod @@ -7,7 +7,14 @@ 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 +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 @@ -27,6 +34,21 @@ OSSL_CMP_ITAV_get0_rootCaKeyUpdate 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. @@ -50,16 +72,73 @@ OSSL_CMP_ITAV_new_rootCaKeyUpdate() creates a new B structure of type B that includes an RootCaKeyUpdateContent structure with the optional I, I, and I certificates. -OSSL_CMP_ITAV_get0_rootCaKeyUpdate() requires that I has infoType -B. -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. -If I is not NULL, it assigns to I<*newWithOld> the internal pointer -to the certificate contained in the newWithOld infoValue sub-field of I. -If I is not NULL, it assigns to I<*oldWithNew> the internal pointer -to the certificate contained in the oldWithNew infoValue sub-field of I. -Each of these pointers will be NULL if the respective sub-field is not set. +OSSL_CMP_ITAV_get0_rootCaKeyUpdate() +requires that I has type B. +It assigns NULL to I<*newWithNew> if no root CA key update value is in I, +otherwise an internal pointer to the certificate contained in the newWithNew +field of the RootCaKeyUpdateContent structure. +If I is not NULL, it assigns to I<*newWithOld> an internal pointer +to the certificate contained in the newWithOld field. +If I is not NULL, it assigns to I<*oldWithNew> an internal pointer +to the certificate contained in the oldWithNew field. +Each of these two pointers will be NULL if no root CA key update value +is in I or the respective field is not present. + +OSSL_CMP_CRLSTATUS_new1() allocates a new B structure +that contains either a copy of the distribution point name I +or a copy of the certificate issuer I, while giving both is an error. +If given, a copy of the CRL issuance time I 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 if present. +It fills the CRLSource field with a copy of the first data item found using the I +and/or I parameters as follows. +Any available distribution point name is preferred over issuer names. +Data from I, if present, is preferred over data from I. +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, + +=item the issuer field of the authority key identifier of I, + +=item the issuer DN of I, + +=item the issuer field of the authority key identifier of I, and + +=item the issuer DN of I. + +=back + +If is set, a candidate issuer name of type B is +accepted only if it contains exactly one general name of type directoryName. + +OSSL_CMP_CRLSTATUS_get0() reads the fields of I +and assigns them to I<*dpn>, I<*issuer>, and I<*thisUpdate>. +I<*thisUpdate> is assigned only if the I 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 structure of +type B that includes the optionally given list of +CRL status data, each of which is of type B. + +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. +The pointer may be NULL if no CRL status data is included. +It is an error if the infoType of I is not B. + +OSSL_CMP_ITAV_new_crls() creates a new B structure +of type B including an empty list of CRLs if the I 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. +The pointer may be NULL if no CRL is included. +It is an error if the infoType of I is not B. =head1 NOTES @@ -67,12 +146,15 @@ 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 @@ -86,6 +168,11 @@ 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. +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. diff --git a/doc/man3/OSSL_CMP_exec_certreq.pod b/doc/man3/OSSL_CMP_exec_certreq.pod index 54632ce93697bc..56e6bb8ef2cc40 100644 --- a/doc/man3/OSSL_CMP_exec_certreq.pod +++ b/doc/man3/OSSL_CMP_exec_certreq.pod @@ -15,7 +15,8 @@ OSSL_CMP_try_certreq, 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 @@ -41,6 +42,9 @@ OSSL_CMP_get1_rootCaKeyUpdate 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 @@ -157,6 +161,14 @@ The trust placed in it cannot be stronger than the trust placed in the I certificate if present, otherwise it cannot be stronger than the weakest trust in any of the certificates in the trust store of I. +OSSL_CMP_get1_crlUpdate() uses a genm request message with infoType crlStatusList +to obtain CRL from the CMP server referenced by I in a genp response message +with infoType crls. It uses I and I to create +a request with a status field as described for L. +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). @@ -193,7 +205,7 @@ and the output parameter I has been used to assign the received value unless I 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, @@ -211,7 +223,7 @@ L, L, L, L, L, L, L, L, -L +L, L =head1 HISTORY @@ -220,8 +232,8 @@ The OpenSSL CMP support was added in OpenSSL 3.0. 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 diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod index c6206e1759093f..2c9758522e158d 100644 --- a/doc/man3/X509_dup.pod +++ b/doc/man3/X509_dup.pod @@ -44,6 +44,7 @@ DISPLAYTEXT_free, DISPLAYTEXT_new, DIST_POINT_NAME_free, DIST_POINT_NAME_new, +DIST_POINT_NAME_dup, DIST_POINT_free, DIST_POINT_new, DSAparams_dup, @@ -132,6 +133,7 @@ OCSP_SIGNATURE_free, 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, diff --git a/include/openssl/cmp.h.in b/include/openssl/cmp.h.in index da82a3f41927ad..6f5d0660ecbca9 100644 --- a/include/openssl/cmp.h.in +++ b/include/openssl/cmp.h.in @@ -228,6 +228,12 @@ DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV) {- 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) @@ -257,7 +263,7 @@ void OSSL_CMP_ITAV_set0(OSSL_CMP_ITAV *itav, ASN1_OBJECT *type, 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); @@ -278,6 +284,22 @@ int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const 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 */ @@ -521,6 +543,9 @@ 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); +int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert, + const X509_CRL *last_crl, + X509_CRL **crl); # ifdef __cplusplus } diff --git a/include/openssl/cmperr.h b/include/openssl/cmperr.h index 90222e4dacfe7a..700ffbeb7beb62 100644 --- a/include/openssl/cmperr.h +++ b/include/openssl/cmperr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-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 @@ -60,7 +60,9 @@ # 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 @@ -100,6 +102,7 @@ # 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 @@ -107,6 +110,7 @@ # 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 diff --git a/include/openssl/x509v3.h.in b/include/openssl/x509v3.h.in index 569680378dfd03..e49dcfa6140796 100644 --- a/include/openssl/x509v3.h.in +++ b/include/openssl/x509v3.h.in @@ -178,6 +178,8 @@ typedef struct ACCESS_DESCRIPTION_st { 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"); @@ -201,6 +203,7 @@ typedef struct DIST_POINT_NAME_st { /* 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 diff --git a/test/recipes/80-test_cmp_http_data/Mock/newcrl.pem b/test/recipes/80-test_cmp_http_data/Mock/newcrl.pem new file mode 100644 index 00000000000000..101d7cd67c5184 --- /dev/null +++ b/test/recipes/80-test_cmp_http_data/Mock/newcrl.pem @@ -0,0 +1,12 @@ +-----BEGIN X509 CRL----- +MIIBtDCBnQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJBVTETMBEGA1UE +CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk +MRMwEQYDVQQDEwpzdWJpbnRlckNBFw0yNDAyMjMxNTQ3NTFaFw0zNzA5MTIxNTQ3 +NTFaoA8wDTALBgNVHRQEBAICEAcwDQYJKoZIhvcNAQELBQADggEBAFyUvxWlxjLA +DjTq/N26EXH6GZxmDyr5tjPk1KQBRY/jPNWvxloXFIH7PAtzInJmEoF2PCDw290Z +BRuftPaxVW1tcHAsZzL5QFSGa2wWSLGCHpZCg9twcLQbGrOq7+S2M2ZjOVxSMN1u +ok/QLhuqniPieOUetzafqUNknYJahILnomLhPoQBzko9EdtBJkygOGdj/3T07iLy +hicW0QlBA5B9oCIUmknnx4kCh6VlsSq9FJTs2HXZhJHF0VVFbAlbjHMFkwjTh31r +Bc8u1D35T0kqwbTbVmtPghdpW2uJ+9LsWXdrlTGGlRJXA+3d13hKlFMFcQEavf4h +wVlABZ6eEPo= +-----END X509 CRL----- diff --git a/test/recipes/80-test_cmp_http_data/Mock/oldcrl.pem b/test/recipes/80-test_cmp_http_data/Mock/oldcrl.pem new file mode 100644 index 00000000000000..f596289d1db6f5 --- /dev/null +++ b/test/recipes/80-test_cmp_http_data/Mock/oldcrl.pem @@ -0,0 +1,12 @@ +-----BEGIN X509 CRL----- +MIIBtDCBnQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJBVTETMBEGA1UE +CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk +MRMwEQYDVQQDEwpzdWJpbnRlckNBFw0yNDAyMjMxNTQ3MzhaFw0zNDEyMTcxNTQ3 +MzhaoA8wDTALBgNVHRQEBAICEAYwDQYJKoZIhvcNAQELBQADggEBANfH339j7LXB +9X+Vpk1xjTSRwoIQ7C/LZbOJ4tiVaNsBd+3rlOgJEnYPuB883ylAy3TOPn9taMXe +kmPebHC4WDhESNbwm8kdFNz6Ghvvn4TuDcSgWV8xxtw5AHVfnCs8801KI8pcn7K6 +MwGdJ7CPvB38SFn5ssKQueLySRfL+bRWXpgB79hjFE7J1ukaUr2xg3q4YFQwexld +xuaIR0AiFyTVKWTWLEdAKRzPiYTmx1ZMyYEdwh17l6nWh/UgfUEqmK9ub2Mqh20h +g7/Nwf0iaQS7bui7DgzkW76dbXcmAmTkU8VLznOLIheus8uj6Kl2TewO5PvjVGeu +Fgt7CED5epw= +-----END X509 CRL----- diff --git a/test/recipes/80-test_cmp_http_data/Mock/server.cnf b/test/recipes/80-test_cmp_http_data/Mock/server.cnf index 5e330789c946ff..86a11f6a368297 100644 --- a/test/recipes/80-test_cmp_http_data/Mock/server.cnf +++ b/test/recipes/80-test_cmp_http_data/Mock/server.cnf @@ -12,6 +12,7 @@ no_cache_extracerts = 1 ref_cert = signer_only.crt rsp_cert = signer_only.crt +rsp_crl = newcrl.pem rsp_capubs = trusted.crt rsp_extracerts = signer_issuing.crt diff --git a/test/recipes/80-test_cmp_http_data/test_commands.csv b/test/recipes/80-test_cmp_http_data/test_commands.csv index 6aa18599b18701..997899b7688b5c 100644 --- a/test/recipes/80-test_cmp_http_data/test_commands.csv +++ b/test/recipes/80-test_cmp_http_data/test_commands.csv @@ -86,6 +86,16 @@ expected,description, -section,val, -cmd,val,val2, -cacertsout,val,val2, -infoty 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,,,,, diff --git a/util/libcrypto.num b/util/libcrypto.num index 7f646cbba99268..62323e7e3734f8 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5547,3 +5547,14 @@ ERR_pop ? 3_3_0 EXIST::FUNCTION: X509_STORE_get1_objects ? 3_3_0 EXIST::FUNCTION: OPENSSL_LH_set_thunks ? 3_3_0 EXIST::FUNCTION: OPENSSL_LH_doall_arg_thunk ? 3_3_0 EXIST::FUNCTION: +DIST_POINT_NAME_dup ? 3_3_0 EXIST::FUNCTION: +GENERAL_NAME_set1_X509_NAME ? 3_3_0 EXIST::FUNCTION: +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 diff --git a/util/other.syms b/util/other.syms index b45ba45bb58719..5e164a76acb229 100644 --- a/util/other.syms +++ b/util/other.syms @@ -53,6 +53,7 @@ EVP_RAND datatype EVP_RAND_CTX datatype EVP_SIGNATURE datatype GEN_SESSION_CB datatype +GENERAL_NAME datatype NAMING_AUTHORITY datatype OPENSSL_Applink external OSSL_ALGORITHM datatype