Path: blob/main/crypto/heimdal/lib/hx509/hxtool.c
106751 views
/*1* Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233#include "hx_locl.h"3435#include <hxtool-commands.h>36#include <sl.h>37#include <rtbl.h>38#include <parse_time.h>3940static hx509_context context;4142static char *stat_file_string;43static int version_flag;44static int help_flag;4546struct getargs args[] = {47{ "statistic-file", 0, arg_string, &stat_file_string, NULL, NULL },48{ "version", 0, arg_flag, &version_flag, NULL, NULL },49{ "help", 0, arg_flag, &help_flag, NULL, NULL }50};51int num_args = sizeof(args) / sizeof(args[0]);5253static void54usage(int code)55{56arg_printusage(args, num_args, NULL, "command");57printf("Use \"%s help\" to get more help\n", getprogname());58exit(code);59}6061/*62*63*/6465static void66lock_strings(hx509_lock lock, getarg_strings *pass)67{68int i;69for (i = 0; i < pass->num_strings; i++) {70int ret = hx509_lock_command_string(lock, pass->strings[i]);71if (ret)72errx(1, "hx509_lock_command_string: %s: %d",73pass->strings[i], ret);74}75}7677/*78*79*/8081static void82certs_strings(hx509_context contextp, const char *type, hx509_certs certs,83hx509_lock lock, const getarg_strings *s)84{85int i, ret;8687for (i = 0; i < s->num_strings; i++) {88ret = hx509_certs_append(contextp, certs, lock, s->strings[i]);89if (ret)90hx509_err(contextp, 1, ret,91"hx509_certs_append: %s %s", type, s->strings[i]);92}93}9495/*96*97*/9899static void100parse_oid(const char *str, const heim_oid *def, heim_oid *oid)101{102int ret;103if (str)104ret = der_parse_heim_oid (str, " .", oid);105else106ret = der_copy_oid(def, oid);107if (ret)108errx(1, "parse_oid failed for: %s", str ? str : "default oid");109}110111/*112*113*/114115static void116peer_strings(hx509_context contextp,117hx509_peer_info *peer,118const getarg_strings *s)119{120AlgorithmIdentifier *val;121int ret, i;122123ret = hx509_peer_info_alloc(contextp, peer);124if (ret)125hx509_err(contextp, 1, ret, "hx509_peer_info_alloc");126127val = calloc(s->num_strings, sizeof(*val));128if (val == NULL)129err(1, "malloc");130131for (i = 0; i < s->num_strings; i++)132parse_oid(s->strings[i], NULL, &val[i].algorithm);133134ret = hx509_peer_info_set_cms_algs(contextp, *peer, val, s->num_strings);135if (ret)136hx509_err(contextp, 1, ret, "hx509_peer_info_set_cms_algs");137138for (i = 0; i < s->num_strings; i++)139free_AlgorithmIdentifier(&val[i]);140free(val);141}142143/*144*145*/146147struct pem_data {148heim_octet_string *os;149int detached_data;150};151152static int153pem_reader(hx509_context contextp, const char *type,154const hx509_pem_header *headers,155const void *data , size_t length, void *ctx)156{157struct pem_data *p = (struct pem_data *)ctx;158const char *h;159160p->os->data = malloc(length);161if (p->os->data == NULL)162return ENOMEM;163memcpy(p->os->data, data, length);164p->os->length = length;165166h = hx509_pem_find_header(headers, "Content-disposition");167if (h && strcasecmp(h, "detached") == 0)168p->detached_data = 1;169170return 0;171}172173/*174*175*/176177int178cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv)179{180hx509_verify_ctx ctx = NULL;181heim_oid type;182heim_octet_string c, co, signeddata, *sd = NULL;183hx509_certs store = NULL;184hx509_certs signers = NULL;185hx509_certs anchors = NULL;186hx509_lock lock;187int ret, flags = 0;188189size_t sz;190void *p = NULL;191192if (opt->missing_revoke_flag)193hx509_context_set_missing_revoke(context, 1);194195hx509_lock_init(context, &lock);196lock_strings(lock, &opt->pass_strings);197198ret = hx509_verify_init_ctx(context, &ctx);199if (ret)200hx509_err(context, 1, ret, "hx509_verify_init_ctx");201202ret = hx509_certs_init(context, "MEMORY:cms-anchors", 0, NULL, &anchors);203if (ret)204hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");205ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store);206if (ret)207hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");208209certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings);210certs_strings(context, "store", store, lock, &opt->certificate_strings);211212if (opt->pem_flag) {213struct pem_data pd;214FILE *f;215216pd.os = &co;217pd.detached_data = 0;218219f = fopen(argv[0], "r");220if (f == NULL)221err(1, "Failed to open file %s", argv[0]);222223ret = hx509_pem_read(context, f, pem_reader, &pd);224fclose(f);225if (ret)226errx(1, "PEM reader failed: %d", ret);227228if (pd.detached_data && opt->signed_content_string == NULL) {229char *r = strrchr(argv[0], '.');230if (r && strcasecmp(r, ".pem") == 0) {231char *s = strdup(argv[0]);232if (s == NULL)233errx(1, "malloc: out of memory");234s[r - argv[0]] = '\0';235ret = _hx509_map_file_os(s, &signeddata);236if (ret)237errx(1, "map_file: %s: %d", s, ret);238free(s);239sd = &signeddata;240}241}242243} else {244ret = rk_undumpdata(argv[0], &p, &sz);245if (ret)246err(1, "map_file: %s: %d", argv[0], ret);247248co.data = p;249co.length = sz;250}251252if (opt->signed_content_string) {253ret = _hx509_map_file_os(opt->signed_content_string, &signeddata);254if (ret)255errx(1, "map_file: %s: %d", opt->signed_content_string, ret);256sd = &signeddata;257}258259if (opt->content_info_flag) {260heim_octet_string uwco;261heim_oid oid;262263ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL);264if (ret)265errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret);266267if (der_heim_oid_cmp(&oid, &asn1_oid_id_pkcs7_signedData) != 0)268errx(1, "Content is not SignedData");269der_free_oid(&oid);270271if (p == NULL)272der_free_octet_string(&co);273else {274rk_xfree(p);275p = NULL;276}277co = uwco;278}279280hx509_verify_attach_anchors(ctx, anchors);281282if (!opt->signer_allowed_flag)283flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER;284if (opt->allow_wrong_oid_flag)285flags |= HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH;286287ret = hx509_cms_verify_signed(context, ctx, flags, co.data, co.length, sd,288store, &type, &c, &signers);289if (p != co.data)290der_free_octet_string(&co);291else292rk_xfree(p);293if (ret)294hx509_err(context, 1, ret, "hx509_cms_verify_signed");295296{297char *str;298der_print_heim_oid(&type, '.', &str);299printf("type: %s\n", str);300free(str);301der_free_oid(&type);302}303if (signers == NULL) {304printf("unsigned\n");305} else {306printf("signers:\n");307hx509_certs_iter_f(context, signers, hx509_ci_print_names, stdout);308}309310hx509_verify_destroy_ctx(ctx);311312hx509_certs_free(&store);313hx509_certs_free(&signers);314hx509_certs_free(&anchors);315316hx509_lock_free(lock);317318if (argc > 1) {319ret = _hx509_write_file(argv[1], c.data, c.length);320if (ret)321errx(1, "hx509_write_file: %d", ret);322}323324der_free_octet_string(&c);325326if (sd)327_hx509_unmap_file_os(sd);328329return 0;330}331332static int333print_signer(hx509_context contextp, void *ctx, hx509_cert cert)334{335hx509_pem_header **header = ctx;336char *signer_name = NULL;337hx509_name name;338int ret;339340ret = hx509_cert_get_subject(cert, &name);341if (ret)342errx(1, "hx509_cert_get_subject");343344ret = hx509_name_to_string(name, &signer_name);345hx509_name_free(&name);346if (ret)347errx(1, "hx509_name_to_string");348349hx509_pem_add_header(header, "Signer", signer_name);350351free(signer_name);352return 0;353}354355int356cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv)357{358heim_oid contentType;359hx509_peer_info peer = NULL;360heim_octet_string o;361hx509_query *q;362hx509_lock lock;363hx509_certs store, pool, anchors, signer = NULL;364size_t sz;365void *p;366int ret, flags = 0;367char *infile, *outfile = NULL;368369memset(&contentType, 0, sizeof(contentType));370371infile = argv[0];372373if (argc < 2) {374asprintf(&outfile, "%s.%s", infile,375opt->pem_flag ? "pem" : "cms-signeddata");376if (outfile == NULL)377errx(1, "out of memory");378} else379outfile = argv[1];380381hx509_lock_init(context, &lock);382lock_strings(lock, &opt->pass_strings);383384ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store);385if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");386ret = hx509_certs_init(context, "MEMORY:cert-pool", 0, NULL, &pool);387if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");388389certs_strings(context, "store", store, lock, &opt->certificate_strings);390certs_strings(context, "pool", pool, lock, &opt->pool_strings);391392if (opt->anchors_strings.num_strings) {393ret = hx509_certs_init(context, "MEMORY:cert-anchors",3940, NULL, &anchors);395if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");396certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings);397} else398anchors = NULL;399400if (opt->detached_signature_flag)401flags |= HX509_CMS_SIGNATURE_DETACHED;402if (opt->id_by_name_flag)403flags |= HX509_CMS_SIGNATURE_ID_NAME;404if (!opt->signer_flag) {405flags |= HX509_CMS_SIGNATURE_NO_SIGNER;406407}408409if (opt->signer_flag) {410ret = hx509_query_alloc(context, &q);411if (ret)412errx(1, "hx509_query_alloc: %d", ret);413414hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);415hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);416417if (opt->signer_string)418hx509_query_match_friendly_name(q, opt->signer_string);419420ret = hx509_certs_filter(context, store, q, &signer);421hx509_query_free(context, q);422if (ret)423hx509_err(context, 1, ret, "hx509_certs_find");424}425if (!opt->embedded_certs_flag)426flags |= HX509_CMS_SIGNATURE_NO_CERTS;427if (opt->embed_leaf_only_flag)428flags |= HX509_CMS_SIGNATURE_LEAF_ONLY;429430ret = rk_undumpdata(infile, &p, &sz);431if (ret)432err(1, "map_file: %s: %d", infile, ret);433434if (opt->peer_alg_strings.num_strings)435peer_strings(context, &peer, &opt->peer_alg_strings);436437parse_oid(opt->content_type_string, &asn1_oid_id_pkcs7_data, &contentType);438439ret = hx509_cms_create_signed(context,440flags,441&contentType,442p,443sz,444NULL,445signer,446peer,447anchors,448pool,449&o);450if (ret)451hx509_err(context, 1, ret, "hx509_cms_create_signed: %d", ret);452453hx509_certs_free(&anchors);454hx509_certs_free(&pool);455hx509_certs_free(&store);456rk_xfree(p);457hx509_lock_free(lock);458hx509_peer_info_free(peer);459der_free_oid(&contentType);460461if (opt->content_info_flag) {462heim_octet_string wo;463464ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData, &o, &wo);465if (ret)466errx(1, "hx509_cms_wrap_ContentInfo: %d", ret);467468der_free_octet_string(&o);469o = wo;470}471472if (opt->pem_flag) {473hx509_pem_header *header = NULL;474FILE *f;475476hx509_pem_add_header(&header, "Content-disposition",477opt->detached_signature_flag ?478"detached" : "inline");479if (signer) {480ret = hx509_certs_iter_f(context, signer, print_signer, header);481if (ret)482hx509_err(context, 1, ret, "print signer");483}484485f = fopen(outfile, "w");486if (f == NULL)487err(1, "open %s", outfile);488489ret = hx509_pem_write(context, "CMS SIGNEDDATA", header, f,490o.data, o.length);491fclose(f);492hx509_pem_free_header(header);493if (ret)494errx(1, "hx509_pem_write: %d", ret);495496} else {497ret = _hx509_write_file(outfile, o.data, o.length);498if (ret)499errx(1, "hx509_write_file: %d", ret);500}501502hx509_certs_free(&signer);503free(o.data);504505return 0;506}507508int509cms_unenvelope(struct cms_unenvelope_options *opt, int argc, char **argv)510{511heim_oid contentType = { 0, NULL };512heim_octet_string o, co;513hx509_certs certs;514size_t sz;515void *p;516int ret;517hx509_lock lock;518int flags = 0;519520hx509_lock_init(context, &lock);521lock_strings(lock, &opt->pass_strings);522523ret = rk_undumpdata(argv[0], &p, &sz);524if (ret)525err(1, "map_file: %s: %d", argv[0], ret);526527co.data = p;528co.length = sz;529530if (opt->content_info_flag) {531heim_octet_string uwco;532heim_oid oid;533534ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL);535if (ret)536errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret);537538if (der_heim_oid_cmp(&oid, &asn1_oid_id_pkcs7_envelopedData) != 0)539errx(1, "Content is not SignedData");540der_free_oid(&oid);541542co = uwco;543}544545ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs);546if (ret)547errx(1, "hx509_certs_init: MEMORY: %d", ret);548549certs_strings(context, "store", certs, lock, &opt->certificate_strings);550551if (opt->allow_weak_crypto_flag)552flags |= HX509_CMS_UE_ALLOW_WEAK;553554ret = hx509_cms_unenvelope(context, certs, flags, co.data, co.length,555NULL, 0, &contentType, &o);556if (co.data != p)557der_free_octet_string(&co);558if (ret)559hx509_err(context, 1, ret, "hx509_cms_unenvelope");560561rk_xfree(p);562hx509_lock_free(lock);563hx509_certs_free(&certs);564der_free_oid(&contentType);565566ret = _hx509_write_file(argv[1], o.data, o.length);567if (ret)568errx(1, "hx509_write_file: %d", ret);569570der_free_octet_string(&o);571572return 0;573}574575int576cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv)577{578heim_oid contentType;579heim_octet_string o;580const heim_oid *enctype = NULL;581hx509_query *q;582hx509_certs certs;583hx509_cert cert;584int ret;585size_t sz;586void *p;587hx509_lock lock;588int flags = 0;589590memset(&contentType, 0, sizeof(contentType));591592hx509_lock_init(context, &lock);593lock_strings(lock, &opt->pass_strings);594595ret = rk_undumpdata(argv[0], &p, &sz);596if (ret)597err(1, "map_file: %s: %d", argv[0], ret);598599ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs);600if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");601602certs_strings(context, "store", certs, lock, &opt->certificate_strings);603604if (opt->allow_weak_crypto_flag)605flags |= HX509_CMS_EV_ALLOW_WEAK;606607if (opt->encryption_type_string) {608enctype = hx509_crypto_enctype_by_name(opt->encryption_type_string);609if (enctype == NULL)610errx(1, "encryption type: %s no found",611opt->encryption_type_string);612}613614ret = hx509_query_alloc(context, &q);615if (ret)616errx(1, "hx509_query_alloc: %d", ret);617618hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT);619620ret = hx509_certs_find(context, certs, q, &cert);621hx509_query_free(context, q);622if (ret)623errx(1, "hx509_certs_find: %d", ret);624625parse_oid(opt->content_type_string, &asn1_oid_id_pkcs7_data, &contentType);626627ret = hx509_cms_envelope_1(context, flags, cert, p, sz, enctype,628&contentType, &o);629if (ret)630errx(1, "hx509_cms_envelope_1: %d", ret);631632hx509_cert_free(cert);633hx509_certs_free(&certs);634rk_xfree(p);635der_free_oid(&contentType);636637if (opt->content_info_flag) {638heim_octet_string wo;639640ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_envelopedData, &o, &wo);641if (ret)642errx(1, "hx509_cms_wrap_ContentInfo: %d", ret);643644der_free_octet_string(&o);645o = wo;646}647648hx509_lock_free(lock);649650ret = _hx509_write_file(argv[1], o.data, o.length);651if (ret)652errx(1, "hx509_write_file: %d", ret);653654der_free_octet_string(&o);655656return 0;657}658659static void660print_certificate(hx509_context hxcontext, hx509_cert cert, int verbose)661{662const char *fn;663int ret;664665fn = hx509_cert_get_friendly_name(cert);666if (fn)667printf(" friendly name: %s\n", fn);668printf(" private key: %s\n",669_hx509_cert_private_key(cert) ? "yes" : "no");670671ret = hx509_print_cert(hxcontext, cert, NULL);672if (ret)673errx(1, "failed to print cert");674675if (verbose) {676hx509_validate_ctx vctx;677678hx509_validate_ctx_init(hxcontext, &vctx);679hx509_validate_ctx_set_print(vctx, hx509_print_stdout, stdout);680hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VALIDATE);681hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VERBOSE);682683hx509_validate_cert(hxcontext, vctx, cert);684685hx509_validate_ctx_free(vctx);686}687}688689690struct print_s {691int counter;692int verbose;693};694695static int696print_f(hx509_context hxcontext, void *ctx, hx509_cert cert)697{698struct print_s *s = ctx;699700printf("cert: %d\n", s->counter++);701print_certificate(context, cert, s->verbose);702703return 0;704}705706int707pcert_print(struct print_options *opt, int argc, char **argv)708{709hx509_certs certs;710hx509_lock lock;711struct print_s s;712713s.counter = 0;714s.verbose = opt->content_flag;715716hx509_lock_init(context, &lock);717lock_strings(lock, &opt->pass_strings);718719while(argc--) {720int ret;721ret = hx509_certs_init(context, argv[0], 0, lock, &certs);722if (ret) {723if (opt->never_fail_flag) {724printf("ignoreing failure: %d\n", ret);725continue;726}727hx509_err(context, 1, ret, "hx509_certs_init");728}729if (opt->info_flag)730hx509_certs_info(context, certs, NULL, NULL);731hx509_certs_iter_f(context, certs, print_f, &s);732hx509_certs_free(&certs);733argv++;734}735736hx509_lock_free(lock);737738return 0;739}740741742static int743validate_f(hx509_context hxcontext, void *ctx, hx509_cert c)744{745hx509_validate_cert(hxcontext, ctx, c);746return 0;747}748749int750pcert_validate(struct validate_options *opt, int argc, char **argv)751{752hx509_validate_ctx ctx;753hx509_certs certs;754hx509_lock lock;755756hx509_lock_init(context, &lock);757lock_strings(lock, &opt->pass_strings);758759hx509_validate_ctx_init(context, &ctx);760hx509_validate_ctx_set_print(ctx, hx509_print_stdout, stdout);761hx509_validate_ctx_add_flags(ctx, HX509_VALIDATE_F_VALIDATE);762763while(argc--) {764int ret;765ret = hx509_certs_init(context, argv[0], 0, lock, &certs);766if (ret)767errx(1, "hx509_certs_init: %d", ret);768hx509_certs_iter_f(context, certs, validate_f, ctx);769hx509_certs_free(&certs);770argv++;771}772hx509_validate_ctx_free(ctx);773774hx509_lock_free(lock);775776return 0;777}778779int780certificate_copy(struct certificate_copy_options *opt, int argc, char **argv)781{782hx509_certs certs;783hx509_lock inlock, outlock = NULL;784int ret;785786hx509_lock_init(context, &inlock);787lock_strings(inlock, &opt->in_pass_strings);788789if (opt->out_pass_string) {790hx509_lock_init(context, &outlock);791ret = hx509_lock_command_string(outlock, opt->out_pass_string);792if (ret)793errx(1, "hx509_lock_command_string: %s: %d",794opt->out_pass_string, ret);795}796797ret = hx509_certs_init(context, argv[argc - 1],798HX509_CERTS_CREATE, inlock, &certs);799if (ret)800hx509_err(context, 1, ret, "hx509_certs_init");801802while(argc-- > 1) {803int retx;804retx = hx509_certs_append(context, certs, inlock, argv[0]);805if (retx)806hx509_err(context, 1, retx, "hx509_certs_append");807argv++;808}809810ret = hx509_certs_store(context, certs, 0, outlock);811if (ret)812hx509_err(context, 1, ret, "hx509_certs_store");813814hx509_certs_free(&certs);815hx509_lock_free(inlock);816hx509_lock_free(outlock);817818return 0;819}820821struct verify {822hx509_verify_ctx ctx;823hx509_certs chain;824const char *hostname;825int errors;826int count;827};828829static int830verify_f(hx509_context hxcontext, void *ctx, hx509_cert c)831{832struct verify *v = ctx;833int ret;834835ret = hx509_verify_path(hxcontext, v->ctx, c, v->chain);836if (ret) {837char *s = hx509_get_error_string(hxcontext, ret);838printf("verify_path: %s: %d\n", s, ret);839hx509_free_error_string(s);840v->errors++;841} else {842v->count++;843printf("path ok\n");844}845846if (v->hostname) {847ret = hx509_verify_hostname(hxcontext, c, 0, HX509_HN_HOSTNAME,848v->hostname, NULL, 0);849if (ret) {850printf("verify_hostname: %d\n", ret);851v->errors++;852}853}854855return 0;856}857858int859pcert_verify(struct verify_options *opt, int argc, char **argv)860{861hx509_certs anchors, chain, certs;862hx509_revoke_ctx revoke_ctx;863hx509_verify_ctx ctx;864struct verify v;865int ret;866867memset(&v, 0, sizeof(v));868869if (opt->missing_revoke_flag)870hx509_context_set_missing_revoke(context, 1);871872ret = hx509_verify_init_ctx(context, &ctx);873if (ret)874hx509_err(context, 1, ret, "hx509_verify_init_ctx");875ret = hx509_certs_init(context, "MEMORY:anchors", 0, NULL, &anchors);876if (ret)877hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");878ret = hx509_certs_init(context, "MEMORY:chain", 0, NULL, &chain);879if (ret)880hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");881ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs);882if (ret)883hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");884885if (opt->allow_proxy_certificate_flag)886hx509_verify_set_proxy_certificate(ctx, 1);887888if (opt->time_string) {889const char *p;890struct tm tm;891time_t t;892893memset(&tm, 0, sizeof(tm));894895p = strptime (opt->time_string, "%Y-%m-%d", &tm);896if (p == NULL)897errx(1, "Failed to parse time %s, need to be on format %%Y-%%m-%%d",898opt->time_string);899900t = tm2time (tm, 0);901902hx509_verify_set_time(ctx, t);903}904905if (opt->hostname_string)906v.hostname = opt->hostname_string;907if (opt->max_depth_integer)908hx509_verify_set_max_depth(ctx, opt->max_depth_integer);909910ret = hx509_revoke_init(context, &revoke_ctx);911if (ret)912errx(1, "hx509_revoke_init: %d", ret);913914while(argc--) {915char *s = *argv++;916917if (strncmp(s, "chain:", 6) == 0) {918s += 6;919920ret = hx509_certs_append(context, chain, NULL, s);921if (ret)922hx509_err(context, 1, ret, "hx509_certs_append: chain: %s: %d", s, ret);923924} else if (strncmp(s, "anchor:", 7) == 0) {925s += 7;926927ret = hx509_certs_append(context, anchors, NULL, s);928if (ret)929hx509_err(context, 1, ret, "hx509_certs_append: anchor: %s: %d", s, ret);930931} else if (strncmp(s, "cert:", 5) == 0) {932s += 5;933934ret = hx509_certs_append(context, certs, NULL, s);935if (ret)936hx509_err(context, 1, ret, "hx509_certs_append: certs: %s: %d",937s, ret);938939} else if (strncmp(s, "crl:", 4) == 0) {940s += 4;941942ret = hx509_revoke_add_crl(context, revoke_ctx, s);943if (ret)944errx(1, "hx509_revoke_add_crl: %s: %d", s, ret);945946} else if (strncmp(s, "ocsp:", 4) == 0) {947s += 5;948949ret = hx509_revoke_add_ocsp(context, revoke_ctx, s);950if (ret)951errx(1, "hx509_revoke_add_ocsp: %s: %d", s, ret);952953} else {954errx(1, "unknown option to verify: `%s'\n", s);955}956}957958hx509_verify_attach_anchors(ctx, anchors);959hx509_verify_attach_revoke(ctx, revoke_ctx);960961v.ctx = ctx;962v.chain = chain;963964hx509_certs_iter_f(context, certs, verify_f, &v);965966hx509_verify_destroy_ctx(ctx);967968hx509_certs_free(&certs);969hx509_certs_free(&chain);970hx509_certs_free(&anchors);971972hx509_revoke_free(&revoke_ctx);973974975if (v.count == 0) {976printf("no certs verify at all\n");977return 1;978}979980if (v.errors) {981printf("failed verifing %d checks\n", v.errors);982return 1;983}984985return 0;986}987988int989query(struct query_options *opt, int argc, char **argv)990{991hx509_lock lock;992hx509_query *q;993hx509_certs certs;994hx509_cert c;995int ret;996997ret = hx509_query_alloc(context, &q);998if (ret)999errx(1, "hx509_query_alloc: %d", ret);10001001hx509_lock_init(context, &lock);1002lock_strings(lock, &opt->pass_strings);10031004ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs);1005if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");10061007while (argc > 0) {10081009ret = hx509_certs_append(context, certs, lock, argv[0]);1010if (ret)1011errx(1, "hx509_certs_append: %s: %d", argv[0], ret);10121013argc--;1014argv++;1015}10161017if (opt->friendlyname_string)1018hx509_query_match_friendly_name(q, opt->friendlyname_string);10191020if (opt->eku_string) {1021heim_oid oid;10221023parse_oid(opt->eku_string, NULL, &oid);10241025ret = hx509_query_match_eku(q, &oid);1026if (ret)1027errx(1, "hx509_query_match_eku: %d", ret);1028der_free_oid(&oid);1029}10301031if (opt->private_key_flag)1032hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);10331034if (opt->keyEncipherment_flag)1035hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT);10361037if (opt->digitalSignature_flag)1038hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);10391040if (opt->expr_string)1041hx509_query_match_expr(context, q, opt->expr_string);10421043ret = hx509_certs_find(context, certs, q, &c);1044hx509_query_free(context, q);1045if (ret)1046printf("no match found (%d)\n", ret);1047else {1048printf("match found\n");1049if (opt->print_flag)1050print_certificate(context, c, 0);1051}10521053hx509_cert_free(c);1054hx509_certs_free(&certs);10551056hx509_lock_free(lock);10571058return ret;1059}10601061int1062ocsp_fetch(struct ocsp_fetch_options *opt, int argc, char **argv)1063{1064hx509_certs reqcerts, pool;1065heim_octet_string req, nonce_data, *nonce = &nonce_data;1066hx509_lock lock;1067int i, ret;1068char *file;1069const char *url = "/";10701071memset(&nonce, 0, sizeof(nonce));10721073hx509_lock_init(context, &lock);1074lock_strings(lock, &opt->pass_strings);10751076/* no nonce */1077if (!opt->nonce_flag)1078nonce = NULL;10791080if (opt->url_path_string)1081url = opt->url_path_string;10821083ret = hx509_certs_init(context, "MEMORY:ocsp-pool", 0, NULL, &pool);1084if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");10851086certs_strings(context, "ocsp-pool", pool, lock, &opt->pool_strings);10871088file = argv[0];10891090ret = hx509_certs_init(context, "MEMORY:ocsp-req", 0, NULL, &reqcerts);1091if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");10921093for (i = 1; i < argc; i++) {1094ret = hx509_certs_append(context, reqcerts, lock, argv[i]);1095if (ret)1096errx(1, "hx509_certs_append: req: %s: %d", argv[i], ret);1097}10981099ret = hx509_ocsp_request(context, reqcerts, pool, NULL, NULL, &req, nonce);1100if (ret)1101errx(1, "hx509_ocsp_request: req: %d", ret);11021103{1104FILE *f;11051106f = fopen(file, "w");1107if (f == NULL)1108abort();11091110fprintf(f,1111"POST %s HTTP/1.0\r\n"1112"Content-Type: application/ocsp-request\r\n"1113"Content-Length: %ld\r\n"1114"\r\n",1115url,1116(unsigned long)req.length);1117fwrite(req.data, req.length, 1, f);1118fclose(f);1119}11201121if (nonce)1122der_free_octet_string(nonce);11231124hx509_certs_free(&reqcerts);1125hx509_certs_free(&pool);11261127return 0;1128}11291130int1131ocsp_print(struct ocsp_print_options *opt, int argc, char **argv)1132{1133hx509_revoke_ocsp_print(context, argv[0], stdout);1134return 0;1135}11361137/*1138*1139*/11401141static int1142verify_o(hx509_context hxcontext, void *ctx, hx509_cert c)1143{1144heim_octet_string *os = ctx;1145time_t expiration;1146int ret;11471148ret = hx509_ocsp_verify(context, 0, c, 0,1149os->data, os->length, &expiration);1150if (ret) {1151char *s = hx509_get_error_string(hxcontext, ret);1152printf("ocsp_verify: %s: %d\n", s, ret);1153hx509_free_error_string(s);1154} else1155printf("expire: %d\n", (int)expiration);11561157return ret;1158}115911601161int1162ocsp_verify(struct ocsp_verify_options *opt, int argc, char **argv)1163{1164hx509_lock lock;1165hx509_certs certs;1166int ret, i;1167heim_octet_string os;11681169hx509_lock_init(context, &lock);11701171if (opt->ocsp_file_string == NULL)1172errx(1, "no ocsp file given");11731174ret = _hx509_map_file_os(opt->ocsp_file_string, &os);1175if (ret)1176err(1, "map_file: %s: %d", argv[0], ret);11771178ret = hx509_certs_init(context, "MEMORY:test-certs", 0, NULL, &certs);1179if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");11801181for (i = 0; i < argc; i++) {1182ret = hx509_certs_append(context, certs, lock, argv[i]);1183if (ret)1184hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]);1185}11861187ret = hx509_certs_iter_f(context, certs, verify_o, &os);11881189hx509_certs_free(&certs);1190_hx509_unmap_file_os(&os);1191hx509_lock_free(lock);11921193return ret;1194}11951196static int1197read_private_key(const char *fn, hx509_private_key *key)1198{1199hx509_private_key *keys;1200hx509_certs certs;1201int ret;12021203*key = NULL;12041205ret = hx509_certs_init(context, fn, 0, NULL, &certs);1206if (ret)1207hx509_err(context, 1, ret, "hx509_certs_init: %s", fn);12081209ret = _hx509_certs_keys_get(context, certs, &keys);1210hx509_certs_free(&certs);1211if (ret)1212hx509_err(context, 1, ret, "hx509_certs_keys_get");1213if (keys[0] == NULL)1214errx(1, "no keys in key store: %s", fn);12151216*key = _hx509_private_key_ref(keys[0]);1217_hx509_certs_keys_free(context, keys);12181219return 0;1220}12211222static void1223get_key(const char *fn, const char *type, int optbits,1224hx509_private_key *signer)1225{1226int ret;12271228if (type) {1229BIGNUM *e;1230RSA *rsa;1231unsigned char *p0, *p;1232size_t len;1233int bits = 1024;12341235if (fn == NULL)1236errx(1, "no key argument, don't know here to store key");12371238if (strcasecmp(type, "rsa") != 0)1239errx(1, "can only handle rsa keys for now");12401241e = BN_new();1242BN_set_word(e, 0x10001);12431244if (optbits)1245bits = optbits;12461247rsa = RSA_new();1248if(rsa == NULL)1249errx(1, "RSA_new failed");12501251ret = RSA_generate_key_ex(rsa, bits, e, NULL);1252if(ret != 1)1253errx(1, "RSA_new failed");12541255BN_free(e);12561257len = i2d_RSAPrivateKey(rsa, NULL);12581259p0 = p = malloc(len);1260if (p == NULL)1261errx(1, "out of memory");12621263i2d_RSAPrivateKey(rsa, &p);12641265rk_dumpdata(fn, p0, len);1266memset(p0, 0, len);1267free(p0);12681269RSA_free(rsa);12701271} else if (fn == NULL)1272err(1, "no private key");12731274ret = read_private_key(fn, signer);1275if (ret)1276err(1, "read_private_key");1277}12781279int1280request_create(struct request_create_options *opt, int argc, char **argv)1281{1282heim_octet_string request;1283hx509_request req;1284int ret, i;1285hx509_private_key signer;1286SubjectPublicKeyInfo key;1287const char *outfile = argv[0];12881289memset(&key, 0, sizeof(key));1290memset(&signer, 0, sizeof(signer));12911292get_key(opt->key_string,1293opt->generate_key_string,1294opt->key_bits_integer,1295&signer);12961297hx509_request_init(context, &req);12981299if (opt->subject_string) {1300hx509_name name = NULL;13011302ret = hx509_parse_name(context, opt->subject_string, &name);1303if (ret)1304errx(1, "hx509_parse_name: %d\n", ret);1305hx509_request_set_name(context, req, name);13061307if (opt->verbose_flag) {1308char *s;1309hx509_name_to_string(name, &s);1310printf("%s\n", s);1311}1312hx509_name_free(&name);1313}13141315for (i = 0; i < opt->email_strings.num_strings; i++) {1316ret = _hx509_request_add_email(context, req,1317opt->email_strings.strings[i]);1318if (ret)1319hx509_err(context, 1, ret, "hx509_request_add_email");1320}13211322for (i = 0; i < opt->dnsname_strings.num_strings; i++) {1323ret = _hx509_request_add_dns_name(context, req,1324opt->dnsname_strings.strings[i]);1325if (ret)1326hx509_err(context, 1, ret, "hx509_request_add_dns_name");1327}132813291330ret = hx509_private_key2SPKI(context, signer, &key);1331if (ret)1332errx(1, "hx509_private_key2SPKI: %d\n", ret);13331334ret = hx509_request_set_SubjectPublicKeyInfo(context,1335req,1336&key);1337free_SubjectPublicKeyInfo(&key);1338if (ret)1339hx509_err(context, 1, ret, "hx509_request_set_SubjectPublicKeyInfo");13401341ret = _hx509_request_to_pkcs10(context,1342req,1343signer,1344&request);1345if (ret)1346hx509_err(context, 1, ret, "_hx509_request_to_pkcs10");13471348hx509_private_key_free(&signer);1349hx509_request_free(&req);13501351if (ret == 0)1352rk_dumpdata(outfile, request.data, request.length);1353der_free_octet_string(&request);13541355return 0;1356}13571358int1359request_print(struct request_print_options *opt, int argc, char **argv)1360{1361int ret, i;13621363printf("request print\n");13641365for (i = 0; i < argc; i++) {1366hx509_request req;13671368ret = _hx509_request_parse(context, argv[i], &req);1369if (ret)1370hx509_err(context, 1, ret, "parse_request: %s", argv[i]);13711372ret = _hx509_request_print(context, req, stdout);1373hx509_request_free(&req);1374if (ret)1375hx509_err(context, 1, ret, "Failed to print file %s", argv[i]);1376}13771378return 0;1379}13801381int1382info(void *opt, int argc, char **argv)1383{13841385ENGINE_add_conf_module();13861387{1388const RSA_METHOD *m = RSA_get_default_method();1389if (m != NULL)1390printf("rsa: %s\n", RSA_meth_get0_name(m));1391}1392{1393const DH_METHOD *m = DH_get_default_method();1394if (m != NULL)1395printf("dh: %s\n", DH_meth_get0_name(m));1396}1397#ifdef HAVE_OPENSSL1398{1399printf("ecdsa: ECDSA_METHOD-not-export\n");1400}1401#else1402{1403printf("ecdsa: hcrypto null\n");1404}1405#endif1406{1407int ret = RAND_status();1408printf("rand: %s\n", ret == 1 ? "ok" : "not available");1409}14101411return 0;1412}14131414int1415random_data(void *opt, int argc, char **argv)1416{1417void *ptr;1418int len, ret;14191420len = parse_bytes(argv[0], "byte");1421if (len <= 0) {1422fprintf(stderr, "bad argument to random-data\n");1423return 1;1424}14251426ptr = malloc(len);1427if (ptr == NULL) {1428fprintf(stderr, "out of memory\n");1429return 1;1430}14311432ret = RAND_bytes(ptr, len);1433if (ret != 1) {1434free(ptr);1435fprintf(stderr, "did not get cryptographic strong random\n");1436return 1;1437}14381439fwrite(ptr, len, 1, stdout);1440fflush(stdout);14411442free(ptr);14431444return 0;1445}14461447int1448crypto_available(struct crypto_available_options *opt, int argc, char **argv)1449{1450AlgorithmIdentifier *val;1451unsigned int len, i;1452int ret, type = HX509_SELECT_ALL;14531454if (opt->type_string) {1455if (strcmp(opt->type_string, "all") == 0)1456type = HX509_SELECT_ALL;1457else if (strcmp(opt->type_string, "digest") == 0)1458type = HX509_SELECT_DIGEST;1459else if (strcmp(opt->type_string, "public-sig") == 0)1460type = HX509_SELECT_PUBLIC_SIG;1461else if (strcmp(opt->type_string, "secret") == 0)1462type = HX509_SELECT_SECRET_ENC;1463else1464errx(1, "unknown type: %s", opt->type_string);1465}14661467ret = hx509_crypto_available(context, type, NULL, &val, &len);1468if (ret)1469errx(1, "hx509_crypto_available");14701471for (i = 0; i < len; i++) {1472char *s;1473der_print_heim_oid (&val[i].algorithm, '.', &s);1474printf("%s\n", s);1475free(s);1476}14771478hx509_crypto_free_algs(val, len);14791480return 0;1481}14821483int1484crypto_select(struct crypto_select_options *opt, int argc, char **argv)1485{1486hx509_peer_info peer = NULL;1487AlgorithmIdentifier selected;1488int ret, type = HX509_SELECT_DIGEST;1489char *s;14901491if (opt->type_string) {1492if (strcmp(opt->type_string, "digest") == 0)1493type = HX509_SELECT_DIGEST;1494else if (strcmp(opt->type_string, "public-sig") == 0)1495type = HX509_SELECT_PUBLIC_SIG;1496else if (strcmp(opt->type_string, "secret") == 0)1497type = HX509_SELECT_SECRET_ENC;1498else1499errx(1, "unknown type: %s", opt->type_string);1500}15011502if (opt->peer_cmstype_strings.num_strings)1503peer_strings(context, &peer, &opt->peer_cmstype_strings);15041505ret = hx509_crypto_select(context, type, NULL, peer, &selected);1506if (ret)1507errx(1, "hx509_crypto_available");15081509der_print_heim_oid (&selected.algorithm, '.', &s);1510printf("%s\n", s);1511free(s);1512free_AlgorithmIdentifier(&selected);15131514hx509_peer_info_free(peer);15151516return 0;1517}15181519int1520hxtool_hex(struct hex_options *opt, int argc, char **argv)1521{15221523if (opt->decode_flag) {1524char buf[1024], buf2[1024], *p;1525ssize_t len;15261527while(fgets(buf, sizeof(buf), stdin) != NULL) {1528buf[strcspn(buf, "\r\n")] = '\0';1529p = buf;1530while(isspace(*(unsigned char *)p))1531p++;1532len = hex_decode(p, buf2, strlen(p));1533if (len < 0)1534errx(1, "hex_decode failed");1535if (fwrite(buf2, 1, len, stdout) != (size_t)len)1536errx(1, "fwrite failed");1537}1538} else {1539char buf[28], *p;1540ssize_t len;15411542while((len = fread(buf, 1, sizeof(buf), stdin)) != 0) {1543len = hex_encode(buf, len, &p);1544if (len < 0)1545continue;1546fprintf(stdout, "%s\n", p);1547free(p);1548}1549}1550return 0;1551}15521553struct cert_type_opt {1554int pkinit;1555};155615571558static int1559https_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt)1560{1561return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth);1562}15631564static int1565https_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt)1566{1567return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_clientAuth);1568}15691570static int1571peap_server(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt)1572{1573return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_serverAuth);1574}15751576static int1577pkinit_kdc(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt)1578{1579opt->pkinit++;1580return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkkdcekuoid);1581}15821583static int1584pkinit_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt)1585{1586int ret;15871588opt->pkinit++;15891590ret = hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkekuoid);1591if (ret)1592return ret;15931594ret = hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_ms_client_authentication);1595if (ret)1596return ret;15971598return hx509_ca_tbs_add_eku(context, tbs, &asn1_oid_id_pkinit_ms_eku);1599}16001601static int1602email_client(hx509_context contextp, hx509_ca_tbs tbs, struct cert_type_opt *opt)1603{1604return hx509_ca_tbs_add_eku(contextp, tbs, &asn1_oid_id_pkix_kp_emailProtection);1605}16061607struct {1608const char *type;1609const char *desc;1610int (*eval)(hx509_context, hx509_ca_tbs, struct cert_type_opt *);1611} certtypes[] = {1612{1613"https-server",1614"Used for HTTPS server and many other TLS server certificate types",1615https_server1616},1617{1618"https-client",1619"Used for HTTPS client certificates",1620https_client1621},1622{1623"email-client",1624"Certificate will be use for email",1625email_client1626},1627{1628"pkinit-client",1629"Certificate used for Kerberos PK-INIT client certificates",1630pkinit_client1631},1632{1633"pkinit-kdc",1634"Certificates used for Kerberos PK-INIT KDC certificates",1635pkinit_kdc1636},1637{1638"peap-server",1639"Certificate used for Radius PEAP (Protected EAP)",1640peap_server1641}1642};16431644static void1645print_eval_types(FILE *out)1646{1647rtbl_t table;1648unsigned i;16491650table = rtbl_create();1651rtbl_add_column_by_id (table, 0, "Name", 0);1652rtbl_add_column_by_id (table, 1, "Description", 0);16531654for (i = 0; i < sizeof(certtypes)/sizeof(certtypes[0]); i++) {1655rtbl_add_column_entry_by_id(table, 0, certtypes[i].type);1656rtbl_add_column_entry_by_id(table, 1, certtypes[i].desc);1657}16581659rtbl_format (table, out);1660rtbl_destroy (table);1661}16621663static int1664eval_types(hx509_context contextp,1665hx509_ca_tbs tbs,1666const struct certificate_sign_options *opt)1667{1668struct cert_type_opt ctopt;1669int i;1670size_t j;1671int ret;16721673memset(&ctopt, 0, sizeof(ctopt));16741675for (i = 0; i < opt->type_strings.num_strings; i++) {1676const char *type = opt->type_strings.strings[i];16771678for (j = 0; j < sizeof(certtypes)/sizeof(certtypes[0]); j++) {1679if (strcasecmp(type, certtypes[j].type) == 0) {1680ret = (*certtypes[j].eval)(contextp, tbs, &ctopt);1681if (ret)1682hx509_err(contextp, 1, ret,1683"Failed to evaluate cert type %s", type);1684break;1685}1686}1687if (j >= sizeof(certtypes)/sizeof(certtypes[0])) {1688fprintf(stderr, "Unknown certificate type %s\n\n", type);1689fprintf(stderr, "Available types:\n");1690print_eval_types(stderr);1691exit(1);1692}1693}16941695if (opt->pk_init_principal_string) {1696if (!ctopt.pkinit)1697errx(1, "pk-init principal given but no pk-init oid");16981699ret = hx509_ca_tbs_add_san_pkinit(contextp, tbs,1700opt->pk_init_principal_string);1701if (ret)1702hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_pkinit");1703}17041705if (opt->ms_upn_string) {1706if (!ctopt.pkinit)1707errx(1, "MS upn given but no pk-init oid");17081709ret = hx509_ca_tbs_add_san_ms_upn(contextp, tbs, opt->ms_upn_string);1710if (ret)1711hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_ms_upn");1712}171317141715for (i = 0; i < opt->hostname_strings.num_strings; i++) {1716const char *hostname = opt->hostname_strings.strings[i];17171718ret = hx509_ca_tbs_add_san_hostname(contextp, tbs, hostname);1719if (ret)1720hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname");1721}17221723for (i = 0; i < opt->email_strings.num_strings; i++) {1724const char *email = opt->email_strings.strings[i];17251726ret = hx509_ca_tbs_add_san_rfc822name(contextp, tbs, email);1727if (ret)1728hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_hostname");17291730ret = hx509_ca_tbs_add_eku(contextp, tbs,1731&asn1_oid_id_pkix_kp_emailProtection);1732if (ret)1733hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_eku");1734}17351736if (opt->jid_string) {1737ret = hx509_ca_tbs_add_san_jid(contextp, tbs, opt->jid_string);1738if (ret)1739hx509_err(contextp, 1, ret, "hx509_ca_tbs_add_san_jid");1740}17411742return 0;1743}17441745int1746hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)1747{1748int ret;1749hx509_ca_tbs tbs;1750hx509_cert signer = NULL, cert = NULL;1751hx509_private_key private_key = NULL;1752hx509_private_key cert_key = NULL;1753hx509_name subject = NULL;1754SubjectPublicKeyInfo spki;1755int delta = 0;17561757memset(&spki, 0, sizeof(spki));17581759if (opt->ca_certificate_string == NULL && !opt->self_signed_flag)1760errx(1, "--ca-certificate argument missing (not using --self-signed)");1761if (opt->ca_private_key_string == NULL && opt->generate_key_string == NULL && opt->self_signed_flag)1762errx(1, "--ca-private-key argument missing (using --self-signed)");1763if (opt->certificate_string == NULL)1764errx(1, "--certificate argument missing");17651766if (opt->template_certificate_string) {1767if (opt->template_fields_string == NULL)1768errx(1, "--template-certificate not no --template-fields");1769}17701771if (opt->lifetime_string) {1772delta = parse_time(opt->lifetime_string, "day");1773if (delta < 0)1774errx(1, "Invalid lifetime: %s", opt->lifetime_string);1775}17761777if (opt->ca_certificate_string) {1778hx509_certs cacerts = NULL;1779hx509_query *q;17801781ret = hx509_certs_init(context, opt->ca_certificate_string, 0,1782NULL, &cacerts);1783if (ret)1784hx509_err(context, 1, ret,1785"hx509_certs_init: %s", opt->ca_certificate_string);17861787ret = hx509_query_alloc(context, &q);1788if (ret)1789errx(1, "hx509_query_alloc: %d", ret);17901791hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);1792if (!opt->issue_proxy_flag)1793hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN);17941795ret = hx509_certs_find(context, cacerts, q, &signer);1796hx509_query_free(context, q);1797hx509_certs_free(&cacerts);1798if (ret)1799hx509_err(context, 1, ret, "no CA certificate found");1800} else if (opt->self_signed_flag) {1801if (opt->generate_key_string == NULL1802&& opt->ca_private_key_string == NULL)1803errx(1, "no signing private key");18041805if (opt->req_string)1806errx(1, "can't be self-signing and have a request at the same time");1807} else1808errx(1, "missing ca key");18091810if (opt->ca_private_key_string) {18111812ret = read_private_key(opt->ca_private_key_string, &private_key);1813if (ret)1814err(1, "read_private_key");18151816ret = hx509_private_key2SPKI(context, private_key, &spki);1817if (ret)1818errx(1, "hx509_private_key2SPKI: %d\n", ret);18191820if (opt->self_signed_flag)1821cert_key = private_key;1822}18231824if (opt->req_string) {1825hx509_request req;18261827ret = _hx509_request_parse(context, opt->req_string, &req);1828if (ret)1829hx509_err(context, 1, ret, "parse_request: %s", opt->req_string);1830ret = hx509_request_get_name(context, req, &subject);1831if (ret)1832hx509_err(context, 1, ret, "get name");1833ret = hx509_request_get_SubjectPublicKeyInfo(context, req, &spki);1834if (ret)1835hx509_err(context, 1, ret, "get spki");1836hx509_request_free(&req);1837}18381839if (opt->generate_key_string) {1840struct hx509_generate_private_context *keyctx;18411842ret = _hx509_generate_private_key_init(context,1843&asn1_oid_id_pkcs1_rsaEncryption,1844&keyctx);1845if (ret)1846hx509_err(context, 1, ret, "generate private key");18471848if (opt->issue_ca_flag)1849_hx509_generate_private_key_is_ca(context, keyctx);18501851if (opt->key_bits_integer)1852_hx509_generate_private_key_bits(context, keyctx,1853opt->key_bits_integer);18541855ret = _hx509_generate_private_key(context, keyctx,1856&cert_key);1857_hx509_generate_private_key_free(&keyctx);1858if (ret)1859hx509_err(context, 1, ret, "generate private key");18601861ret = hx509_private_key2SPKI(context, cert_key, &spki);1862if (ret)1863errx(1, "hx509_private_key2SPKI: %d\n", ret);18641865if (opt->self_signed_flag)1866private_key = cert_key;1867}18681869if (opt->certificate_private_key_string) {1870ret = read_private_key(opt->certificate_private_key_string, &cert_key);1871if (ret)1872err(1, "read_private_key for certificate");1873}18741875if (opt->subject_string) {1876if (subject)1877hx509_name_free(&subject);1878ret = hx509_parse_name(context, opt->subject_string, &subject);1879if (ret)1880hx509_err(context, 1, ret, "hx509_parse_name");1881}18821883/*1884*1885*/18861887ret = hx509_ca_tbs_init(context, &tbs);1888if (ret)1889hx509_err(context, 1, ret, "hx509_ca_tbs_init");18901891if (opt->template_certificate_string) {1892hx509_cert template;1893hx509_certs tcerts;1894int flags;18951896ret = hx509_certs_init(context, opt->template_certificate_string, 0,1897NULL, &tcerts);1898if (ret)1899hx509_err(context, 1, ret,1900"hx509_certs_init: %s", opt->template_certificate_string);19011902ret = hx509_get_one_cert(context, tcerts, &template);19031904hx509_certs_free(&tcerts);1905if (ret)1906hx509_err(context, 1, ret, "no template certificate found");19071908flags = parse_units(opt->template_fields_string,1909hx509_ca_tbs_template_units(), "");19101911ret = hx509_ca_tbs_set_template(context, tbs, flags, template);1912if (ret)1913hx509_err(context, 1, ret, "hx509_ca_tbs_set_template");19141915hx509_cert_free(template);1916}19171918if (opt->serial_number_string) {1919heim_integer serialNumber;19201921ret = der_parse_hex_heim_integer(opt->serial_number_string,1922&serialNumber);1923if (ret)1924err(1, "der_parse_hex_heim_integer");1925ret = hx509_ca_tbs_set_serialnumber(context, tbs, &serialNumber);1926if (ret)1927hx509_err(context, 1, ret, "hx509_ca_tbs_init");1928der_free_heim_integer(&serialNumber);1929}19301931if (spki.subjectPublicKey.length) {1932ret = hx509_ca_tbs_set_spki(context, tbs, &spki);1933if (ret)1934hx509_err(context, 1, ret, "hx509_ca_tbs_set_spki");1935}19361937if (subject) {1938ret = hx509_ca_tbs_set_subject(context, tbs, subject);1939if (ret)1940hx509_err(context, 1, ret, "hx509_ca_tbs_set_subject");1941}19421943if (opt->crl_uri_string) {1944ret = hx509_ca_tbs_add_crl_dp_uri(context, tbs,1945opt->crl_uri_string, NULL);1946if (ret)1947hx509_err(context, 1, ret, "hx509_ca_tbs_add_crl_dp_uri");1948}19491950eval_types(context, tbs, opt);19511952if (opt->issue_ca_flag) {1953ret = hx509_ca_tbs_set_ca(context, tbs, opt->path_length_integer);1954if (ret)1955hx509_err(context, 1, ret, "hx509_ca_tbs_set_ca");1956}1957if (opt->issue_proxy_flag) {1958ret = hx509_ca_tbs_set_proxy(context, tbs, opt->path_length_integer);1959if (ret)1960hx509_err(context, 1, ret, "hx509_ca_tbs_set_proxy");1961}1962if (opt->domain_controller_flag) {1963hx509_ca_tbs_set_domaincontroller(context, tbs);1964if (ret)1965hx509_err(context, 1, ret, "hx509_ca_tbs_set_domaincontroller");1966}19671968if (delta) {1969ret = hx509_ca_tbs_set_notAfter_lifetime(context, tbs, delta);1970if (ret)1971hx509_err(context, 1, ret, "hx509_ca_tbs_set_notAfter_lifetime");1972}19731974if (opt->self_signed_flag) {1975ret = hx509_ca_sign_self(context, tbs, private_key, &cert);1976if (ret)1977hx509_err(context, 1, ret, "hx509_ca_sign_self");1978} else {1979ret = hx509_ca_sign(context, tbs, signer, &cert);1980if (ret)1981hx509_err(context, 1, ret, "hx509_ca_sign");1982}19831984if (cert_key) {1985ret = _hx509_cert_assign_key(cert, cert_key);1986if (ret)1987hx509_err(context, 1, ret, "_hx509_cert_assign_key");1988}19891990{1991hx509_certs certs;19921993ret = hx509_certs_init(context, opt->certificate_string,1994HX509_CERTS_CREATE, NULL, &certs);1995if (ret)1996hx509_err(context, 1, ret, "hx509_certs_init");19971998ret = hx509_certs_add(context, certs, cert);1999if (ret)2000hx509_err(context, 1, ret, "hx509_certs_add");20012002ret = hx509_certs_store(context, certs, 0, NULL);2003if (ret)2004hx509_err(context, 1, ret, "hx509_certs_store");20052006hx509_certs_free(&certs);2007}20082009if (subject)2010hx509_name_free(&subject);2011if (signer)2012hx509_cert_free(signer);2013hx509_cert_free(cert);2014free_SubjectPublicKeyInfo(&spki);20152016if (private_key != cert_key)2017hx509_private_key_free(&private_key);2018hx509_private_key_free(&cert_key);20192020hx509_ca_tbs_free(&tbs);20212022return 0;2023}20242025static int2026test_one_cert(hx509_context hxcontext, void *ctx, hx509_cert cert)2027{2028heim_octet_string sd, c;2029hx509_verify_ctx vctx = ctx;2030hx509_certs signer = NULL;2031heim_oid type;2032int ret;20332034if (_hx509_cert_private_key(cert) == NULL)2035return 0;20362037ret = hx509_cms_create_signed_1(context, 0, NULL, NULL, 0,2038NULL, cert, NULL, NULL, NULL, &sd);2039if (ret)2040errx(1, "hx509_cms_create_signed_1");20412042ret = hx509_cms_verify_signed(context, vctx, 0, sd.data, sd.length,2043NULL, NULL, &type, &c, &signer);2044free(sd.data);2045if (ret)2046hx509_err(context, 1, ret, "hx509_cms_verify_signed");20472048printf("create-signature verify-sigature done\n");20492050free(c.data);20512052return 0;2053}20542055int2056test_crypto(struct test_crypto_options *opt, int argc, char ** argv)2057{2058hx509_verify_ctx vctx;2059hx509_certs certs;2060hx509_lock lock;2061int i, ret;20622063hx509_lock_init(context, &lock);2064lock_strings(lock, &opt->pass_strings);20652066ret = hx509_certs_init(context, "MEMORY:test-crypto", 0, NULL, &certs);2067if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY");20682069for (i = 0; i < argc; i++) {2070ret = hx509_certs_append(context, certs, lock, argv[i]);2071if (ret)2072hx509_err(context, 1, ret, "hx509_certs_append");2073}20742075ret = hx509_verify_init_ctx(context, &vctx);2076if (ret)2077hx509_err(context, 1, ret, "hx509_verify_init_ctx");20782079hx509_verify_attach_anchors(vctx, certs);20802081ret = hx509_certs_iter_f(context, certs, test_one_cert, vctx);2082if (ret)2083hx509_err(context, 1, ret, "hx509_cert_iter");20842085hx509_certs_free(&certs);20862087return 0;2088}20892090int2091statistic_print(struct statistic_print_options*opt, int argc, char **argv)2092{2093int type = 0;20942095if (stat_file_string == NULL)2096errx(1, "no stat file");20972098if (opt->type_integer)2099type = opt->type_integer;21002101hx509_query_unparse_stats(context, type, stdout);2102return 0;2103}21042105/*2106*2107*/21082109int2110crl_sign(struct crl_sign_options *opt, int argc, char **argv)2111{2112hx509_crl crl;2113heim_octet_string os;2114hx509_cert signer = NULL;2115hx509_lock lock;2116int ret;21172118hx509_lock_init(context, &lock);2119lock_strings(lock, &opt->pass_strings);21202121ret = hx509_crl_alloc(context, &crl);2122if (ret)2123errx(1, "crl alloc");21242125if (opt->signer_string == NULL)2126errx(1, "signer missing");21272128{2129hx509_certs certs = NULL;2130hx509_query *q;21312132ret = hx509_certs_init(context, opt->signer_string, 0,2133NULL, &certs);2134if (ret)2135hx509_err(context, 1, ret,2136"hx509_certs_init: %s", opt->signer_string);21372138ret = hx509_query_alloc(context, &q);2139if (ret)2140hx509_err(context, 1, ret, "hx509_query_alloc: %d", ret);21412142hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);21432144ret = hx509_certs_find(context, certs, q, &signer);2145hx509_query_free(context, q);2146hx509_certs_free(&certs);2147if (ret)2148hx509_err(context, 1, ret, "no signer certificate found");2149}21502151if (opt->lifetime_string) {2152int delta;21532154delta = parse_time(opt->lifetime_string, "day");2155if (delta < 0)2156errx(1, "Invalid lifetime: %s", opt->lifetime_string);21572158hx509_crl_lifetime(context, crl, delta);2159}21602161{2162hx509_certs revoked = NULL;2163int i;21642165ret = hx509_certs_init(context, "MEMORY:revoked-certs", 0,2166NULL, &revoked);2167if (ret)2168hx509_err(context, 1, ret,2169"hx509_certs_init: MEMORY cert");21702171for (i = 0; i < argc; i++) {2172ret = hx509_certs_append(context, revoked, lock, argv[i]);2173if (ret)2174hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]);2175}21762177hx509_crl_add_revoked_certs(context, crl, revoked);2178hx509_certs_free(&revoked);2179}21802181hx509_crl_sign(context, signer, crl, &os);21822183if (opt->crl_file_string)2184rk_dumpdata(opt->crl_file_string, os.data, os.length);21852186free(os.data);21872188hx509_crl_free(context, &crl);2189hx509_cert_free(signer);2190hx509_lock_free(lock);21912192return 0;2193}21942195/*2196*2197*/21982199int2200help(void *opt, int argc, char **argv)2201{2202sl_slc_help(commands, argc, argv);2203return 0;2204}22052206int2207main(int argc, char **argv)2208{2209int ret, optidx = 0;22102211setprogname (argv[0]);22122213if(getarg(args, num_args, argc, argv, &optidx))2214usage(1);2215if(help_flag)2216usage(0);2217if(version_flag) {2218print_version(NULL);2219exit(0);2220}2221argv += optidx;2222argc -= optidx;22232224if (argc == 0)2225usage(1);22262227ret = hx509_context_init(&context);2228if (ret)2229errx(1, "hx509_context_init failed with %d", ret);22302231if (stat_file_string)2232hx509_query_statistic_file(context, stat_file_string);22332234ret = sl_command(commands, argc, argv);2235if(ret == -1)2236warnx ("unrecognized command: %s", argv[0]);22372238hx509_context_free(&context);22392240return ret;2241}224222432244