diff options
Diffstat (limited to 'lib/hx509/hxtool.c')
| -rw-r--r-- | lib/hx509/hxtool.c | 889 |
1 files changed, 572 insertions, 317 deletions
diff --git a/lib/hx509/hxtool.c b/lib/hx509/hxtool.c index 55410b1da75d..4bd467f4284a 100644 --- a/lib/hx509/hxtool.c +++ b/lib/hx509/hxtool.c @@ -1,41 +1,41 @@ /* - * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include "hx_locl.h" -RCSID("$Id: hxtool.c 22333 2007-12-17 01:03:43Z lha $"); #include <hxtool-commands.h> #include <sl.h> +#include <rtbl.h> #include <parse_time.h> static hx509_context context; @@ -45,9 +45,9 @@ static int version_flag; static int help_flag; struct getargs args[] = { - { "statistic-file", 0, arg_string, &stat_file_string }, - { "version", 0, arg_flag, &version_flag }, - { "help", 0, arg_flag, &help_flag } + { "statistic-file", 0, arg_string, &stat_file_string, NULL, NULL }, + { "version", 0, arg_flag, &version_flag, NULL, NULL }, + { "help", 0, arg_flag, &help_flag, NULL, NULL } }; int num_args = sizeof(args) / sizeof(args[0]); @@ -70,7 +70,7 @@ lock_strings(hx509_lock lock, getarg_strings *pass) for (i = 0; i < pass->num_strings; i++) { int ret = hx509_lock_command_string(lock, pass->strings[i]); if (ret) - errx(1, "hx509_lock_command_string: %s: %d", + errx(1, "hx509_lock_command_string: %s: %d", pass->strings[i], ret); } } @@ -80,15 +80,15 @@ lock_strings(hx509_lock lock, getarg_strings *pass) */ static void -certs_strings(hx509_context context, const char *type, hx509_certs certs, +certs_strings(hx509_context contextp, const char *type, hx509_certs certs, hx509_lock lock, const getarg_strings *s) { int i, ret; for (i = 0; i < s->num_strings; i++) { - ret = hx509_certs_append(context, certs, lock, s->strings[i]); + ret = hx509_certs_append(contextp, certs, lock, s->strings[i]); if (ret) - hx509_err(context, 1, ret, + hx509_err(contextp, 1, ret, "hx509_certs_append: %s %s", type, s->strings[i]); } } @@ -114,27 +114,27 @@ parse_oid(const char *str, const heim_oid *def, heim_oid *oid) */ static void -peer_strings(hx509_context context, - hx509_peer_info *peer, +peer_strings(hx509_context contextp, + hx509_peer_info *peer, const getarg_strings *s) { AlgorithmIdentifier *val; int ret, i; - - ret = hx509_peer_info_alloc(context, peer); + + ret = hx509_peer_info_alloc(contextp, peer); if (ret) - hx509_err(context, 1, ret, "hx509_peer_info_alloc"); - + hx509_err(contextp, 1, ret, "hx509_peer_info_alloc"); + val = calloc(s->num_strings, sizeof(*val)); if (val == NULL) err(1, "malloc"); for (i = 0; i < s->num_strings; i++) parse_oid(s->strings[i], NULL, &val[i].algorithm); - - ret = hx509_peer_info_set_cms_algs(context, *peer, val, s->num_strings); + + ret = hx509_peer_info_set_cms_algs(contextp, *peer, val, s->num_strings); if (ret) - hx509_err(context, 1, ret, "hx509_peer_info_set_cms_algs"); + hx509_err(contextp, 1, ret, "hx509_peer_info_set_cms_algs"); for (i = 0; i < s->num_strings; i++) free_AlgorithmIdentifier(&val[i]); @@ -145,6 +145,36 @@ peer_strings(hx509_context context, * */ +struct pem_data { + heim_octet_string *os; + int detached_data; +}; + +static int +pem_reader(hx509_context contextp, const char *type, + const hx509_pem_header *headers, + const void *data , size_t length, void *ctx) +{ + struct pem_data *p = (struct pem_data *)ctx; + const char *h; + + p->os->data = malloc(length); + if (p->os->data == NULL) + return ENOMEM; + memcpy(p->os->data, data, length); + p->os->length = length; + + h = hx509_pem_find_header(headers, "Content-disposition"); + if (h && strcasecmp(h, "detached") == 0) + p->detached_data = 1; + + return 0; +} + +/* + * + */ + int cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv) { @@ -155,10 +185,10 @@ cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv) hx509_certs signers = NULL; hx509_certs anchors = NULL; hx509_lock lock; - int ret; + int ret, flags = 0; size_t sz; - void *p; + void *p = NULL; if (opt->missing_revoke_flag) hx509_context_set_missing_revoke(context, 1); @@ -166,27 +196,66 @@ cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv) hx509_lock_init(context, &lock); lock_strings(lock, &opt->pass_strings); - ret = _hx509_map_file(argv[0], &p, &sz, NULL); - if (ret) - err(1, "map_file: %s: %d", argv[0], ret); - - if (opt->signed_content_string) { - ret = _hx509_map_file_os(opt->signed_content_string, &signeddata, NULL); - if (ret) - err(1, "map_file: %s: %d", opt->signed_content_string, ret); - sd = &signeddata; - } - ret = hx509_verify_init_ctx(context, &ctx); + if (ret) + hx509_err(context, 1, ret, "hx509_verify_init_ctx"); ret = hx509_certs_init(context, "MEMORY:cms-anchors", 0, NULL, &anchors); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); certs_strings(context, "store", store, lock, &opt->certificate_strings); - co.data = p; - co.length = sz; + if (opt->pem_flag) { + struct pem_data pd; + FILE *f; + + pd.os = &co; + pd.detached_data = 0; + + f = fopen(argv[0], "r"); + if (f == NULL) + err(1, "Failed to open file %s", argv[0]); + + ret = hx509_pem_read(context, f, pem_reader, &pd); + fclose(f); + if (ret) + errx(1, "PEM reader failed: %d", ret); + + if (pd.detached_data && opt->signed_content_string == NULL) { + char *r = strrchr(argv[0], '.'); + if (r && strcasecmp(r, ".pem") == 0) { + char *s = strdup(argv[0]); + if (s == NULL) + errx(1, "malloc: out of memory"); + s[r - argv[0]] = '\0'; + ret = _hx509_map_file_os(s, &signeddata); + if (ret) + errx(1, "map_file: %s: %d", s, ret); + free(s); + sd = &signeddata; + } + } + + } else { + ret = rk_undumpdata(argv[0], &p, &sz); + if (ret) + err(1, "map_file: %s: %d", argv[0], ret); + + co.data = p; + co.length = sz; + } + + if (opt->signed_content_string) { + ret = _hx509_map_file_os(opt->signed_content_string, &signeddata); + if (ret) + errx(1, "map_file: %s: %d", opt->signed_content_string, ret); + sd = &signeddata; + } if (opt->content_info_flag) { heim_octet_string uwco; @@ -196,19 +265,32 @@ cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv) if (ret) errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret); - if (der_heim_oid_cmp(&oid, oid_id_pkcs7_signedData()) != 0) + if (der_heim_oid_cmp(&oid, &asn1_oid_id_pkcs7_signedData) != 0) errx(1, "Content is not SignedData"); der_free_oid(&oid); + if (p == NULL) + der_free_octet_string(&co); + else { + rk_xfree(p); + p = NULL; + } co = uwco; } hx509_verify_attach_anchors(ctx, anchors); - ret = hx509_cms_verify_signed(context, ctx, co.data, co.length, sd, + if (!opt->signer_allowed_flag) + flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER; + if (opt->allow_wrong_oid_flag) + flags |= HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; + + ret = hx509_cms_verify_signed(context, ctx, flags, co.data, co.length, sd, store, &type, &c, &signers); - if (co.data != p) + if (p != co.data) der_free_octet_string(&co); + else + rk_xfree(p); if (ret) hx509_err(context, 1, ret, "hx509_cms_verify_signed"); @@ -219,8 +301,12 @@ cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv) free(str); der_free_oid(&type); } - printf("signers:\n"); - hx509_certs_iter(context, signers, hx509_ci_print_names, stdout); + if (signers == NULL) { + printf("unsigned\n"); + } else { + printf("signers:\n"); + hx509_certs_iter_f(context, signers, hx509_ci_print_names, stdout); + } hx509_verify_destroy_ctx(ctx); @@ -230,18 +316,43 @@ cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv) hx509_lock_free(lock); - ret = _hx509_write_file(argv[1], c.data, c.length); - if (ret) - errx(1, "hx509_write_file: %d", ret); + if (argc > 1) { + ret = _hx509_write_file(argv[1], c.data, c.length); + if (ret) + errx(1, "hx509_write_file: %d", ret); + } der_free_octet_string(&c); - _hx509_unmap_file(p, sz); + if (sd) _hx509_unmap_file_os(sd); return 0; } +static int +print_signer(hx509_context contextp, void *ctx, hx509_cert cert) +{ + hx509_pem_header **header = ctx; + char *signer_name = NULL; + hx509_name name; + int ret; + + ret = hx509_cert_get_subject(cert, &name); + if (ret) + errx(1, "hx509_cert_get_subject"); + + ret = hx509_name_to_string(name, &signer_name); + hx509_name_free(&name); + if (ret) + errx(1, "hx509_name_to_string"); + + hx509_pem_add_header(header, "Signer", signer_name); + + free(signer_name); + return 0; +} + int cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) { @@ -250,96 +361,100 @@ cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) heim_octet_string o; hx509_query *q; hx509_lock lock; - hx509_certs store, pool, anchors; - hx509_cert cert; + hx509_certs store, pool, anchors, signer = NULL; size_t sz; void *p; int ret, flags = 0; - char *signer_name = NULL; + char *infile, *outfile = NULL; memset(&contentType, 0, sizeof(contentType)); - if (argc < 2) - errx(1, "argc < 2"); + infile = argv[0]; + + if (argc < 2) { + asprintf(&outfile, "%s.%s", infile, + opt->pem_flag ? "pem" : "cms-signeddata"); + if (outfile == NULL) + errx(1, "out of memory"); + } else + outfile = argv[1]; hx509_lock_init(context, &lock); lock_strings(lock, &opt->pass_strings); ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); ret = hx509_certs_init(context, "MEMORY:cert-pool", 0, NULL, &pool); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); certs_strings(context, "store", store, lock, &opt->certificate_strings); certs_strings(context, "pool", pool, lock, &opt->pool_strings); if (opt->anchors_strings.num_strings) { - ret = hx509_certs_init(context, "MEMORY:cert-anchors", + ret = hx509_certs_init(context, "MEMORY:cert-anchors", 0, NULL, &anchors); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); } else anchors = NULL; if (opt->detached_signature_flag) - flags |= HX509_CMS_SIGATURE_DETACHED; + flags |= HX509_CMS_SIGNATURE_DETACHED; if (opt->id_by_name_flag) - flags |= HX509_CMS_SIGATURE_ID_NAME; + flags |= HX509_CMS_SIGNATURE_ID_NAME; + if (!opt->signer_flag) { + flags |= HX509_CMS_SIGNATURE_NO_SIGNER; - ret = hx509_query_alloc(context, &q); - if (ret) - errx(1, "hx509_query_alloc: %d", ret); + } - hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); - hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); - - if (opt->signer_string) - hx509_query_match_friendly_name(q, opt->signer_string); + if (opt->signer_flag) { + ret = hx509_query_alloc(context, &q); + if (ret) + errx(1, "hx509_query_alloc: %d", ret); - ret = hx509_certs_find(context, store, q, &cert); - hx509_query_free(context, q); - if (ret) - hx509_err(context, 1, ret, "hx509_certs_find"); + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); - ret = _hx509_map_file(argv[0], &p, &sz, NULL); + if (opt->signer_string) + hx509_query_match_friendly_name(q, opt->signer_string); + + ret = hx509_certs_filter(context, store, q, &signer); + hx509_query_free(context, q); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_find"); + } + if (!opt->embedded_certs_flag) + flags |= HX509_CMS_SIGNATURE_NO_CERTS; + if (opt->embed_leaf_only_flag) + flags |= HX509_CMS_SIGNATURE_LEAF_ONLY; + + ret = rk_undumpdata(infile, &p, &sz); if (ret) - err(1, "map_file: %s: %d", argv[0], ret); + err(1, "map_file: %s: %d", infile, ret); if (opt->peer_alg_strings.num_strings) peer_strings(context, &peer, &opt->peer_alg_strings); - parse_oid(opt->content_type_string, oid_id_pkcs7_data(), &contentType); - - ret = hx509_cms_create_signed_1(context, - flags, - &contentType, - p, - sz, - NULL, - cert, - peer, - anchors, - pool, - &o); + parse_oid(opt->content_type_string, &asn1_oid_id_pkcs7_data, &contentType); + + ret = hx509_cms_create_signed(context, + flags, + &contentType, + p, + sz, + NULL, + signer, + peer, + anchors, + pool, + &o); if (ret) - errx(1, "hx509_cms_create_signed: %d", ret); - - { - hx509_name name; - - ret = hx509_cert_get_subject(cert, &name); - if (ret) - errx(1, "hx509_cert_get_subject"); - - ret = hx509_name_to_string(name, &signer_name); - hx509_name_free(&name); - if (ret) - errx(1, "hx509_name_to_string"); - } - + hx509_err(context, 1, ret, "hx509_cms_create_signed: %d", ret); hx509_certs_free(&anchors); hx509_certs_free(&pool); - hx509_cert_free(cert); hx509_certs_free(&store); - _hx509_unmap_file(p, sz); + rk_xfree(p); hx509_lock_free(lock); hx509_peer_info_free(peer); der_free_oid(&contentType); @@ -347,7 +462,7 @@ cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) if (opt->content_info_flag) { heim_octet_string wo; - ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &o, &wo); + ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData, &o, &wo); if (ret) errx(1, "hx509_cms_wrap_ContentInfo: %d", ret); @@ -359,15 +474,20 @@ cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) hx509_pem_header *header = NULL; FILE *f; - hx509_pem_add_header(&header, "Content-disposition", - opt->detached_signature_flag ? "detached" : "inline"); - hx509_pem_add_header(&header, "Signer", signer_name); + hx509_pem_add_header(&header, "Content-disposition", + opt->detached_signature_flag ? + "detached" : "inline"); + if (signer) { + ret = hx509_certs_iter_f(context, signer, print_signer, header); + if (ret) + hx509_err(context, 1, ret, "print signer"); + } - f = fopen(argv[1], "w"); + f = fopen(outfile, "w"); if (f == NULL) - err(1, "open %s", argv[1]); - - ret = hx509_pem_write(context, "CMS SIGNEDDATA", header, f, + err(1, "open %s", outfile); + + ret = hx509_pem_write(context, "CMS SIGNEDDATA", header, f, o.data, o.length); fclose(f); hx509_pem_free_header(header); @@ -375,12 +495,12 @@ cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) errx(1, "hx509_pem_write: %d", ret); } else { - ret = _hx509_write_file(argv[1], o.data, o.length); + ret = _hx509_write_file(outfile, o.data, o.length); if (ret) errx(1, "hx509_write_file: %d", ret); } - free(signer_name); + hx509_certs_free(&signer); free(o.data); return 0; @@ -396,11 +516,12 @@ cms_unenvelope(struct cms_unenvelope_options *opt, int argc, char **argv) void *p; int ret; hx509_lock lock; + int flags = 0; hx509_lock_init(context, &lock); lock_strings(lock, &opt->pass_strings); - ret = _hx509_map_file(argv[0], &p, &sz, NULL); + ret = rk_undumpdata(argv[0], &p, &sz); if (ret) err(1, "map_file: %s: %d", argv[0], ret); @@ -415,7 +536,7 @@ cms_unenvelope(struct cms_unenvelope_options *opt, int argc, char **argv) if (ret) errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret); - if (der_heim_oid_cmp(&oid, oid_id_pkcs7_envelopedData()) != 0) + if (der_heim_oid_cmp(&oid, &asn1_oid_id_pkcs7_envelopedData) != 0) errx(1, "Content is not SignedData"); der_free_oid(&oid); @@ -428,14 +549,17 @@ cms_unenvelope(struct cms_unenvelope_options *opt, int argc, char **argv) certs_strings(context, "store", certs, lock, &opt->certificate_strings); - ret = hx509_cms_unenvelope(context, certs, 0, co.data, co.length, - NULL, &contentType, &o); + if (opt->allow_weak_crypto_flag) + flags |= HX509_CMS_UE_ALLOW_WEAK; + + ret = hx509_cms_unenvelope(context, certs, flags, co.data, co.length, + NULL, 0, &contentType, &o); if (co.data != p) der_free_octet_string(&co); if (ret) hx509_err(context, 1, ret, "hx509_cms_unenvelope"); - _hx509_unmap_file(p, sz); + rk_xfree(p); hx509_lock_free(lock); hx509_certs_free(&certs); der_free_oid(&contentType); @@ -462,24 +586,29 @@ cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv) size_t sz; void *p; hx509_lock lock; + int flags = 0; memset(&contentType, 0, sizeof(contentType)); hx509_lock_init(context, &lock); lock_strings(lock, &opt->pass_strings); - ret = _hx509_map_file(argv[0], &p, &sz, NULL); + ret = rk_undumpdata(argv[0], &p, &sz); if (ret) err(1, "map_file: %s: %d", argv[0], ret); ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); certs_strings(context, "store", certs, lock, &opt->certificate_strings); + if (opt->allow_weak_crypto_flag) + flags |= HX509_CMS_EV_ALLOW_WEAK; + if (opt->encryption_type_string) { enctype = hx509_crypto_enctype_by_name(opt->encryption_type_string); if (enctype == NULL) - errx(1, "encryption type: %s no found", + errx(1, "encryption type: %s no found", opt->encryption_type_string); } @@ -494,22 +623,22 @@ cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv) if (ret) errx(1, "hx509_certs_find: %d", ret); - parse_oid(opt->content_type_string, oid_id_pkcs7_data(), &contentType); + parse_oid(opt->content_type_string, &asn1_oid_id_pkcs7_data, &contentType); - ret = hx509_cms_envelope_1(context, 0, cert, p, sz, enctype, + ret = hx509_cms_envelope_1(context, flags, cert, p, sz, enctype, &contentType, &o); if (ret) errx(1, "hx509_cms_envelope_1: %d", ret); hx509_cert_free(cert); hx509_certs_free(&certs); - _hx509_unmap_file(p, sz); + rk_xfree(p); der_free_oid(&contentType); if (opt->content_info_flag) { heim_octet_string wo; - ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_envelopedData(), &o, &wo); + ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_envelopedData, &o, &wo); if (ret) errx(1, "hx509_cms_wrap_ContentInfo: %d", ret); @@ -531,46 +660,18 @@ cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv) static void print_certificate(hx509_context hxcontext, hx509_cert cert, int verbose) { - hx509_name name; const char *fn; - char *str; int ret; - + fn = hx509_cert_get_friendly_name(cert); if (fn) printf(" friendly name: %s\n", fn); - printf(" private key: %s\n", + printf(" private key: %s\n", _hx509_cert_private_key(cert) ? "yes" : "no"); - ret = hx509_cert_get_issuer(cert, &name); - hx509_name_to_string(name, &str); - hx509_name_free(&name); - printf(" issuer: \"%s\"\n", str); - free(str); - - ret = hx509_cert_get_subject(cert, &name); - hx509_name_to_string(name, &str); - hx509_name_free(&name); - printf(" subject: \"%s\"\n", str); - free(str); - - { - heim_integer serialNumber; - - hx509_cert_get_serialnumber(cert, &serialNumber); - der_print_hex_heim_integer(&serialNumber, &str); - der_free_heim_integer(&serialNumber); - printf(" serial: %s\n", str); - free(str); - } - - printf(" keyusage: "); - ret = hx509_cert_keyusage_print(hxcontext, cert, &str); - if (ret == 0) { - printf("%s\n", str); - free(str); - } else - printf("no"); + ret = hx509_print_cert(hxcontext, cert, NULL); + if (ret) + errx(1, "failed to print cert"); if (verbose) { hx509_validate_ctx vctx; @@ -579,7 +680,7 @@ print_certificate(hx509_context hxcontext, hx509_cert cert, int verbose) hx509_validate_ctx_set_print(vctx, hx509_print_stdout, stdout); hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VALIDATE); hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VERBOSE); - + hx509_validate_cert(hxcontext, vctx, cert); hx509_validate_ctx_free(vctx); @@ -596,7 +697,7 @@ static int print_f(hx509_context hxcontext, void *ctx, hx509_cert cert) { struct print_s *s = ctx; - + printf("cert: %d\n", s->counter++); print_certificate(context, cert, s->verbose); @@ -619,11 +720,16 @@ pcert_print(struct print_options *opt, int argc, char **argv) while(argc--) { int ret; ret = hx509_certs_init(context, argv[0], 0, lock, &certs); - if (ret) + if (ret) { + if (opt->never_fail_flag) { + printf("ignoreing failure: %d\n", ret); + continue; + } hx509_err(context, 1, ret, "hx509_certs_init"); + } if (opt->info_flag) hx509_certs_info(context, certs, NULL, NULL); - hx509_certs_iter(context, certs, print_f, &s); + hx509_certs_iter_f(context, certs, print_f, &s); hx509_certs_free(&certs); argv++; } @@ -660,7 +766,7 @@ pcert_validate(struct validate_options *opt, int argc, char **argv) ret = hx509_certs_init(context, argv[0], 0, lock, &certs); if (ret) errx(1, "hx509_certs_init: %d", ret); - hx509_certs_iter(context, certs, validate_f, ctx); + hx509_certs_iter_f(context, certs, validate_f, ctx); hx509_certs_free(&certs); argv++; } @@ -675,31 +781,40 @@ int certificate_copy(struct certificate_copy_options *opt, int argc, char **argv) { hx509_certs certs; - hx509_lock lock; + hx509_lock inlock, outlock = NULL; int ret; - hx509_lock_init(context, &lock); - lock_strings(lock, &opt->in_pass_strings); + hx509_lock_init(context, &inlock); + lock_strings(inlock, &opt->in_pass_strings); + + if (opt->out_pass_string) { + hx509_lock_init(context, &outlock); + ret = hx509_lock_command_string(outlock, opt->out_pass_string); + if (ret) + errx(1, "hx509_lock_command_string: %s: %d", + opt->out_pass_string, ret); + } - ret = hx509_certs_init(context, argv[argc - 1], - HX509_CERTS_CREATE, lock, &certs); + ret = hx509_certs_init(context, argv[argc - 1], + HX509_CERTS_CREATE, inlock, &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"); + int retx; + retx = hx509_certs_append(context, certs, inlock, argv[0]); + if (retx) + hx509_err(context, 1, retx, "hx509_certs_append"); argv++; } - ret = hx509_certs_store(context, certs, 0, NULL); + ret = hx509_certs_store(context, certs, 0, outlock); if (ret) hx509_err(context, 1, ret, "hx509_certs_store"); hx509_certs_free(&certs); - hx509_lock_free(lock); + hx509_lock_free(inlock); + hx509_lock_free(outlock); return 0; } @@ -709,6 +824,7 @@ struct verify { hx509_certs chain; const char *hostname; int errors; + int count; }; static int @@ -723,8 +839,10 @@ verify_f(hx509_context hxcontext, void *ctx, hx509_cert c) printf("verify_path: %s: %d\n", s, ret); hx509_free_error_string(s); v->errors++; - } else + } else { + v->count++; printf("path ok\n"); + } if (v->hostname) { ret = hx509_verify_hostname(hxcontext, c, 0, HX509_HN_HOSTNAME, @@ -753,9 +871,17 @@ pcert_verify(struct verify_options *opt, int argc, char **argv) hx509_context_set_missing_revoke(context, 1); ret = hx509_verify_init_ctx(context, &ctx); + if (ret) + hx509_err(context, 1, ret, "hx509_verify_init_ctx"); ret = hx509_certs_init(context, "MEMORY:anchors", 0, NULL, &anchors); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); ret = hx509_certs_init(context, "MEMORY:chain", 0, NULL, &chain); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs); + if (ret) + hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); if (opt->allow_proxy_certificate_flag) hx509_verify_set_proxy_certificate(ctx, 1); @@ -771,7 +897,7 @@ pcert_verify(struct verify_options *opt, int argc, char **argv) if (p == NULL) errx(1, "Failed to parse time %s, need to be on format %%Y-%%m-%%d", opt->time_string); - + t = tm2time (tm, 0); hx509_verify_set_time(ctx, t); @@ -808,7 +934,7 @@ pcert_verify(struct verify_options *opt, int argc, char **argv) ret = hx509_certs_append(context, certs, NULL, s); if (ret) - hx509_err(context, 1, ret, "hx509_certs_append: certs: %s: %d", + hx509_err(context, 1, ret, "hx509_certs_append: certs: %s: %d", s, ret); } else if (strncmp(s, "crl:", 4) == 0) { @@ -836,7 +962,7 @@ pcert_verify(struct verify_options *opt, int argc, char **argv) v.ctx = ctx; v.chain = chain; - hx509_certs_iter(context, certs, verify_f, &v); + hx509_certs_iter_f(context, certs, verify_f, &v); hx509_verify_destroy_ctx(ctx); @@ -846,6 +972,12 @@ pcert_verify(struct verify_options *opt, int argc, char **argv) hx509_revoke_free(&revoke_ctx); + + if (v.count == 0) { + printf("no certs verify at all\n"); + return 1; + } + if (v.errors) { printf("failed verifing %d checks\n", v.errors); return 1; @@ -871,6 +1003,7 @@ query(struct query_options *opt, int argc, char **argv) lock_strings(lock, &opt->pass_strings); ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); while (argc > 0) { @@ -885,6 +1018,17 @@ query(struct query_options *opt, int argc, char **argv) if (opt->friendlyname_string) hx509_query_match_friendly_name(q, opt->friendlyname_string); + if (opt->eku_string) { + heim_oid oid; + + parse_oid(opt->eku_string, NULL, &oid); + + ret = hx509_query_match_eku(q, &oid); + if (ret) + errx(1, "hx509_query_match_eku: %d", ret); + der_free_oid(&oid); + } + if (opt->private_key_flag) hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); @@ -894,6 +1038,9 @@ query(struct query_options *opt, int argc, char **argv) if (opt->digitalSignature_flag) hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); + if (opt->expr_string) + hx509_query_match_expr(context, q, opt->expr_string); + ret = hx509_certs_find(context, certs, q, &c); hx509_query_free(context, q); if (ret) @@ -935,12 +1082,14 @@ ocsp_fetch(struct ocsp_fetch_options *opt, int argc, char **argv) url = opt->url_path_string; ret = hx509_certs_init(context, "MEMORY:ocsp-pool", 0, NULL, &pool); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); certs_strings(context, "ocsp-pool", pool, lock, &opt->pool_strings); file = argv[0]; ret = hx509_certs_init(context, "MEMORY:ocsp-req", 0, NULL, &reqcerts); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); for (i = 1; i < argc; i++) { ret = hx509_certs_append(context, reqcerts, lock, argv[i]); @@ -951,7 +1100,7 @@ ocsp_fetch(struct ocsp_fetch_options *opt, int argc, char **argv) ret = hx509_ocsp_request(context, reqcerts, pool, NULL, NULL, &req, nonce); if (ret) errx(1, "hx509_ocsp_request: req: %d", ret); - + { FILE *f; @@ -959,7 +1108,7 @@ ocsp_fetch(struct ocsp_fetch_options *opt, int argc, char **argv) if (f == NULL) abort(); - fprintf(f, + fprintf(f, "POST %s HTTP/1.0\r\n" "Content-Type: application/ocsp-request\r\n" "Content-Length: %ld\r\n" @@ -997,7 +1146,7 @@ verify_o(hx509_context hxcontext, void *ctx, hx509_cert c) time_t expiration; int ret; - ret = hx509_ocsp_verify(context, 0, c, 0, + ret = hx509_ocsp_verify(context, 0, c, 0, os->data, os->length, &expiration); if (ret) { char *s = hx509_get_error_string(hxcontext, ret); @@ -1017,17 +1166,18 @@ ocsp_verify(struct ocsp_verify_options *opt, int argc, char **argv) hx509_certs certs; int ret, i; heim_octet_string os; - + hx509_lock_init(context, &lock); if (opt->ocsp_file_string == NULL) errx(1, "no ocsp file given"); - ret = _hx509_map_file(opt->ocsp_file_string, &os.data, &os.length, NULL); + ret = _hx509_map_file_os(opt->ocsp_file_string, &os); if (ret) err(1, "map_file: %s: %d", argv[0], ret); - + ret = hx509_certs_init(context, "MEMORY:test-certs", 0, NULL, &certs); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); for (i = 0; i < argc; i++) { ret = hx509_certs_append(context, certs, lock, argv[i]); @@ -1035,10 +1185,10 @@ ocsp_verify(struct ocsp_verify_options *opt, int argc, char **argv) hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]); } - ret = hx509_certs_iter(context, certs, verify_o, &os); + ret = hx509_certs_iter_f(context, certs, verify_o, &os); hx509_certs_free(&certs); - _hx509_unmap_file(os.data, os.length); + _hx509_unmap_file_os(&os); hx509_lock_free(lock); return ret; @@ -1050,7 +1200,7 @@ read_private_key(const char *fn, hx509_private_key *key) hx509_private_key *keys; hx509_certs certs; int ret; - + *key = NULL; ret = hx509_certs_init(context, fn, 0, NULL, &certs); @@ -1085,10 +1235,10 @@ get_key(const char *fn, const char *type, int optbits, if (fn == NULL) errx(1, "no key argument, don't know here to store key"); - + if (strcasecmp(type, "rsa") != 0) errx(1, "can only handle rsa keys for now"); - + e = BN_new(); BN_set_word(e, 0x10001); @@ -1110,13 +1260,13 @@ get_key(const char *fn, const char *type, int optbits, p0 = p = malloc(len); if (p == NULL) errx(1, "out of memory"); - + i2d_RSAPrivateKey(rsa, &p); rk_dumpdata(fn, p0, len); memset(p0, 0, len); free(p0); - + RSA_free(rsa); } else if (fn == NULL) @@ -1139,12 +1289,12 @@ request_create(struct request_create_options *opt, int argc, char **argv) memset(&key, 0, sizeof(key)); - get_key(opt->key_string, + get_key(opt->key_string, opt->generate_key_string, opt->key_bits_integer, &signer); - - _hx509_request_init(context, &req); + + hx509_request_init(context, &req); if (opt->subject_string) { hx509_name name = NULL; @@ -1152,7 +1302,7 @@ request_create(struct request_create_options *opt, int argc, char **argv) ret = hx509_parse_name(context, opt->subject_string, &name); if (ret) errx(1, "hx509_parse_name: %d\n", ret); - _hx509_request_set_name(context, req, name); + hx509_request_set_name(context, req, name); if (opt->verbose_flag) { char *s; @@ -1163,26 +1313,30 @@ request_create(struct request_create_options *opt, int argc, char **argv) } for (i = 0; i < opt->email_strings.num_strings; i++) { - ret = _hx509_request_add_email(context, req, + ret = _hx509_request_add_email(context, req, opt->email_strings.strings[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_email"); } for (i = 0; i < opt->dnsname_strings.num_strings; i++) { - ret = _hx509_request_add_dns_name(context, req, + ret = _hx509_request_add_dns_name(context, req, opt->dnsname_strings.strings[i]); + if (ret) + hx509_err(context, 1, ret, "hx509_request_add_dns_name"); } - ret = _hx509_private_key2SPKI(context, signer, &key); + ret = hx509_private_key2SPKI(context, signer, &key); if (ret) - errx(1, "_hx509_private_key2SPKI: %d\n", ret); + errx(1, "hx509_private_key2SPKI: %d\n", ret); - ret = _hx509_request_set_SubjectPublicKeyInfo(context, + ret = hx509_request_set_SubjectPublicKeyInfo(context, req, &key); free_SubjectPublicKeyInfo(&key); if (ret) - hx509_err(context, 1, ret, "_hx509_request_set_SubjectPublicKeyInfo"); + hx509_err(context, 1, ret, "hx509_request_set_SubjectPublicKeyInfo"); ret = _hx509_request_to_pkcs10(context, req, @@ -1191,8 +1345,8 @@ request_create(struct request_create_options *opt, int argc, char **argv) if (ret) hx509_err(context, 1, ret, "_hx509_request_to_pkcs10"); - _hx509_private_key_free(&signer); - _hx509_request_free(&req); + hx509_private_key_free(&signer); + hx509_request_free(&req); if (ret == 0) rk_dumpdata(outfile, request.data, request.length); @@ -1216,7 +1370,7 @@ request_print(struct request_print_options *opt, int argc, char **argv) hx509_err(context, 1, ret, "parse_request: %s", argv[i]); ret = _hx509_request_print(context, req, stdout); - _hx509_request_free(&req); + hx509_request_free(&req); if (ret) hx509_err(context, 1, ret, "Failed to print file %s", argv[i]); } @@ -1240,6 +1394,15 @@ info(void *opt, int argc, char **argv) if (m != NULL) printf("dh: %s\n", m->name); } +#ifdef HAVE_OPENSSL + { + printf("ecdsa: ECDSA_METHOD-not-export\n"); + } +#else + { + printf("ecdsa: hcrypto null\n"); + } +#endif { int ret = RAND_status(); printf("rand: %s\n", ret == 1 ? "ok" : "not available"); @@ -1286,7 +1449,7 @@ crypto_available(struct crypto_available_options *opt, int argc, char **argv) { AlgorithmIdentifier *val; unsigned int len, i; - int ret, type; + int ret, type = HX509_SELECT_ALL; if (opt->type_string) { if (strcmp(opt->type_string, "all") == 0) @@ -1299,8 +1462,7 @@ crypto_available(struct crypto_available_options *opt, int argc, char **argv) type = HX509_SELECT_SECRET_ENC; else errx(1, "unknown type: %s", opt->type_string); - } else - type = HX509_SELECT_ALL; + } ret = hx509_crypto_available(context, type, NULL, &val, &len); if (ret) @@ -1323,7 +1485,7 @@ crypto_select(struct crypto_select_options *opt, int argc, char **argv) { hx509_peer_info peer = NULL; AlgorithmIdentifier selected; - int ret, type; + int ret, type = HX509_SELECT_DIGEST; char *s; if (opt->type_string) { @@ -1335,8 +1497,7 @@ crypto_select(struct crypto_select_options *opt, int argc, char **argv) type = HX509_SELECT_SECRET_ENC; else errx(1, "unknown type: %s", opt->type_string); - } else - type = HX509_SELECT_DIGEST; + } if (opt->peer_cmstype_strings.num_strings) peer_strings(context, &peer, &opt->peer_cmstype_strings); @@ -1371,15 +1532,17 @@ hxtool_hex(struct hex_options *opt, int argc, char **argv) len = hex_decode(p, buf2, strlen(p)); if (len < 0) errx(1, "hex_decode failed"); - if (fwrite(buf2, 1, len, stdout) != len) + if (fwrite(buf2, 1, len, stdout) != (size_t)len) errx(1, "fwrite failed"); } } else { - char buf[28], *p; - size_t len; + char buf[28], *p; + ssize_t len; while((len = fread(buf, 1, sizeof(buf), stdin)) != 0) { len = hex_encode(buf, len, &p); + if (len < 0) + continue; fprintf(stdout, "%s\n", p); free(p); } @@ -1387,112 +1550,193 @@ hxtool_hex(struct hex_options *opt, int argc, char **argv) return 0; } +struct cert_type_opt { + int pkinit; +}; + + +static int +https_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth); +} + +static int +https_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_clientAuth); +} + +static int +peap_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth); +} + +static int +pkinit_kdc(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + opt->pkinit++; + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkkdcekuoid); +} + +static int +pkinit_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + int ret; + + opt->pkinit++; + + ret = hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkekuoid); + if (ret) + return ret; + + ret = hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_ms_client_authentication); + if (ret) + return ret; + + return hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_pkinit_ms_eku); +} + static int -eval_types(hx509_context context, +email_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt) +{ + return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_emailProtection); +} + +struct { + const char *type; + const char *desc; + int (*eval)(hx509_context, hx509_ca_tbs, struct cert_type_opt *); +} certtypes[] = { + { + "https-server", + "Used for HTTPS server and many other TLS server certificate types", + https_server + }, + { + "https-client", + "Used for HTTPS client certificates", + https_client + }, + { + "email-client", + "Certificate will be use for email", + email_client + }, + { + "pkinit-client", + "Certificate used for Kerberos PK-INIT client certificates", + pkinit_client + }, + { + "pkinit-kdc", + "Certificates used for Kerberos PK-INIT KDC certificates", + pkinit_kdc + }, + { + "peap-server", + "Certificate used for Radius PEAP (Protected EAP)", + peap_server + } +}; + +static void +print_eval_types(FILE *out) +{ + rtbl_t table; + unsigned i; + + table = rtbl_create(); + rtbl_add_column_by_id (table, 0, "Name", 0); + rtbl_add_column_by_id (table, 1, "Description", 0); + + for (i = 0; i < sizeof(certtypes)/sizeof(certtypes[0]); i++) { + rtbl_add_column_entry_by_id(table, 0, certtypes[i].type); + rtbl_add_column_entry_by_id(table, 1, certtypes[i].desc); + } + + rtbl_format (table, out); + rtbl_destroy (table); +} + +static int +eval_types(hx509_context contextp, hx509_ca_tbs tbs, const struct certificate_sign_options *opt) { - int pkinit = 0; - int i, ret; + struct cert_type_opt ctopt; + int i; + size_t j; + int ret; + + memset(&ctopt, 0, sizeof(ctopt)); for (i = 0; i < opt->type_strings.num_strings; i++) { const char *type = opt->type_strings.strings[i]; - - if (strcmp(type, "https-server") == 0) { - ret = hx509_ca_tbs_add_eku(context, tbs, - oid_id_pkix_kp_serverAuth()); - if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); - } else if (strcmp(type, "https-client") == 0) { - ret = hx509_ca_tbs_add_eku(context, tbs, - oid_id_pkix_kp_clientAuth()); - if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); - } else if (strcmp(type, "peap-server") == 0) { - ret = hx509_ca_tbs_add_eku(context, tbs, - oid_id_pkix_kp_serverAuth()); - if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); - } else if (strcmp(type, "pkinit-kdc") == 0) { - pkinit++; - ret = hx509_ca_tbs_add_eku(context, tbs, - oid_id_pkkdcekuoid()); - if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); - } else if (strcmp(type, "pkinit-client") == 0) { - pkinit++; - ret = hx509_ca_tbs_add_eku(context, tbs, - oid_id_pkekuoid()); - if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); - - ret = hx509_ca_tbs_add_eku(context, tbs, - oid_id_ms_client_authentication()); - if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); - - ret = hx509_ca_tbs_add_eku(context, tbs, - oid_id_pkinit_ms_eku()); - if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); - } else if (strcmp(type, "email") == 0) { - ret = hx509_ca_tbs_add_eku(context, tbs, - oid_id_pkix_kp_emailProtection()); - if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); - } else - errx(1, "unknown type %s", type); + for (j = 0; j < sizeof(certtypes)/sizeof(certtypes[0]); j++) { + if (strcasecmp(type, certtypes[j].type) == 0) { + ret = (*certtypes[j].eval)(contextp, tbs, &ctopt); + if (ret) + hx509_err(contextp, 1, ret, + "Failed to evaluate cert type %s", type); + break; + } + } + if (j >= sizeof(certtypes)/sizeof(certtypes[0])) { + fprintf(stderr, "Unknown certificate type %s\n\n", type); + fprintf(stderr, "Available types:\n"); + print_eval_types(stderr); + exit(1); + } } - if (pkinit > 1) - errx(1, "More the one PK-INIT type given"); - if (opt->pk_init_principal_string) { - if (!pkinit) + if (!ctopt.pkinit) errx(1, "pk-init principal given but no pk-init oid"); - ret = hx509_ca_tbs_add_san_pkinit(context, tbs, + ret = hx509_ca_tbs_add_san_pkinit(contextp, tbs, opt->pk_init_principal_string); if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_pkinit"); + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_pkinit"); } if (opt->ms_upn_string) { - if (!pkinit) - errx(1, "MS up given but no pk-init oid"); + if (!ctopt.pkinit) + errx(1, "MS upn given but no pk-init oid"); - ret = hx509_ca_tbs_add_san_ms_upn(context, tbs, opt->ms_upn_string); + ret = hx509_ca_tbs_add_san_ms_upn(contextp, tbs, opt->ms_upn_string); if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_ms_upn"); + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_ms_upn"); } - + for (i = 0; i < opt->hostname_strings.num_strings; i++) { const char *hostname = opt->hostname_strings.strings[i]; - ret = hx509_ca_tbs_add_san_hostname(context, tbs, hostname); + ret = hx509_ca_tbs_add_san_hostname(contextp, tbs, hostname); if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname"); + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname"); } for (i = 0; i < opt->email_strings.num_strings; i++) { const char *email = opt->email_strings.strings[i]; - ret = hx509_ca_tbs_add_san_rfc822name(context, tbs, email); + ret = hx509_ca_tbs_add_san_rfc822name(contextp, tbs, email); if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname"); - - ret = hx509_ca_tbs_add_eku(context, tbs, - oid_id_pkix_kp_emailProtection()); + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname"); + + ret = hx509_ca_tbs_add_eku(contextp, tbs, + &asn1_oid_id_pkix_kp_emailProtection); if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_eku"); } if (opt->jid_string) { - ret = hx509_ca_tbs_add_san_jid(context, tbs, opt->jid_string); + ret = hx509_ca_tbs_add_san_jid(contextp, tbs, opt->jid_string); if (ret) - hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_jid"); + hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_jid"); } return 0; @@ -1557,6 +1801,9 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) if (opt->generate_key_string == NULL && opt->ca_private_key_string == NULL) errx(1, "no signing private key"); + + if (opt->req_string) + errx(1, "can't be self-signing and have a request at the same time"); } else errx(1, "missing ca key"); @@ -1566,9 +1813,9 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) if (ret) err(1, "read_private_key"); - ret = _hx509_private_key2SPKI(context, private_key, &spki); + ret = hx509_private_key2SPKI(context, private_key, &spki); if (ret) - errx(1, "_hx509_private_key2SPKI: %d\n", ret); + errx(1, "hx509_private_key2SPKI: %d\n", ret); if (opt->self_signed_flag) cert_key = private_key; @@ -1580,21 +1827,23 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) ret = _hx509_request_parse(context, opt->req_string, &req); if (ret) hx509_err(context, 1, ret, "parse_request: %s", opt->req_string); - ret = _hx509_request_get_name(context, req, &subject); + ret = hx509_request_get_name(context, req, &subject); if (ret) hx509_err(context, 1, ret, "get name"); - ret = _hx509_request_get_SubjectPublicKeyInfo(context, req, &spki); + ret = hx509_request_get_SubjectPublicKeyInfo(context, req, &spki); if (ret) hx509_err(context, 1, ret, "get spki"); - _hx509_request_free(&req); + hx509_request_free(&req); } if (opt->generate_key_string) { struct hx509_generate_private_context *keyctx; - ret = _hx509_generate_private_key_init(context, - oid_id_pkcs1_rsaEncryption(), + ret = _hx509_generate_private_key_init(context, + &asn1_oid_id_pkcs1_rsaEncryption, &keyctx); + if (ret) + hx509_err(context, 1, ret, "generate private key"); if (opt->issue_ca_flag) _hx509_generate_private_key_is_ca(context, keyctx); @@ -1608,10 +1857,10 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) _hx509_generate_private_key_free(&keyctx); if (ret) hx509_err(context, 1, ret, "generate private key"); - - ret = _hx509_private_key2SPKI(context, cert_key, &spki); + + ret = hx509_private_key2SPKI(context, cert_key, &spki); if (ret) - errx(1, "_hx509_private_key2SPKI: %d\n", ret); + errx(1, "hx509_private_key2SPKI: %d\n", ret); if (opt->self_signed_flag) private_key = cert_key; @@ -1638,7 +1887,7 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) ret = hx509_ca_tbs_init(context, &tbs); if (ret) hx509_err(context, 1, ret, "hx509_ca_tbs_init"); - + if (opt->template_certificate_string) { hx509_cert template; hx509_certs tcerts; @@ -1656,7 +1905,7 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) if (ret) hx509_err(context, 1, ret, "no template certificate found"); - flags = parse_units(opt->template_fields_string, + flags = parse_units(opt->template_fields_string, hx509_ca_tbs_template_units(), ""); ret = hx509_ca_tbs_set_template(context, tbs, flags, template); @@ -1692,7 +1941,7 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) } if (opt->crl_uri_string) { - ret = hx509_ca_tbs_add_crl_dp_uri(context, tbs, + ret = hx509_ca_tbs_add_crl_dp_uri(context, tbs, opt->crl_uri_string, NULL); if (ret) hx509_err(context, 1, ret, "hx509_ca_tbs_add_crl_dp_uri"); @@ -1720,7 +1969,7 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) ret = hx509_ca_tbs_set_notAfter_lifetime(context, tbs, delta); if (ret) hx509_err(context, 1, ret, "hx509_ca_tbs_set_notAfter_lifetime"); - } + } if (opt->self_signed_flag) { ret = hx509_ca_sign_self(context, tbs, private_key, &cert); @@ -1736,12 +1985,12 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) ret = _hx509_cert_assign_key(cert, cert_key); if (ret) hx509_err(context, 1, ret, "_hx509_cert_assign_key"); - } + } { hx509_certs certs; - ret = hx509_certs_init(context, opt->certificate_string, + ret = hx509_certs_init(context, opt->certificate_string, HX509_CERTS_CREATE, NULL, &certs); if (ret) hx509_err(context, 1, ret, "hx509_certs_init"); @@ -1765,8 +2014,8 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) free_SubjectPublicKeyInfo(&spki); if (private_key != cert_key) - _hx509_private_key_free(&private_key); - _hx509_private_key_free(&cert_key); + hx509_private_key_free(&private_key); + hx509_private_key_free(&cert_key); hx509_ca_tbs_free(&tbs); @@ -1790,7 +2039,7 @@ test_one_cert(hx509_context hxcontext, void *ctx, hx509_cert cert) if (ret) errx(1, "hx509_cms_create_signed_1"); - ret = hx509_cms_verify_signed(context, vctx, sd.data, sd.length, + ret = hx509_cms_verify_signed(context, vctx, 0, sd.data, sd.length, NULL, NULL, &type, &c, &signer); free(sd.data); if (ret) @@ -1815,6 +2064,7 @@ test_crypto(struct test_crypto_options *opt, int argc, char ** argv) lock_strings(lock, &opt->pass_strings); ret = hx509_certs_init(context, "MEMORY:test-crypto", 0, NULL, &certs); + if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); for (i = 0; i < argc; i++) { ret = hx509_certs_append(context, certs, lock, argv[i]); @@ -1828,7 +2078,9 @@ test_crypto(struct test_crypto_options *opt, int argc, char ** argv) hx509_verify_attach_anchors(vctx, certs); - ret = hx509_certs_iter(context, certs, test_one_cert, vctx); + ret = hx509_certs_iter_f(context, certs, test_one_cert, vctx); + if (ret) + hx509_err(context, 1, ret, "hx509_cert_iter"); hx509_certs_free(&certs); @@ -1880,7 +2132,7 @@ crl_sign(struct crl_sign_options *opt, int argc, char **argv) ret = hx509_certs_init(context, opt->signer_string, 0, NULL, &certs); if (ret) - hx509_err(context, 1, ret, + hx509_err(context, 1, ret, "hx509_certs_init: %s", opt->signer_string); ret = hx509_query_alloc(context, &q); @@ -1912,6 +2164,9 @@ crl_sign(struct crl_sign_options *opt, int argc, char **argv) ret = hx509_certs_init(context, "MEMORY:revoked-certs", 0, NULL, &revoked); + if (ret) + hx509_err(context, 1, ret, + "hx509_certs_init: MEMORY cert"); for (i = 0; i < argc; i++) { ret = hx509_certs_append(context, revoked, lock, argv[i]); |
