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:
@@ -1,4 +1,18 @@
|
|||||||
|
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>
|
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
|
* test_ca.in: test reissueing ca certificate (xxx time
|
||||||
validAfter).
|
validAfter).
|
||||||
|
@@ -138,6 +138,7 @@ CLEANFILES = $(BUILT_SOURCES) \
|
|||||||
$(TESTS) \
|
$(TESTS) \
|
||||||
hxtool-commands.c hxtool-commands.h *.tmp \
|
hxtool-commands.c hxtool-commands.h *.tmp \
|
||||||
request.out \
|
request.out \
|
||||||
|
out.pem out2.pem \
|
||||||
sd.data sd.data.out \
|
sd.data sd.data.out \
|
||||||
ev.data ev.data.out \
|
ev.data ev.data.out \
|
||||||
cert-proxy.der cert-ca.der cert-ee.der pkcs10-request.der \
|
cert-proxy.der cert-ca.der cert-ee.der pkcs10-request.der \
|
||||||
|
@@ -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).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -236,8 +236,8 @@ int
|
|||||||
_hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
|
_hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
|
||||||
{
|
{
|
||||||
if (cert->private_key)
|
if (cert->private_key)
|
||||||
_hx509_free_private_key(&cert->private_key);
|
_hx509_private_key_free(&cert->private_key);
|
||||||
cert->private_key = private_key;
|
cert->private_key = _hx509_private_key_ref(private_key);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,7 +258,7 @@ hx509_cert_free(hx509_cert cert)
|
|||||||
(cert->release)(cert, cert->ctx);
|
(cert->release)(cert, cert->ctx);
|
||||||
|
|
||||||
if (cert->private_key)
|
if (cert->private_key)
|
||||||
_hx509_free_private_key(&cert->private_key);
|
_hx509_private_key_free(&cert->private_key);
|
||||||
|
|
||||||
free_Certificate(cert->data);
|
free_Certificate(cert->data);
|
||||||
free(cert->data);
|
free(cert->data);
|
||||||
@@ -1071,6 +1071,14 @@ _hx509_cert_private_key(hx509_cert p)
|
|||||||
return p->private_key;
|
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
|
int
|
||||||
_hx509_cert_private_decrypt(hx509_context context,
|
_hx509_cert_private_decrypt(hx509_context context,
|
||||||
const heim_octet_string *ciphertext,
|
const heim_octet_string *ciphertext,
|
||||||
|
@@ -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).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -101,7 +101,7 @@ free_private_key(struct private_key *key)
|
|||||||
{
|
{
|
||||||
free_AlgorithmIdentifier(&key->alg);
|
free_AlgorithmIdentifier(&key->alg);
|
||||||
if (key->private_key)
|
if (key->private_key)
|
||||||
_hx509_free_private_key(&key->private_key);
|
_hx509_private_key_free(&key->private_key);
|
||||||
der_free_octet_string(&key->localKeyId);
|
der_free_octet_string(&key->localKeyId);
|
||||||
free(key);
|
free(key);
|
||||||
}
|
}
|
||||||
@@ -188,10 +188,8 @@ match_localkeyid(hx509_context context,
|
|||||||
ret = hx509_certs_find(context, certs, &q, &cert);
|
ret = hx509_certs_find(context, certs, &q, &cert);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
|
||||||
if (value->private_key) {
|
if (value->private_key)
|
||||||
_hx509_cert_assign_key(cert, value->private_key);
|
_hx509_cert_assign_key(cert, value->private_key);
|
||||||
value->private_key = NULL;
|
|
||||||
}
|
|
||||||
hx509_cert_free(cert);
|
hx509_cert_free(cert);
|
||||||
}
|
}
|
||||||
return ret;
|
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);
|
ret = _hx509_match_keys(c, value->private_key);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
_hx509_cert_assign_key(c, value->private_key);
|
_hx509_cert_assign_key(c, value->private_key);
|
||||||
value->private_key = NULL;
|
|
||||||
hx509_cert_free(c);
|
hx509_cert_free(c);
|
||||||
found = 0;
|
found = 0;
|
||||||
break;
|
break;
|
||||||
@@ -246,9 +243,9 @@ match_keys(hx509_context context, struct private_key *value, hx509_certs certs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_hx509_collector_collect(hx509_context context,
|
_hx509_collector_collect_certs(hx509_context context,
|
||||||
struct hx509_collector *c,
|
struct hx509_collector *c,
|
||||||
hx509_certs *ret_certs)
|
hx509_certs *ret_certs)
|
||||||
{
|
{
|
||||||
hx509_certs certs;
|
hx509_certs certs;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
@@ -279,6 +276,37 @@ _hx509_collector_collect(hx509_context context,
|
|||||||
return 0;
|
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
|
void
|
||||||
_hx509_collector_free(struct hx509_collector *c)
|
_hx509_collector_free(struct hx509_collector *c)
|
||||||
{
|
{
|
||||||
|
@@ -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).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -42,14 +42,22 @@ enum crypto_op_type {
|
|||||||
COT_SIGN
|
COT_SIGN
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hx509_private_key {
|
|
||||||
const struct signature_alg *md;
|
struct hx509_private_key_ops {
|
||||||
const heim_oid *signature_alg;
|
const char *pemtype;
|
||||||
struct {
|
const heim_oid *(*key_oid)(void);
|
||||||
RSA *rsa;
|
int (*get_spki)(hx509_context,
|
||||||
} private_key;
|
const hx509_private_key,
|
||||||
/* new crypto layer */
|
SubjectPublicKeyInfo *);
|
||||||
void *key;
|
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,
|
int (*handle_alg)(const hx509_private_key,
|
||||||
const AlgorithmIdentifier *,
|
const AlgorithmIdentifier *,
|
||||||
enum crypto_op_type);
|
enum crypto_op_type);
|
||||||
@@ -60,20 +68,29 @@ struct hx509_private_key {
|
|||||||
AlgorithmIdentifier *,
|
AlgorithmIdentifier *,
|
||||||
heim_octet_string *);
|
heim_octet_string *);
|
||||||
#if 0
|
#if 0
|
||||||
const AlgorithmIdentifier *
|
const AlgorithmIdentifier *(*preferred_sig_alg)
|
||||||
(*preferred_sig_alg)(const hx509_private_key_key,
|
(const hx509_private_key,
|
||||||
const hx509_peer_info);
|
const hx509_peer_info);
|
||||||
int (*unwrap)(hx509_context context,
|
int (*unwrap)(hx509_context context,
|
||||||
const hx509_private_key,
|
const hx509_private_key,
|
||||||
const AlgorithmIdentifier *,
|
const AlgorithmIdentifier *,
|
||||||
const heim_octet_string *,
|
const heim_octet_string *,
|
||||||
heim_octet_string *);
|
heim_octet_string *);
|
||||||
int (*get_spki)(hx509_context context,
|
|
||||||
const hx509_private_key_key,
|
|
||||||
SubjectPublicKeyInfo *);
|
|
||||||
#endif
|
#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 *,
|
const heim_octet_string *,
|
||||||
AlgorithmIdentifier *,
|
AlgorithmIdentifier *,
|
||||||
heim_octet_string *);
|
heim_octet_string *);
|
||||||
int (*parse_private_key)(hx509_context,
|
int (*private_key2SPKI)(hx509_context,
|
||||||
const struct signature_alg *,
|
hx509_private_key,
|
||||||
const void *data,
|
SubjectPublicKeyInfo *);
|
||||||
size_t len,
|
|
||||||
hx509_private_key private_key);
|
|
||||||
int (*private_key2SPKI)(hx509_private_key private_key,
|
|
||||||
SubjectPublicKeyInfo *spki);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -330,11 +343,10 @@ rsa_create_signature(hx509_context context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rsa_parse_private_key(hx509_context context,
|
rsa_private_key_import(hx509_context context,
|
||||||
const struct signature_alg *sig_alg,
|
const void *data,
|
||||||
const void *data,
|
size_t len,
|
||||||
size_t len,
|
hx509_private_key private_key)
|
||||||
hx509_private_key private_key)
|
|
||||||
{
|
{
|
||||||
const unsigned char *p = data;
|
const unsigned char *p = data;
|
||||||
|
|
||||||
@@ -351,7 +363,8 @@ rsa_parse_private_key(hx509_context context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rsa_private_key2SPKI(hx509_private_key private_key,
|
rsa_private_key2SPKI(hx509_context context,
|
||||||
|
hx509_private_key private_key,
|
||||||
SubjectPublicKeyInfo *spki)
|
SubjectPublicKeyInfo *spki)
|
||||||
{
|
{
|
||||||
int len, ret;
|
int len, ret;
|
||||||
@@ -361,14 +374,17 @@ rsa_private_key2SPKI(hx509_private_key private_key,
|
|||||||
len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL);
|
len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL);
|
||||||
|
|
||||||
spki->subjectPublicKey.data = malloc(len);
|
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;
|
return ENOMEM;
|
||||||
|
}
|
||||||
spki->subjectPublicKey.length = len * 8;
|
spki->subjectPublicKey.length = len * 8;
|
||||||
|
|
||||||
ret = _hx509_set_digest_alg(&spki->algorithm,
|
ret = _hx509_set_digest_alg(&spki->algorithm,
|
||||||
oid_id_pkcs1_rsaEncryption(),
|
oid_id_pkcs1_rsaEncryption(),
|
||||||
"\x05\x00", 2);
|
"\x05\x00", 2);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
hx509_set_error_string(context, 0, ret, "malloc - out of memory");
|
||||||
free(spki->subjectPublicKey.data);
|
free(spki->subjectPublicKey.data);
|
||||||
spki->subjectPublicKey.data = NULL;
|
spki->subjectPublicKey.data = NULL;
|
||||||
spki->subjectPublicKey.length = 0;
|
spki->subjectPublicKey.length = 0;
|
||||||
@@ -383,6 +399,90 @@ rsa_private_key2SPKI(hx509_private_key private_key,
|
|||||||
return 0;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int
|
static int
|
||||||
dsa_parse_private_key(hx509_context context,
|
dsa_parse_private_key(hx509_context context,
|
||||||
const struct signature_alg *sig_alg,
|
|
||||||
const void *data,
|
const void *data,
|
||||||
size_t len,
|
size_t len,
|
||||||
hx509_private_key private_key)
|
hx509_private_key private_key)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
const unsigned char *p = data;
|
const unsigned char *p = data;
|
||||||
|
|
||||||
private_key->private_key.dsa =
|
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();
|
private_key->signature_alg = oid_id_dsa_with_sha1();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
/* else */
|
||||||
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
|
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
|
||||||
"No support to parse DSA keys");
|
"No support to parse DSA keys");
|
||||||
return HX509_PARSING_KEY_FAILED;
|
return HX509_PARSING_KEY_FAILED;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -699,7 +798,6 @@ static struct signature_alg pkcs1_rsa_sha1_alg = {
|
|||||||
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
||||||
rsa_verify_signature,
|
rsa_verify_signature,
|
||||||
rsa_create_signature,
|
rsa_create_signature,
|
||||||
rsa_parse_private_key,
|
|
||||||
rsa_private_key2SPKI
|
rsa_private_key2SPKI
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -712,7 +810,6 @@ static struct signature_alg rsa_with_sha256_alg = {
|
|||||||
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
||||||
rsa_verify_signature,
|
rsa_verify_signature,
|
||||||
rsa_create_signature,
|
rsa_create_signature,
|
||||||
rsa_parse_private_key,
|
|
||||||
rsa_private_key2SPKI
|
rsa_private_key2SPKI
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -725,7 +822,6 @@ static struct signature_alg rsa_with_sha1_alg = {
|
|||||||
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
||||||
rsa_verify_signature,
|
rsa_verify_signature,
|
||||||
rsa_create_signature,
|
rsa_create_signature,
|
||||||
rsa_parse_private_key,
|
|
||||||
rsa_private_key2SPKI
|
rsa_private_key2SPKI
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -738,7 +834,6 @@ static struct signature_alg rsa_with_md5_alg = {
|
|||||||
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
||||||
rsa_verify_signature,
|
rsa_verify_signature,
|
||||||
rsa_create_signature,
|
rsa_create_signature,
|
||||||
rsa_parse_private_key,
|
|
||||||
rsa_private_key2SPKI
|
rsa_private_key2SPKI
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -751,7 +846,6 @@ static struct signature_alg rsa_with_md2_alg = {
|
|||||||
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
||||||
rsa_verify_signature,
|
rsa_verify_signature,
|
||||||
rsa_create_signature,
|
rsa_create_signature,
|
||||||
rsa_parse_private_key,
|
|
||||||
rsa_private_key2SPKI
|
rsa_private_key2SPKI
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -764,7 +858,6 @@ static struct signature_alg dsa_sha1_alg = {
|
|||||||
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
|
||||||
dsa_verify_signature,
|
dsa_verify_signature,
|
||||||
/* create_signature */ NULL,
|
/* create_signature */ NULL,
|
||||||
dsa_parse_private_key
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct signature_alg sha256_alg = {
|
static struct signature_alg sha256_alg = {
|
||||||
@@ -838,19 +931,29 @@ find_sig_alg(const heim_oid *oid)
|
|||||||
return NULL;
|
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;
|
int i;
|
||||||
for (i = 0; sig_algs[i]; i++) {
|
for (i = 0; private_algs[i]; i++) {
|
||||||
if (sig_algs[i]->key_oid == NULL)
|
if (private_algs[i]->key_oid == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (der_heim_oid_cmp((*sig_algs[i]->key_oid)(), oid) == 0)
|
if (der_heim_oid_cmp((*private_algs[i]->key_oid)(), oid) == 0)
|
||||||
return sig_algs[i];
|
return private_algs[i];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
_hx509_verify_signature(hx509_context context,
|
_hx509_verify_signature(hx509_context context,
|
||||||
const Certificate *signer,
|
const Certificate *signer,
|
||||||
@@ -916,11 +1019,11 @@ _hx509_create_signature(hx509_context context,
|
|||||||
{
|
{
|
||||||
const struct signature_alg *md;
|
const struct signature_alg *md;
|
||||||
|
|
||||||
if (signer && signer->handle_alg &&
|
if (signer && signer->ops && signer->ops->handle_alg &&
|
||||||
(*signer->handle_alg)(signer, alg, COT_SIGN))
|
(*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);
|
signatureAlgorithm, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
md = find_sig_alg(&alg->algorithm);
|
md = find_sig_alg(&alg->algorithm);
|
||||||
@@ -1089,28 +1192,26 @@ _hx509_parse_private_key(hx509_context context,
|
|||||||
size_t len,
|
size_t len,
|
||||||
hx509_private_key *private_key)
|
hx509_private_key *private_key)
|
||||||
{
|
{
|
||||||
const struct signature_alg *md;
|
struct hx509_private_key_ops *ops;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
*private_key = NULL;
|
*private_key = NULL;
|
||||||
|
|
||||||
md = find_key_alg(key_oid);
|
ops = find_private_alg(key_oid);
|
||||||
if (md == NULL) {
|
if (ops == NULL) {
|
||||||
hx509_clear_error_string(context);
|
hx509_clear_error_string(context);
|
||||||
return HX509_SIG_ALG_NO_SUPPORTED;
|
return HX509_SIG_ALG_NO_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = _hx509_new_private_key(private_key);
|
ret = _hx509_private_key_init(private_key, ops, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
hx509_set_error_string(context, 0, ret, "out of memory");
|
hx509_set_error_string(context, 0, ret, "out of memory");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (*md->parse_private_key)(context, md, data, len, *private_key);
|
ret = (*ops->import)(context, data, len, *private_key);
|
||||||
if (ret)
|
if (ret)
|
||||||
_hx509_free_private_key(private_key);
|
_hx509_private_key_free(private_key);
|
||||||
else
|
|
||||||
(*private_key)->md = md;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1124,13 +1225,42 @@ _hx509_private_key2SPKI(hx509_context context,
|
|||||||
hx509_private_key private_key,
|
hx509_private_key private_key,
|
||||||
SubjectPublicKeyInfo *spki)
|
SubjectPublicKeyInfo *spki)
|
||||||
{
|
{
|
||||||
const struct signature_alg *md = private_key->md;
|
const struct hx509_private_key_ops *ops = private_key->ops;
|
||||||
if (md->private_key2SPKI == NULL) {
|
if (ops == NULL || ops->get_spki == NULL) {
|
||||||
hx509_set_error_string(context, 0, HX509_UNIMPLEMENTED_OPERATION,
|
hx509_set_error_string(context, 0, HX509_UNIMPLEMENTED_OPERATION,
|
||||||
"Private key have no key2SPKI function");
|
"Private key have no key2SPKI function");
|
||||||
return HX509_UNIMPLEMENTED_OPERATION;
|
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; }
|
{ return &_hx509_signature_rsa_data; }
|
||||||
|
|
||||||
int
|
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));
|
*key = calloc(1, sizeof(**key));
|
||||||
if (*key == NULL)
|
if (*key == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
(*key)->ref = 1;
|
||||||
|
(*key)->ops = ops;
|
||||||
|
(*key)->private_key.keydata = keydata;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
hx509_private_key
|
||||||
_hx509_free_private_key(hx509_private_key *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)
|
if ((*key)->private_key.rsa)
|
||||||
RSA_free((*key)->private_key.rsa);
|
RSA_free((*key)->private_key.rsa);
|
||||||
(*key)->private_key.rsa = NULL;
|
(*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;
|
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 {
|
struct hx509cipher {
|
||||||
const char *name;
|
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->q = BN_dup(private_key->private_key.rsa->q);
|
||||||
rsa->dmp1 = BN_dup(private_key->private_key.rsa->dmp1);
|
rsa->dmp1 = BN_dup(private_key->private_key.rsa->dmp1);
|
||||||
rsa->dmq1 = BN_dup(private_key->private_key.rsa->dmq1);
|
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 ||
|
if (rsa->n == NULL || rsa->e == NULL ||
|
||||||
rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL ||
|
rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL ||
|
||||||
|
@@ -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).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -93,6 +93,9 @@ typedef enum {
|
|||||||
HX509_QUERY_OPTION_END = 0xffff
|
HX509_QUERY_OPTION_END = 0xffff
|
||||||
} hx509_query_option;
|
} hx509_query_option;
|
||||||
|
|
||||||
|
/* flags to hx509_certs_init */
|
||||||
|
#define HX509_CERTS_CREATE 0x01
|
||||||
|
|
||||||
/* flags to hx509_set_error_string */
|
/* flags to hx509_set_error_string */
|
||||||
#define HX509_ERROR_APPEND 0x01
|
#define HX509_ERROR_APPEND 0x01
|
||||||
|
|
||||||
|
@@ -77,6 +77,8 @@ typedef struct hx509_path hx509_path;
|
|||||||
|
|
||||||
typedef void (*_hx509_cert_release_func)(struct hx509_cert_data *, void *);
|
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-private.h>
|
||||||
#include <hx509_err.h>
|
#include <hx509_err.h>
|
||||||
|
|
||||||
@@ -146,6 +148,7 @@ struct hx509_keyset_ops {
|
|||||||
int flags;
|
int flags;
|
||||||
int (*init)(hx509_context, hx509_certs, void **,
|
int (*init)(hx509_context, hx509_certs, void **,
|
||||||
int, const char *, hx509_lock);
|
int, const char *, hx509_lock);
|
||||||
|
int (*store)(hx509_context, hx509_certs, void *, int, hx509_lock);
|
||||||
int (*free)(hx509_certs, void *);
|
int (*free)(hx509_certs, void *);
|
||||||
int (*add)(hx509_context, hx509_certs, void *, hx509_cert);
|
int (*add)(hx509_context, hx509_certs, void *, hx509_cert);
|
||||||
int (*query)(hx509_context, hx509_certs, void *,
|
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 (*iter_end)(hx509_context, hx509_certs, void *, void *);
|
||||||
int (*printinfo)(hx509_context, hx509_certs,
|
int (*printinfo)(hx509_context, hx509_certs,
|
||||||
void *, int (*)(void *, char *), void *);
|
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 {
|
struct _hx509_password {
|
||||||
|
@@ -236,6 +236,25 @@ command = {
|
|||||||
argument="certificate ..."
|
argument="certificate ..."
|
||||||
help = "Validate content of certificates"
|
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 = {
|
command = {
|
||||||
name = "ocsp-fetch"
|
name = "ocsp-fetch"
|
||||||
option = {
|
option = {
|
||||||
@@ -511,11 +530,6 @@ command = {
|
|||||||
type = "string"
|
type = "string"
|
||||||
help = "pkcs10 request"
|
help = "pkcs10 request"
|
||||||
}
|
}
|
||||||
option = {
|
|
||||||
long = "out-key"
|
|
||||||
type = "string"
|
|
||||||
help = "out key"
|
|
||||||
}
|
|
||||||
option = {
|
option = {
|
||||||
long = "generate-key"
|
long = "generate-key"
|
||||||
type = "string"
|
type = "string"
|
||||||
|
@@ -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).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -540,6 +540,38 @@ pcert_validate(struct validate_options *opt, int argc, char **argv)
|
|||||||
return 0;
|
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 {
|
struct verify {
|
||||||
hx509_verify_ctx ctx;
|
hx509_verify_ctx ctx;
|
||||||
hx509_certs chain;
|
hx509_certs chain;
|
||||||
@@ -801,24 +833,25 @@ ocsp_print(struct ocsp_print_options *opt, int argc, char **argv)
|
|||||||
static int
|
static int
|
||||||
read_private_key(const char *fn, hx509_private_key *key)
|
read_private_key(const char *fn, hx509_private_key *key)
|
||||||
{
|
{
|
||||||
void *data;
|
hx509_private_key *keys;
|
||||||
size_t len;
|
hx509_certs certs;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
*key = NULL;
|
*key = NULL;
|
||||||
|
|
||||||
ret = _hx509_map_file(fn, &data, &len, NULL);
|
ret = hx509_certs_init(context, fn, 0, NULL, &certs);
|
||||||
if (ret)
|
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,
|
ret = _hx509_certs_keys_get(context, certs, &keys);
|
||||||
oid_id_pkcs1_rsaEncryption(),
|
hx509_certs_free(&certs);
|
||||||
data,
|
|
||||||
len,
|
|
||||||
key);
|
|
||||||
_hx509_unmap_file(data, len);
|
|
||||||
if (ret)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -944,7 +977,7 @@ request_create(struct request_create_options *opt, int argc, char **argv)
|
|||||||
if (ret)
|
if (ret)
|
||||||
hx509_err(context, ret, 1, "_hx509_request_to_pkcs10");
|
hx509_err(context, ret, 1, "_hx509_request_to_pkcs10");
|
||||||
|
|
||||||
_hx509_free_private_key(&signer);
|
_hx509_private_key_free(&signer);
|
||||||
_hx509_request_free(&req);
|
_hx509_request_free(&req);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
@@ -1269,6 +1302,7 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
|
|||||||
hx509_certs cacerts = NULL;
|
hx509_certs cacerts = NULL;
|
||||||
hx509_cert signer = NULL, cert = NULL;
|
hx509_cert signer = NULL, cert = NULL;
|
||||||
hx509_private_key private_key = NULL;
|
hx509_private_key private_key = NULL;
|
||||||
|
hx509_private_key cert_key = NULL;
|
||||||
hx509_name subject = NULL;
|
hx509_name subject = NULL;
|
||||||
SubjectPublicKeyInfo spki;
|
SubjectPublicKeyInfo spki;
|
||||||
int delta = 0;
|
int delta = 0;
|
||||||
@@ -1319,7 +1353,8 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
|
|||||||
if (ret)
|
if (ret)
|
||||||
hx509_err(context, ret, 1, "no CA certificate found");
|
hx509_err(context, ret, 1, "no CA certificate found");
|
||||||
} else if (opt->self_signed_flag) {
|
} 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");
|
errx(1, "no signing private key");
|
||||||
} else
|
} else
|
||||||
errx(1, "missing ca key");
|
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) {
|
if (opt->generate_key_string) {
|
||||||
hx509_private_key key;
|
|
||||||
|
|
||||||
get_key(opt->out_key_string,
|
ret = _hx509_generate_private_key(context,
|
||||||
opt->generate_key_string,
|
oid_id_pkcs1_rsaEncryption(),
|
||||||
opt->key_bits_integer,
|
&cert_key);
|
||||||
&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)
|
if (ret)
|
||||||
errx(1, "_hx509_private_key2SPKI: %d\n", ret);
|
errx(1, "_hx509_private_key2SPKI: %d\n", ret);
|
||||||
|
|
||||||
if (opt->self_signed_flag)
|
if (opt->self_signed_flag)
|
||||||
private_key = key;
|
private_key = cert_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt->subject_string) {
|
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");
|
hx509_err(context, ret, 1, "hx509_ca_sign");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (cert_key) {
|
||||||
Certificate *c = _hx509_get_cert(cert);
|
ret = _hx509_cert_assign_key(cert, cert_key);
|
||||||
heim_octet_string data;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
ASN1_MALLOC_ENCODE(Certificate, data.data, data.length, c, &size, ret);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
err(1, "malloc out of memory");
|
hx509_err(context, ret, 1, "_hx509_cert_assign_key");
|
||||||
if (data.length != size)
|
}
|
||||||
_hx509_abort("internal ASN.1 encoder error");
|
|
||||||
|
|
||||||
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;
|
return 0;
|
||||||
|
@@ -122,6 +122,24 @@ hx509_certs_init(hx509_context context,
|
|||||||
return 0;
|
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
|
void
|
||||||
hx509_certs_free(hx509_certs *certs)
|
hx509_certs_free(hx509_certs *certs)
|
||||||
{
|
{
|
||||||
@@ -381,3 +399,41 @@ _hx509_pi_printf(int (*func)(void *, char *), void *ctx,
|
|||||||
(*func)(ctx, str);
|
(*func)(ctx, str);
|
||||||
free(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);
|
||||||
|
}
|
||||||
|
@@ -207,6 +207,7 @@ static struct hx509_keyset_ops keyset_dir = {
|
|||||||
"DIR",
|
"DIR",
|
||||||
0,
|
0,
|
||||||
dir_init,
|
dir_init,
|
||||||
|
NULL,
|
||||||
dir_free,
|
dir_free,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@@ -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).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -36,6 +36,7 @@ RCSID("$Id$");
|
|||||||
|
|
||||||
struct ks_file {
|
struct ks_file {
|
||||||
hx509_certs certs;
|
hx509_certs certs;
|
||||||
|
char *fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct header {
|
struct header {
|
||||||
@@ -430,8 +431,12 @@ parse_pem_file(hx509_context context,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = malloc(i);
|
p = emalloc(i);
|
||||||
i = base64_decode(buf, p);
|
i = base64_decode(buf, p);
|
||||||
|
if (i < 0) {
|
||||||
|
free(p);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
data = erealloc(data, len + i);
|
data = erealloc(data, len + i);
|
||||||
memcpy(((char *)data) + len, p, i);
|
memcpy(((char *)data) + len, p, i);
|
||||||
@@ -459,6 +464,7 @@ parse_pem_file(hx509_context context,
|
|||||||
"Found no matching PEM format for %s",
|
"Found no matching PEM format for %s",
|
||||||
type);
|
type);
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
free(data);
|
free(data);
|
||||||
data = NULL;
|
data = NULL;
|
||||||
len = 0;
|
len = 0;
|
||||||
@@ -498,9 +504,10 @@ file_init(hx509_context context,
|
|||||||
hx509_certs certs, void **data, int flags,
|
hx509_certs certs, void **data, int flags,
|
||||||
const char *residue, hx509_lock lock)
|
const char *residue, hx509_lock lock)
|
||||||
{
|
{
|
||||||
char *files = NULL, *p, *pnext;
|
char *p, *pnext;
|
||||||
struct ks_file *f = NULL;
|
struct ks_file *f = NULL;
|
||||||
struct hx509_collector *c;
|
struct hx509_collector *c = NULL;
|
||||||
|
hx509_private_key *keys = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
*data = NULL;
|
*data = NULL;
|
||||||
@@ -508,25 +515,41 @@ file_init(hx509_context context,
|
|||||||
if (lock == NULL)
|
if (lock == NULL)
|
||||||
lock = _hx509_empty_lock;
|
lock = _hx509_empty_lock;
|
||||||
|
|
||||||
c = _hx509_collector_alloc(context, lock);
|
|
||||||
if (c == NULL)
|
|
||||||
return ENOMEM;
|
|
||||||
|
|
||||||
f = calloc(1, sizeof(*f));
|
f = calloc(1, sizeof(*f));
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
hx509_clear_error_string(context);
|
hx509_clear_error_string(context);
|
||||||
ret = ENOMEM;
|
return ENOMEM;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
files = strdup(residue);
|
f->fn = strdup(residue);
|
||||||
if (files == NULL) {
|
if (f->fn == NULL) {
|
||||||
hx509_clear_error_string(context);
|
hx509_clear_error_string(context);
|
||||||
ret = ENOMEM;
|
ret = ENOMEM;
|
||||||
goto out;
|
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;
|
int found_data;
|
||||||
|
|
||||||
pnext = strchr(p, ',');
|
pnext = strchr(p, ',');
|
||||||
@@ -559,15 +582,29 @@ 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:
|
out:
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
*data = f;
|
*data = f;
|
||||||
else
|
else {
|
||||||
|
if (f->fn)
|
||||||
|
free(f->fn);
|
||||||
free(f);
|
free(f);
|
||||||
free(files);
|
}
|
||||||
|
if (c)
|
||||||
_hx509_collector_free(c);
|
_hx509_collector_free(c);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,11 +613,117 @@ file_free(hx509_certs certs, void *data)
|
|||||||
{
|
{
|
||||||
struct ks_file *f = data;
|
struct ks_file *f = data;
|
||||||
hx509_certs_free(&f->certs);
|
hx509_certs_free(&f->certs);
|
||||||
|
free(f->fn);
|
||||||
free(f);
|
free(f);
|
||||||
return 0;
|
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
|
static int
|
||||||
file_iter_start(hx509_context context,
|
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);
|
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 = {
|
static struct hx509_keyset_ops keyset_file = {
|
||||||
"FILE",
|
"FILE",
|
||||||
0,
|
0,
|
||||||
file_init,
|
file_init,
|
||||||
|
file_store,
|
||||||
file_free,
|
file_free,
|
||||||
NULL,
|
file_add,
|
||||||
NULL,
|
NULL,
|
||||||
file_iter_start,
|
file_iter_start,
|
||||||
file_iter,
|
file_iter,
|
||||||
file_iter_end
|
file_iter_end,
|
||||||
|
NULL,
|
||||||
|
file_getkeys,
|
||||||
|
file_addkey
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -42,8 +42,11 @@ RCSID("Id$");
|
|||||||
|
|
||||||
struct mem_data {
|
struct mem_data {
|
||||||
char *name;
|
char *name;
|
||||||
unsigned long len;
|
struct {
|
||||||
hx509_cert *val;
|
unsigned long len;
|
||||||
|
hx509_cert *val;
|
||||||
|
} certs;
|
||||||
|
hx509_private_key *keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -72,9 +75,11 @@ mem_free(hx509_certs certs, void *data)
|
|||||||
struct mem_data *mem = data;
|
struct mem_data *mem = data;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
|
||||||
for (i = 0; i < mem->len; i++)
|
for (i = 0; i < mem->certs.len; i++)
|
||||||
hx509_cert_free(mem->val[i]);
|
hx509_cert_free(mem->certs.val[i]);
|
||||||
free(mem->val);
|
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->name);
|
||||||
free(mem);
|
free(mem);
|
||||||
|
|
||||||
@@ -87,13 +92,14 @@ mem_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
|
|||||||
struct mem_data *mem = data;
|
struct mem_data *mem = data;
|
||||||
hx509_cert *val;
|
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)
|
if (val == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
mem->val = val;
|
mem->certs.val = val;
|
||||||
mem->val[mem->len] = hx509_cert_ref(c);
|
mem->certs.val[mem->certs.len] = hx509_cert_ref(c);
|
||||||
mem->len++;
|
mem->certs.len++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -125,12 +131,12 @@ mem_iter(hx509_context contexst,
|
|||||||
unsigned long *iter = cursor;
|
unsigned long *iter = cursor;
|
||||||
struct mem_data *mem = data;
|
struct mem_data *mem = data;
|
||||||
|
|
||||||
if (*iter >= mem->len) {
|
if (*iter >= mem->certs.len) {
|
||||||
*cert = NULL;
|
*cert = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cert = hx509_cert_ref(mem->val[*iter]);
|
*cert = hx509_cert_ref(mem->certs.val[*iter]);
|
||||||
(*iter)++;
|
(*iter)++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -145,16 +151,69 @@ mem_iter_end(hx509_context context,
|
|||||||
return 0;
|
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 = {
|
static struct hx509_keyset_ops keyset_mem = {
|
||||||
"MEMORY",
|
"MEMORY",
|
||||||
0,
|
0,
|
||||||
mem_init,
|
mem_init,
|
||||||
|
NULL,
|
||||||
mem_free,
|
mem_free,
|
||||||
mem_add,
|
mem_add,
|
||||||
NULL,
|
NULL,
|
||||||
mem_iter_start,
|
mem_iter_start,
|
||||||
mem_iter,
|
mem_iter,
|
||||||
mem_iter_end
|
mem_iter_end,
|
||||||
|
NULL,
|
||||||
|
mem_getkeys,
|
||||||
|
mem_addkey
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -82,6 +82,7 @@ struct hx509_keyset_ops keyset_null = {
|
|||||||
"NULL",
|
"NULL",
|
||||||
0,
|
0,
|
||||||
null_init,
|
null_init,
|
||||||
|
NULL,
|
||||||
null_free,
|
null_free,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@@ -616,7 +616,7 @@ collect_private_key(hx509_context context,
|
|||||||
localKeyId.data = query[0].pValue;
|
localKeyId.data = query[0].pValue;
|
||||||
localKeyId.length = query[0].ulValueLen;
|
localKeyId.length = query[0].ulValueLen;
|
||||||
|
|
||||||
ret = _hx509_new_private_key(&key);
|
ret = _hx509_private_key_init(&key, NULL, NULL);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -661,7 +661,7 @@ collect_private_key(hx509_context context,
|
|||||||
&localKeyId);
|
&localKeyId);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
_hx509_free_private_key(&key);
|
_hx509_private_key_free(&key);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -790,7 +790,7 @@ p11_list_keys(hx509_context context,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = _hx509_collector_collect(context, collector, &slot->certs);
|
ret = _hx509_collector_collect_certs(context, collector, &slot->certs);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
_hx509_collector_free(collector);
|
_hx509_collector_free(collector);
|
||||||
@@ -1164,6 +1164,7 @@ static struct hx509_keyset_ops keyset_pkcs11 = {
|
|||||||
"PKCS11",
|
"PKCS11",
|
||||||
0,
|
0,
|
||||||
p11_init,
|
p11_init,
|
||||||
|
NULL,
|
||||||
p11_free,
|
p11_free,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@@ -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).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -36,6 +36,7 @@ RCSID("$Id$");
|
|||||||
|
|
||||||
struct ks_pkcs12 {
|
struct ks_pkcs12 {
|
||||||
hx509_certs certs;
|
hx509_certs certs;
|
||||||
|
char *fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int (*collector_func)(hx509_context,
|
typedef int (*collector_func)(hx509_context,
|
||||||
@@ -65,24 +66,47 @@ find_attribute(const PKCS12_Attributes *attrs, const heim_oid *oid)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
keyBag_parser(hx509_context context,
|
||||||
|
struct hx509_collector *c,
|
||||||
|
const void *data, size_t length,
|
||||||
|
const PKCS12_Attributes *attrs)
|
||||||
|
{
|
||||||
|
const PKCS12_Attribute *attr;
|
||||||
|
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
|
static int
|
||||||
ShroudedKeyBag_parser(hx509_context context,
|
ShroudedKeyBag_parser(hx509_context context,
|
||||||
struct hx509_collector *c,
|
struct hx509_collector *c,
|
||||||
const void *data, size_t length,
|
const void *data, size_t length,
|
||||||
const PKCS12_Attributes *attrs)
|
const PKCS12_Attributes *attrs)
|
||||||
{
|
{
|
||||||
const PKCS12_Attribute *attr;
|
|
||||||
PKCS8EncryptedPrivateKeyInfo pk;
|
PKCS8EncryptedPrivateKeyInfo pk;
|
||||||
PKCS8PrivateKeyInfo ki;
|
|
||||||
heim_octet_string content;
|
heim_octet_string content;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&pk, 0, sizeof(pk));
|
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);
|
ret = decode_PKCS8EncryptedPrivateKeyInfo(data, length, &pk, NULL);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -96,22 +120,9 @@ ShroudedKeyBag_parser(hx509_context context,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = decode_PKCS8PrivateKeyInfo(content.data, content.length,
|
ret = keyBag_parser(context, c, content.data, content.length, attrs);
|
||||||
&ki, NULL);
|
|
||||||
der_free_octet_string(&content);
|
der_free_octet_string(&content);
|
||||||
if (ret)
|
return ret;
|
||||||
return ret;
|
|
||||||
|
|
||||||
_hx509_collector_private_key_add(context,
|
|
||||||
c,
|
|
||||||
&ki.privateKeyAlgorithm,
|
|
||||||
NULL,
|
|
||||||
&ki.privateKey,
|
|
||||||
&attr->attrValues);
|
|
||||||
|
|
||||||
free_PKCS8PrivateKeyInfo(&ki);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -130,6 +141,11 @@ certBag_parser(hx509_context context,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return 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,
|
ret = decode_PKCS12_OctetString(cb.certValue.data,
|
||||||
cb.certValue.length,
|
cb.certValue.length,
|
||||||
&os,
|
&os,
|
||||||
@@ -285,6 +301,7 @@ envelopedData_parser(hx509_context context,
|
|||||||
|
|
||||||
|
|
||||||
struct type bagtypes[] = {
|
struct type bagtypes[] = {
|
||||||
|
{ oid_id_pkcs12_keyBag, keyBag_parser },
|
||||||
{ oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser },
|
{ oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser },
|
||||||
{ oid_id_pkcs12_certBag, certBag_parser },
|
{ oid_id_pkcs12_certBag, certBag_parser },
|
||||||
{ oid_id_pkcs7_data, safeContent_parser },
|
{ oid_id_pkcs7_data, safeContent_parser },
|
||||||
@@ -334,6 +351,21 @@ p12_init(hx509_context context,
|
|||||||
goto out;
|
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);
|
ret = _hx509_map_file(residue, &buf, &len, NULL);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -392,7 +424,7 @@ p12_init(hx509_context context,
|
|||||||
|
|
||||||
free_PKCS12_AuthenticatedSafe(&as);
|
free_PKCS12_AuthenticatedSafe(&as);
|
||||||
|
|
||||||
ret = _hx509_collector_collect(context, c, &p12->certs);
|
ret = _hx509_collector_collect_certs(context, c, &p12->certs);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
*data = p12;
|
*data = p12;
|
||||||
|
|
||||||
@@ -408,15 +440,212 @@ out:
|
|||||||
return ret;
|
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
|
static int
|
||||||
p12_free(hx509_certs certs, void *data)
|
p12_free(hx509_certs certs, void *data)
|
||||||
{
|
{
|
||||||
struct ks_pkcs12 *p12 = data;
|
struct ks_pkcs12 *p12 = data;
|
||||||
hx509_certs_free(&p12->certs);
|
hx509_certs_free(&p12->certs);
|
||||||
|
free(p12->fn);
|
||||||
free(p12);
|
free(p12);
|
||||||
return 0;
|
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
|
static int
|
||||||
p12_iter_start(hx509_context context,
|
p12_iter_start(hx509_context context,
|
||||||
hx509_certs certs,
|
hx509_certs certs,
|
||||||
@@ -452,8 +681,9 @@ static struct hx509_keyset_ops keyset_pkcs12 = {
|
|||||||
"PKCS12",
|
"PKCS12",
|
||||||
0,
|
0,
|
||||||
p12_init,
|
p12_init,
|
||||||
|
p12_store,
|
||||||
p12_free,
|
p12_free,
|
||||||
NULL,
|
p12_add,
|
||||||
NULL,
|
NULL,
|
||||||
p12_iter_start,
|
p12_iter_start,
|
||||||
p12_iter,
|
p12_iter,
|
||||||
|
@@ -44,7 +44,7 @@ fi
|
|||||||
echo "create certificate request"
|
echo "create certificate request"
|
||||||
${hxtool} request-create \
|
${hxtool} request-create \
|
||||||
--subject="CN=Love,DC=it,DC=su,DC=se" \
|
--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
|
pkcs10-request.der || exit 1
|
||||||
|
|
||||||
echo "issue certificate"
|
echo "issue certificate"
|
||||||
@@ -52,7 +52,7 @@ ${hxtool} issue-certificate \
|
|||||||
--ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \
|
--ca-certificate=FILE:$srcdir/data/ca.crt,$srcdir/data/ca.key \
|
||||||
--subject="cn=foo" \
|
--subject="cn=foo" \
|
||||||
--req="pkcs10-request.der" \
|
--req="pkcs10-request.der" \
|
||||||
--certificate="cert-ee.der" || exit 1
|
--certificate="FILE:cert-ee.der" || exit 1
|
||||||
|
|
||||||
echo "verify certificate"
|
echo "verify certificate"
|
||||||
${hxtool} verify --missing-revoke \
|
${hxtool} verify --missing-revoke \
|
||||||
@@ -65,7 +65,7 @@ ${hxtool} issue-certificate \
|
|||||||
--subject="cn=foo" \
|
--subject="cn=foo" \
|
||||||
--lifetime="10years 1 month" \
|
--lifetime="10years 1 month" \
|
||||||
--req="pkcs10-request.der" \
|
--req="pkcs10-request.der" \
|
||||||
--certificate="cert-ee.der" || exit 1
|
--certificate="FILE:cert-ee.der" || exit 1
|
||||||
|
|
||||||
echo "issue certificate (with https ekus)"
|
echo "issue certificate (with https ekus)"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
@@ -74,7 +74,7 @@ ${hxtool} issue-certificate \
|
|||||||
--type="https-server" \
|
--type="https-server" \
|
||||||
--type="https-client" \
|
--type="https-client" \
|
||||||
--req="pkcs10-request.der" \
|
--req="pkcs10-request.der" \
|
||||||
--certificate="cert-ee.der" || exit 1
|
--certificate="FILE:cert-ee.der" || exit 1
|
||||||
|
|
||||||
echo "issue certificate (pkinit KDC)"
|
echo "issue certificate (pkinit KDC)"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
@@ -83,7 +83,7 @@ ${hxtool} issue-certificate \
|
|||||||
--type="pkinit-kdc" \
|
--type="pkinit-kdc" \
|
||||||
--pk-init-principal="krbtgt/TEST.H5L.SE@TEST.H5L.SE" \
|
--pk-init-principal="krbtgt/TEST.H5L.SE@TEST.H5L.SE" \
|
||||||
--req="pkcs10-request.der" \
|
--req="pkcs10-request.der" \
|
||||||
--certificate="cert-ee.der" || exit 1
|
--certificate="FILE:cert-ee.der" || exit 1
|
||||||
|
|
||||||
echo "issue certificate (pkinit client)"
|
echo "issue certificate (pkinit client)"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
@@ -92,7 +92,7 @@ ${hxtool} issue-certificate \
|
|||||||
--type="pkinit-client" \
|
--type="pkinit-client" \
|
||||||
--pk-init-principal="lha@TEST.H5L.SE" \
|
--pk-init-principal="lha@TEST.H5L.SE" \
|
||||||
--req="pkcs10-request.der" \
|
--req="pkcs10-request.der" \
|
||||||
--certificate="cert-ee.der" || exit 1
|
--certificate="FILE:cert-ee.der" || exit 1
|
||||||
|
|
||||||
echo "issue certificate (hostnames)"
|
echo "issue certificate (hostnames)"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
@@ -102,7 +102,7 @@ ${hxtool} issue-certificate \
|
|||||||
--hostname="www.test.h5l.se" \
|
--hostname="www.test.h5l.se" \
|
||||||
--hostname="ftp.test.h5l.se" \
|
--hostname="ftp.test.h5l.se" \
|
||||||
--req="pkcs10-request.der" \
|
--req="pkcs10-request.der" \
|
||||||
--certificate="cert-ee.der" || exit 1
|
--certificate="FILE:cert-ee.der" || exit 1
|
||||||
|
|
||||||
echo "issue certificate (email)"
|
echo "issue certificate (email)"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
@@ -111,14 +111,14 @@ ${hxtool} issue-certificate \
|
|||||||
--email="lha@test.h5l.se" \
|
--email="lha@test.h5l.se" \
|
||||||
--email="test@test.h5l.se" \
|
--email="test@test.h5l.se" \
|
||||||
--req="pkcs10-request.der" \
|
--req="pkcs10-request.der" \
|
||||||
--certificate="cert-ee.der" || exit 1
|
--certificate="FILE:cert-ee.der" || exit 1
|
||||||
|
|
||||||
echo "issue self-signed cert"
|
echo "issue self-signed cert"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
--self-signed \
|
--self-signed \
|
||||||
--ca-private-key=$srcdir/data/key.der \
|
--ca-private-key=FILE:$srcdir/data/key.der \
|
||||||
--subject="cn=test" \
|
--subject="cn=test" \
|
||||||
--certificate="cert-ee.der" || exit 1
|
--certificate="FILE:cert-ee.der" || exit 1
|
||||||
|
|
||||||
echo "issue ca cert"
|
echo "issue ca cert"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
@@ -126,22 +126,22 @@ ${hxtool} issue-certificate \
|
|||||||
--issue-ca \
|
--issue-ca \
|
||||||
--subject="cn=ca-cert" \
|
--subject="cn=ca-cert" \
|
||||||
--req="pkcs10-request.der" \
|
--req="pkcs10-request.der" \
|
||||||
--certificate="cert-ca.der" || exit 1
|
--certificate="FILE:cert-ca.der" || exit 1
|
||||||
|
|
||||||
echo "issue self-signed ca cert"
|
echo "issue self-signed ca cert"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
--self-signed \
|
--self-signed \
|
||||||
--issue-ca \
|
--issue-ca \
|
||||||
--ca-private-key=$srcdir/data/key.der \
|
--ca-private-key=FILE:$srcdir/data/key.der \
|
||||||
--subject="cn=ca-root" \
|
--subject="cn=ca-root" \
|
||||||
--certificate="cert-ca.der" || exit 1
|
--certificate="FILE:cert-ca.der" || exit 1
|
||||||
|
|
||||||
echo "issue proxy certificate"
|
echo "issue proxy certificate"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
--ca-certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \
|
--ca-certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \
|
||||||
--issue-proxy \
|
--issue-proxy \
|
||||||
--req="pkcs10-request.der" \
|
--req="pkcs10-request.der" \
|
||||||
--certificate="cert-proxy.der" || exit 1
|
--certificate="FILE:cert-proxy.der" || exit 1
|
||||||
|
|
||||||
echo "verify proxy cert"
|
echo "verify proxy cert"
|
||||||
${hxtool} verify --missing-revoke \
|
${hxtool} verify --missing-revoke \
|
||||||
@@ -156,17 +156,15 @@ ${hxtool} issue-certificate \
|
|||||||
--issue-ca \
|
--issue-ca \
|
||||||
--serial-number="deadbeaf" \
|
--serial-number="deadbeaf" \
|
||||||
--generate-key=rsa \
|
--generate-key=rsa \
|
||||||
--out-key="ca2-key.der" \
|
|
||||||
--subject="cn=ca2-cert" \
|
--subject="cn=ca2-cert" \
|
||||||
--certificate="cert-ca.der" || exit 1
|
--certificate="FILE:cert-ca.der" || exit 1
|
||||||
|
|
||||||
echo "issue ee cert (generate rsa key)"
|
echo "issue ee cert (generate rsa key)"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
--ca-certificate=FILE:cert-ca.der,ca2-key.der \
|
--ca-certificate=FILE:cert-ca.der \
|
||||||
--generate-key=rsa \
|
--generate-key=rsa \
|
||||||
--out-key="ee2-key.der" \
|
|
||||||
--subject="cn=cert-ee2" \
|
--subject="cn=cert-ee2" \
|
||||||
--certificate="cert-ee.der" || exit 1
|
--certificate="FILE:cert-ee.der" || exit 1
|
||||||
|
|
||||||
echo "verify certificate"
|
echo "verify certificate"
|
||||||
${hxtool} verify --missing-revoke \
|
${hxtool} verify --missing-revoke \
|
||||||
@@ -186,17 +184,15 @@ ${hxtool} cms-verify-sd \
|
|||||||
sd.data sd.data.out > /dev/null || exit 1
|
sd.data sd.data.out > /dev/null || exit 1
|
||||||
cmp "$srcdir/test_name.c" sd.data.out || 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"
|
echo "extend ca cert"
|
||||||
${hxtool} issue-certificate \
|
${hxtool} issue-certificate \
|
||||||
--self-signed \
|
--self-signed \
|
||||||
--issue-ca \
|
--issue-ca \
|
||||||
--lifetime="2years" \
|
--lifetime="2years" \
|
||||||
--serial-number="deadbeaf" \
|
--serial-number="deadbeaf" \
|
||||||
--ca-private-key=ca2-key.der \
|
--ca-private-key=FILE:cert-ca.der \
|
||||||
--subject="cn=ca2-cert" \
|
--subject="cn=ca2-cert" \
|
||||||
--certificate="cert-ca.der" || exit 1
|
--certificate="FILE:cert-ca.der" || exit 1
|
||||||
openssl x509 -in cert-ca.der -inform der -text > diff2
|
|
||||||
|
|
||||||
echo "verify certificate generated by previous ca"
|
echo "verify certificate generated by previous ca"
|
||||||
${hxtool} verify --missing-revoke \
|
${hxtool} verify --missing-revoke \
|
||||||
|
@@ -148,5 +148,20 @@ ${hxtool} crypto-available \
|
|||||||
cmp test ${srcdir}/tst-crypto-available3 > /dev/null || \
|
cmp test ${srcdir}/tst-crypto-available3 > /dev/null || \
|
||||||
{ echo "available3 failure"; exit 1; }
|
{ 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
|
exit 0
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005 Kungliga Tekniska H<>gskolan
|
# Copyright (c) 2005 - 2007 Kungliga Tekniska H<>gskolan
|
||||||
# (Royal Institute of Technology, Stockholm, Sweden).
|
# (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
@@ -60,6 +60,11 @@ ${hxtool} query \
|
|||||||
--friendlyname=friendlyname-test-not \
|
--friendlyname=friendlyname-test-not \
|
||||||
PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null && exit 1
|
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)"
|
echo "check for ca cert (friendlyname)"
|
||||||
${hxtool} query \
|
${hxtool} query \
|
||||||
--pass=PASS:foobar \
|
--pass=PASS:foobar \
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005 Kungliga Tekniska H<>gskolan
|
# Copyright (c) 2005 - 2007 Kungliga Tekniska H<>gskolan
|
||||||
# (Royal Institute of Technology, Stockholm, Sweden).
|
# (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
@@ -44,7 +44,7 @@ fi
|
|||||||
|
|
||||||
${hxtool} request-create \
|
${hxtool} request-create \
|
||||||
--subject="CN=Love,DC=it,DC=su,DC=se" \
|
--subject="CN=Love,DC=it,DC=su,DC=se" \
|
||||||
--key=$srcdir/data/key.der \
|
--key=FILE:$srcdir/data/key.der \
|
||||||
request.out || exit 1
|
request.out || exit 1
|
||||||
|
|
||||||
${hxtool} pkcs10-print \
|
${hxtool} pkcs10-print \
|
||||||
@@ -53,5 +53,5 @@ ${hxtool} pkcs10-print \
|
|||||||
${hxtool} request-create \
|
${hxtool} request-create \
|
||||||
--subject="CN=Love,DC=it,DC=su,DC=se" \
|
--subject="CN=Love,DC=it,DC=su,DC=se" \
|
||||||
--dnsname=nutcracker.it.su.se \
|
--dnsname=nutcracker.it.su.se \
|
||||||
--key=$srcdir/data/key.der \
|
--key=FILE:$srcdir/data/key.der \
|
||||||
request.out || exit 1
|
request.out || exit 1
|
||||||
|
Reference in New Issue
Block a user