From 3f6b76eb54583bfe05e4289a72a04e5b2d348921 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Thu, 10 Jul 2025 17:34:26 +0200 Subject: [PATCH 1/4] OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR: use new TA(s) for whole transaction (also pkiconf); update doc --- crypto/cmp/cmp_vfy.c | 25 ++++++++++++++++++------- doc/man3/OSSL_CMP_CTX_new.pod | 14 +++++++++----- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 47bf38b2af..225f5ba944 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -319,9 +319,11 @@ static int check_cert_path(const OSSL_CMP_CTX *ctx, X509_STORE *store, /* * Exceptional handling for 3GPP TS 33.310 [3G/LTE Network Domain Security * (NDS); Authentication Framework (AF)], only to use for IP messages - * and if the ctx option is explicitly set: use self-issued certificates - * from extraCerts as trust anchor to validate sender cert - - * provided it also can validate the newly enrolled certificate + * and if the ctx option is explicitly set: use self-issued certificates from + * extraCerts as trust anchors when validating the CMP message protection cert + * in this and any subsequent responses from the server in the same transaction, + * but only if these trust anchors can also be used for validating + * the newly enrolled certificate received in the IP message. */ static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, X509 *scrt) @@ -358,6 +360,14 @@ static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx, */ valid = OSSL_CMP_validate_cert_path(ctx, store, newcrt); X509_free(newcrt); + + /* + * on success, add self-issued extraCerts to trust store, + * for use with validating any subsequent responses, such as pkiconf + */ + if (valid && (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, msg->extraCerts, + 1 /* self-issued only */))) + return 0; } err: @@ -552,10 +562,11 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) * (in this order) and is path is validated against ctx->trusted. * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert(). * - * If ctx->permitTAInExtraCertsForIR is true and when validating a CMP IP msg, - * the trust anchor for validating the IP msg may be taken from msg->extraCerts - * if a self-issued certificate is found there that can be used to - * validate the enrolled certificate returned in the IP. + * If ctx->permitTAInExtraCertsForIR is true, when validating a CMP IP message, + * trust anchors for validating the IP message (and any subsequent responses + * by the server in the same transaction) may be taken from msg->extraCerts + * if self-issued certificates are found there that can also be used + * to validate the newly enrolled certificate returned in the IP msg. * This is according to the need given in 3GPP TS 33.310. * * Returns 1 on success, 0 on error or validation failed. diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod index ab7aaa453b..342d15753a 100644 --- a/doc/man3/OSSL_CMP_CTX_new.pod +++ b/doc/man3/OSSL_CMP_CTX_new.pod @@ -343,13 +343,17 @@ Else, 'digitalSignature' must be allowed by CMP signer certificates. =item B -Allow retrieving a trust anchor from extraCerts and using that -to validate the certificate chain of an IP message. This is a quirk option added to support 3GPP TS 33.310. +It allows using self-issued certificates from the extraCerts in an IP message +as trust anchors when validating the CMP message protection certificate +in this and any subsequent responses from the server in the same transaction, +but only if these trust anchors can also be used for validating +the newly enrolled certificate received in the IP message. -Note that using this option is dangerous as the certificate obtained -this way has not been authenticated (at least not at CMP level). -Taking it over as a trust anchor implements trust-on-first-use (TOFU). +Note that using this option is dangerous as the to-be-trusted certificates +obtained this way have not been authenticated (at least not at CMP level). +Taking them over as initial trust anchors +implements a form of trust-on-first-use (TOFU). =item B From 8d5a9726ec93233abbccb9aba5c69e1cb20538a0 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Thu, 10 Jul 2025 17:37:11 +0200 Subject: [PATCH 2/4] apps/cmp.c: add -ta_in_ip_extracerts option if OPENSSL_CMP_APP_ALLOW_UNSAFE is defined at build time Fixes #27888 --- apps/cmp.c | 29 ++++++++++++++++++++++++++++- doc/man1/openssl-cmp.pod.in | 20 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/apps/cmp.c b/apps/cmp.c index 6f2fea4f55..fd350563f0 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -87,6 +87,9 @@ static char *opt_srvcert = NULL; static char *opt_expect_sender = NULL; static int opt_ignore_keyusage = 0; static int opt_unprotected_errors = 0; +#ifdef OPENSSL_CMP_APP_ALLOW_UNSAFE +static int opt_ta_in_ip_extracerts = 0; +#endif static int opt_no_cache_extracerts = 0; static char *opt_srvcertout = NULL; static char *opt_extracertsout = NULL; @@ -253,7 +256,11 @@ typedef enum OPTION_choice { OPT_TRUSTED, OPT_UNTRUSTED, OPT_SRVCERT, OPT_EXPECT_SENDER, - OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, OPT_NO_CACHE_EXTRACERTS, + OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, +#ifdef OPENSSL_CMP_APP_ALLOW_UNSAFE + OPT_TA_IN_IP_EXTRACERTS, +#endif + OPT_NO_CACHE_EXTRACERTS, OPT_SRVCERTOUT, OPT_EXTRACERTSOUT, OPT_CACERTSOUT, OPT_OLDWITHOLD, OPT_NEWWITHNEW, OPT_NEWWITHOLD, OPT_OLDWITHNEW, OPT_CRLCERT, OPT_OLDCRL, OPT_CRLOUT, @@ -441,6 +448,14 @@ const OPTIONS cmp_options[] = { "certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf"}, {OPT_MORE_STR, 0, 0, "WARNING: This setting leads to behavior allowing violation of RFC 4210"}, +#ifdef OPENSSL_CMP_APP_ALLOW_UNSAFE + {"ta_in_ip_extracerts", OPT_TA_IN_IP_EXTRACERTS, '-', + "Permit using self-issued certificates from the extraCerts in an IP message"}, + {OPT_MORE_STR, 0, 0, + "as trust anchors under conditions defined by 3GPP TS 33.310"}, + {OPT_MORE_STR, 0, 0, + "WARNING: This setting leads to behavior allowing violation of RFC 9810"}, +#endif {"no_cache_extracerts", OPT_NO_CACHE_EXTRACERTS, '-', "Do not keep certificates received in the extraCerts CMP message field"}, { "srvcertout", OPT_SRVCERTOUT, 's', @@ -666,6 +681,9 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {&opt_trusted}, {&opt_untrusted}, {&opt_srvcert}, {&opt_expect_sender}, {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors}, +#ifdef OPENSSL_CMP_APP_ALLOW_UNSAFE + {(char **)&opt_ta_in_ip_extracerts}, +#endif {(char **)&opt_no_cache_extracerts}, {&opt_srvcertout}, {&opt_extracertsout}, {&opt_cacertsout}, {&opt_oldwithold}, {&opt_newwithnew}, {&opt_newwithold}, {&opt_oldwithnew}, @@ -1340,6 +1358,10 @@ static int setup_verification_ctx(OSSL_CMP_CTX *ctx) if (opt_unprotected_errors) (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1); +#ifdef OPENSSL_CMP_APP_ALLOW_UNSAFE + if (opt_ta_in_ip_extracerts) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR, 1); +#endif if (opt_out_trusted != NULL) { /* for use in OSSL_CMP_certConf_cb() */ X509_VERIFY_PARAM *out_vpm = NULL; @@ -2921,6 +2943,11 @@ static int get_opts(int argc, char **argv) case OPT_UNPROTECTED_ERRORS: opt_unprotected_errors = 1; break; +#ifdef OPENSSL_CMP_APP_ALLOW_UNSAFE + case OPT_TA_IN_IP_EXTRACERTS: + opt_ta_in_ip_extracerts = 1; + break; +#endif case OPT_NO_CACHE_EXTRACERTS: opt_no_cache_extracerts = 1; break; diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index f44615d1fc..00a3f08565 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -70,6 +70,7 @@ Server authentication options: [B<-expect_sender> I] [B<-ignore_keyusage>] [B<-unprotected_errors>] +[B<-ta_in_ip_extracerts>] [B<-no_cache_extracerts>] [B<-srvcertout> I] [B<-extracertsout> I] @@ -714,6 +715,23 @@ with a signature key." =back +=item B<-ta_in_ip_extracerts> + +This is a quirk option added to support 3GPP TS 33.310, +available only if OpenSSL has been built with B. +B This leads to behavior violating RFC 9810. + +It allows using self-issued certificates from the extraCerts in an IP message +as trust anchors when validating the CMP message protection certificate +in this and any subsequent responses from the server in the same transaction, +but only if these trust anchors can also be used for validating +the newly enrolled certificate received in the IP message. + +Note that using this option is dangerous as the to-be-trusted certificates +obtained this way have not been authenticated (at least not at CMP level). +Taking them over as initial trust anchors +implements a form of trust-on-first-use (TOFU). + =item B<-no_cache_extracerts> Do not cache certificates in the extraCerts field of CMP messages received. @@ -1529,6 +1547,8 @@ and B<-rsp_crl> options were added in OpenSSL 3.4. B<-centralkeygen>, b<-newkeyout>, B<-rsp_key> and B<-rsp_keypass> were added in OpenSSL 3.5. +The B<-ta_in_ip_extracerts> quirk option was added in OpenSSL 3.6. + =head1 COPYRIGHT Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. From 873e49572c274c2a71b914227d33efc02a28652a Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Sat, 26 Jul 2025 13:11:36 +0200 Subject: [PATCH 3/4] fixup! apps/cmp.c: add -ta_in_ip_extracerts option if OPENSSL_CMP_APP_ALLOW_UNSAFE is defined at build time --- doc/man1/openssl-cmp.pod.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index 00a3f08565..5d11754c6a 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -719,12 +719,12 @@ with a signature key." This is a quirk option added to support 3GPP TS 33.310, available only if OpenSSL has been built with B. -B This leads to behavior violating RFC 9810. +B This leads to behavior violating RFCs 4210 and 9810. It allows using self-issued certificates from the extraCerts in an IP message as trust anchors when validating the CMP message protection certificate in this and any subsequent responses from the server in the same transaction, -but only if these trust anchors can also be used for validating +but only if these extraCerts can also be used as trust anchors for validating the newly enrolled certificate received in the IP message. Note that using this option is dangerous as the to-be-trusted certificates From fd6662cf755b6b643457b69ee36644a0831590dc Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Sat, 26 Jul 2025 13:12:22 +0200 Subject: [PATCH 4/4] fixup! OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR: use new TA(s) for whole transaction (also pkiconf); update doc --- crypto/cmp/cmp_vfy.c | 25 ++++++++++++------------- doc/man3/OSSL_CMP_CTX_new.pod | 3 ++- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 225f5ba944..0b06d7ec8c 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -322,7 +322,7 @@ static int check_cert_path(const OSSL_CMP_CTX *ctx, X509_STORE *store, * and if the ctx option is explicitly set: use self-issued certificates from * extraCerts as trust anchors when validating the CMP message protection cert * in this and any subsequent responses from the server in the same transaction, - * but only if these trust anchors can also be used for validating + * but only if these extraCerts can also be used as trust anchors for validating * the newly enrolled certificate received in the IP message. */ static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx, @@ -330,12 +330,20 @@ static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx, { int valid = 0; X509_STORE *store; + STACK_OF(X509) *extraCerts; if (!ctx->permitTAInExtraCertsForIR) return 0; + /* + * Initially, use extraCerts from the IP message. + * For subsequent msgs (pollRep or PKIConf) in the same transaction, + * use extraCertsIn remembered from earlier message (typically, the IP message). + * The extraCertsIn field will be cleared by OSSL_CMP_CTX_reinit(). + */ + extraCerts = ctx->extraCertsIn == NULL ? msg->extraCerts : ctx->extraCertsIn; if ((store = X509_STORE_new()) == NULL - || !ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts, + || !ossl_cmp_X509_STORE_add1_certs(store, extraCerts, 1 /* self-issued only */)) goto err; @@ -344,7 +352,7 @@ static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx, if (!valid) { ossl_cmp_warn(ctx, "also exceptional 3GPP mode cert path validation failed"); - } else { + } else if (OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_IP) { /* * verify that the newly enrolled certificate (which assumed rid == * OSSL_CMP_CERTREQID) can also be validated with the same trusted store @@ -360,14 +368,6 @@ static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx, */ valid = OSSL_CMP_validate_cert_path(ctx, store, newcrt); X509_free(newcrt); - - /* - * on success, add self-issued extraCerts to trust store, - * for use with validating any subsequent responses, such as pkiconf - */ - if (valid && (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, msg->extraCerts, - 1 /* self-issued only */))) - return 0; } err: @@ -434,8 +434,7 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, { int ret = 0; - if (ctx->permitTAInExtraCertsForIR - && OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_IP) + if (ctx->permitTAInExtraCertsForIR) ossl_cmp_info(ctx, mode_3gpp ? "normal mode failed; trying now 3GPP mode trusting extraCerts" : "trying first normal mode using trust store"); diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod index 342d15753a..a529b7cd01 100644 --- a/doc/man3/OSSL_CMP_CTX_new.pod +++ b/doc/man3/OSSL_CMP_CTX_new.pod @@ -344,10 +344,11 @@ Else, 'digitalSignature' must be allowed by CMP signer certificates. =item B This is a quirk option added to support 3GPP TS 33.310. +It leads to behavior violating RFCs 4210 and 9810. It allows using self-issued certificates from the extraCerts in an IP message as trust anchors when validating the CMP message protection certificate in this and any subsequent responses from the server in the same transaction, -but only if these trust anchors can also be used for validating +but only if these extraCerts can also be used as trust anchors for validating the newly enrolled certificate received in the IP message. Note that using this option is dangerous as the to-be-trusted certificates