add import/export type for private keys

This commit is contained in:
Love Hornquist Astrand
2010-10-03 16:32:01 -07:00
parent dfc54c6eea
commit 48ad3e1e65
6 changed files with 77 additions and 35 deletions

View File

@@ -145,6 +145,7 @@ _hx509_collector_private_key_add(hx509_context context,
} else { } else {
ret = _hx509_parse_private_key(context, alg, ret = _hx509_parse_private_key(context, alg,
key_data->data, key_data->length, key_data->data, key_data->length,
HX509_KEY_FORMAT_DER,
&key->private_key); &key->private_key);
if (ret) if (ret)
goto out; goto out;

View File

@@ -53,9 +53,11 @@ struct hx509_private_key_ops {
SubjectPublicKeyInfo *); SubjectPublicKeyInfo *);
int (*export)(hx509_context context, int (*export)(hx509_context context,
const hx509_private_key, const hx509_private_key,
hx509_key_format_t,
heim_octet_string *); heim_octet_string *);
int (*import)(hx509_context, const AlgorithmIdentifier *, int (*import)(hx509_context, const AlgorithmIdentifier *,
const void *, size_t, hx509_private_key); const void *, size_t, hx509_key_format_t,
hx509_private_key);
int (*generate_private_key)(hx509_context, int (*generate_private_key)(hx509_context,
struct hx509_generate_private_context *, struct hx509_generate_private_context *,
hx509_private_key); hx509_private_key);
@@ -750,18 +752,27 @@ rsa_private_key_import(hx509_context context,
const AlgorithmIdentifier *keyai, const AlgorithmIdentifier *keyai,
const void *data, const void *data,
size_t len, size_t len,
hx509_key_format_t format,
hx509_private_key private_key) hx509_private_key private_key)
{ {
const unsigned char *p = data; switch (format) {
case HX509_KEY_FORMAT_DER: {
const unsigned char *p = data;
private_key->private_key.rsa =
d2i_RSAPrivateKey(NULL, &p, len);
if (private_key->private_key.rsa == NULL) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
"Failed to parse RSA key");
return HX509_PARSING_KEY_FAILED;
}
private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
break;
private_key->private_key.rsa =
d2i_RSAPrivateKey(NULL, &p, len);
if (private_key->private_key.rsa == NULL) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
"Failed to parse RSA key");
return HX509_PARSING_KEY_FAILED;
} }
private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION; default:
return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
}
return 0; return 0;
} }
@@ -844,6 +855,7 @@ rsa_generate_private_key(hx509_context context,
static int static int
rsa_private_key_export(hx509_context context, rsa_private_key_export(hx509_context context,
const hx509_private_key key, const hx509_private_key key,
hx509_key_format_t format,
heim_octet_string *data) heim_octet_string *data)
{ {
int ret; int ret;
@@ -851,25 +863,32 @@ rsa_private_key_export(hx509_context context,
data->data = NULL; data->data = NULL;
data->length = 0; data->length = 0;
ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL); switch (format) {
if (ret <= 0) { case HX509_KEY_FORMAT_DER:
ret = EINVAL;
hx509_set_error_string(context, 0, ret, 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"); "Private key is not exportable");
return ret; return ret;
} }
data->data = malloc(ret); data->data = malloc(ret);
if (data->data == NULL) { if (data->data == NULL) {
ret = ENOMEM; ret = ENOMEM;
hx509_set_error_string(context, 0, ret, "malloc out of memory"); hx509_set_error_string(context, 0, ret, "malloc out of memory");
return ret; return ret;
} }
data->length = ret; data->length = ret;
{ {
unsigned char *p = data->data; unsigned char *p = data->data;
i2d_RSAPrivateKey(key->private_key.rsa, &p); i2d_RSAPrivateKey(key->private_key.rsa, &p);
}
break;
default:
return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
} }
return 0; return 0;
@@ -915,9 +934,10 @@ ecdsa_private_key2SPKI(hx509_context context,
static int static int
ecdsa_private_key_export(hx509_context context, ecdsa_private_key_export(hx509_context context,
const hx509_private_key key, const hx509_private_key key,
hx509_key_format_t format,
heim_octet_string *data) heim_octet_string *data)
{ {
return ENOMEM; return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
} }
static int static int
@@ -925,6 +945,7 @@ ecdsa_private_key_import(hx509_context context,
const AlgorithmIdentifier *keyai, const AlgorithmIdentifier *keyai,
const void *data, const void *data,
size_t len, size_t len,
hx509_key_format_t format,
hx509_private_key private_key) hx509_private_key private_key)
{ {
const unsigned char *p = data; const unsigned char *p = data;
@@ -959,13 +980,21 @@ ecdsa_private_key_import(hx509_context context,
pkey = &key; pkey = &key;
} }
private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len); switch (format) {
if (private_key->private_key.ecdsa == NULL) { case HX509_KEY_FORMAT_DER:
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
"Failed to parse EC private key"); private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
return HX509_PARSING_KEY_FAILED; if (private_key->private_key.ecdsa == NULL) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
"Failed to parse EC private key");
return HX509_PARSING_KEY_FAILED;
}
private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
break;
default:
return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
} }
private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
return 0; return 0;
} }
@@ -1733,6 +1762,7 @@ _hx509_parse_private_key(hx509_context context,
const AlgorithmIdentifier *keyai, const AlgorithmIdentifier *keyai,
const void *data, const void *data,
size_t len, size_t len,
hx509_key_format_t format,
hx509_private_key *private_key) hx509_private_key *private_key)
{ {
struct hx509_private_key_ops *ops; struct hx509_private_key_ops *ops;
@@ -1752,7 +1782,7 @@ _hx509_parse_private_key(hx509_context context,
return ret; return ret;
} }
ret = (*ops->import)(context, keyai, data, len, *private_key); ret = (*ops->import)(context, keyai, data, len, format, *private_key);
if (ret) if (ret)
_hx509_private_key_free(private_key); _hx509_private_key_free(private_key);
@@ -2045,13 +2075,14 @@ _hx509_private_key_get_internal(hx509_context context,
int int
_hx509_private_key_export(hx509_context context, _hx509_private_key_export(hx509_context context,
const hx509_private_key key, const hx509_private_key key,
hx509_key_format_t format,
heim_octet_string *data) heim_octet_string *data)
{ {
if (key->ops->export == NULL) { if (key->ops->export == NULL) {
hx509_clear_error_string(context); hx509_clear_error_string(context);
return HX509_UNIMPLEMENTED_OPERATION; return HX509_UNIMPLEMENTED_OPERATION;
} }
return (*key->ops->export)(context, key, data); return (*key->ops->export)(context, key, format, data);
} }
/* /*

View File

@@ -76,6 +76,13 @@ enum {
HX509_CRYPTO_PADDING_NONE = 1 HX509_CRYPTO_PADDING_NONE = 1
}; };
enum {
HX509_KEY_FORMAT_GUESS = 0,
HX509_KEY_FORMAT_DER = 1,
HX509_KEY_FORMAT_WIN_BACKUPKEY = 2
};
typedef uint32_t hx509_key_format_t;
struct hx509_cert_attribute_data { struct hx509_cert_attribute_data {
heim_oid oid; heim_oid oid;
heim_octet_string data; heim_octet_string data;

View File

@@ -66,6 +66,7 @@ error_code RSA_PRIVATE_ENCRYPT, "RSA private encyption failed"
error_code RSA_PUBLIC_DECRYPT, "RSA public decryption failed" error_code RSA_PUBLIC_DECRYPT, "RSA public decryption failed"
error_code RSA_PRIVATE_DECRYPT, "RSA private decryption failed" error_code RSA_PRIVATE_DECRYPT, "RSA private decryption failed"
error_code ALGORITHM_BEST_BEFORE, "Algorithm has passed its best before date" error_code ALGORITHM_BEST_BEFORE, "Algorithm has passed its best before date"
error_code KEY_FORMAT_UNSUPPORTED, "Key format is unsupported"
# revoke related errors # revoke related errors
index 96 index 96

View File

@@ -541,7 +541,8 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
free(data.data); free(data.data);
if (_hx509_cert_private_key_exportable(c)) { if (_hx509_cert_private_key_exportable(c)) {
hx509_private_key key = _hx509_cert_private_key(c); hx509_private_key key = _hx509_cert_private_key(c);
ret = _hx509_private_key_export(context, key, &data); ret = _hx509_private_key_export(context, key,
HX509_KEY_FORMAT_DER, &data);
if (ret) if (ret)
break; break;
hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f, hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f,

View File

@@ -535,6 +535,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
} }
ret = _hx509_private_key_export(context, ret = _hx509_private_key_export(context,
_hx509_cert_private_key(c), _hx509_cert_private_key(c),
HX509_KEY_FORMAT_DER,
&pki.privateKey); &pki.privateKey);
if (ret) { if (ret) {
free_PKCS8PrivateKeyInfo(&pki); free_PKCS8PrivateKeyInfo(&pki);