diff options
author | Dr. David von Oheimb <David.von.Oheimb@siemens.com> | 2020-09-04 15:24:14 +0200 |
---|---|---|
committer | Dr. David von Oheimb <David.von.Oheimb@siemens.com> | 2020-09-05 18:11:12 +0200 |
commit | 15076c26d794dbbdc5413a72e7feded0c9a2ba07 (patch) | |
tree | 19ed48870fcc21002b9053e3e9d3f8ca5d584be7 /crypto/cmp | |
parent | 39082af2fa6549c3d92c917ea5a423bca57c7b42 (diff) |
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 <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12791)
Diffstat (limited to 'crypto/cmp')
-rw-r--r-- | crypto/cmp/cmp_ctx.c | 28 | ||||
-rw-r--r-- | crypto/cmp/cmp_err.c | 2 | ||||
-rw-r--r-- | crypto/cmp/cmp_local.h | 1 | ||||
-rw-r--r-- | crypto/cmp/cmp_protect.c | 2 | ||||
-rw-r--r-- | crypto/cmp/cmp_util.c | 58 |
5 files changed, 58 insertions, 33 deletions
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 <cert> as high up as possible using - * the given list of candidate certificates, similarly to ssl_add_cert_chain(). + * Builds a certificate chain starting from <cert> + * using the optional list of intermediate CA certificates <certs>. + * If <store> is NULL builds the chain as far down as possible, ignoring errors. + * Else the chain must reach a trust anchor contained in <store>. * - * 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; } |