hx509: support reading private keys from PEM files
This commit adds: - hx509_cert_init_private_key() for creating an hx509_cert object that has just a private key - hx509_cert_have_private_key_only() for checking whether an hx509_cert object has just a private key This also generalizes the get_key() internal function in hxtool, which is tasked with reding or generating a private key for use in signing CSRs. Now hxtool request-create can read/write private keys to/from PEM files, not just DER files. This is needed to support key types other than just RSA for CSRs and certificates.
This commit is contained in:
@@ -212,6 +212,29 @@ _hx509_cert_get_version(const Certificate *t)
|
|||||||
return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
|
return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hx509_cert
|
||||||
|
cert_init(hx509_context context, heim_error_t *error)
|
||||||
|
{
|
||||||
|
hx509_cert cert;
|
||||||
|
|
||||||
|
cert = malloc(sizeof(*cert));
|
||||||
|
if (cert == NULL) {
|
||||||
|
if (error)
|
||||||
|
*error = heim_error_create_enomem();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cert->ref = 1;
|
||||||
|
cert->friendlyname = NULL;
|
||||||
|
cert->attrs.len = 0;
|
||||||
|
cert->attrs.val = NULL;
|
||||||
|
cert->private_key = NULL;
|
||||||
|
cert->basename = NULL;
|
||||||
|
cert->release = NULL;
|
||||||
|
cert->ctx = NULL;
|
||||||
|
cert->data= NULL;
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate and init an hx509 certificate object from the decoded
|
* Allocate and init an hx509 certificate object from the decoded
|
||||||
* certificate `c´.
|
* certificate `c´.
|
||||||
@@ -231,20 +254,8 @@ hx509_cert_init(hx509_context context, const Certificate *c, heim_error_t *error
|
|||||||
hx509_cert cert;
|
hx509_cert cert;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cert = malloc(sizeof(*cert));
|
if ((cert = cert_init(context, error)) == NULL)
|
||||||
if (cert == NULL) {
|
return NULL;
|
||||||
if (error)
|
|
||||||
*error = heim_error_create_enomem();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
cert->ref = 1;
|
|
||||||
cert->friendlyname = NULL;
|
|
||||||
cert->attrs.len = 0;
|
|
||||||
cert->attrs.val = NULL;
|
|
||||||
cert->private_key = NULL;
|
|
||||||
cert->basename = NULL;
|
|
||||||
cert->release = NULL;
|
|
||||||
cert->ctx = NULL;
|
|
||||||
|
|
||||||
cert->data = calloc(1, sizeof(*(cert->data)));
|
cert->data = calloc(1, sizeof(*(cert->data)));
|
||||||
if (cert->data == NULL) {
|
if (cert->data == NULL) {
|
||||||
@@ -262,6 +273,31 @@ hx509_cert_init(hx509_context context, const Certificate *c, heim_error_t *error
|
|||||||
return cert;
|
return cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate and init an hx509 certificate object containing only a private key
|
||||||
|
* (but no Certificate).
|
||||||
|
*
|
||||||
|
* @param context A hx509 context.
|
||||||
|
* @param key
|
||||||
|
* @param error
|
||||||
|
*
|
||||||
|
* @return Returns an hx509 certificate
|
||||||
|
*
|
||||||
|
* @ingroup hx509_cert
|
||||||
|
*/
|
||||||
|
|
||||||
|
HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL
|
||||||
|
hx509_cert_init_private_key(hx509_context context,
|
||||||
|
hx509_private_key key,
|
||||||
|
heim_error_t *error)
|
||||||
|
{
|
||||||
|
hx509_cert cert;
|
||||||
|
|
||||||
|
if ((cert = cert_init(context, error)))
|
||||||
|
(void) _hx509_cert_assign_key(cert, key);
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just like hx509_cert_init(), but instead of a decode certificate
|
* Just like hx509_cert_init(), but instead of a decode certificate
|
||||||
* takes an pointer and length to a memory region that contains a
|
* takes an pointer and length to a memory region that contains a
|
||||||
@@ -360,7 +396,8 @@ hx509_cert_free(hx509_cert cert)
|
|||||||
if (cert->private_key)
|
if (cert->private_key)
|
||||||
hx509_private_key_free(&cert->private_key);
|
hx509_private_key_free(&cert->private_key);
|
||||||
|
|
||||||
free_Certificate(cert->data);
|
if (cert->data)
|
||||||
|
free_Certificate(cert->data);
|
||||||
free(cert->data);
|
free(cert->data);
|
||||||
|
|
||||||
for (i = 0; i < cert->attrs.len; i++) {
|
for (i = 0; i < cert->attrs.len; i++) {
|
||||||
@@ -1598,12 +1635,36 @@ _hx509_cert_private_key(hx509_cert p)
|
|||||||
return p->private_key;
|
return p->private_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate whether a hx509_cert has a private key.
|
||||||
|
*
|
||||||
|
* @param p a hx509 certificate
|
||||||
|
*
|
||||||
|
* @return 1 if p has a private key, 0 otherwise.
|
||||||
|
*
|
||||||
|
* @ingroup hx509_cert
|
||||||
|
*/
|
||||||
HX509_LIB_FUNCTION int HX509_LIB_CALL
|
HX509_LIB_FUNCTION int HX509_LIB_CALL
|
||||||
hx509_cert_have_private_key(hx509_cert p)
|
hx509_cert_have_private_key(hx509_cert p)
|
||||||
{
|
{
|
||||||
return p->private_key ? 1 : 0;
|
return p->private_key ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate whether a hx509_cert has a private key only (no certificate).
|
||||||
|
*
|
||||||
|
* @param p a hx509 certificate
|
||||||
|
*
|
||||||
|
* @return 1 if p has a private key only (no certificate), 0 otherwise.
|
||||||
|
*
|
||||||
|
* @ingroup hx509_cert
|
||||||
|
*/
|
||||||
|
HX509_LIB_FUNCTION int HX509_LIB_CALL
|
||||||
|
hx509_cert_have_private_key_only(hx509_cert p)
|
||||||
|
{
|
||||||
|
return p->private_key && !p->data ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
HX509_LIB_FUNCTION int HX509_LIB_CALL
|
HX509_LIB_FUNCTION int HX509_LIB_CALL
|
||||||
_hx509_cert_private_key_exportable(hx509_cert p)
|
_hx509_cert_private_key_exportable(hx509_cert p)
|
||||||
|
@@ -535,19 +535,28 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
|
|||||||
heim_octet_string data;
|
heim_octet_string data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = hx509_cert_binary(context, c, &data);
|
if (hx509_cert_have_private_key_only(c)) {
|
||||||
if (ret)
|
data.length = 0;
|
||||||
return ret;
|
data.data = NULL;
|
||||||
|
} else {
|
||||||
|
ret = hx509_cert_binary(context, c, &data);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
switch (sc->format) {
|
switch (sc->format) {
|
||||||
case USE_DER:
|
case USE_DER:
|
||||||
fwrite(data.data, data.length, 1, sc->f);
|
if (data.data) {
|
||||||
free(data.data);
|
fwrite(data.data, data.length, 1, sc->f);
|
||||||
|
free(data.data);
|
||||||
|
} /* XXX else write private key instead */
|
||||||
break;
|
break;
|
||||||
case USE_PEM:
|
case USE_PEM:
|
||||||
hx509_pem_write(context, "CERTIFICATE", NULL, sc->f,
|
if (data.data) {
|
||||||
data.data, data.length);
|
hx509_pem_write(context, "CERTIFICATE", NULL, sc->f,
|
||||||
free(data.data);
|
data.data, data.length);
|
||||||
|
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,
|
ret = _hx509_private_key_export(context, key,
|
||||||
|
@@ -80,8 +80,11 @@ EXPORTS
|
|||||||
hx509_cert_get_notBefore
|
hx509_cert_get_notBefore
|
||||||
hx509_cert_get_serialnumber
|
hx509_cert_get_serialnumber
|
||||||
hx509_cert_get_subject
|
hx509_cert_get_subject
|
||||||
|
hx509_cert_have_private_key
|
||||||
|
hx509_cert_have_private_key_only
|
||||||
hx509_cert_init
|
hx509_cert_init
|
||||||
hx509_cert_init_data
|
hx509_cert_init_data
|
||||||
|
hx509_cert_init_private_key
|
||||||
hx509_cert_keyusage_print
|
hx509_cert_keyusage_print
|
||||||
hx509_cert_ref
|
hx509_cert_ref
|
||||||
hx509_cert_set_friendly_name
|
hx509_cert_set_friendly_name
|
||||||
|
@@ -74,8 +74,11 @@ HEIMDAL_X509_1.2 {
|
|||||||
hx509_cert_get_subject;
|
hx509_cert_get_subject;
|
||||||
hx509_cert_get_issuer_unique_id;
|
hx509_cert_get_issuer_unique_id;
|
||||||
hx509_cert_get_subject_unique_id;
|
hx509_cert_get_subject_unique_id;
|
||||||
|
hx509_cert_have_private_key;
|
||||||
|
hx509_cert_have_private_key_only;
|
||||||
hx509_cert_init;
|
hx509_cert_init;
|
||||||
hx509_cert_init_data;
|
hx509_cert_init_data;
|
||||||
|
hx509_cert_init_private_key;
|
||||||
hx509_cert_keyusage_print;
|
hx509_cert_keyusage_print;
|
||||||
hx509_cert_public_encrypt;
|
hx509_cert_public_encrypt;
|
||||||
hx509_cert_ref;
|
hx509_cert_ref;
|
||||||
|
Reference in New Issue
Block a user