summaryrefslogtreecommitdiffstats
path: root/crypto/cmp
diff options
context:
space:
mode:
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>2020-09-04 15:24:14 +0200
committerDr. David von Oheimb <David.von.Oheimb@siemens.com>2020-09-05 18:11:12 +0200
commit15076c26d794dbbdc5413a72e7feded0c9a2ba07 (patch)
tree19ed48870fcc21002b9053e3e9d3f8ca5d584be7 /crypto/cmp
parent39082af2fa6549c3d92c917ea5a423bca57c7b42 (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.c28
-rw-r--r--crypto/cmp/cmp_err.c2
-rw-r--r--crypto/cmp/cmp_local.h1
-rw-r--r--crypto/cmp/cmp_protect.c2
-rw-r--r--crypto/cmp/cmp_util.c58
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;
}