From 15076c26d794dbbdc5413a72e7feded0c9a2ba07 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Fri, 4 Sep 2020 15:24:14 +0200 Subject: Strengthen chain building for CMP * Add -own_trusted option to CMP app * Add OSSL_CMP_CTX_build_cert_chain() * Add optional trust store arg to ossl_cmp_build_cert_chain() * Extend the tests in cmp_protect_test.c and the documentation accordingly Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/12791) --- apps/cmp.c | 34 ++++++++++++------ crypto/cmp/cmp_ctx.c | 28 +++++++++++++++ crypto/cmp/cmp_err.c | 2 ++ crypto/cmp/cmp_local.h | 1 + crypto/cmp/cmp_protect.c | 2 +- crypto/cmp/cmp_util.c | 58 ++++++++++++++---------------- crypto/err/openssl.txt | 1 + doc/internal/man3/ossl_cmp_msg_protect.pod | 30 +++++++--------- doc/man1/openssl-cmp.pod.in | 14 +++++++- doc/man3/OSSL_CMP_CTX_new.pod | 17 +++++++++ include/openssl/cmp.h | 6 ++-- include/openssl/cmperr.h | 1 + test/cmp_protect_test.c | 28 +++++++++++++-- util/libcrypto.num | 1 + 14 files changed, 157 insertions(+), 66 deletions(-) diff --git a/apps/cmp.c b/apps/cmp.c index 1af27f7881..799ec34e1f 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -97,6 +97,7 @@ static char *opt_cacertsout = NULL; static char *opt_ref = NULL; static char *opt_secret = NULL; static char *opt_cert = NULL; +static char *opt_own_trusted = NULL; static char *opt_key = NULL; static char *opt_keypass = NULL; static char *opt_digest = NULL; @@ -218,7 +219,7 @@ typedef enum OPTION_choice { OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, OPT_EXTRACERTSOUT, OPT_CACERTSOUT, - OPT_REF, OPT_SECRET, OPT_CERT, OPT_KEY, OPT_KEYPASS, + OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS, OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS, OPT_UNPROTECTED_REQUESTS, @@ -383,6 +384,8 @@ const OPTIONS cmp_options[] = { "Client's current certificate (needed unless using -secret for PBM);"}, {OPT_MORE_STR, 0, 0, "any further certs included are appended in extraCerts field"}, + {"own_trusted", OPT_OWN_TRUSTED, 's', + "Optional certs to verify chain building for own CMP signer cert"}, {"key", OPT_KEY, 's', "Private key for the client's current certificate"}, {"keypass", OPT_KEYPASS, 's', "Client private key (and cert and old cert file) pass phrase source"}, @@ -536,7 +539,8 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors}, {&opt_extracertsout}, {&opt_cacertsout}, - {&opt_ref}, {&opt_secret}, {&opt_cert}, {&opt_key}, {&opt_keypass}, + {&opt_ref}, {&opt_secret}, + {&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass}, {&opt_digest}, {&opt_mac}, {&opt_extracerts}, {(char **)&opt_unprotected_requests}, @@ -1595,6 +1599,7 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) if (opt_cert != NULL) { X509 *cert; STACK_OF(X509) *certs = NULL; + X509_STORE *own_trusted = NULL; int ok = 0; if (!load_cert_certs(opt_cert, &cert, &certs, 0, opt_keypass, @@ -1603,18 +1608,24 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) goto err; ok = OSSL_CMP_CTX_set1_cert(ctx, cert); X509_free(cert); - - if (ok) { - /* add any remaining certs to the list of untrusted certs */ - STACK_OF(X509) *untrusted = OSSL_CMP_CTX_get0_untrusted_certs(ctx); - ok = untrusted != NULL ? - X509_add_certs(untrusted, certs, - X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP) - : OSSL_CMP_CTX_set1_untrusted_certs(ctx, certs); + if (!ok) { + CMP_err("out of memory"); + } else { + if (opt_own_trusted != NULL) { + own_trusted = load_certstore(opt_own_trusted, + "trusted certs for verifying own CMP signer cert"); + ok = own_trusted != NULL + && set1_store_parameters(own_trusted) + && truststore_set_host_etc(own_trusted, NULL); + } + ok = ok && OSSL_CMP_CTX_build_cert_chain(ctx, own_trusted, certs); } + X509_STORE_free(own_trusted); sk_X509_pop_free(certs, X509_free); if (!ok) goto err; + } else if (opt_own_trusted != NULL) { + CMP_warn("-own_trusted option is ignored without -cert"); } if (!setup_certs(opt_extracerts, "extra certificates for CMP", ctx, @@ -2400,6 +2411,9 @@ static int get_opts(int argc, char **argv) case OPT_CERT: opt_cert = opt_str("cert"); break; + case OPT_OWN_TRUSTED: + opt_own_trusted = opt_str("own_trusted"); + break; case OPT_KEY: opt_key = opt_str("key"); break; diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c index 50c5d0e061..adb3ff564b 100644 --- a/crypto/cmp/cmp_ctx.c +++ b/crypto/cmp/cmp_ctx.c @@ -742,6 +742,34 @@ int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx, */ DEFINE_OSSL_CMP_CTX_set1_up_ref(cert, X509) +int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted, + STACK_OF(X509) *candidates) +{ + STACK_OF(X509) *chain; + + if (ctx == NULL) { + CMPerr(0, CMP_R_NULL_ARGUMENT); + return 0; + } + + if (ctx->untrusted_certs != NULL ? + !X509_add_certs(ctx->untrusted_certs, candidates, + X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP) : + !OSSL_CMP_CTX_set1_untrusted_certs(ctx, candidates)) + return 0; + + ossl_cmp_debug(ctx, "trying to build chain for own CMP signer cert"); + chain = ossl_cmp_build_cert_chain(ctx->libctx, ctx->propq, own_trusted, + ctx->untrusted_certs, ctx->cert); + if (chain == NULL) { + CMPerr(0, CMP_R_FAILED_BUILDING_OWN_CHAIN); + return 0; + } + ossl_cmp_debug(ctx, "success building chain for own CMP signer cert"); + sk_X509_pop_free(chain, X509_free); /* TODO(3.0) replace this by 'ctx->chain = chain;' when ctx->chain is available */ + return 1; +} + /* * Set the old certificate that we are updating in KUR * or the certificate to be revoked in RR, respectively. diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c index 19d1556426..260e8386d5 100644 --- a/crypto/cmp/cmp_err.c +++ b/crypto/cmp/cmp_err.c @@ -73,6 +73,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "error validating protection"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_SIGNATURE), "error validating signature"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_BUILDING_OWN_CHAIN), + "failed building own chain"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY), "failed extracting pubkey"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILURE_OBTAINING_RANDOM), diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h index a6e55cfd1b..e3dcb94704 100644 --- a/crypto/cmp/cmp_local.h +++ b/crypto/cmp/cmp_local.h @@ -747,6 +747,7 @@ int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt, const unsigned char *bytes, int len); STACK_OF(X509) *ossl_cmp_build_cert_chain(OPENSSL_CTX *libctx, const char *propq, + X509_STORE *store, STACK_OF(X509) *certs, X509 *cert); /* from cmp_ctx.c */ diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c index 140b1720c8..2a008bd0bf 100644 --- a/crypto/cmp/cmp_protect.c +++ b/crypto/cmp/cmp_protect.c @@ -152,7 +152,7 @@ int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg) ossl_cmp_debug(ctx, "trying to build chain for own CMP signer cert"); - chain = ossl_cmp_build_cert_chain(ctx->libctx, ctx->propq, + chain = ossl_cmp_build_cert_chain(ctx->libctx, ctx->propq, NULL, ctx->untrusted_certs, ctx->cert); res = X509_add_certs(msg->extraCerts, chain, X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c index c4797f1691..c2ee9b6e0d 100644 --- a/crypto/cmp/cmp_util.c +++ b/crypto/cmp/cmp_util.c @@ -206,56 +206,49 @@ int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs, } /*- - * Builds up the chain of intermediate CA certificates - * starting from the given certificate as high up as possible using - * the given list of candidate certificates, similarly to ssl_add_cert_chain(). + * Builds a certificate chain starting from + * using the optional list of intermediate CA certificates . + * If is NULL builds the chain as far down as possible, ignoring errors. + * Else the chain must reach a trust anchor contained in . * - * Intended use of this function is to find all the certificates above the trust - * anchor needed to verify an EE's own certificate. Those are supposed to be - * included in the ExtraCerts field of every first CMP message of a transaction - * when MSG_SIG_ALG is utilized. + * Returns NULL on error, else a pointer to a stack of (up_ref'ed) certificates + * starting with given EE certificate and followed by all available intermediate + * certificates down towards any trust anchor but without including the latter. * - * NOTE: This allocates a stack and increments the reference count of each cert, - * so when not needed any more the stack and all its elements should be freed. + * NOTE: If a non-NULL stack is returned the caller is responsible for freeing. * NOTE: In case there is more than one possibility for the chain, * OpenSSL seems to take the first one; check X509_verify_cert() for details. - * - * returns a pointer to a stack of (up_ref'ed) X509 certificates containing: - * - the EE certificate given in the function arguments (cert) - * - all intermediate certificates up the chain toward the trust anchor - * whereas the (self-signed) trust anchor is not included - * returns NULL on error */ +/* TODO this should be of more general interest and thus be exported. */ STACK_OF(X509) *ossl_cmp_build_cert_chain(OPENSSL_CTX *libctx, const char *propq, + X509_STORE *store, STACK_OF(X509) *certs, X509 *cert) { STACK_OF(X509) *chain = NULL, *result = NULL; - X509_STORE *store = X509_STORE_new(); + X509_STORE *ts = store == NULL ? X509_STORE_new() : store; X509_STORE_CTX *csc = NULL; - if (certs == NULL || cert == NULL || store == NULL) { + if (ts == NULL || cert == NULL) { CMPerr(0, CMP_R_NULL_ARGUMENT); goto err; } - csc = X509_STORE_CTX_new_with_libctx(libctx, propq); - if (csc == NULL) + if ((csc = X509_STORE_CTX_new_with_libctx(libctx, propq)) == NULL) goto err; - - if (!ossl_cmp_X509_STORE_add1_certs(store, certs, 0) - || !X509_STORE_CTX_init(csc, store, cert, NULL)) + if (store == NULL && certs != NULL + && !ossl_cmp_X509_STORE_add1_certs(ts, certs, 0)) goto err; + if (!X509_STORE_CTX_init(csc, ts, cert, + store == NULL ? NULL : certs)) + goto err; + /* disable any cert status/revocation checking etc. */ + X509_VERIFY_PARAM_clear_flags(X509_STORE_CTX_get0_param(csc), + ~(X509_V_FLAG_USE_CHECK_TIME + | X509_V_FLAG_NO_CHECK_TIME)); - (void)ERR_set_mark(); - /* - * ignore return value as it would fail without trust anchor given in store - */ - (void)X509_verify_cert(csc); - - /* don't leave any new errors in the queue */ - (void)ERR_pop_to_mark(); - + if (X509_verify_cert(csc) <= 0 && store != NULL) + goto err; chain = X509_STORE_CTX_get0_chain(csc); /* result list to store the up_ref'ed not self-signed certificates */ @@ -269,7 +262,8 @@ STACK_OF(X509) } err: - X509_STORE_free(store); + if (store == NULL) + X509_STORE_free(ts); X509_STORE_CTX_free(csc); return result; } diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 592fb6b50a..7c37a3e56e 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2114,6 +2114,7 @@ CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection CMP_R_ERROR_VALIDATING_SIGNATURE:171:error validating signature +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 diff --git a/doc/internal/man3/ossl_cmp_msg_protect.pod b/doc/internal/man3/ossl_cmp_msg_protect.pod index 6c33db6954..39f5146530 100644 --- a/doc/internal/man3/ossl_cmp_msg_protect.pod +++ b/doc/internal/man3/ossl_cmp_msg_protect.pod @@ -14,6 +14,7 @@ ossl_cmp_msg_add_extraCerts STACK_OF(X509) *ossl_cmp_build_cert_chain(OPENSSL_CTX *libctx, const char *propq, + X509_STORE *store, STACK_OF(X509) *certs, X509 *cert); ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg); @@ -22,19 +23,15 @@ ossl_cmp_msg_add_extraCerts =head1 DESCRIPTION -ossl_cmp_build_cert_chain() builds up the chain of intermediate CA certificates -starting from the given certificate I as high up as possible using -the given list of candidate certificates, similarly to ssl_add_cert_chain(). +ossl_cmp_build_cert_chain() builds a certificate chain starting from I +using the optional list of intermediate CA certificates I. +If I is NULL builds the chain as far down as possible, ignoring errors. +Else the chain must reach a trust anchor contained in I. It internally uses a B structure associated with the library context I and property query string I, both of which may be NULL. -Intended use of this function is to find all the certificates above the trust -anchor needed to verify an EE's own certificate. -Those are supposed to be included in the ExtraCerts field of every first -CMP message of a transaction when MSG_SIG_ALG is utilized. -This allocates a stack and increments the reference count of each cert, -so when not needed any more the stack and all its elements should be freed. +If a non-NULL stack is returned the caller is responsible for freeing it. In case there is more than one possibility for the chain, -OpenSSL seems to take the first one; check X509_verify_cert() for details. +OpenSSL seems to take the first one; check L for details. ossl_cmp_calc_protection() calculates the protection for the given I according to the algorithm and parameters in the message header's protectionAlg @@ -46,10 +43,10 @@ If there is a secretValue it selects PBMAC, else if there is a protection cert it selects Signature and uses L. It also sets the protectionAlg field in the message header accordingly. -ossl_cmp_msg_add_extraCerts() adds elements to the extraCerts field in the given -message I. It tries to build the certificate chain of the client cert in -the I if present by using certificates in ctx->untrusted_certs; -if no untrusted certs are set, it will at least add the client certificate. +ossl_cmp_msg_add_extraCerts() adds elements to the extraCerts field in I. +If signature-based message protection is used it adds first the CMP signer cert +ctx->cert and then its chain ctx->chain. If this chain is not present in I +tries to build it using ctx->untrusted_certs and caches the result in ctx->chain. In any case all the certificates explicitly specified to be sent out (i.e., IextraCertsOut>) are added. Note that it will NOT add the root certificate of the chain, i.e, the trust anchor (unless it is part of extraCertsOut). @@ -62,9 +59,8 @@ CMP is defined in RFC 4210 (and CRMF in RFC 4211). ossl_cmp_build_cert_chain() returns NULL on error, else a pointer to a stack of (up_ref'ed) certificates -containing the EE certificate given in the function arguments (cert) -and all intermediate certificates up the chain toward the trust anchor. -The (self-signed) trust anchor is not included. +starting with given EE certificate and followed by all available intermediate +certificates down towards (but excluding) any trusted root certificate. ossl_cmp_calc_protection() returns the protection on success, else NULL. diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index d91bd31684..3dc193cd4d 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -32,6 +32,7 @@ B B [B<-ref> I] [B<-secret> I] [B<-cert> I] +[B<-own_trusted> I] [B<-key> I] [B<-keypass> I] [B<-digest> I] @@ -617,7 +618,7 @@ B section in L. =item B<-cert> I -The client's current certificate. +The client's current CMP signer certificate. Requires the corresponding key to be given with B<-key>. The subject of this certificate will be used as sender of outgoing CMP messages, while the subject of B<-oldcert> or B<-subjectName> may provide fallback values. @@ -629,6 +630,16 @@ For Key Update Request (KUR) messages this is also used as the certificate to be updated if the B<-oldcert> option is not given. If the file includes further certs, they are appended to the untrusted certs. +=item B<-own_trusted> I + +If this list of certificates is provided then the chain built for +the CMP signer certificate given with the B<-cert> option is verified +using the given certificates as trust anchors. + +Multiple filenames may be given, separated by commas and/or whitespace +(where in the latter case the whole argument must be enclosed in "..."). +Each source may contain multiple certificates. + =item B<-key> I The corresponding private key file for the client's current certificate given in @@ -694,6 +705,7 @@ The only value with effect is B. =item B<-otherpass> I Pass phrase source for certificate given with the B<-trusted>, B<-untrusted>, +B<-own_trusted>, B<-out_trusted>, B<-extracerts>, B<-tls_extra>, or B<-tls_trusted> options. If not given here, the password will be prompted for if needed. diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod index fda5150434..f4425d511a 100644 --- a/doc/man3/OSSL_CMP_CTX_new.pod +++ b/doc/man3/OSSL_CMP_CTX_new.pod @@ -29,6 +29,7 @@ OSSL_CMP_CTX_get0_trustedStore, OSSL_CMP_CTX_set1_untrusted_certs, OSSL_CMP_CTX_get0_untrusted_certs, OSSL_CMP_CTX_set1_cert, +OSSL_CMP_CTX_build_cert_chain, OSSL_CMP_CTX_set1_pkey, OSSL_CMP_CTX_set1_referenceValue, OSSL_CMP_CTX_set1_secretValue, @@ -104,6 +105,8 @@ OSSL_CMP_CTX_set1_senderNonce /* client authentication: */ int OSSL_CMP_CTX_set1_cert(OSSL_CMP_CTX *ctx, X509 *cert); + int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted, + STACK_OF(X509) *candidates); int OSSL_CMP_CTX_set1_pkey(OSSL_CMP_CTX *ctx, EVP_PKEY *pkey); int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx, const unsigned char *ref, int len); @@ -436,6 +439,20 @@ messages, while the subject of any cert set via B and any value set via B are used as fallback. The B argument may be NULL to clear the entry. +OSSL_CMP_CTX_build_cert_chain() builds a certificate chain for the CMP signer +certificate previously set in the B. It adds the optional B, +a list of intermediate CA certs that may already constitute the targeted chain, +to the untrusted certs that may already exist in the B. +Then the function uses this augumented set of certs for chain construction. +If I is NULL it builds the chain as far down as possible and +ignores any verification errors. Else the CMP signer certificate must be +verifiable where the chain reaches a trust anchor contained in I. +On success the function stores the resulting chain in B +for inclusion in the extraCerts field of signature-protected messages. +Calling this function is optional; by default a chain construction +is performed on demand that is equivalent to calling this function +with the B and I arguments being NULL. + OSSL_CMP_CTX_set1_pkey() sets the private key corresponding to the protection certificate B set via B. This key is used create signature-based protection (protectionAlg = MSG_SIG_ALG) diff --git a/include/openssl/cmp.h b/include/openssl/cmp.h index d12d48ba4f..edab120364 100644 --- a/include/openssl/cmp.h +++ b/include/openssl/cmp.h @@ -295,6 +295,8 @@ int OSSL_CMP_CTX_set1_untrusted_certs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs); STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted_certs(const OSSL_CMP_CTX *ctx); /* client authentication: */ int OSSL_CMP_CTX_set1_cert(OSSL_CMP_CTX *ctx, X509 *cert); +int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted, + STACK_OF(X509) *candidates); int OSSL_CMP_CTX_set1_pkey(OSSL_CMP_CTX *ctx, EVP_PKEY *pkey); int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx, const unsigned char *ref, int len); @@ -322,6 +324,8 @@ int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav); /* certificate confirmation: */ typedef int (*OSSL_CMP_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, const char **txt); +int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, + const char **text); int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb); int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg); void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx); @@ -437,8 +441,6 @@ X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type, OSSL_CMP_exec_certreq(ctx, OSSL_CMP_KUR, NULL) int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, const OSSL_CRMF_MSG *crm, int *checkAfter); -int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, - const char **text); X509 *OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx); STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx); diff --git a/include/openssl/cmperr.h b/include/openssl/cmperr.h index 2ae82974a9..190e1a96bd 100644 --- a/include/openssl/cmperr.h +++ b/include/openssl/cmperr.h @@ -66,6 +66,7 @@ int ERR_load_CMP_strings(void); # define CMP_R_ERROR_UNEXPECTED_CERTCONF 160 # define CMP_R_ERROR_VALIDATING_PROTECTION 140 # define CMP_R_ERROR_VALIDATING_SIGNATURE 171 +# define CMP_R_FAILED_BUILDING_OWN_CHAIN 164 # define CMP_R_FAILED_EXTRACTING_PUBKEY 141 # define CMP_R_FAILURE_OBTAINING_RANDOM 110 # define CMP_R_FAIL_INFO_OUT_OF_RANGE 129 diff --git a/test/cmp_protect_test.c b/test/cmp_protect_test.c index 66cc6af370..7132ccc5cb 100644 --- a/test/cmp_protect_test.c +++ b/test/cmp_protect_test.c @@ -333,8 +333,9 @@ static int execute_cmp_build_cert_chain_test(CMP_PROTECT_TEST_FIXTURE *fixture) { int ret = 0; OSSL_CMP_CTX *ctx = fixture->cmp_ctx; + X509_STORE *store; STACK_OF(X509) *chain = - ossl_cmp_build_cert_chain(ctx->libctx, ctx->propq, + ossl_cmp_build_cert_chain(ctx->libctx, ctx->propq, NULL, fixture->certs, fixture->cert); if (TEST_ptr(chain)) { @@ -342,12 +343,30 @@ static int execute_cmp_build_cert_chain_test(CMP_PROTECT_TEST_FIXTURE *fixture) ret = TEST_int_eq(0, STACK_OF_X509_cmp(chain, fixture->chain)); sk_X509_pop_free(chain, X509_free); } + if (!ret) + return 0; + + if (TEST_ptr(store = X509_STORE_new()) + && TEST_true(X509_STORE_add_cert(store, root))) { + X509_VERIFY_PARAM_set_flags(X509_STORE_get0_param(store), + X509_V_FLAG_NO_CHECK_TIME); + chain = ossl_cmp_build_cert_chain(ctx->libctx, ctx->propq, + store, fixture->certs, fixture->cert); + ret = TEST_int_eq(fixture->expected, chain != NULL); + if (ret && chain != NULL) { + /* Check whether chain built is equal to the expected one */ + ret = TEST_int_eq(0, STACK_OF_X509_cmp(chain, fixture->chain)); + sk_X509_pop_free(chain, X509_free); + } + } + X509_STORE_free(store); return ret; } static int test_cmp_build_cert_chain(void) { SETUP_TEST_FIXTURE(CMP_PROTECT_TEST_FIXTURE, set_up); + fixture->expected = 1; fixture->cert = endentity2; if (!TEST_ptr(fixture->certs = sk_X509_new_null()) || !TEST_ptr(fixture->chain = sk_X509_new_null()) @@ -366,6 +385,7 @@ static int test_cmp_build_cert_chain(void) static int test_cmp_build_cert_chain_missing_intermediate(void) { SETUP_TEST_FIXTURE(CMP_PROTECT_TEST_FIXTURE, set_up); + fixture->expected = 0; fixture->cert = endentity2; if (!TEST_ptr(fixture->certs = sk_X509_new_null()) || !TEST_ptr(fixture->chain = sk_X509_new_null()) @@ -379,9 +399,10 @@ static int test_cmp_build_cert_chain_missing_intermediate(void) return result; } -static int test_cmp_build_cert_chain_missing_root(void) +static int test_cmp_build_cert_chain_no_root(void) { SETUP_TEST_FIXTURE(CMP_PROTECT_TEST_FIXTURE, set_up); + fixture->expected = 1; fixture->cert = endentity2; if (!TEST_ptr(fixture->certs = sk_X509_new_null()) || !TEST_ptr(fixture->chain = sk_X509_new_null()) @@ -399,6 +420,7 @@ static int test_cmp_build_cert_chain_missing_root(void) static int test_cmp_build_cert_chain_no_certs(void) { SETUP_TEST_FIXTURE(CMP_PROTECT_TEST_FIXTURE, set_up); + fixture->expected = 0; fixture->cert = endentity2; if (!TEST_ptr(fixture->certs = sk_X509_new_null()) || !TEST_ptr(fixture->chain = sk_X509_new_null()) @@ -556,7 +578,7 @@ int setup_tests(void) #ifndef OPENSSL_NO_EC ADD_TEST(test_cmp_build_cert_chain); - ADD_TEST(test_cmp_build_cert_chain_missing_root); + ADD_TEST(test_cmp_build_cert_chain_no_root); ADD_TEST(test_cmp_build_cert_chain_missing_intermediate); ADD_TEST(test_cmp_build_cert_chain_no_certs); #endif diff --git a/util/libcrypto.num b/util/libcrypto.num index cfe1cb8bc6..25ee44144b 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4774,6 +4774,7 @@ OSSL_CMP_CTX_set1_untrusted_certs ? 3_0_0 EXIST::FUNCTION:CMP OSSL_CMP_CTX_get0_untrusted_certs ? 3_0_0 EXIST::FUNCTION:CMP OSSL_CMP_CTX_set1_cert ? 3_0_0 EXIST::FUNCTION:CMP OSSL_CMP_CTX_set1_pkey ? 3_0_0 EXIST::FUNCTION:CMP +OSSL_CMP_CTX_build_cert_chain ? 3_0_0 EXIST::FUNCTION:CMP OSSL_CMP_CTX_set1_referenceValue ? 3_0_0 EXIST::FUNCTION:CMP OSSL_CMP_CTX_set1_secretValue ? 3_0_0 EXIST::FUNCTION:CMP OSSL_CMP_CTX_set1_recipient ? 3_0_0 EXIST::FUNCTION:CMP -- cgit v1.2.1