From 7c6577ba9f5eb348476a53d822a4db6af0d36d36 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Tue, 13 Jun 2023 21:56:57 +0200 Subject: [PATCH] CMP lib and app: add optional certProfile request message header and respective -profile option Also add missing getter functionss OSSL_CMP_{CTX,HDR}_get0_geninfo_ITAVs() to CMP API. Reviewed-by: Tomas Mraz Reviewed-by: Shane Lontis Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/21281) --- CHANGES.md | 5 ++ apps/cmp.c | 44 ++++++++++++++- apps/lib/cmp_mock_srv.c | 36 +++++++++++++ crypto/cmp/cmp_asn.c | 54 ++++++++++++------- crypto/cmp/cmp_ctx.c | 2 + crypto/cmp/cmp_err.c | 2 + crypto/cmp/cmp_hdr.c | 10 ++++ crypto/cmp/cmp_local.h | 2 + crypto/err/openssl.txt | 1 + doc/man1/openssl-cmp.pod.in | 10 +++- doc/man3/OSSL_CMP_CTX_new.pod | 13 ++++- doc/man3/OSSL_CMP_HDR_get0_transactionID.pod | 10 +++- doc/man3/OSSL_CMP_ITAV_set0.pod | 35 ++++++++++-- include/openssl/cmp.h.in | 8 +++ include/openssl/cmperr.h | 1 + .../80-test_cmp_http_data/test_commands.csv | 5 ++ util/libcrypto.num | 4 ++ 17 files changed, 213 insertions(+), 29 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 93365619fa..f1c8bce1b3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -33,6 +33,11 @@ OpenSSL 3.3 *James Muir* + * Added several new features of CMPv3 defined in RFC 9480 and RFC 9483: + - `certProfile` request message header and respective `-profile` CLI option + + *David von Oheimb* + * The build of exporters (such as `.pc` files for pkg-config) cleaned up to be less hard coded in the build file templates, and to allow easier addition of more exporters. With that, an exporter for CMake is also diff --git a/apps/cmp.c b/apps/cmp.c index dd5a69af7c..67f281e0aa 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -112,6 +112,7 @@ static int opt_cmd = -1; static char *opt_geninfo = NULL; static char *opt_infotype_s = NULL; static int opt_infotype = NID_undef; +static char *opt_profile = NULL; /* certificate enrollment */ static char *opt_newkey = NULL; @@ -210,7 +211,7 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY, - OPT_CMD, OPT_INFOTYPE, OPT_GENINFO, + OPT_CMD, OPT_INFOTYPE, OPT_PROFILE, OPT_GENINFO, OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT, OPT_DAYS, OPT_REQEXTS, @@ -291,6 +292,8 @@ const OPTIONS cmp_options[] = { "InfoType name for requesting specific info in genm, with specific support"}, {OPT_MORE_STR, 0, 0, "for 'caCerts' and 'rootCaCert'"}, + {"profile", OPT_PROFILE, 's', + "Certificate profile name to place in generalInfo field of request PKIHeader"}, {"geninfo", OPT_GENINFO, 's', "generalInfo integer values to place in request PKIHeader with given OID"}, {OPT_MORE_STR, 0, 0, @@ -587,7 +590,7 @@ typedef union { static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {&opt_config}, {&opt_section}, {(char **)&opt_verbosity}, - {&opt_cmd_s}, {&opt_infotype_s}, {&opt_geninfo}, + {&opt_cmd_s}, {&opt_infotype_s}, {&opt_profile}, {&opt_geninfo}, {&opt_newkey}, {&opt_newkeypass}, {&opt_subject}, {(char **)&opt_days}, {&opt_reqexts}, @@ -1837,6 +1840,37 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) return 0; } +static int add_certProfile(OSSL_CMP_CTX *ctx, const char *name) +{ + OSSL_CMP_ITAV *itav = NULL; + STACK_OF(ASN1_UTF8STRING) *sk; + ASN1_UTF8STRING *utf8string; + + if (ctx == NULL || name == NULL) + return 0; + + if ((sk = sk_ASN1_UTF8STRING_new_reserve(NULL, 1)) == NULL) + return 0; + if ((utf8string = ASN1_UTF8STRING_new()) == NULL) + goto err; + if (!ASN1_STRING_set(utf8string, name, (int)strlen(name))) { + ASN1_STRING_free(utf8string); + goto err; + } + /* Due to sk_ASN1_UTF8STRING_new_reserve(NULL, 1), this surely succeeds: */ + (void)sk_ASN1_UTF8STRING_push(sk, utf8string); + if ((itav = OSSL_CMP_ITAV_new0_certProfile(sk)) == NULL) + goto err; + if (OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) + return 1; + OSSL_CMP_ITAV_free(itav); + return 0; + + err: + sk_ASN1_UTF8STRING_pop_free(sk, ASN1_UTF8STRING_free); + return 0; +} + static int handle_opt_geninfo(OSSL_CMP_CTX *ctx) { long value; @@ -2078,6 +2112,8 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) if (opt_geninfo != NULL && !handle_opt_geninfo(ctx)) goto err; + if (opt_profile != NULL && !add_certProfile(ctx, opt_profile)) + goto err; /* not printing earlier, to minimize confusion in case setup fails before */ if (opt_rspin != NULL) @@ -2603,6 +2639,9 @@ static int get_opts(int argc, char **argv) case OPT_INFOTYPE: opt_infotype_s = opt_str(); break; + case OPT_PROFILE: + opt_profile = opt_str(); + break; case OPT_GENINFO: opt_geninfo = opt_str(); break; @@ -3131,6 +3170,7 @@ int cmp_main(int argc, char **argv) cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq()); if (cmp_ctx == NULL) goto err; + OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity); if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) { CMP_err1("cannot set up error reporting and logging for %s", prog); diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c index a0450446c1..d58937ea78 100644 --- a/apps/lib/cmp_mock_srv.c +++ b/apps/lib/cmp_mock_srv.c @@ -241,6 +241,42 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, /* give final response after polling */ ctx->curr_pollCount = 0; + /* accept cert profile for cr messages only with the configured name */ + if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_CR) { + STACK_OF(OSSL_CMP_ITAV) *itavs = + OSSL_CMP_HDR_get0_geninfo_ITAVs(OSSL_CMP_MSG_get0_header(cert_req)); + int i; + + for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) { + OSSL_CMP_ITAV *itav = sk_OSSL_CMP_ITAV_value(itavs, i); + ASN1_OBJECT *obj = OSSL_CMP_ITAV_get0_type(itav); + STACK_OF(ASN1_UTF8STRING) *strs; + ASN1_UTF8STRING *str; + const char *data; + + if (OBJ_obj2nid(obj) == NID_id_it_certProfile) { + if (!OSSL_CMP_ITAV_get0_certProfile(itav, &strs)) + return NULL; + if (sk_ASN1_UTF8STRING_num(strs) < 1) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE); + return NULL; + } + str = sk_ASN1_UTF8STRING_value(strs, 0); + if (str == NULL + || (data = + (const char *)ASN1_STRING_get0_data(str)) == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } + if (strcmp(data, "profile1") != 0) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE); + return NULL; + } + break; + } + } + } + /* accept cert update request only for the reference cert, if given */ if (bodytype == OSSL_CMP_KUR && crm != NULL /* thus not p10cr */ && ctx->refCert != NULL) { diff --git a/crypto/cmp/cmp_asn.c b/crypto/cmp/cmp_asn.c index 0133dc5f80..3049d4f080 100644 --- a/crypto/cmp/cmp_asn.c +++ b/crypto/cmp/cmp_asn.c @@ -58,11 +58,7 @@ IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT) ASN1_SEQUENCE(OSSL_CMP_ERRORMSGCONTENT) = { ASN1_SIMPLE(OSSL_CMP_ERRORMSGCONTENT, pKIStatusInfo, OSSL_CMP_PKISI), ASN1_OPT(OSSL_CMP_ERRORMSGCONTENT, errorCode, ASN1_INTEGER), - /* - * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING - * so it is used directly - * - */ + /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ERRORMSGCONTENT, errorDetails, ASN1_UTF8STRING) } ASN1_SEQUENCE_END(OSSL_CMP_ERRORMSGCONTENT) @@ -121,6 +117,9 @@ ASN1_ADB(OSSL_CMP_ITAV) = { ADB_ENTRY(NID_id_it_rootCaKeyUpdate, ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaKeyUpdate, OSSL_CMP_ROOTCAKEYUPDATE)), + ADB_ENTRY(NID_id_it_certProfile, + ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.certProfile, + ASN1_UTF8STRING)), } ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0, &infotypeandvalue_default_tt, NULL); @@ -190,13 +189,40 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p, return 1; err: - if (created != 0) { + if (created) { sk_OSSL_CMP_ITAV_free(*itav_sk_p); *itav_sk_p = NULL; } return 0; } +OSSL_CMP_ITAV +*OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) *certProfile) +{ + OSSL_CMP_ITAV *itav; + + if ((itav = OSSL_CMP_ITAV_new()) == NULL) + return NULL; + itav->infoType = OBJ_nid2obj(NID_id_it_certProfile); + itav->infoValue.certProfile = certProfile; + return itav; +} + +int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav, + STACK_OF(ASN1_UTF8STRING) **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_certProfile) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + *out = itav->infoValue.certProfile; + return 1; +} + OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts) { OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_new(); @@ -327,7 +353,7 @@ int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a) } static int ossl_cmp_msg_cb(int operation, ASN1_VALUE **pval, - const ASN1_ITEM *it, void *exarg) + ossl_unused const ASN1_ITEM *it, void *exarg) { OSSL_CMP_MSG *msg = (OSSL_CMP_MSG *)*pval; @@ -417,14 +443,9 @@ ASN1_ITEM_TEMPLATE_END(OSSL_CMP_PKISTATUS) ASN1_SEQUENCE(OSSL_CMP_PKISI) = { ASN1_SIMPLE(OSSL_CMP_PKISI, status, OSSL_CMP_PKISTATUS), - /* - * CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING - * so it is used directly - */ + /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_PKISI, statusString, ASN1_UTF8STRING), - /* - * OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING so used directly - */ + /* OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING, used directly */ ASN1_OPT(OSSL_CMP_PKISI, failInfo, ASN1_BIT_STRING) } ASN1_SEQUENCE_END(OSSL_CMP_PKISI) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_PKISI) @@ -541,10 +562,7 @@ ASN1_SEQUENCE(OSSL_CMP_PKIHEADER) = { ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, transactionID, ASN1_OCTET_STRING, 4), ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, senderNonce, ASN1_OCTET_STRING, 5), ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, recipNonce, ASN1_OCTET_STRING, 6), - /* - * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING - * so it is used directly - */ + /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, freeText, ASN1_UTF8STRING, 7), ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, generalInfo, OSSL_CMP_ITAV, 8) diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c index 947d2ceb8f..5e542200e9 100644 --- a/crypto/cmp/cmp_ctx.c +++ b/crypto/cmp/cmp_ctx.c @@ -534,6 +534,8 @@ int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx) return 1; } +DEFINE_OSSL_CMP_CTX_get0(geninfo_ITAVs, STACK_OF(OSSL_CMP_ITAV)) + /* Add an itav for the body of outgoing general messages */ int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav) { diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c index 3853e52605..c4d5c97f9e 100644 --- a/crypto/cmp/cmp_err.c +++ b/crypto/cmp/cmp_err.c @@ -144,6 +144,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "transactionid unmatched"}, {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"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS), "unexpected pkistatus"}, diff --git a/crypto/cmp/cmp_hdr.c b/crypto/cmp/cmp_hdr.c index 5fabf1aa33..4358b38873 100644 --- a/crypto/cmp/cmp_hdr.c +++ b/crypto/cmp/cmp_hdr.c @@ -72,6 +72,16 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr) return hdr->recipNonce; } +STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr) +{ + if (hdr == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return NULL; + } + return hdr->generalInfo; +} + /* a NULL-DN as an empty sequence of RDNs */ int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name) { diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h index 29aa84cd2a..b8da48ac43 100644 --- a/crypto/cmp/cmp_local.h +++ b/crypto/cmp/cmp_local.h @@ -254,6 +254,8 @@ struct ossl_cmp_itav_st { OSSL_CMP_MSGS *origPKIMessage; /* NID_id_it_suppLangTags - Supported Language Tags */ STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue; + /* NID_id_it_certProfile - Certificate Profile */ + STACK_OF(ASN1_UTF8STRING) *certProfile; /* NID_id_it_caCerts - CA Certificates */ STACK_OF(X509) *caCerts; /* NID_id_it_rootCaCert - Root CA Certificate */ diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 5f60bd52d2..8e6d9ddcae 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -272,6 +272,7 @@ CMP_R_TOTAL_TIMEOUT:184:total timeout 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_PKIBODY:133:unexpected pkibody CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus CMP_R_UNEXPECTED_PVNO:153:unexpected pvno diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index 051c749d08..ee54697c9c 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -17,6 +17,7 @@ Generic message options: [B<-cmd> I] [B<-infotype> I] +[B<-profile> I] [B<-geninfo> I] Certificate enrollment options: @@ -246,6 +247,11 @@ Set InfoType name to use for requesting specific info in B, e.g., C. So far, there is specific support for C and C. +=item B<-profile> I + +Name of a certificate profile to place in +the PKIHeader generalInfo field of request messages. + =item B<-geninfo> I generalInfo integer values to place in request PKIHeader with given OID, @@ -1390,7 +1396,9 @@ L, L, L The B application was added in OpenSSL 3.0. -The B<-engine option> was deprecated in OpenSSL 3.0. +The B<-engine> option was deprecated in OpenSSL 3.0. + +The B<-profile> option was added in OpenSSL 3.3. =head1 COPYRIGHT diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod index 8109970171..d038f2f61c 100644 --- a/doc/man3/OSSL_CMP_CTX_new.pod +++ b/doc/man3/OSSL_CMP_CTX_new.pod @@ -39,6 +39,7 @@ OSSL_CMP_CTX_set1_secretValue, OSSL_CMP_CTX_set1_recipient, OSSL_CMP_CTX_push0_geninfo_ITAV, OSSL_CMP_CTX_reset_geninfo_ITAVs, +OSSL_CMP_CTX_get0_geninfo_ITAVs, OSSL_CMP_CTX_set1_extraCertsOut, OSSL_CMP_CTX_set0_newPkey, OSSL_CMP_CTX_get0_newPkey, @@ -127,6 +128,8 @@ OSSL_CMP_CTX_set1_senderNonce int OSSL_CMP_CTX_set1_recipient(OSSL_CMP_CTX *ctx, const X509_NAME *name); int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav); int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx); + STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_CTX_get0_geninfo_ITAVs(const OSSL_CMP_CTX *ctx); int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx, STACK_OF(X509) *extraCertsOut); @@ -540,12 +543,16 @@ the issuer of the CMP signer certificate, as far as any of those is present, else the NULL-DN as last resort. OSSL_CMP_CTX_push0_geninfo_ITAV() adds I to the stack in the I to be -added to the GeneralInfo field of the CMP PKIMessage header of a request +added to the generalInfo field of the CMP PKIMessage header of a request message sent with this context. OSSL_CMP_CTX_reset_geninfo_ITAVs() clears any ITAVs that were added by OSSL_CMP_CTX_push0_geninfo_ITAV(). +OSSL_CMP_CTX_get0_geninfo_ITAVs() returns the list of ITAVs set in I +for inclusion in the generalInfo field of the CMP PKIMessage header of requests +or NULL if not set. + OSSL_CMP_CTX_set1_extraCertsOut() sets the stack of extraCerts that will be sent to remote. @@ -737,6 +744,7 @@ OSSL_CMP_CTX_get_http_cb_arg(), OSSL_CMP_CTX_get_transfer_cb_arg(), OSSL_CMP_CTX_get0_trusted(), OSSL_CMP_CTX_get0_untrusted(), +OSSL_CMP_CTX_get0_geninfo_ITAVs(), OSSL_CMP_CTX_get0_newPkey(), OSSL_CMP_CTX_get_certConf_cb_arg(), OSSL_CMP_CTX_get0_statusString(), @@ -841,10 +849,11 @@ in OpenSSL 3.2. OSSL_CMP_CTX_reset_geninfo_ITAVs() was added in OpenSSL 3.0.8. +OSSL_CMP_CTX_set1_serialNumber(), OSSL_CMP_CTX_get0_libctx(), OSSL_CMP_CTX_get0_propq(), and OSSL_CMP_CTX_get0_validatedSrvCert() were added in OpenSSL 3.2. -OSSL_CMP_CTX_set1_serialNumber() was added in OpenSSL 3.2. +OSSL_CMP_CTX_get0_geninfo_ITAVs() was added in OpenSSL 3.3. =head1 COPYRIGHT diff --git a/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod b/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod index 36bdf1917f..6e79e9a0e3 100644 --- a/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod +++ b/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod @@ -3,7 +3,8 @@ =head1 NAME OSSL_CMP_HDR_get0_transactionID, -OSSL_CMP_HDR_get0_recipNonce +OSSL_CMP_HDR_get0_recipNonce, +OSSL_CMP_HDR_get0_geninfo_ITAVs - functions manipulating CMP message headers =head1 SYNOPSIS @@ -14,6 +15,8 @@ OSSL_CMP_HDR_get0_recipNonce OSSL_CMP_PKIHEADER *hdr); ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr); + STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr); =head1 DESCRIPTION @@ -22,6 +25,9 @@ PKIHeader. OSSL_CMP_HDR_get0_recipNonce returns the recipient nonce of the given PKIHeader. +OSSL_CMP_HDR_get0_geninfo_ITAVs() returns the list of ITAVs +in the generalInfo field of the given PKIHeader. + =head1 NOTES CMP is defined in RFC 4210. @@ -35,6 +41,8 @@ or NULL if the respective entry does not exist and on error. The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_HDR_get0_geninfo_ITAVs() was added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OSSL_CMP_ITAV_set0.pod b/doc/man3/OSSL_CMP_ITAV_set0.pod index 5dd9bcb266..13d7868a6d 100644 --- a/doc/man3/OSSL_CMP_ITAV_set0.pod +++ b/doc/man3/OSSL_CMP_ITAV_set0.pod @@ -6,7 +6,9 @@ OSSL_CMP_ITAV_create, OSSL_CMP_ITAV_set0, OSSL_CMP_ITAV_get0_type, OSSL_CMP_ITAV_get0_value, -OSSL_CMP_ITAV_push0_stack_item +OSSL_CMP_ITAV_push0_stack_item, +OSSL_CMP_ITAV_new0_certProfile, +OSSL_CMP_ITAV_get0_certProfile - OSSL_CMP_ITAV utility functions =head1 SYNOPSIS @@ -20,6 +22,10 @@ OSSL_CMP_ITAV_push0_stack_item 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, OSSL_CMP_ITAV *itav); + OSSL_CMP_ITAV + *OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) *certProfile); + int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav, + STACK_OF(ASN1_UTF8STRING) **out); =head1 DESCRIPTION @@ -43,21 +49,37 @@ the I as generic B pointer. OSSL_CMP_ITAV_push0_stack_item() pushes I to the stack pointed to by I<*itav_sk_p>. It creates a new stack if I<*itav_sk_p> points to NULL. +OSSL_CMP_ITAV_new0_certProfile() creates a new B structure +of type B that includes the optionally given list of profile names. +On success, ownership of the list is with the new B structure. + +OSSL_CMP_ITAV_get0_certProfile() on success assigns to I<*out> +an internal pointer to the +list of certificate profile names contained in the infoValue field of I. +The pointer may be NULL if no profile name is included. +It is an error if the infoType of I is not B. + =head1 NOTES -CMP is defined in RFC 4210 (and CRMF in RFC 4211). +CMP is defined in RFC 4210 and RFC 9480 (and CRMF in RFC 4211). + +OIDs to use as types in B can be found at +L. +The respective OpenSSL NIDs, such as B, +are defined in the F<< >> header file. =head1 RETURN VALUES -OSSL_CMP_ITAV_create() returns a pointer to the ITAV structure on success, -or NULL on error. +OSSL_CMP_ITAV_create() and OSSL_CMP_ITAV_new0_certProfile() +return a pointer to an ITAV structure on success, or NULL on error. OSSL_CMP_ITAV_set0() does not return a value. OSSL_CMP_ITAV_get0_type() and OSSL_CMP_ITAV_get0_value() return the respective pointer or NULL if their input is NULL. -OSSL_CMP_ITAV_push0_stack_item() returns 1 on success, 0 on error. +OSSL_CMP_ITAV_push0_stack_item() and OSSL_CMP_ITAV_get0_certProfile() +return 1 on success, 0 on error. =head1 EXAMPLES @@ -96,6 +118,9 @@ L, L, L The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_ITAV_new0_certProfile() and OSSL_CMP_ITAV_get0_certProfile() +were added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. diff --git a/include/openssl/cmp.h.in b/include/openssl/cmp.h.in index 5bd8beb57a..fa4fe000ba 100644 --- a/include/openssl/cmp.h.in +++ b/include/openssl/cmp.h.in @@ -261,6 +261,10 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p, OSSL_CMP_ITAV *itav); void OSSL_CMP_ITAV_free(OSSL_CMP_ITAV *itav); +OSSL_CMP_ITAV *OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) + *certProfile); +int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav, + STACK_OF(ASN1_UTF8STRING) **out); OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts); int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out); @@ -351,6 +355,8 @@ int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, int OSSL_CMP_CTX_set1_recipient(OSSL_CMP_CTX *ctx, const X509_NAME *name); int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav); int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx); +STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_CTX_get0_geninfo_ITAVs(const OSSL_CMP_CTX *ctx); int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx, STACK_OF(X509) *extraCertsOut); /* certificate template: */ @@ -403,6 +409,8 @@ OSSL_CMP_STATUSINFO_new(int status, int fail_info, const char *text); ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const OSSL_CMP_PKIHEADER *hdr); ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr); +STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr); /* from cmp_msg.c */ OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg); diff --git a/include/openssl/cmperr.h b/include/openssl/cmperr.h index 57a6effbe3..dec9e0be45 100644 --- a/include/openssl/cmperr.h +++ b/include/openssl/cmperr.h @@ -98,6 +98,7 @@ # define CMP_R_TRANSACTIONID_UNMATCHED 152 # define CMP_R_TRANSFER_ERROR 159 # define CMP_R_UNCLEAN_CTX 191 +# define CMP_R_UNEXPECTED_CERTPROFILE 196 # define CMP_R_UNEXPECTED_PKIBODY 133 # define CMP_R_UNEXPECTED_PKISTATUS 185 # define CMP_R_UNEXPECTED_PVNO 153 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 5ab2ca3fd7..869bab7c99 100644 --- a/test/recipes/80-test_cmp_http_data/test_commands.csv +++ b/test/recipes/80-test_cmp_http_data/test_commands.csv @@ -77,6 +77,11 @@ 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,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,,,,, +0,profile extra argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,profile1,profile2,,, +,,,,,,,,,,,,,,,,,,, 1,geninfo, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int:987,BLANK,,BLANK, 0,geninfo missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,,,,, 0,geninfo bad syntax: leading '.', -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,.1.2.3:int:987,BLANK,,BLANK, diff --git a/util/libcrypto.num b/util/libcrypto.num index c9941a383b..60f320c33a 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5536,4 +5536,8 @@ 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 +OSSL_CMP_CTX_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP +OSSL_CMP_HDR_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP +OSSL_CMP_ITAV_new0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP +OSSL_CMP_ITAV_get0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP EVP_DigestSqueeze ? 3_3_0 EXIST::FUNCTION: