Factor out private key operation out of the signing, operations, support import, export, and generation of private keys. Add support for writing PEM and PKCS12 files with private keys in them.

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@19778 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2007-01-09 10:52:13 +00:00
parent 3fbaf4f844
commit 80977a02f6
20 changed files with 1046 additions and 202 deletions

View File

@@ -1,5 +1,19 @@
2007-01-09 Love H<>rnquist <20>strand <lha@it.su.se>
* Factor out private key operation out of the signing, operations,
support import, export, and generation of private keys. Add
support for writing PEM and PKCS12 files with private keys in them.
* data/gen-req.sh: Generate a no password pkcs12 file.
2007-01-08 Love H<>rnquist <20>strand <lha@it.su.se>
* cms.c: Check for internal ASN1 encoder error.
2007-01-05 Love H<>rnquist <20>strand <lha@it.su.se>
* Makefile.am: Drop most of the pkcs11 files.
* test_ca.in: test reissueing ca certificate (xxx time
validAfter).

View File

@@ -138,6 +138,7 @@ CLEANFILES = $(BUILT_SOURCES) \
$(TESTS) \
hxtool-commands.c hxtool-commands.h *.tmp \
request.out \
out.pem out2.pem \
sd.data sd.data.out \
ev.data ev.data.out \
cert-proxy.der cert-ca.der cert-ee.der pkcs10-request.der \

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004 - 2006 Kungliga Tekniska H<>gskolan
* Copyright (c) 2004 - 2007 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -236,8 +236,8 @@ int
_hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
{
if (cert->private_key)
_hx509_free_private_key(&cert->private_key);
cert->private_key = private_key;
_hx509_private_key_free(&cert->private_key);
cert->private_key = _hx509_private_key_ref(private_key);
return 0;
}
@@ -258,7 +258,7 @@ hx509_cert_free(hx509_cert cert)
(cert->release)(cert, cert->ctx);
if (cert->private_key)
_hx509_free_private_key(&cert->private_key);
_hx509_private_key_free(&cert->private_key);
free_Certificate(cert->data);
free(cert->data);
@@ -1071,6 +1071,14 @@ _hx509_cert_private_key(hx509_cert p)
return p->private_key;
}
int
_hx509_cert_private_key_exportable(hx509_cert p)
{
if (p->private_key == NULL)
return 0;
return _hx509_private_key_exportable(p->private_key);
}
int
_hx509_cert_private_decrypt(hx509_context context,
const heim_octet_string *ciphertext,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004 - 2006 Kungliga Tekniska H<>gskolan
* Copyright (c) 2004 - 2007 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -101,7 +101,7 @@ free_private_key(struct private_key *key)
{
free_AlgorithmIdentifier(&key->alg);
if (key->private_key)
_hx509_free_private_key(&key->private_key);
_hx509_private_key_free(&key->private_key);
der_free_octet_string(&key->localKeyId);
free(key);
}
@@ -188,10 +188,8 @@ match_localkeyid(hx509_context context,
ret = hx509_certs_find(context, certs, &q, &cert);
if (ret == 0) {
if (value->private_key) {
if (value->private_key)
_hx509_cert_assign_key(cert, value->private_key);
value->private_key = NULL;
}
hx509_cert_free(cert);
}
return ret;
@@ -229,7 +227,6 @@ match_keys(hx509_context context, struct private_key *value, hx509_certs certs)
ret = _hx509_match_keys(c, value->private_key);
if (ret) {
_hx509_cert_assign_key(c, value->private_key);
value->private_key = NULL;
hx509_cert_free(c);
found = 0;
break;
@@ -246,7 +243,7 @@ match_keys(hx509_context context, struct private_key *value, hx509_certs certs)
}
int
_hx509_collector_collect(hx509_context context,
_hx509_collector_collect_certs(hx509_context context,
struct hx509_collector *c,
hx509_certs *ret_certs)
{
@@ -279,6 +276,37 @@ _hx509_collector_collect(hx509_context context,
return 0;
}
int
_hx509_collector_collect_private_keys(hx509_context context,
struct hx509_collector *c,
hx509_private_key **keys)
{
int i, nkeys;
*keys = NULL;
for (i = 0, nkeys = 0; i < c->val.len; i++)
if (c->val.data[i]->private_key)
nkeys++;
*keys = calloc(nkeys + 1, sizeof(**keys));
if (*keys == NULL) {
hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
return ENOMEM;
}
for (i = 0, nkeys = 0; i < c->val.len; i++) {
if (c->val.data[i]->private_key) {
(*keys)[nkeys++] = c->val.data[i]->private_key;
c->val.data[i]->private_key = NULL;
}
}
(*keys)[nkeys++] = NULL;
return 0;
}
void
_hx509_collector_free(struct hx509_collector *c)
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004 - 2006 Kungliga Tekniska H<>gskolan
* Copyright (c) 2004 - 2007 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -42,14 +42,22 @@ enum crypto_op_type {
COT_SIGN
};
struct hx509_private_key {
const struct signature_alg *md;
const heim_oid *signature_alg;
struct {
RSA *rsa;
} private_key;
/* new crypto layer */
void *key;
struct hx509_private_key_ops {
const char *pemtype;
const heim_oid *(*key_oid)(void);
int (*get_spki)(hx509_context,
const hx509_private_key,
SubjectPublicKeyInfo *);
int (*export)(hx509_context context,
const hx509_private_key,
heim_octet_string *);
int (*import)(hx509_context,
const void *data,
size_t len,
hx509_private_key private_key);
int (*generate_private_key)(hx509_context context,
hx509_private_key private_key);
int (*handle_alg)(const hx509_private_key,
const AlgorithmIdentifier *,
enum crypto_op_type);
@@ -60,20 +68,29 @@ struct hx509_private_key {
AlgorithmIdentifier *,
heim_octet_string *);
#if 0
const AlgorithmIdentifier *
(*preferred_sig_alg)(const hx509_private_key_key,
const AlgorithmIdentifier *(*preferred_sig_alg)
(const hx509_private_key,
const hx509_peer_info);
int (*unwrap)(hx509_context context,
const hx509_private_key,
const AlgorithmIdentifier *,
const heim_octet_string *,
heim_octet_string *);
int (*get_spki)(hx509_context context,
const hx509_private_key_key,
SubjectPublicKeyInfo *);
#endif
};
struct hx509_private_key {
unsigned int ref;
const struct signature_alg *md;
const heim_oid *signature_alg;
union {
RSA *rsa;
void *keydata;
} private_key;
/* new crypto layer */
hx509_private_key_ops *ops;
};
/*
*
*/
@@ -106,13 +123,9 @@ struct signature_alg {
const heim_octet_string *,
AlgorithmIdentifier *,
heim_octet_string *);
int (*parse_private_key)(hx509_context,
const struct signature_alg *,
const void *data,
size_t len,
hx509_private_key private_key);
int (*private_key2SPKI)(hx509_private_key private_key,
SubjectPublicKeyInfo *spki);
int (*private_key2SPKI)(hx509_context,
hx509_private_key,
SubjectPublicKeyInfo *);
};
/*
@@ -330,8 +343,7 @@ rsa_create_signature(hx509_context context,
}
static int
rsa_parse_private_key(hx509_context context,
const struct signature_alg *sig_alg,
rsa_private_key_import(hx509_context context,
const void *data,
size_t len,
hx509_private_key private_key)
@@ -351,7 +363,8 @@ rsa_parse_private_key(hx509_context context,
}
static int
rsa_private_key2SPKI(hx509_private_key private_key,
rsa_private_key2SPKI(hx509_context context,
hx509_private_key private_key,
SubjectPublicKeyInfo *spki)
{
int len, ret;
@@ -361,14 +374,17 @@ rsa_private_key2SPKI(hx509_private_key private_key,
len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL);
spki->subjectPublicKey.data = malloc(len);
if (spki->subjectPublicKey.data == NULL)
if (spki->subjectPublicKey.data == NULL) {
hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
return ENOMEM;
}
spki->subjectPublicKey.length = len * 8;
ret = _hx509_set_digest_alg(&spki->algorithm,
oid_id_pkcs1_rsaEncryption(),
"\x05\x00", 2);
if (ret) {
hx509_set_error_string(context, 0, ret, "malloc - out of memory");
free(spki->subjectPublicKey.data);
spki->subjectPublicKey.data = NULL;
spki->subjectPublicKey.length = 0;
@@ -383,6 +399,90 @@ rsa_private_key2SPKI(hx509_private_key private_key,
return 0;
}
static int
cb_func(int a, int b, BN_GENCB *c)
{
return 1;
}
static int
rsa_generate_private_key(hx509_context context, hx509_private_key private_key)
{
BN_GENCB cb;
BIGNUM *e;
int ret;
static const int default_rsa_e = 65537;
static const int default_rsa_bits = 1024;
private_key->private_key.rsa = RSA_new();
if (private_key->private_key.rsa == NULL) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
"Failed to generate RSA key");
return HX509_PARSING_KEY_FAILED;
}
e = BN_new();
BN_set_word(e, default_rsa_e);
BN_GENCB_set(&cb, cb_func, NULL);
ret = RSA_generate_key_ex(private_key->private_key.rsa,
default_rsa_bits, e, &cb);
BN_free(e);
if (ret != 1) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
"Failed to generate RSA key");
return HX509_PARSING_KEY_FAILED;
}
private_key->signature_alg = oid_id_pkcs1_sha1WithRSAEncryption();
return 0;
}
static int
rsa_private_key_export(hx509_context context,
const hx509_private_key key,
heim_octet_string *data)
{
int ret;
data->data = NULL;
data->length = 0;
ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL);
if (ret <= 0) {
ret = EINVAL;
hx509_set_error_string(context, 0, ret,
"Private key is not exportable");
return ret;
}
data->data = malloc(ret);
if (data->data == NULL) {
ret = ENOMEM;
hx509_set_error_string(context, 0, ret, "malloc out of memory");
return ret;
}
data->length = ret;
{
unsigned char *p = data->data;
i2d_RSAPrivateKey(key->private_key.rsa, &p);
}
return 0;
}
static hx509_private_key_ops rsa_private_key_ops = {
"RSA PRIVATE KEY",
oid_id_pkcs1_rsaEncryption,
rsa_private_key2SPKI,
rsa_private_key_export,
rsa_private_key_import,
rsa_generate_private_key
};
/*
*
@@ -473,14 +573,13 @@ dsa_verify_signature(hx509_context context,
return ret;
}
#if 0
static int
dsa_parse_private_key(hx509_context context,
const struct signature_alg *sig_alg,
const void *data,
size_t len,
hx509_private_key private_key)
{
#if 0
const unsigned char *p = data;
private_key->private_key.dsa =
@@ -490,12 +589,12 @@ dsa_parse_private_key(hx509_context context,
private_key->signature_alg = oid_id_dsa_with_sha1();
return 0;
#else
/* else */
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
"No support to parse DSA keys");
return HX509_PARSING_KEY_FAILED;
#endif
}
#endif
static int
@@ -699,7 +798,6 @@ static struct signature_alg pkcs1_rsa_sha1_alg = {
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
rsa_create_signature,
rsa_parse_private_key,
rsa_private_key2SPKI
};
@@ -712,7 +810,6 @@ static struct signature_alg rsa_with_sha256_alg = {
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
rsa_create_signature,
rsa_parse_private_key,
rsa_private_key2SPKI
};
@@ -725,7 +822,6 @@ static struct signature_alg rsa_with_sha1_alg = {
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
rsa_create_signature,
rsa_parse_private_key,
rsa_private_key2SPKI
};
@@ -738,7 +834,6 @@ static struct signature_alg rsa_with_md5_alg = {
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
rsa_create_signature,
rsa_parse_private_key,
rsa_private_key2SPKI
};
@@ -751,7 +846,6 @@ static struct signature_alg rsa_with_md2_alg = {
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
rsa_create_signature,
rsa_parse_private_key,
rsa_private_key2SPKI
};
@@ -764,7 +858,6 @@ static struct signature_alg dsa_sha1_alg = {
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
dsa_verify_signature,
/* create_signature */ NULL,
dsa_parse_private_key
};
static struct signature_alg sha256_alg = {
@@ -838,19 +931,29 @@ find_sig_alg(const heim_oid *oid)
return NULL;
}
static const struct signature_alg *
find_key_alg(const heim_oid *oid)
/*
*
*/
static struct hx509_private_key_ops *private_algs[] = {
&rsa_private_key_ops,
NULL
};
static hx509_private_key_ops *
find_private_alg(const heim_oid *oid)
{
int i;
for (i = 0; sig_algs[i]; i++) {
if (sig_algs[i]->key_oid == NULL)
for (i = 0; private_algs[i]; i++) {
if (private_algs[i]->key_oid == NULL)
continue;
if (der_heim_oid_cmp((*sig_algs[i]->key_oid)(), oid) == 0)
return sig_algs[i];
if (der_heim_oid_cmp((*private_algs[i]->key_oid)(), oid) == 0)
return private_algs[i];
}
return NULL;
}
int
_hx509_verify_signature(hx509_context context,
const Certificate *signer,
@@ -916,10 +1019,10 @@ _hx509_create_signature(hx509_context context,
{
const struct signature_alg *md;
if (signer && signer->handle_alg &&
(*signer->handle_alg)(signer, alg, COT_SIGN))
if (signer && signer->ops && signer->ops->handle_alg &&
(*signer->ops->handle_alg)(signer, alg, COT_SIGN))
{
return (*signer->sign)(context, signer, alg, data,
return (*signer->ops->sign)(context, signer, alg, data,
signatureAlgorithm, sig);
}
@@ -1089,28 +1192,26 @@ _hx509_parse_private_key(hx509_context context,
size_t len,
hx509_private_key *private_key)
{
const struct signature_alg *md;
struct hx509_private_key_ops *ops;
int ret;
*private_key = NULL;
md = find_key_alg(key_oid);
if (md == NULL) {
ops = find_private_alg(key_oid);
if (ops == NULL) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_NO_SUPPORTED;
}
ret = _hx509_new_private_key(private_key);
ret = _hx509_private_key_init(private_key, ops, NULL);
if (ret) {
hx509_set_error_string(context, 0, ret, "out of memory");
return ret;
}
ret = (*md->parse_private_key)(context, md, data, len, *private_key);
ret = (*ops->import)(context, data, len, *private_key);
if (ret)
_hx509_free_private_key(private_key);
else
(*private_key)->md = md;
_hx509_private_key_free(private_key);
return ret;
}
@@ -1124,13 +1225,42 @@ _hx509_private_key2SPKI(hx509_context context,
hx509_private_key private_key,
SubjectPublicKeyInfo *spki)
{
const struct signature_alg *md = private_key->md;
if (md->private_key2SPKI == NULL) {
const struct hx509_private_key_ops *ops = private_key->ops;
if (ops == NULL || ops->get_spki == NULL) {
hx509_set_error_string(context, 0, HX509_UNIMPLEMENTED_OPERATION,
"Private key have no key2SPKI function");
return HX509_UNIMPLEMENTED_OPERATION;
}
return (*md->private_key2SPKI)(private_key, spki);
return (*ops->get_spki)(context, private_key, spki);
}
int
_hx509_generate_private_key(hx509_context context,
const heim_oid *key_oid,
hx509_private_key *private_key)
{
struct hx509_private_key_ops *ops;
int ret;
*private_key = NULL;
ops = find_private_alg(key_oid);
if (ops == NULL) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_NO_SUPPORTED;
}
ret = _hx509_private_key_init(private_key, ops, NULL);
if (ret) {
hx509_set_error_string(context, 0, ret, "out of memory");
return ret;
}
ret = (*ops->generate_private_key)(context, *private_key);
if (ret)
_hx509_private_key_free(private_key);
return ret;
}
@@ -1259,17 +1389,47 @@ hx509_signature_rsa(void)
{ return &_hx509_signature_rsa_data; }
int
_hx509_new_private_key(hx509_private_key *key)
_hx509_private_key_init(hx509_private_key *key,
hx509_private_key_ops *ops,
void *keydata)
{
*key = calloc(1, sizeof(**key));
if (*key == NULL)
return ENOMEM;
(*key)->ref = 1;
(*key)->ops = ops;
(*key)->private_key.keydata = keydata;
return 0;
}
int
_hx509_free_private_key(hx509_private_key *key)
hx509_private_key
_hx509_private_key_ref(hx509_private_key key)
{
if (key->ref <= 0)
_hx509_abort("refcount <= 0");
key->ref++;
if (key->ref == 0)
_hx509_abort("refcount == 0");
return key;
}
const char *
_hx509_private_pem_name(hx509_private_key key)
{
return key->ops->pemtype;
}
int
_hx509_private_key_free(hx509_private_key *key)
{
if (key == NULL || *key == NULL)
return 0;
if ((*key)->ref <= 0)
_hx509_abort("refcount <= 0");
if (--(*key)->ref > 0)
return 0;
if ((*key)->private_key.rsa)
RSA_free((*key)->private_key.rsa);
(*key)->private_key.rsa = NULL;
@@ -1288,6 +1448,41 @@ _hx509_private_key_assign_rsa(hx509_private_key key, void *ptr)
key->md = &pkcs1_rsa_sha1_alg;
}
int
_hx509_private_key_oid(hx509_context context,
const hx509_private_key key,
heim_oid *data)
{
int ret;
ret = der_copy_oid((*key->ops->key_oid)(), data);
if (ret)
hx509_set_error_string(context, 0, ret, "malloc out of memory");
return ret;
}
int
_hx509_private_key_exportable(hx509_private_key key)
{
if (key->ops->export == NULL)
return 0;
return 1;
}
int
_hx509_private_key_export(hx509_context context,
const hx509_private_key key,
heim_octet_string *data)
{
if (key->ops->export == NULL) {
hx509_clear_error_string(context);
return HX509_UNIMPLEMENTED_OPERATION;
}
return (*key->ops->export)(context, key, data);
}
/*
*
*/
struct hx509cipher {
const char *name;
@@ -2082,6 +2277,7 @@ _hx509_match_keys(hx509_cert c, hx509_private_key private_key)
rsa->q = BN_dup(private_key->private_key.rsa->q);
rsa->dmp1 = BN_dup(private_key->private_key.rsa->dmp1);
rsa->dmq1 = BN_dup(private_key->private_key.rsa->dmq1);
rsa->iqmp = BN_dup(private_key->private_key.rsa->iqmp);
if (rsa->n == NULL || rsa->e == NULL ||
rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL ||

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004 - 2006 Kungliga Tekniska H<>gskolan
* Copyright (c) 2004 - 2007 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -93,6 +93,9 @@ typedef enum {
HX509_QUERY_OPTION_END = 0xffff
} hx509_query_option;
/* flags to hx509_certs_init */
#define HX509_CERTS_CREATE 0x01
/* flags to hx509_set_error_string */
#define HX509_ERROR_APPEND 0x01

View File

@@ -77,6 +77,8 @@ typedef struct hx509_path hx509_path;
typedef void (*_hx509_cert_release_func)(struct hx509_cert_data *, void *);
typedef struct hx509_private_key_ops hx509_private_key_ops;
#include <hx509-private.h>
#include <hx509_err.h>
@@ -146,6 +148,7 @@ struct hx509_keyset_ops {
int flags;
int (*init)(hx509_context, hx509_certs, void **,
int, const char *, hx509_lock);
int (*store)(hx509_context, hx509_certs, void *, int, hx509_lock);
int (*free)(hx509_certs, void *);
int (*add)(hx509_context, hx509_certs, void *, hx509_cert);
int (*query)(hx509_context, hx509_certs, void *,
@@ -155,6 +158,8 @@ struct hx509_keyset_ops {
int (*iter_end)(hx509_context, hx509_certs, void *, void *);
int (*printinfo)(hx509_context, hx509_certs,
void *, int (*)(void *, char *), void *);
int (*getkeys)(hx509_context, hx509_certs, void *, hx509_private_key **);
int (*addkey)(hx509_context, hx509_certs, void *, hx509_private_key);
};
struct _hx509_password {

View File

@@ -236,6 +236,25 @@ command = {
argument="certificate ..."
help = "Validate content of certificates"
}
command = {
name = "certificate-copy"
name = "cc"
option = {
long = "in-pass"
type = "strings"
argument = "password"
help = "password, prompter, or environment"
}
option = {
long = "out-pass"
type = "string"
argument = "password"
help = "password, prompter, or environment"
}
min_args="2"
argument="in-certificates-1 ... out-certificate"
help = "Copy in certificates stores into out certificate store"
}
command = {
name = "ocsp-fetch"
option = {
@@ -511,11 +530,6 @@ command = {
type = "string"
help = "pkcs10 request"
}
option = {
long = "out-key"
type = "string"
help = "out key"
}
option = {
long = "generate-key"
type = "string"

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004 - 2006 Kungliga Tekniska H<>gskolan
* Copyright (c) 2004 - 2007 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -540,6 +540,38 @@ pcert_validate(struct validate_options *opt, int argc, char **argv)
return 0;
}
int
certificate_copy(struct certificate_copy_options *opt, int argc, char **argv)
{
hx509_certs certs;
hx509_lock lock;
int ret;
hx509_lock_init(context, &lock);
lock_strings(lock, &opt->in_pass_strings);
ret = hx509_certs_init(context, argv[argc - 1],
HX509_CERTS_CREATE, lock, &certs);
if (ret)
hx509_err(context, 1, ret, "hx509_certs_init");
while(argc-- > 1) {
int ret;
ret = hx509_certs_append(context, certs, lock, argv[0]);
if (ret)
hx509_err(context, 1, ret, "hx509_certs_append");
argv++;
}
ret = hx509_certs_store(context, certs, 0, NULL);
if (ret)
hx509_err(context, 1, ret, "hx509_certs_store");
hx509_certs_free(&certs);
return 0;
}
struct verify {
hx509_verify_ctx ctx;
hx509_certs chain;
@@ -801,24 +833,25 @@ ocsp_print(struct ocsp_print_options *opt, int argc, char **argv)
static int
read_private_key(const char *fn, hx509_private_key *key)
{
void *data;
size_t len;
hx509_private_key *keys;
hx509_certs certs;
int ret;
*key = NULL;
ret = _hx509_map_file(fn, &data, &len, NULL);
ret = hx509_certs_init(context, fn, 0, NULL, &certs);
if (ret)
err(1, "read_private_key: map_file: %s: %d", fn, ret);
hx509_err(context, ret, 1, "hx509_certs_init: %s", fn);
ret = _hx509_parse_private_key(context,
oid_id_pkcs1_rsaEncryption(),
data,
len,
key);
_hx509_unmap_file(data, len);
ret = _hx509_certs_keys_get(context, certs, &keys);
hx509_certs_free(&certs);
if (ret)
errx(1, "read_private_key: _hx509_parse_private_key: %d", ret);
hx509_err(context, ret, 1, "hx509_certs_keys_get");
if (keys[0] == NULL)
errx(1, "no keys in key store: %s", fn);
*key = _hx509_private_key_ref(keys[0]);
_hx509_certs_keys_free(context, keys);
return 0;
}
@@ -944,7 +977,7 @@ request_create(struct request_create_options *opt, int argc, char **argv)
if (ret)
hx509_err(context, ret, 1, "_hx509_request_to_pkcs10");
_hx509_free_private_key(&signer);
_hx509_private_key_free(&signer);
_hx509_request_free(&req);
if (ret == 0)
@@ -1269,6 +1302,7 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
hx509_certs cacerts = NULL;
hx509_cert signer = NULL, cert = NULL;
hx509_private_key private_key = NULL;
hx509_private_key cert_key = NULL;
hx509_name subject = NULL;
SubjectPublicKeyInfo spki;
int delta = 0;
@@ -1319,7 +1353,8 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
if (ret)
hx509_err(context, ret, 1, "no CA certificate found");
} else if (opt->self_signed_flag) {
if (opt->generate_key_string == NULL && opt->ca_private_key_string == NULL)
if (opt->generate_key_string == NULL
&& opt->ca_private_key_string == NULL)
errx(1, "no signing private key");
} else
errx(1, "missing ca key");
@@ -1364,19 +1399,19 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
}
if (opt->generate_key_string) {
hx509_private_key key;
get_key(opt->out_key_string,
opt->generate_key_string,
opt->key_bits_integer,
&key);
ret = _hx509_generate_private_key(context,
oid_id_pkcs1_rsaEncryption(),
&cert_key);
if (ret)
hx509_err(context, ret, 1, "generate private key");
ret = _hx509_private_key2SPKI(context, key, &spki);
ret = _hx509_private_key2SPKI(context, cert_key, &spki);
if (ret)
errx(1, "_hx509_private_key2SPKI: %d\n", ret);
if (opt->self_signed_flag)
private_key = key;
private_key = cert_key;
}
if (opt->subject_string) {
@@ -1451,19 +1486,29 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
hx509_err(context, ret, 1, "hx509_ca_sign");
}
{
Certificate *c = _hx509_get_cert(cert);
heim_octet_string data;
size_t size;
ASN1_MALLOC_ENCODE(Certificate, data.data, data.length, c, &size, ret);
if (cert_key) {
ret = _hx509_cert_assign_key(cert, cert_key);
if (ret)
err(1, "malloc out of memory");
if (data.length != size)
_hx509_abort("internal ASN.1 encoder error");
hx509_err(context, ret, 1, "_hx509_cert_assign_key");
}
rk_dumpdata(opt->certificate_string, data.data, data.length);
free(data.data);
{
hx509_certs certs;
ret = hx509_certs_init(context, opt->certificate_string,
HX509_CERTS_CREATE, NULL, &certs);
if (ret)
hx509_err(context, ret, 1, "hx509_certs_init");
ret = hx509_certs_add(context, certs, cert);
if (ret)
hx509_err(context, ret, 1, "hx509_certs_add");
ret = hx509_certs_store(context, certs, 0, NULL);
if (ret)
hx509_err(context, 1, ret, "hx509_certs_store");
hx509_certs_free(&certs);
}
return 0;

View File

@@ -122,6 +122,24 @@ hx509_certs_init(hx509_context context,
return 0;
}
int
hx509_certs_store(hx509_context context,
hx509_certs certs,
int flags,
hx509_lock lock)
{
if (certs->ops->store == NULL) {
hx509_set_error_string(context, 0, EINVAL,
"keystore if type %s doesn't support "
"store operation",
certs->ops->name);
return EINVAL;
}
return (*certs->ops->store)(context, certs, certs->ops_data, flags, lock);
}
void
hx509_certs_free(hx509_certs *certs)
{
@@ -381,3 +399,41 @@ _hx509_pi_printf(int (*func)(void *, char *), void *ctx,
(*func)(ctx, str);
free(str);
}
int
_hx509_certs_keys_get(hx509_context context,
hx509_certs certs,
hx509_private_key **keys)
{
if (certs->ops->getkeys == NULL) {
*keys = NULL;
return 0;
}
return (*certs->ops->getkeys)(context, certs, certs->ops_data, keys);
}
int
_hx509_certs_keys_add(hx509_context context,
hx509_certs certs,
hx509_private_key key)
{
if (certs->ops->addkey == NULL) {
hx509_set_error_string(context, 0, EINVAL,
"keystore if type %s doesn't support "
"key add operation",
certs->ops->name);
return EINVAL;
}
return (*certs->ops->addkey)(context, certs, certs->ops_data, key);
}
void
_hx509_certs_keys_free(hx509_context context,
hx509_private_key *keys)
{
int i;
for (i = 0; keys[i]; i++)
_hx509_private_key_free(&keys[i]);
free(keys);
}

View File

@@ -207,6 +207,7 @@ static struct hx509_keyset_ops keyset_dir = {
"DIR",
0,
dir_init,
NULL,
dir_free,
NULL,
NULL,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005 - 2006 Kungliga Tekniska H<>gskolan
* Copyright (c) 2005 - 2007 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -36,6 +36,7 @@ RCSID("$Id$");
struct ks_file {
hx509_certs certs;
char *fn;
};
struct header {
@@ -430,8 +431,12 @@ parse_pem_file(hx509_context context,
break;
}
p = malloc(i);
p = emalloc(i);
i = base64_decode(buf, p);
if (i < 0) {
free(p);
goto out;
}
data = erealloc(data, len + i);
memcpy(((char *)data) + len, p, i);
@@ -459,6 +464,7 @@ parse_pem_file(hx509_context context,
"Found no matching PEM format for %s",
type);
}
out:
free(data);
data = NULL;
len = 0;
@@ -498,9 +504,10 @@ file_init(hx509_context context,
hx509_certs certs, void **data, int flags,
const char *residue, hx509_lock lock)
{
char *files = NULL, *p, *pnext;
char *p, *pnext;
struct ks_file *f = NULL;
struct hx509_collector *c;
struct hx509_collector *c = NULL;
hx509_private_key *keys = NULL;
int ret;
*data = NULL;
@@ -508,25 +515,41 @@ file_init(hx509_context context,
if (lock == NULL)
lock = _hx509_empty_lock;
c = _hx509_collector_alloc(context, lock);
if (c == NULL)
return ENOMEM;
f = calloc(1, sizeof(*f));
if (f == NULL) {
hx509_clear_error_string(context);
ret = ENOMEM;
goto out;
return ENOMEM;
}
files = strdup(residue);
if (files == NULL) {
f->fn = strdup(residue);
if (f->fn == NULL) {
hx509_clear_error_string(context);
ret = ENOMEM;
goto out;
}
for (p = files; p != NULL; p = pnext) {
/*
* XXX this is broken, the function should parse the file before
* overwriting it
*/
if (flags & HX509_CERTS_CREATE) {
ret = hx509_certs_init(context, "MEMORY:ks-file-create",
0, lock, &f->certs);
if (ret)
goto out;
*data = f;
return 0;
}
c = _hx509_collector_alloc(context, lock);
if (c == NULL) {
ret = ENOMEM;
hx509_set_error_string(context, 0, ret, "out of memory");
goto out;
}
for (p = f->fn; p != NULL; p = pnext) {
int found_data;
pnext = strchr(p, ',');
@@ -559,14 +582,28 @@ file_init(hx509_context context,
}
}
ret = _hx509_collector_collect(context, c, &f->certs);
ret = _hx509_collector_collect_certs(context, c, &f->certs);
if (ret)
goto out;
ret = _hx509_collector_collect_private_keys(context, c, &keys);
if (ret == 0) {
int i;
for (i = 0; keys[i]; i++)
_hx509_certs_keys_add(context, f->certs, keys[i]);
_hx509_certs_keys_free(context, keys);
}
out:
if (ret == 0)
*data = f;
else
else {
if (f->fn)
free(f->fn);
free(f);
free(files);
}
if (c)
_hx509_collector_free(c);
return ret;
}
@@ -576,11 +613,117 @@ file_free(hx509_certs certs, void *data)
{
struct ks_file *f = data;
hx509_certs_free(&f->certs);
free(f->fn);
free(f);
return 0;
}
static void
pem_header(FILE *f, const char *type, const char *str)
{
fprintf(f, "-----%s %s-----\n", type, str);
}
static int
dump_pem_file(hx509_context context, const char *header,
FILE *f, const void *data, size_t size)
{
const char *p = data;
size_t length;
char *line;
#define ENCODE_LINE_LENGTH 54
pem_header(f, "BEGIN", header);
while (size > 0) {
ssize_t l;
length = size;
if (length > ENCODE_LINE_LENGTH)
length = ENCODE_LINE_LENGTH;
l = base64_encode(p, length, &line);
if (l < 0) {
hx509_set_error_string(context, 0, ENOMEM,
"malloc - out of memory");
return ENOMEM;
}
size -= length;
fprintf(f, "%s\n", line);
p += length;
free(line);
}
pem_header(f, "END", header);
return 0;
}
static int
store_private_key(hx509_context context, FILE *f, hx509_private_key key)
{
heim_octet_string data;
int ret;
ret = _hx509_private_key_export(context, key, &data);
if (ret == 0)
dump_pem_file(context, _hx509_private_pem_name(key), f,
data.data, data.length);
free(data.data);
return ret;
}
static int
store_func(hx509_context context, void *ctx, hx509_cert c)
{
FILE *f = (FILE *)ctx;
size_t size;
heim_octet_string data;
int ret;
ASN1_MALLOC_ENCODE(Certificate, data.data, data.length,
_hx509_get_cert(c), &size, ret);
if (ret)
return ret;
if (data.length != size)
_hx509_abort("internal ASN.1 encoder error");
dump_pem_file(context, "CERTIFICATE", f, data.data, data.length);
free(data.data);
if (_hx509_cert_private_key_exportable(c))
store_private_key(context, f, _hx509_cert_private_key(c));
return 0;
}
static int
file_store(hx509_context context,
hx509_certs certs, void *data, int flags, hx509_lock lock)
{
struct ks_file *f = data;
FILE *fh;
int ret;
fh = fopen(f->fn, "w");
if (fh == NULL) {
hx509_set_error_string(context, 0, ENOENT,
"Failed to open file %s for writing");
return ENOENT;
}
ret = hx509_certs_iter(context, f->certs, store_func, fh);
fclose(fh);
return ret;
}
static int
file_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
{
struct ks_file *f = data;
return hx509_certs_add(context, f->certs, c);
}
static int
file_iter_start(hx509_context context,
@@ -608,17 +751,40 @@ file_iter_end(hx509_context context,
return hx509_certs_end_seq(context, f->certs, cursor);
}
static int
file_getkeys(hx509_context context,
hx509_certs certs,
void *data,
hx509_private_key **keys)
{
struct ks_file *f = data;
return _hx509_certs_keys_get(context, f->certs, keys);
}
static int
file_addkey(hx509_context context,
hx509_certs certs,
void *data,
hx509_private_key key)
{
struct ks_file *f = data;
return _hx509_certs_keys_add(context, f->certs, key);
}
static struct hx509_keyset_ops keyset_file = {
"FILE",
0,
file_init,
file_store,
file_free,
NULL,
file_add,
NULL,
file_iter_start,
file_iter,
file_iter_end
file_iter_end,
NULL,
file_getkeys,
file_addkey
};
void

View File

@@ -42,8 +42,11 @@ RCSID("Id$");
struct mem_data {
char *name;
struct {
unsigned long len;
hx509_cert *val;
} certs;
hx509_private_key *keys;
};
static int
@@ -72,9 +75,11 @@ mem_free(hx509_certs certs, void *data)
struct mem_data *mem = data;
unsigned long i;
for (i = 0; i < mem->len; i++)
hx509_cert_free(mem->val[i]);
free(mem->val);
for (i = 0; i < mem->certs.len; i++)
hx509_cert_free(mem->certs.val[i]);
free(mem->certs.val);
for (i = 0; mem->keys && mem->keys[i]; i++)
_hx509_private_key_free(&mem->keys[i]);
free(mem->name);
free(mem);
@@ -87,13 +92,14 @@ mem_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
struct mem_data *mem = data;
hx509_cert *val;
val = realloc(mem->val, (mem->len + 1) * sizeof(mem->val[0]));
val = realloc(mem->certs.val,
(mem->certs.len + 1) * sizeof(mem->certs.val[0]));
if (val == NULL)
return ENOMEM;
mem->val = val;
mem->val[mem->len] = hx509_cert_ref(c);
mem->len++;
mem->certs.val = val;
mem->certs.val[mem->certs.len] = hx509_cert_ref(c);
mem->certs.len++;
return 0;
}
@@ -125,12 +131,12 @@ mem_iter(hx509_context contexst,
unsigned long *iter = cursor;
struct mem_data *mem = data;
if (*iter >= mem->len) {
if (*iter >= mem->certs.len) {
*cert = NULL;
return 0;
}
*cert = hx509_cert_ref(mem->val[*iter]);
*cert = hx509_cert_ref(mem->certs.val[*iter]);
(*iter)++;
return 0;
}
@@ -145,16 +151,69 @@ mem_iter_end(hx509_context context,
return 0;
}
static int
mem_getkeys(hx509_context context,
hx509_certs certs,
void *data,
hx509_private_key **keys)
{
struct mem_data *mem = data;
int i;
for (i = 0; mem->keys && mem->keys[i]; i++)
;
*keys = calloc(i, sizeof(**keys));
for (i = 0; mem->keys && mem->keys[i]; i++) {
(*keys)[i] = _hx509_private_key_ref(mem->keys[i]);
if ((*keys)[i] == NULL) {
while (--i >= 0)
_hx509_private_key_free(&(*keys)[i]);
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
return ENOMEM;
}
}
(*keys)[i] = NULL;
return 0;
}
static int
mem_addkey(hx509_context context,
hx509_certs certs,
void *data,
hx509_private_key key)
{
struct mem_data *mem = data;
void *ptr;
int i;
for (i = 0; mem->keys && mem->keys[i]; i++)
;
ptr = realloc(mem->keys, (i + 2) * sizeof(*mem->keys));
if (ptr == NULL) {
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
return ENOMEM;
}
mem->keys = ptr;
mem->keys[i++] = _hx509_private_key_ref(key);
mem->keys[i++] = NULL;
return 0;
}
static struct hx509_keyset_ops keyset_mem = {
"MEMORY",
0,
mem_init,
NULL,
mem_free,
mem_add,
NULL,
mem_iter_start,
mem_iter,
mem_iter_end
mem_iter_end,
NULL,
mem_getkeys,
mem_addkey
};
void

View File

@@ -82,6 +82,7 @@ struct hx509_keyset_ops keyset_null = {
"NULL",
0,
null_init,
NULL,
null_free,
NULL,
NULL,

View File

@@ -616,7 +616,7 @@ collect_private_key(hx509_context context,
localKeyId.data = query[0].pValue;
localKeyId.length = query[0].ulValueLen;
ret = _hx509_new_private_key(&key);
ret = _hx509_private_key_init(&key, NULL, NULL);
if (ret)
return ret;
@@ -661,7 +661,7 @@ collect_private_key(hx509_context context,
&localKeyId);
if (ret) {
_hx509_free_private_key(&key);
_hx509_private_key_free(&key);
return ret;
}
return 0;
@@ -790,7 +790,7 @@ p11_list_keys(hx509_context context,
if (ret)
goto out;
ret = _hx509_collector_collect(context, collector, &slot->certs);
ret = _hx509_collector_collect_certs(context, collector, &slot->certs);
out:
_hx509_collector_free(collector);
@@ -1164,6 +1164,7 @@ static struct hx509_keyset_ops keyset_pkcs11 = {
"PKCS11",
0,
p11_init,
NULL,
p11_free,
NULL,
NULL,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004 - 2006 Kungliga Tekniska H<>gskolan
* Copyright (c) 2004 - 2007 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -36,6 +36,7 @@ RCSID("$Id$");
struct ks_pkcs12 {
hx509_certs certs;
char *fn;
};
typedef int (*collector_func)(hx509_context,
@@ -66,23 +67,46 @@ find_attribute(const PKCS12_Attributes *attrs, const heim_oid *oid)
}
static int
ShroudedKeyBag_parser(hx509_context context,
keyBag_parser(hx509_context context,
struct hx509_collector *c,
const void *data, size_t length,
const PKCS12_Attributes *attrs)
{
const PKCS12_Attribute *attr;
PKCS8EncryptedPrivateKeyInfo pk;
PKCS8PrivateKeyInfo ki;
const heim_octet_string *os = NULL;
int ret;
attr = find_attribute(attrs, oid_id_pkcs_9_at_localKeyId());
if (attr)
os = &attr->attrValues;
ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL);
if (ret)
return ret;
_hx509_collector_private_key_add(context,
c,
&ki.privateKeyAlgorithm,
NULL,
&ki.privateKey,
&attr->attrValues);
free_PKCS8PrivateKeyInfo(&ki);
return 0;
}
static int
ShroudedKeyBag_parser(hx509_context context,
struct hx509_collector *c,
const void *data, size_t length,
const PKCS12_Attributes *attrs)
{
PKCS8EncryptedPrivateKeyInfo pk;
heim_octet_string content;
int ret;
memset(&pk, 0, sizeof(pk));
attr = find_attribute(attrs, oid_id_pkcs_9_at_localKeyId());
if (attr == NULL)
return 0;
ret = decode_PKCS8EncryptedPrivateKeyInfo(data, length, &pk, NULL);
if (ret)
return ret;
@@ -96,22 +120,9 @@ ShroudedKeyBag_parser(hx509_context context,
if (ret)
return ret;
ret = decode_PKCS8PrivateKeyInfo(content.data, content.length,
&ki, NULL);
ret = keyBag_parser(context, c, content.data, content.length, attrs);
der_free_octet_string(&content);
if (ret)
return ret;
_hx509_collector_private_key_add(context,
c,
&ki.privateKeyAlgorithm,
NULL,
&ki.privateKey,
&attr->attrValues);
free_PKCS8PrivateKeyInfo(&ki);
return 0;
}
static int
@@ -130,6 +141,11 @@ certBag_parser(hx509_context context,
if (ret)
return ret;
if (der_heim_oid_cmp(oid_id_pkcs_9_at_certTypes_x509(), &cb.certType)) {
free_PKCS12_CertBag(&cb);
return 0;
}
ret = decode_PKCS12_OctetString(cb.certValue.data,
cb.certValue.length,
&os,
@@ -285,6 +301,7 @@ envelopedData_parser(hx509_context context,
struct type bagtypes[] = {
{ oid_id_pkcs12_keyBag, keyBag_parser },
{ oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser },
{ oid_id_pkcs12_certBag, certBag_parser },
{ oid_id_pkcs7_data, safeContent_parser },
@@ -334,6 +351,21 @@ p12_init(hx509_context context,
goto out;
}
p12->fn = strdup(residue);
if (p12->fn == NULL) {
ret = ENOMEM;
goto out;
}
if (flags & HX509_CERTS_CREATE) {
ret = hx509_certs_init(context, "MEMORY:ks-file-create",
0, lock, &p12->certs);
if (ret)
goto out;
*data = p12;
return 0;
}
ret = _hx509_map_file(residue, &buf, &len, NULL);
if (ret)
goto out;
@@ -392,7 +424,7 @@ p12_init(hx509_context context,
free_PKCS12_AuthenticatedSafe(&as);
ret = _hx509_collector_collect(context, c, &p12->certs);
ret = _hx509_collector_collect_certs(context, c, &p12->certs);
if (ret == 0)
*data = p12;
@@ -408,15 +440,212 @@ out:
return ret;
}
static int
addBag(hx509_context context,
PKCS12_AuthenticatedSafe *as,
const heim_oid *oid,
void *data,
size_t length)
{
void *ptr;
int ret;
ptr = realloc(as->val, sizeof(as->val[0]) * (as->len + 1));
if (ptr == NULL) {
hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory");
return ENOMEM;
}
as->val = ptr;
ret = der_copy_oid(oid, &as->val[as->len].contentType);
as->val[as->len].content = calloc(1, sizeof(*as->val[0].content));
if (as->val[as->len].content == NULL) {
hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory");
return ENOMEM;
}
as->val[as->len].content->data = data;
as->val[as->len].content->length = length;
as->len++;
return 0;
}
static int
store_func(hx509_context context, void *ctx, hx509_cert c)
{
PKCS12_AuthenticatedSafe *as = ctx;
PKCS12_OctetString os;
PKCS12_CertBag cb;
size_t size;
int ret;
memset(&os, 0, sizeof(os));
memset(&cb, 0, sizeof(cb));
os.data = NULL;
os.length = 0;
ASN1_MALLOC_ENCODE(Certificate, os.data, os.length,
_hx509_get_cert(c), &size, ret);
if (ret)
goto out;
ASN1_MALLOC_ENCODE(PKCS12_OctetString,
cb.certValue.data,cb.certValue.length,
&os, &size, ret);
free(os.data);
if (ret)
goto out;
ret = der_copy_oid(oid_id_pkcs_9_at_certTypes_x509(), &cb.certType);
if (ret) {
free_PKCS12_CertBag(&cb);
goto out;
}
ASN1_MALLOC_ENCODE(PKCS12_CertBag, os.data, os.length,
&cb, &size, ret);
free(cb.certValue.data);
if (ret)
goto out;
ret = addBag(context, as, oid_id_pkcs12_certBag(), os.data, os.length);
if (_hx509_cert_private_key_exportable(c)) {
hx509_private_key key = _hx509_cert_private_key(c);
PKCS8PrivateKeyInfo pki;
memset(&pki, 0, sizeof(pki));
ret = der_parse_hex_heim_integer("00", &pki.version);
if (ret)
return ret;
ret = _hx509_private_key_oid(context, key,
&pki.privateKeyAlgorithm.algorithm);
if (ret) {
free_PKCS8PrivateKeyInfo(&pki);
return ret;
}
ret = _hx509_private_key_export(context,
_hx509_cert_private_key(c),
&pki.privateKey);
if (ret) {
free_PKCS8PrivateKeyInfo(&pki);
return ret;
}
/* set attribute, oid_id_pkcs_9_at_localKeyId() */
ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo, os.data, os.length,
&pki, &size, ret);
free_PKCS8PrivateKeyInfo(&pki);
if (ret)
return ret;
ret = addBag(context, as, oid_id_pkcs12_keyBag(), os.data, os.length);
if (ret)
return ret;
}
out:
return ret;
}
static int
p12_store(hx509_context context,
hx509_certs certs, void *data, int flags, hx509_lock lock)
{
struct ks_pkcs12 *p12 = data;
PKCS12_PFX pfx;
PKCS12_AuthenticatedSafe as;
PKCS12_OctetString asdata;
size_t size;
int ret;
memset(&as, 0, sizeof(as));
memset(&pfx, 0, sizeof(pfx));
ret = hx509_certs_iter(context, p12->certs, store_func, &as);
if (ret)
goto out;
ASN1_MALLOC_ENCODE(PKCS12_AuthenticatedSafe, asdata.data, asdata.length,
&as, &size, ret);
free_PKCS12_AuthenticatedSafe(&as);
if (ret)
return ret;
ret = der_parse_hex_heim_integer("03", &pfx.version);
if (ret) {
free(asdata.data);
goto out;
}
pfx.authSafe.content = calloc(1, sizeof(*pfx.authSafe.content));
ASN1_MALLOC_ENCODE(PKCS12_OctetString,
pfx.authSafe.content->data,
pfx.authSafe.content->length,
&asdata, &size, ret);
free(asdata.data);
if (ret)
goto out;
ret = der_copy_oid(oid_id_pkcs7_data(), &pfx.authSafe.contentType);
if (ret)
goto out;
ASN1_MALLOC_ENCODE(PKCS12_PFX, asdata.data, asdata.length,
&pfx, &size, ret);
if (ret)
goto out;
#if 0
const struct _hx509_password *pw;
pw = _hx509_lock_get_passwords(lock);
if (pw != NULL) {
pfx.macData = calloc(1, sizeof(*pfx.macData));
if (pfx.macData == NULL) {
ret = ENOMEM;
hx509_set_error_string(context, 0, ret, "malloc out of memory");
return ret;
}
if (pfx.macData == NULL) {
free(asdata.data);
goto out;
}
}
ret = calculate_hash(&aspath, pw, pfx.macData);
#endif
rk_dumpdata(p12->fn, asdata.data, asdata.length);
free(asdata.data);
out:
free_PKCS12_AuthenticatedSafe(&as);
free_PKCS12_PFX(&pfx);
return ret;
}
static int
p12_free(hx509_certs certs, void *data)
{
struct ks_pkcs12 *p12 = data;
hx509_certs_free(&p12->certs);
free(p12->fn);
free(p12);
return 0;
}
static int
p12_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
{
struct ks_pkcs12 *p12 = data;
return hx509_certs_add(context, p12->certs, c);
}
static int
p12_iter_start(hx509_context context,
hx509_certs certs,
@@ -452,8 +681,9 @@ static struct hx509_keyset_ops keyset_pkcs12 = {
"PKCS12",
0,
p12_init,
p12_store,
p12_free,
NULL,
p12_add,
NULL,
p12_iter_start,
p12_iter,

View File

@@ -44,7 +44,7 @@ fi
echo "create certificate request"
${hxtool} request-create \
--subject="CN=Love,DC=it,DC=su,DC=se" \
--key=$srcdir/data/key.der \
--key=FILE:$srcdir/data/key.der \
pkcs10-request.der || exit 1
echo "issue certificate"
@@ -52,7 +52,7 @@ ${hxtool} issue-certificate \
--ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \
--subject="cn=foo" \
--req="pkcs10-request.der" \
--certificate="cert-ee.der" || exit 1
--certificate="FILE:cert-ee.der" || exit 1
echo "verify certificate"
${hxtool} verify --missing-revoke \
@@ -65,7 +65,7 @@ ${hxtool} issue-certificate \
--subject="cn=foo" \
--lifetime="10years 1 month" \
--req="pkcs10-request.der" \
--certificate="cert-ee.der" || exit 1
--certificate="FILE:cert-ee.der" || exit 1
echo "issue certificate (with https ekus)"
${hxtool} issue-certificate \
@@ -74,7 +74,7 @@ ${hxtool} issue-certificate \
--type="https-server" \
--type="https-client" \
--req="pkcs10-request.der" \
--certificate="cert-ee.der" || exit 1
--certificate="FILE:cert-ee.der" || exit 1
echo "issue certificate (pkinit KDC)"
${hxtool} issue-certificate \
@@ -83,7 +83,7 @@ ${hxtool} issue-certificate \
--type="pkinit-kdc" \
--pk-init-principal="krbtgt/TEST.H5L.SE@TEST.H5L.SE" \
--req="pkcs10-request.der" \
--certificate="cert-ee.der" || exit 1
--certificate="FILE:cert-ee.der" || exit 1
echo "issue certificate (pkinit client)"
${hxtool} issue-certificate \
@@ -92,7 +92,7 @@ ${hxtool} issue-certificate \
--type="pkinit-client" \
--pk-init-principal="lha@TEST.H5L.SE" \
--req="pkcs10-request.der" \
--certificate="cert-ee.der" || exit 1
--certificate="FILE:cert-ee.der" || exit 1
echo "issue certificate (hostnames)"
${hxtool} issue-certificate \
@@ -102,7 +102,7 @@ ${hxtool} issue-certificate \
--hostname="www.test.h5l.se" \
--hostname="ftp.test.h5l.se" \
--req="pkcs10-request.der" \
--certificate="cert-ee.der" || exit 1
--certificate="FILE:cert-ee.der" || exit 1
echo "issue certificate (email)"
${hxtool} issue-certificate \
@@ -111,14 +111,14 @@ ${hxtool} issue-certificate \
--email="lha@test.h5l.se" \
--email="test@test.h5l.se" \
--req="pkcs10-request.der" \
--certificate="cert-ee.der" || exit 1
--certificate="FILE:cert-ee.der" || exit 1
echo "issue self-signed cert"
${hxtool} issue-certificate \
--self-signed \
--ca-private-key=$srcdir/data/key.der \
--ca-private-key=FILE:$srcdir/data/key.der \
--subject="cn=test" \
--certificate="cert-ee.der" || exit 1
--certificate="FILE:cert-ee.der" || exit 1
echo "issue ca cert"
${hxtool} issue-certificate \
@@ -126,22 +126,22 @@ ${hxtool} issue-certificate \
--issue-ca \
--subject="cn=ca-cert" \
--req="pkcs10-request.der" \
--certificate="cert-ca.der" || exit 1
--certificate="FILE:cert-ca.der" || exit 1
echo "issue self-signed ca cert"
${hxtool} issue-certificate \
--self-signed \
--issue-ca \
--ca-private-key=$srcdir/data/key.der \
--ca-private-key=FILE:$srcdir/data/key.der \
--subject="cn=ca-root" \
--certificate="cert-ca.der" || exit 1
--certificate="FILE:cert-ca.der" || exit 1
echo "issue proxy certificate"
${hxtool} issue-certificate \
--ca-certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \
--issue-proxy \
--req="pkcs10-request.der" \
--certificate="cert-proxy.der" || exit 1
--certificate="FILE:cert-proxy.der" || exit 1
echo "verify proxy cert"
${hxtool} verify --missing-revoke \
@@ -156,17 +156,15 @@ ${hxtool} issue-certificate \
--issue-ca \
--serial-number="deadbeaf" \
--generate-key=rsa \
--out-key="ca2-key.der" \
--subject="cn=ca2-cert" \
--certificate="cert-ca.der" || exit 1
--certificate="FILE:cert-ca.der" || exit 1
echo "issue ee cert (generate rsa key)"
${hxtool} issue-certificate \
--ca-certificate=FILE:cert-ca.der,ca2-key.der \
--ca-certificate=FILE:cert-ca.der \
--generate-key=rsa \
--out-key="ee2-key.der" \
--subject="cn=cert-ee2" \
--certificate="cert-ee.der" || exit 1
--certificate="FILE:cert-ee.der" || exit 1
echo "verify certificate"
${hxtool} verify --missing-revoke \
@@ -186,17 +184,15 @@ ${hxtool} cms-verify-sd \
sd.data sd.data.out > /dev/null || exit 1
cmp "$srcdir/test_name.c" sd.data.out || exit 1
openssl x509 -in cert-ca.der -inform der -text > diff1
echo "extend ca cert"
${hxtool} issue-certificate \
--self-signed \
--issue-ca \
--lifetime="2years" \
--serial-number="deadbeaf" \
--ca-private-key=ca2-key.der \
--ca-private-key=FILE:cert-ca.der \
--subject="cn=ca2-cert" \
--certificate="cert-ca.der" || exit 1
openssl x509 -in cert-ca.der -inform der -text > diff2
--certificate="FILE:cert-ca.der" || exit 1
echo "verify certificate generated by previous ca"
${hxtool} verify --missing-revoke \

View File

@@ -148,5 +148,20 @@ ${hxtool} crypto-available \
cmp test ${srcdir}/tst-crypto-available3 > /dev/null || \
{ echo "available3 failure"; exit 1; }
echo "copy keystore FILE existing -> FILE"
${hxtool} certificate-copy \
FILE:${srcdir}/data/test.crt,${srcdir}/data/test.key \
FILE:out.pem || exit 1
echo "copy keystore FILE -> FILE"
${hxtool} certificate-copy \
FILE:out.pem \
FILE:out2.pem || exit 1
echo "copy keystore FILE -> PKCS12"
${hxtool} certificate-copy \
FILE:out.pem \
PKCS12:out2.pem || exit 1
exit 0

View File

@@ -1,6 +1,6 @@
#!/bin/sh
#
# Copyright (c) 2005 Kungliga Tekniska H<>gskolan
# Copyright (c) 2005 - 2007 Kungliga Tekniska H<>gskolan
# (Royal Institute of Technology, Stockholm, Sweden).
# All rights reserved.
#
@@ -60,6 +60,11 @@ ${hxtool} query \
--friendlyname=friendlyname-test-not \
PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null && exit 1
echo "make sure entry is found (friendlyname, no-pw)"
${hxtool} query \
--friendlyname=friendlyname-cert \
PKCS12:$srcdir/data/test-nopw.p12 >/dev/null 2>/dev/null || exit 1
echo "check for ca cert (friendlyname)"
${hxtool} query \
--pass=PASS:foobar \

View File

@@ -1,6 +1,6 @@
#!/bin/sh
#
# Copyright (c) 2005 Kungliga Tekniska H<>gskolan
# Copyright (c) 2005 - 2007 Kungliga Tekniska H<>gskolan
# (Royal Institute of Technology, Stockholm, Sweden).
# All rights reserved.
#
@@ -44,7 +44,7 @@ fi
${hxtool} request-create \
--subject="CN=Love,DC=it,DC=su,DC=se" \
--key=$srcdir/data/key.der \
--key=FILE:$srcdir/data/key.der \
request.out || exit 1
${hxtool} pkcs10-print \
@@ -53,5 +53,5 @@ ${hxtool} pkcs10-print \
${hxtool} request-create \
--subject="CN=Love,DC=it,DC=su,DC=se" \
--dnsname=nutcracker.it.su.se \
--key=$srcdir/data/key.der \
--key=FILE:$srcdir/data/key.der \
request.out || exit 1