hx509: private key exclusion options

Add two ways to exclude private keys when dealing with an hx509
certificate store.  One as a load option (load no private keys, never
add private keys), one as a store option (store no private keys).

This is useful for CA code so it can have a single store with the
issuer's credentials _and_ the chain for it, and copy those to a store
with the issued certificate and _not_ accidentally include the issuer's
private key.

It would be much safer still to flip the default for this flag, but that
could break out-of-tree libhx509 dependents.
This commit is contained in:
Nicolas Williams
2019-12-06 17:11:01 -06:00
parent 3c0d1258ce
commit e515745996
9 changed files with 177 additions and 61 deletions

View File

@@ -63,6 +63,7 @@ struct hx509_certs_data {
unsigned int ref;
struct hx509_keyset_ops *ops;
void *ops_data;
int flags;
};
static struct hx509_keyset_ops *
@@ -103,6 +104,7 @@ _hx509_ks_register(hx509_context context, struct hx509_keyset_ops *ops)
* @param flags list of flags:
* - HX509_CERTS_CREATE create a new keystore of the specific TYPE.
* - HX509_CERTS_UNPROTECT_ALL fails if any private key failed to be extracted.
* - HX509_CERTS_NO_PRIVATE_KEYS does not load or permit adding private keys
* @param lock a lock that unlocks the certificates store, use NULL to
* select no password/certifictes/prompt lock (see @ref page_lock).
* @param certs return pointer, free with hx509_certs_free().
@@ -158,6 +160,7 @@ hx509_certs_init(hx509_context context,
hx509_clear_error_string(context);
return ENOMEM;
}
c->flags = flags;
c->ops = ops;
c->ref = 1;
@@ -201,9 +204,12 @@ hx509_certs_destroy(hx509_context context,
/**
* Write the certificate store to stable storage.
*
* Use the HX509_CERTS_STORE_NO_PRIVATE_KEYS flag to ensure that no private
* keys are stored, even if added.
*
* @param context A hx509 context.
* @param certs a certificate store to store.
* @param flags currently unused, use 0.
* @param flags currently one flag is defined: HX509_CERTS_STORE_NO_PRIVATE_KEYS
* @param lock a lock that unlocks the certificates store, use NULL to
* select no password/certifictes/prompt lock (see @ref page_lock).
*
@@ -485,6 +491,9 @@ hx509_ci_print_names(hx509_context context, void *ctx, hx509_cert c)
HX509_LIB_FUNCTION int HX509_LIB_CALL
hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert)
{
hx509_cert copy = NULL;
int ret;
if (certs->ops->add == NULL) {
hx509_set_error_string(context, 0, ENOENT,
"Keyset type %s doesn't support add operation",
@@ -492,7 +501,20 @@ hx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert)
return ENOENT;
}
return (*certs->ops->add)(context, certs, certs->ops_data, cert);
if ((certs->flags & HX509_CERTS_NO_PRIVATE_KEYS) &&
hx509_cert_have_private_key(cert)) {
if ((copy = hx509_cert_copy_no_private_key(context, cert,
NULL)) == NULL) {
hx509_set_error_string(context, 0, ENOMEM,
"Could not add certificate to store");
return ENOMEM;
}
cert = copy;
}
ret = (*certs->ops->add)(context, certs, certs->ops_data, cert);
hx509_cert_free(copy);
return ret;
}
/**
@@ -637,8 +659,7 @@ certs_merge_func(hx509_context context, void *ctx, hx509_cert c)
}
/**
* Merge a certificate store into another. The from store is keep
* intact.
* Merge one certificate store into another. The from store is kept intact.
*
* @param context a hx509 context.
* @param to the store to merge into.