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:
@@ -300,6 +300,26 @@ hx509_cert_init(hx509_context context, const Certificate *c, heim_error_t *error
|
||||
return cert;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a certificate object, but drop any private key assignment.
|
||||
*
|
||||
* @param context A hx509 context.
|
||||
* @param src Certificate object
|
||||
* @param error
|
||||
*
|
||||
* @return Returns an hx509 certificate
|
||||
*
|
||||
* @ingroup hx509_cert
|
||||
*/
|
||||
|
||||
HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL
|
||||
hx509_cert_copy_no_private_key(hx509_context context,
|
||||
hx509_cert src,
|
||||
heim_error_t *error)
|
||||
{
|
||||
return hx509_cert_init(context, src->data, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and init an hx509 certificate object containing only a private key
|
||||
* (but no Certificate).
|
||||
|
@@ -154,6 +154,11 @@ typedef enum {
|
||||
/* flags to hx509_certs_init */
|
||||
#define HX509_CERTS_CREATE 0x01
|
||||
#define HX509_CERTS_UNPROTECT_ALL 0x02
|
||||
#define HX509_CERTS_NO_PRIVATE_KEYS 0x04
|
||||
|
||||
/* flags to hx509_certs_store */
|
||||
#define HX509_CERTS_STORE_NO_PRIVATE_KEYS 0x04
|
||||
|
||||
|
||||
/* flags to hx509_set_error_string */
|
||||
#define HX509_ERROR_APPEND 0x01
|
||||
|
@@ -996,6 +996,16 @@ command = {
|
||||
argument = "datetime"
|
||||
help = "check that the certificate's notBefore is after the given time"
|
||||
}
|
||||
option = {
|
||||
long = "has-private-key"
|
||||
type = "flag"
|
||||
help = "check that the certificate has a private key"
|
||||
}
|
||||
option = {
|
||||
long = "lacks-private-key"
|
||||
type = "flag"
|
||||
help = "check that the certificate does not have a private key"
|
||||
}
|
||||
name = "acert"
|
||||
min_args = "1"
|
||||
max_args = "1"
|
||||
|
@@ -2677,6 +2677,7 @@ acert1_validity(struct acert_options *opt, hx509_cert cert)
|
||||
time_t not_after_eq = 0;
|
||||
time_t not_after_lt = 0;
|
||||
time_t not_after_gt = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (opt->valid_now_flag) {
|
||||
time_t now = time(NULL);
|
||||
@@ -2684,12 +2685,12 @@ acert1_validity(struct acert_options *opt, hx509_cert cert)
|
||||
if (hx509_cert_get_notBefore(cert) > now) {
|
||||
if (opt->verbose_flag)
|
||||
fprintf(stderr, "Certificate not valid yet\n");
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
if (hx509_cert_get_notAfter(cert) < now) {
|
||||
if (opt->verbose_flag)
|
||||
fprintf(stderr, "Certificate currently expired\n");
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
if (opt->valid_at_string) {
|
||||
@@ -2699,13 +2700,13 @@ acert1_validity(struct acert_options *opt, hx509_cert cert)
|
||||
if (opt->verbose_flag)
|
||||
fprintf(stderr, "Certificate not valid yet at %s\n",
|
||||
opt->valid_at_string);
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
if (hx509_cert_get_notAfter(cert) < at) {
|
||||
if (opt->verbose_flag)
|
||||
fprintf(stderr, "Certificate expired before %s\n",
|
||||
opt->valid_at_string);
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2727,17 +2728,29 @@ acert1_validity(struct acert_options *opt, hx509_cert cert)
|
||||
(not_before_gt && hx509_cert_get_notBefore(cert) <= not_before_gt)) {
|
||||
if (opt->verbose_flag)
|
||||
fprintf(stderr, "Certificate notBefore not as requested\n");
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
if ((not_after_eq && hx509_cert_get_notAfter(cert) != not_after_eq) ||
|
||||
(not_after_lt && hx509_cert_get_notAfter(cert) >= not_after_lt) ||
|
||||
(not_after_gt && hx509_cert_get_notAfter(cert) <= not_after_gt)) {
|
||||
if (opt->verbose_flag)
|
||||
fprintf(stderr, "Certificate notAfter not as requested\n");
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (opt->has_private_key_flag && !hx509_cert_have_private_key(cert)) {
|
||||
if (opt->verbose_flag)
|
||||
fprintf(stderr, "Certificate does not have a private key\n");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (opt->lacks_private_key_flag && hx509_cert_have_private_key(cert)) {
|
||||
if (opt->verbose_flag)
|
||||
fprintf(stderr, "Certificate does not have a private key\n");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -2810,7 +2823,7 @@ acert1(struct acert_options *opt, size_t cert_num, hx509_cert cert, int *matched
|
||||
if (e == NULL) {
|
||||
if (wanted)
|
||||
return -1;
|
||||
return acert1_validity(opt, cert);;
|
||||
return acert1_validity(opt, cert);
|
||||
}
|
||||
|
||||
for (i = 0; i < e->len; i++) {
|
||||
|
@@ -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.
|
||||
|
@@ -49,7 +49,7 @@ struct ks_file {
|
||||
*/
|
||||
|
||||
static int
|
||||
parse_certificate(hx509_context context, const char *fn,
|
||||
parse_certificate(hx509_context context, const char *fn, int flags,
|
||||
struct hx509_collector *c,
|
||||
const hx509_pem_header *headers,
|
||||
const void *data, size_t len,
|
||||
@@ -74,6 +74,7 @@ parse_certificate(hx509_context context, const char *fn,
|
||||
static int
|
||||
try_decrypt(hx509_context context,
|
||||
struct hx509_collector *collector,
|
||||
int flags,
|
||||
const AlgorithmIdentifier *alg,
|
||||
const EVP_CIPHER *c,
|
||||
const void *ivdata,
|
||||
@@ -122,12 +123,9 @@ try_decrypt(hx509_context context,
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
}
|
||||
|
||||
ret = _hx509_collector_private_key_add(context,
|
||||
collector,
|
||||
alg,
|
||||
NULL,
|
||||
&clear,
|
||||
NULL);
|
||||
if (!(flags & HX509_CERTS_NO_PRIVATE_KEYS))
|
||||
ret = _hx509_collector_private_key_add(context, collector, alg, NULL,
|
||||
&clear, NULL);
|
||||
|
||||
memset_s(clear.data, clear.length, 0, clear.length);
|
||||
free(clear.data);
|
||||
@@ -138,7 +136,7 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
parse_pkcs8_private_key(hx509_context context, const char *fn,
|
||||
parse_pkcs8_private_key(hx509_context context, const char *fn, int flags,
|
||||
struct hx509_collector *c,
|
||||
const hx509_pem_header *headers,
|
||||
const void *data, size_t length,
|
||||
@@ -146,28 +144,28 @@ parse_pkcs8_private_key(hx509_context context, const char *fn,
|
||||
{
|
||||
PKCS8PrivateKeyInfo ki;
|
||||
heim_octet_string keydata;
|
||||
|
||||
int ret;
|
||||
|
||||
ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(flags & HX509_CERTS_NO_PRIVATE_KEYS)) {
|
||||
keydata.data = rk_UNCONST(data);
|
||||
keydata.length = length;
|
||||
|
||||
ret = _hx509_collector_private_key_add(context,
|
||||
c,
|
||||
&ki.privateKeyAlgorithm,
|
||||
NULL,
|
||||
&ki.privateKey,
|
||||
&keydata);
|
||||
}
|
||||
free_PKCS8PrivateKeyInfo(&ki);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_pem_private_key(hx509_context context, const char *fn,
|
||||
parse_pem_private_key(hx509_context context, const char *fn, int flags,
|
||||
struct hx509_collector *c,
|
||||
const hx509_pem_header *headers,
|
||||
const void *data, size_t len,
|
||||
@@ -271,7 +269,7 @@ parse_pem_private_key(hx509_context context, const char *fn,
|
||||
password = pw->val[i];
|
||||
passwordlen = strlen(password);
|
||||
|
||||
ret = try_decrypt(context, c, ai, cipher, ivdata,
|
||||
ret = try_decrypt(context, c, flags, ai, cipher, ivdata,
|
||||
password, passwordlen, data, len);
|
||||
if (ret == 0) {
|
||||
decrypted = 1;
|
||||
@@ -292,14 +290,14 @@ parse_pem_private_key(hx509_context context, const char *fn,
|
||||
|
||||
ret = hx509_lock_prompt(lock, &prompt);
|
||||
if (ret == 0)
|
||||
ret = try_decrypt(context, c, ai, cipher, ivdata, password,
|
||||
strlen(password), data, len);
|
||||
ret = try_decrypt(context, c, flags, ai, cipher, ivdata,
|
||||
password, strlen(password), data, len);
|
||||
/* XXX add password to lock password collection ? */
|
||||
memset_s(password, sizeof(password), 0, sizeof(password));
|
||||
}
|
||||
free(ivdata);
|
||||
|
||||
} else {
|
||||
} else if (!(flags & HX509_CERTS_NO_PRIVATE_KEYS)) {
|
||||
heim_octet_string keydata;
|
||||
|
||||
keydata.data = rk_UNCONST(data);
|
||||
@@ -315,7 +313,7 @@ parse_pem_private_key(hx509_context context, const char *fn,
|
||||
|
||||
struct pem_formats {
|
||||
const char *name;
|
||||
int (*func)(hx509_context, const char *, struct hx509_collector *,
|
||||
int (*func)(hx509_context, const char *, int, struct hx509_collector *,
|
||||
const hx509_pem_header *, const void *, size_t,
|
||||
const AlgorithmIdentifier *);
|
||||
const AlgorithmIdentifier *(*ai)(void);
|
||||
@@ -347,10 +345,11 @@ pem_func(hx509_context context, const char *type,
|
||||
const char *q = formats[j].name;
|
||||
if (strcasecmp(type, q) == 0) {
|
||||
const AlgorithmIdentifier *ai = NULL;
|
||||
|
||||
if (formats[j].ai != NULL)
|
||||
ai = (*formats[j].ai)();
|
||||
|
||||
ret = (*formats[j].func)(context, NULL, pem_ctx->c,
|
||||
ret = (*formats[j].func)(context, NULL, pem_ctx->flags, pem_ctx->c,
|
||||
header, data, len, ai);
|
||||
if (ret && (pem_ctx->flags & HX509_CERTS_UNPROTECT_ALL)) {
|
||||
hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
|
||||
@@ -468,10 +467,12 @@ file_init_common(hx509_context context,
|
||||
|
||||
for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
|
||||
const AlgorithmIdentifier *ai = NULL;
|
||||
|
||||
if (formats[i].ai != NULL)
|
||||
ai = (*formats[i].ai)();
|
||||
|
||||
ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length, ai);
|
||||
ret = (*formats[i].func)(context, p, pem_ctx.flags, pem_ctx.c,
|
||||
NULL, ptr, length, ai);
|
||||
if (ret == 0)
|
||||
break;
|
||||
}
|
||||
@@ -539,6 +540,7 @@ file_free(hx509_certs certs, void *data)
|
||||
struct store_ctx {
|
||||
FILE *f;
|
||||
outformat format;
|
||||
int store_flags;
|
||||
};
|
||||
|
||||
static int HX509_LIB_CALL
|
||||
@@ -563,7 +565,8 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
|
||||
if (data.data) {
|
||||
fwrite(data.data, data.length, 1, sc->f);
|
||||
free(data.data);
|
||||
} else if (_hx509_cert_private_key_exportable(c)) {
|
||||
} else if (_hx509_cert_private_key_exportable(c) &&
|
||||
!(sc->store_flags & HX509_CERTS_STORE_NO_PRIVATE_KEYS)) {
|
||||
hx509_private_key key = _hx509_cert_private_key(c);
|
||||
|
||||
ret = _hx509_private_key_export(context, key,
|
||||
@@ -573,7 +576,8 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
|
||||
}
|
||||
break;
|
||||
case USE_PEM:
|
||||
if (_hx509_cert_private_key_exportable(c)) {
|
||||
if (_hx509_cert_private_key_exportable(c) &&
|
||||
!(sc->store_flags & HX509_CERTS_STORE_NO_PRIVATE_KEYS)) {
|
||||
heim_octet_string priv_key;
|
||||
hx509_private_key key = _hx509_cert_private_key(c);
|
||||
|
||||
@@ -658,6 +662,7 @@ file_store(hx509_context context,
|
||||
return ret;
|
||||
}
|
||||
rk_cloexec_file(sc.f);
|
||||
sc.store_flags = flags;
|
||||
sc.format = ksf->format;
|
||||
|
||||
ret = hx509_certs_iter_f(context, ksf->certs, store_func, &sc);
|
||||
|
@@ -328,6 +328,13 @@ keychain_init(hx509_context context,
|
||||
{
|
||||
struct ks_keychain *ctx;
|
||||
|
||||
if (flags & HX509_CERTS_NO_PRIVATE_KEYS) {
|
||||
hx509_set_error_string(context, 0, ENOTSUP,
|
||||
"KEYCHAIN store does not support not reading "
|
||||
"private keys");
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
hx509_clear_error_string(context);
|
||||
|
@@ -820,6 +820,13 @@ p11_init(hx509_context context,
|
||||
|
||||
*data = NULL;
|
||||
|
||||
if (flags & HX509_CERTS_NO_PRIVATE_KEYS) {
|
||||
hx509_set_error_string(context, 0, ENOTSUP,
|
||||
"PKCS#11 store does not support "
|
||||
"HX509_CERTS_NO_PRIVATE_KEYS flag");
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
if (residue == NULL || residue[0] == '\0') {
|
||||
hx509_set_error_string(context, 0, EINVAL,
|
||||
"PKCS#11 store not specified");
|
||||
|
@@ -36,10 +36,12 @@
|
||||
struct ks_pkcs12 {
|
||||
hx509_certs certs;
|
||||
char *fn;
|
||||
unsigned int store_no_priv_keys;
|
||||
};
|
||||
|
||||
typedef int (*collector_func)(hx509_context,
|
||||
struct hx509_collector *,
|
||||
int,
|
||||
const void *, size_t,
|
||||
const PKCS12_Attributes *);
|
||||
|
||||
@@ -49,8 +51,9 @@ struct type {
|
||||
};
|
||||
|
||||
static void
|
||||
parse_pkcs12_type(hx509_context, struct hx509_collector *, const heim_oid *,
|
||||
const void *, size_t, const PKCS12_Attributes *);
|
||||
parse_pkcs12_type(hx509_context, struct hx509_collector *, int,
|
||||
const heim_oid *, const void *, size_t,
|
||||
const PKCS12_Attributes *);
|
||||
|
||||
|
||||
static const PKCS12_Attribute *
|
||||
@@ -68,6 +71,7 @@ find_attribute(const PKCS12_Attributes *attrs, const heim_oid *oid)
|
||||
static int
|
||||
keyBag_parser(hx509_context context,
|
||||
struct hx509_collector *c,
|
||||
int flags,
|
||||
const void *data, size_t length,
|
||||
const PKCS12_Attributes *attrs)
|
||||
{
|
||||
@@ -76,6 +80,9 @@ keyBag_parser(hx509_context context,
|
||||
const heim_octet_string *os = NULL;
|
||||
int ret;
|
||||
|
||||
if (flags & HX509_CERTS_NO_PRIVATE_KEYS)
|
||||
return 0;
|
||||
|
||||
attr = find_attribute(attrs, &asn1_oid_id_pkcs_9_at_localKeyId);
|
||||
if (attr)
|
||||
os = &attr->attrValues;
|
||||
@@ -97,6 +104,7 @@ keyBag_parser(hx509_context context,
|
||||
static int
|
||||
ShroudedKeyBag_parser(hx509_context context,
|
||||
struct hx509_collector *c,
|
||||
int flags,
|
||||
const void *data, size_t length,
|
||||
const PKCS12_Attributes *attrs)
|
||||
{
|
||||
@@ -119,7 +127,8 @@ ShroudedKeyBag_parser(hx509_context context,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = keyBag_parser(context, c, content.data, content.length, attrs);
|
||||
ret = keyBag_parser(context, c, flags, content.data, content.length,
|
||||
attrs);
|
||||
der_free_octet_string(&content);
|
||||
return ret;
|
||||
}
|
||||
@@ -127,6 +136,7 @@ ShroudedKeyBag_parser(hx509_context context,
|
||||
static int
|
||||
certBag_parser(hx509_context context,
|
||||
struct hx509_collector *c,
|
||||
int flags,
|
||||
const void *data, size_t length,
|
||||
const PKCS12_Attributes *attrs)
|
||||
{
|
||||
@@ -191,6 +201,7 @@ certBag_parser(hx509_context context,
|
||||
static int
|
||||
parse_safe_content(hx509_context context,
|
||||
struct hx509_collector *c,
|
||||
int flags,
|
||||
const unsigned char *p, size_t len)
|
||||
{
|
||||
PKCS12_SafeContents sc;
|
||||
@@ -206,6 +217,7 @@ parse_safe_content(hx509_context context,
|
||||
for (i = 0; i < sc.len ; i++)
|
||||
parse_pkcs12_type(context,
|
||||
c,
|
||||
flags,
|
||||
&sc.val[i].bagId,
|
||||
sc.val[i].bagValue.data,
|
||||
sc.val[i].bagValue.length,
|
||||
@@ -218,6 +230,7 @@ parse_safe_content(hx509_context context,
|
||||
static int
|
||||
safeContent_parser(hx509_context context,
|
||||
struct hx509_collector *c,
|
||||
int flags,
|
||||
const void *data, size_t length,
|
||||
const PKCS12_Attributes *attrs)
|
||||
{
|
||||
@@ -227,7 +240,7 @@ safeContent_parser(hx509_context context,
|
||||
ret = decode_PKCS12_OctetString(data, length, &os, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = parse_safe_content(context, c, os.data, os.length);
|
||||
ret = parse_safe_content(context, c, flags, os.data, os.length);
|
||||
der_free_octet_string(&os);
|
||||
return ret;
|
||||
}
|
||||
@@ -235,6 +248,7 @@ safeContent_parser(hx509_context context,
|
||||
static int
|
||||
encryptedData_parser(hx509_context context,
|
||||
struct hx509_collector *c,
|
||||
int flags,
|
||||
const void *data, size_t length,
|
||||
const PKCS12_Attributes *attrs)
|
||||
{
|
||||
@@ -253,7 +267,8 @@ encryptedData_parser(hx509_context context,
|
||||
return ret;
|
||||
|
||||
if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0)
|
||||
ret = parse_safe_content(context, c, content.data, content.length);
|
||||
ret = parse_safe_content(context, c, flags,
|
||||
content.data, content.length);
|
||||
|
||||
der_free_octet_string(&content);
|
||||
der_free_oid(&contentType);
|
||||
@@ -263,6 +278,7 @@ encryptedData_parser(hx509_context context,
|
||||
static int
|
||||
envelopedData_parser(hx509_context context,
|
||||
struct hx509_collector *c,
|
||||
int flags,
|
||||
const void *data, size_t length,
|
||||
const PKCS12_Attributes *attrs)
|
||||
{
|
||||
@@ -290,7 +306,8 @@ envelopedData_parser(hx509_context context,
|
||||
}
|
||||
|
||||
if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0)
|
||||
ret = parse_safe_content(context, c, content.data, content.length);
|
||||
ret = parse_safe_content(context, c, flags,
|
||||
content.data, content.length);
|
||||
|
||||
der_free_octet_string(&content);
|
||||
der_free_oid(&contentType);
|
||||
@@ -311,6 +328,7 @@ struct type bagtypes[] = {
|
||||
static void
|
||||
parse_pkcs12_type(hx509_context context,
|
||||
struct hx509_collector *c,
|
||||
int flags,
|
||||
const heim_oid *oid,
|
||||
const void *data, size_t length,
|
||||
const PKCS12_Attributes *attrs)
|
||||
@@ -319,7 +337,7 @@ parse_pkcs12_type(hx509_context context,
|
||||
|
||||
for (i = 0; i < sizeof(bagtypes)/sizeof(bagtypes[0]); i++)
|
||||
if (der_heim_oid_cmp(bagtypes[i].oid, oid) == 0)
|
||||
(*bagtypes[i].func)(context, c, data, length, attrs);
|
||||
(*bagtypes[i].func)(context, c, flags, data, length, attrs);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -429,6 +447,7 @@ p12_init(hx509_context context,
|
||||
for (i = 0; i < as.len; i++)
|
||||
parse_pkcs12_type(context,
|
||||
c,
|
||||
flags,
|
||||
&as.val[i].contentType,
|
||||
as.val[i].content->data,
|
||||
as.val[i].content->length,
|
||||
@@ -492,10 +511,15 @@ addBag(hx509_context context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct store_func_ctx {
|
||||
PKCS12_AuthenticatedSafe as;
|
||||
int store_flags;
|
||||
};
|
||||
|
||||
static int HX509_LIB_CALL
|
||||
store_func(hx509_context context, void *ctx, hx509_cert c)
|
||||
store_func(hx509_context context, void *d, hx509_cert c)
|
||||
{
|
||||
PKCS12_AuthenticatedSafe *as = ctx;
|
||||
struct store_func_ctx *ctx = d;
|
||||
PKCS12_OctetString os;
|
||||
PKCS12_CertBag cb;
|
||||
size_t size;
|
||||
@@ -528,9 +552,11 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = addBag(context, as, &asn1_oid_id_pkcs12_certBag, os.data, os.length);
|
||||
ret = addBag(context, &ctx->as, &asn1_oid_id_pkcs12_certBag, os.data,
|
||||
os.length);
|
||||
|
||||
if (_hx509_cert_private_key_exportable(c)) {
|
||||
if (_hx509_cert_private_key_exportable(c) &&
|
||||
!(ctx->store_flags & HX509_CERTS_STORE_NO_PRIVATE_KEYS)) {
|
||||
hx509_private_key key = _hx509_cert_private_key(c);
|
||||
PKCS8PrivateKeyInfo pki;
|
||||
|
||||
@@ -561,7 +587,8 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = addBag(context, as, &asn1_oid_id_pkcs12_keyBag, os.data, os.length);
|
||||
ret = addBag(context, &ctx->as, &asn1_oid_id_pkcs12_keyBag, os.data,
|
||||
os.length);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -576,21 +603,22 @@ p12_store(hx509_context context,
|
||||
{
|
||||
struct ks_pkcs12 *p12 = data;
|
||||
PKCS12_PFX pfx;
|
||||
PKCS12_AuthenticatedSafe as;
|
||||
struct store_func_ctx ctx;
|
||||
PKCS12_OctetString asdata;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
memset(&as, 0, sizeof(as));
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
memset(&pfx, 0, sizeof(pfx));
|
||||
ctx.store_flags = flags;
|
||||
|
||||
ret = hx509_certs_iter_f(context, p12->certs, store_func, &as);
|
||||
ret = hx509_certs_iter_f(context, p12->certs, store_func, &ctx);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ASN1_MALLOC_ENCODE(PKCS12_AuthenticatedSafe, asdata.data, asdata.length,
|
||||
&as, &size, ret);
|
||||
free_PKCS12_AuthenticatedSafe(&as);
|
||||
&ctx.as, &size, ret);
|
||||
free_PKCS12_AuthenticatedSafe(&ctx.as);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -642,7 +670,7 @@ p12_store(hx509_context context,
|
||||
free(asdata.data);
|
||||
|
||||
out:
|
||||
free_PKCS12_AuthenticatedSafe(&as);
|
||||
free_PKCS12_AuthenticatedSafe(&ctx.as);
|
||||
free_PKCS12_PFX(&pfx);
|
||||
|
||||
return ret;
|
||||
|
Reference in New Issue
Block a user