diff --git a/lib/hx509/ca.c b/lib/hx509/ca.c index bcbd777ed..c1324bb37 100644 --- a/lib/hx509/ca.c +++ b/lib/hx509/ca.c @@ -43,9 +43,9 @@ struct hx509_ca_tbs { hx509_name subject; SubjectPublicKeyInfo spki; + KeyUsage ku; ExtKeyUsage eku; GeneralNames san; - unsigned key_usage; heim_integer serial; struct { unsigned int proxy:1; @@ -262,11 +262,9 @@ hx509_ca_tbs_set_template(hx509_context context, return ret; } if (flags & HX509_CA_TEMPLATE_KU) { - KeyUsage ku; - ret = _hx509_cert_get_keyusage(context, cert, &ku); + ret = _hx509_cert_get_keyusage(context, cert, &tbs->ku); if (ret) return ret; - tbs->key_usage = KeyUsage2int(ku); } if (flags & HX509_CA_TEMPLATE_EKU) { ExtKeyUsage eku; @@ -405,6 +403,28 @@ hx509_ca_tbs_set_serialnumber(hx509_context context, return ret; } +/** + * An an extended key usage to the to-be-signed certificate object. + * Duplicates will detected and not added. + * + * @param context A hx509 context. + * @param tbs object to be signed. + * @param oid extended key usage to add. + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_ca + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_ca_tbs_add_ku(hx509_context context, + hx509_ca_tbs tbs, + KeyUsage ku) +{ + tbs->ku = ku; + return 0; +} + /** * An an extended key usage to the to-be-signed certificate object. * Duplicates will detected and not added. @@ -1033,7 +1053,6 @@ ca_sign(hx509_context context, const AlgorithmIdentifier *sigalg; time_t notBefore; time_t notAfter; - unsigned key_usage; sigalg = tbs->sigalg; if (sigalg == NULL) @@ -1053,21 +1072,12 @@ ca_sign(hx509_context context, if (notAfter == 0) notAfter = time(NULL) + 3600 * 24 * 365; - key_usage = tbs->key_usage; - if (key_usage == 0) { - KeyUsage ku; - memset(&ku, 0, sizeof(ku)); - ku.digitalSignature = 1; - ku.keyEncipherment = 1; - key_usage = KeyUsage2int(ku); - } - if (tbs->flags.ca) { - KeyUsage ku; - memset(&ku, 0, sizeof(ku)); - ku.keyCertSign = 1; - ku.cRLSign = 1; - key_usage |= KeyUsage2int(ku); + tbs->ku.keyCertSign = 1; + tbs->ku.cRLSign = 1; + } else if (KeyUsage2int(tbs->ku) == 0) { + tbs->ku.digitalSignature = 1; + tbs->ku.keyEncipherment = 1; } /* @@ -1237,11 +1247,9 @@ ca_sign(hx509_context context, } /* add KeyUsage */ - { - KeyUsage ku; - - ku = int2KeyUsage(key_usage); - ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret); + if (KeyUsage2int(tbs->ku) > 0) { + ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, + &tbs->ku, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Out of memory"); goto out; @@ -1265,7 +1273,7 @@ ca_sign(hx509_context context, } if (size != data.length) _hx509_abort("internal ASN.1 encoder error"); - ret = add_extension(context, tbsc, 0, + ret = add_extension(context, tbsc, 1, &asn1_oid_id_x509_ce_extKeyUsage, &data); free(data.data); if (ret) diff --git a/lib/hx509/hxtool-commands.in b/lib/hx509/hxtool-commands.in index 49e392d03..b772f2b10 100644 --- a/lib/hx509/hxtool-commands.in +++ b/lib/hx509/hxtool-commands.in @@ -426,6 +426,12 @@ command = { type = "string" help = "Subject DN" } + option = { + long = "eku" + type = "strings" + argument = "oid-string" + help = "Add Extended Key Usage OID" + } option = { long = "email" type = "strings" @@ -650,6 +656,17 @@ command = { type = "integer" help = "Maximum path length (CA and proxy certificates), -1 no limit" } + option = { + long = "eku" + type = "strings" + argument = "oid-string" + help = "Add Extended Key Usage OID" + } + option = { + long = "ku" + type = "strings" + help = "Key Usage (digitalSignature, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign, encipherOnly, decipherOnly)" + } option = { long = "hostname" type = "strings" diff --git a/lib/hx509/hxtool.c b/lib/hx509/hxtool.c index 2bafd4907..06345e9a8 100644 --- a/lib/hx509/hxtool.c +++ b/lib/hx509/hxtool.c @@ -1365,6 +1365,15 @@ request_create(struct request_create_options *opt, int argc, char **argv) hx509_err(context, 1, ret, "hx509_request_add_dns_name"); } + for (i = 0; i < opt->eku_strings.num_strings; i++) { + heim_oid oid; + + parse_oid(opt->eku_strings.strings[i], NULL, &oid); + ret = _hx509_request_add_eku(context, req, &oid); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_eku"); + } + ret = hx509_private_key2SPKI(context, signer, &key); if (ret) @@ -1792,6 +1801,7 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) hx509_private_key cert_key = NULL; hx509_name subject = NULL; SubjectPublicKeyInfo spki; + size_t i; int delta = 0; memset(&spki, 0, sizeof(spki)); @@ -1803,10 +1813,8 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) if (opt->certificate_string == NULL) errx(1, "--certificate argument missing"); - if (opt->template_certificate_string) { - if (opt->template_fields_string == NULL) - errx(1, "--template-certificate not no --template-fields"); - } + if (opt->template_certificate_string && opt->template_fields_string == NULL) + errx(1, "--template-certificate used but no --template-fields given"); if (opt->lifetime_string) { delta = parse_time(opt->lifetime_string, "day"); @@ -1928,6 +1936,31 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) if (ret) hx509_err(context, 1, ret, "hx509_ca_tbs_init"); + for (i = 0; i < opt->eku_strings.num_strings; i++) { + heim_oid oid; + + parse_oid(opt->eku_strings.strings[i], NULL, &oid); + ret = hx509_ca_tbs_add_eku(context, tbs, &oid); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_eku"); + } + if (opt->ku_strings.num_strings) { + const struct units *kus = asn1_KeyUsage_units(); + const struct units *kup; + uint64_t n = 0; + + for (i = 0; i < opt->ku_strings.num_strings; i++) { + for (kup = kus; kup->name; kup++) { + if (strcmp(kup->name, opt->ku_strings.strings[i])) + continue; + n |= kup->mult; + break; + } + } + ret = hx509_ca_tbs_add_ku(context, tbs, int2KeyUsage(n)); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_ku"); + } if (opt->signature_algorithm_string) { const AlgorithmIdentifier *sigalg; if (strcasecmp(opt->signature_algorithm_string, "rsa-with-sha1") == 0) diff --git a/lib/hx509/libhx509-exports.def b/lib/hx509/libhx509-exports.def index acdcdaeac..328936d67 100644 --- a/lib/hx509/libhx509-exports.def +++ b/lib/hx509/libhx509-exports.def @@ -18,6 +18,7 @@ EXPORTS hx509_private_key_free _hx509_private_key_ref _hx509_request_add_dns_name + _hx509_request_add_eku _hx509_request_add_email _hx509_private_key_export _hx509_private_key_exportable @@ -42,6 +43,7 @@ EXPORTS hx509_ca_sign_self hx509_ca_tbs_add_crl_dp_uri hx509_ca_tbs_add_eku + hx509_ca_tbs_add_ku hx509_ca_tbs_add_san_hostname hx509_ca_tbs_add_san_jid hx509_ca_tbs_add_san_ms_upn diff --git a/lib/hx509/version-script.map b/lib/hx509/version-script.map index 995281d56..621a22d60 100644 --- a/lib/hx509/version-script.map +++ b/lib/hx509/version-script.map @@ -22,6 +22,7 @@ HEIMDAL_X509_1.2 { _hx509_private_key_oid; _hx509_private_key_ref; _hx509_request_add_dns_name; + _hx509_request_add_eku; _hx509_request_add_email; _hx509_request_parse; _hx509_request_print; @@ -34,6 +35,7 @@ HEIMDAL_X509_1.2 { hx509_ca_sign_self; hx509_ca_tbs_add_crl_dp_uri; hx509_ca_tbs_add_eku; + hx509_ca_tbs_add_ku; hx509_ca_tbs_add_san_hostname; hx509_ca_tbs_add_san_jid; hx509_ca_tbs_add_san_ms_upn;