add import/export type for private keys
This commit is contained in:
@@ -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;
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user