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,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).

View File

@@ -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 \

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). * (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,

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). * (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)
{ {

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). * (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 ||

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). * (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

View File

@@ -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 {

View File

@@ -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"

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). * (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;

View File

@@ -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);
}

View File

@@ -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,

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). * (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

View File

@@ -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

View File

@@ -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,

View File

@@ -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,

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). * (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,

View File

@@ -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 \

View File

@@ -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

View File

@@ -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 \

View File

@@ -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