From: Dr. David von Oheimb Date: Sat, 3 Dec 2022 16:49:08 +0000 (+0100) Subject: CMP: add support for genm with crlStatusList and genp with crls X-Git-Tag: openssl-3.4.0-alpha1~614 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40a200f9e781381d72d234c886e38bcfce36bbc8;p=thirdparty%2Fopenssl.git CMP: add support for genm with crlStatusList and genp with crls Introduce the capability to retrieve and update Certificate Revocation Lists (CRLs) in the CMP client, as specified in section 4.3.4 of RFC 9483. To request a CRL update, the CMP client can send a genm message with the option -infotype crlStatusList. The server will respond with a genp message containing the updated CRL, using the -infoType id-it-crls. The client can then save the CRL in a specified file using the -crlout parameter. Co-authored-by: Rajeev Ranjan Reviewed-by: Todd Short Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23768) --- diff --git a/CHANGES.md b/CHANGES.md index 28e1c0ae4d8..73587dc7325 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -110,6 +110,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 213596f7231..407ee5ec32e 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 fcc1ef7bb4f..6b4290460aa 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 b0c8dfbb8c3..1c7bf22f6b0 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) { @@ -418,6 +475,21 @@ static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid, 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 daa6a4c49b6..f20e5098ca9 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; @@ -339,6 +358,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 56ac3691d76..689aa6a9520 100644 --- a/crypto/cmp/cmp_err.c +++ b/crypto/cmp/cmp_err.c @@ -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 7c38d3367c5..8d92019c839 100644 --- a/crypto/cmp/cmp_genm.c +++ b/crypto/cmp/cmp_genm.c @@ -346,3 +346,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 4358b38873f..59205ef8c72 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 89f05d75366..9ebd1858a55 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 1607ad835f3..5102c481e34 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 8f560e171ca..839b2c1afef 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 1f67bf2f63a..c71e5b91116 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 c7cb6d5d4fb..aab005baaef 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 @@ -3327,6 +3331,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 \ @@ -3979,6 +3984,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 f9f33db569f..abfac3c420b 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 00000000000..903a33944eb --- /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 133907d8acd..982f840a8ec 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. @@ -64,18 +86,77 @@ to the certificate contained in the oldWithNew infoValue sub-field of I. 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 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 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 @@ -89,6 +170,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 54632ce9369..56e6bb8ef2c 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 4ecd5c0830c..17100a45ffb 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, @@ -135,6 +136,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 ad9eb3429d6..c46b9ab594f 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 0d876e501c5..700ffbeb7be 100644 --- a/include/openssl/cmperr.h +++ b/include/openssl/cmperr.h @@ -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 b8711d5304f..a967064f4c4 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 00000000000..101d7cd67c5 --- /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 00000000000..f596289d1db --- /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 5e330789c94..86a11f6a368 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 aabf2dc1e62..69dff91b7d8 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 77b66ee2725..facac4db4fc 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5536,12 +5536,23 @@ X509_STORE_CTX_set_get_crl 5663 3_2_0 EXIST::FUNCTION: 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: diff --git a/util/other.syms b/util/other.syms index bf6ae33d5ac..df47478f520 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