diff options
author | Rajeev Ranjan <ranjan.rajeev@siemens.com> | 2024-05-15 13:11:09 +0200 |
---|---|---|
committer | Dr. David von Oheimb <dev@ddvo.net> | 2024-06-20 13:38:13 +0200 |
commit | 6a3579e190fd52f49b1e5eafb4d002684eb0ff42 (patch) | |
tree | 7041c8caf1fb6a5e0b640f084ad9fad312fdf84c /apps | |
parent | e2a4d68a03b8a3576b0fe917a602b3a283d105a5 (diff) | |
download | openssl-6a3579e190fd52f49b1e5eafb4d002684eb0ff42.zip openssl-6a3579e190fd52f49b1e5eafb4d002684eb0ff42.tar.gz openssl-6a3579e190fd52f49b1e5eafb4d002684eb0ff42.tar.bz2 |
CMP: add support for requesting cert template using genm/genp
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/24409)
Diffstat (limited to 'apps')
-rw-r--r-- | apps/cmp.c | 177 | ||||
-rw-r--r-- | apps/lib/cmp_mock_srv.c | 44 |
2 files changed, 220 insertions, 1 deletions
@@ -97,6 +97,8 @@ static char *opt_oldwithnew = NULL; static char *opt_crlcert = NULL; static char *opt_oldcrl = NULL; static char *opt_crlout = NULL; +static char *opt_template = NULL; +static char *opt_keyspec = NULL; /* client authentication */ static char *opt_ref = NULL; @@ -225,6 +227,7 @@ typedef enum OPTION_choice { OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY, OPT_CMD, OPT_INFOTYPE, OPT_PROFILE, OPT_GENINFO, + OPT_TEMPLATE, OPT_KEYSPEC, OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT, OPT_DAYS, OPT_REQEXTS, @@ -313,6 +316,10 @@ const OPTIONS cmp_options[] = { "Comma-separated list of OID and value to place in generalInfo PKIHeader"}, {OPT_MORE_STR, 0, 0, "of form <OID>:int:<n> or <OID>:str:<s>, e.g. \'1.2.3.4:int:56789, id-kp:str:name'"}, + { "template", OPT_TEMPLATE, 's', + "File to save certTemplate received in genp of type certReqTemplate"}, + { "keyspec", OPT_KEYSPEC, 's', + "Optional file to save Key specification received in genp of type certReqTemplate"}, OPT_SECTION("Certificate enrollment"), {"newkey", OPT_NEWKEY, 's', @@ -620,6 +627,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {&opt_config}, {&opt_section}, {(char **)&opt_verbosity}, {&opt_cmd_s}, {&opt_infotype_s}, {&opt_profile}, {&opt_geninfo}, + {&opt_template}, {&opt_keyspec}, {&opt_newkey}, {&opt_newkeypass}, {&opt_subject}, {(char **)&opt_days}, {&opt_reqexts}, @@ -2176,6 +2184,17 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) if (opt_oldwithnew != NULL) CMP_warn1("-oldwithnew %s", msg); } + if (opt_cmd != CMP_GENM || opt_infotype != NID_id_it_certReqTemplate) { + const char *msg = "option is ignored unless -cmd 'genm' and -infotype 'certReqTemplate' is given"; + + if (opt_template != NULL) + CMP_warn1("-template %s", msg); + if (opt_keyspec != NULL) + CMP_warn1("-keyspec %s", msg); + } else { + if (opt_template == NULL) + CMP_err("missing -template option for genm with infotype certReqTemplate"); + } if (!setup_verification_ctx(ctx)) goto err; @@ -2420,6 +2439,57 @@ static int save_crl_or_delete(X509_CRL *crl, const char *file, const char *desc) return (crl == NULL) ? delete_file(file, desc) : save_crl(crl, file, desc); } +static int save_template(const char *file, const OSSL_CRMF_CERTTEMPLATE *tmpl) +{ + BIO *bio = BIO_new_file(file, "wb"); + + if (bio == NULL) { + CMP_err1("error saving certTemplate from genp: cannot open file %s", + file); + return 0; + } + if (!ASN1_i2d_bio_of(OSSL_CRMF_CERTTEMPLATE, i2d_OSSL_CRMF_CERTTEMPLATE, + bio, tmpl)) { + CMP_err1("error saving certTemplate from genp: cannot write file %s", + file); + return 0; + } else { + CMP_info1("stored certTemplate from genp to file '%s'", file); + } + BIO_free(bio); + return 1; +} + +static int save_keyspec(const char *file, const OSSL_CMP_ATAVS *keyspec) +{ + BIO *bio = BIO_new_file(file, "wb"); + + if (bio == NULL) { + CMP_err1("error saving keySpec from genp: cannot open file %s", file); + return 0; + } + + if (!ASN1_i2d_bio_of(OSSL_CMP_ATAVS, i2d_OSSL_CMP_ATAVS, bio, keyspec)) { + CMP_err1("error saving keySpec from genp: cannot write file %s", file); + return 0; + } else { + CMP_info1("stored keySpec from genp to file '%s'", file); + } + BIO_free(bio); + return 1; +} + +static const char *nid_name(int nid) +{ + const char *name = OBJ_nid2ln(nid); + + if (name == NULL) + name = OBJ_nid2sn(nid); + if (name == NULL) + name = "<unknown OID>"; + return name; +} + static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs) { int i, ret = 1; @@ -2845,6 +2915,12 @@ static int get_opts(int argc, char **argv) case OPT_GENINFO: opt_geninfo = opt_str(); break; + case OPT_TEMPLATE: + opt_template = opt_str(); + break; + case OPT_KEYSPEC: + opt_keyspec = opt_str(); + break; case OPT_NEWKEY: opt_newkey = opt_str(); @@ -3154,6 +3230,71 @@ static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) } #endif +static void print_keyspec(OSSL_CMP_ATAVS *keySpec) +{ + const char *desc = "specifications contained in keySpec from genp"; + BIO *mem; + int i; + const char *p; + long len; + + if (keySpec == NULL) { + CMP_info1("No %s", desc); + return; + } + + mem = BIO_new(BIO_s_mem()); + if (mem == NULL) { + CMP_err1("Out of memory - cannot dump key %s", desc); + return; + } + BIO_printf(mem, "Key %s:\n", desc); + + for (i = 0; i < sk_OSSL_CMP_ATAV_num(keySpec); i++) { + OSSL_CMP_ATAV *atav = sk_OSSL_CMP_ATAV_value(keySpec, i); + ASN1_OBJECT *type = OSSL_CMP_ATAV_get0_type(atav /* may be NULL */); + int nid = OBJ_obj2nid(type); + + switch (nid) { + case NID_id_regCtrl_algId: + { + X509_ALGOR *alg = OSSL_CMP_ATAV_get0_algId(atav); + const ASN1_OBJECT *oid; + int paramtype; + const void *param; + + X509_ALGOR_get0(&oid, ¶mtype, ¶m, alg); + BIO_printf(mem, "Key algorithm: "); + i2a_ASN1_OBJECT(mem, oid); + if (paramtype == V_ASN1_UNDEF || alg->parameter == NULL) { + BIO_printf(mem, "\n"); + } else { + BIO_printf(mem, " - "); + ASN1_item_print(mem, (ASN1_VALUE *)alg, + 0, ASN1_ITEM_rptr(X509_ALGOR), NULL); + } + } + break; + case NID_id_regCtrl_rsaKeyLen: + BIO_printf(mem, "Key algorithm: RSA %d\n", + OSSL_CMP_ATAV_get_rsaKeyLen(atav)); + break; + default: + BIO_printf(mem, "Invalid key spec: %s\n", nid_name(nid)); + break; + } + } + BIO_printf(mem, "End of key %s", desc); + + len = BIO_get_mem_data(mem, &p); + if (len > INT_MAX) + CMP_err1("Info too large - cannot dump key %s", desc); + else + CMP_info2("%.*s", (int)len, p); + BIO_free(mem); + return; +} + static void print_status(void) { /* print PKIStatusInfo */ @@ -3300,6 +3441,42 @@ static int do_genm(OSSL_CMP_CTX *ctx) X509_CRL_free(crl); return res; + } else if (opt_infotype == NID_id_it_certReqTemplate) { + OSSL_CRMF_CERTTEMPLATE *certTemplate; + OSSL_CMP_ATAVS *keySpec; + int res = 0; + + if (!OSSL_CMP_get1_certReqTemplate(ctx, &certTemplate, &keySpec)) + return 0; + + if (certTemplate == NULL) { + CMP_warn("no certificate request template available"); + if (!delete_file(opt_template, "certTemplate from genp")) + return 0; + if (opt_keyspec != NULL + && !delete_file(opt_keyspec, "keySpec from genp")) + return 0; + return 1; + } + if (!save_template(opt_template, certTemplate)) + goto tmpl_end; + + print_keyspec(keySpec); + if (opt_keyspec != NULL) { + if (keySpec == NULL) { + CMP_warn("no key specifications available"); + if (!delete_file(opt_keyspec, "keySpec from genp")) + goto tmpl_end; + } else if (!save_keyspec(opt_keyspec, keySpec)) { + goto tmpl_end; + } + } + + res = 1; + tmpl_end: + OSSL_CRMF_CERTTEMPLATE_free(certTemplate); + sk_OSSL_CMP_ATAV_pop_free(keySpec, OSSL_CMP_ATAV_free); + return res; } else { OSSL_CMP_ITAV *req; STACK_OF(OSSL_CMP_ITAV) *itavs; diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c index b69d29a..ce62af2 100644 --- a/apps/lib/cmp_mock_srv.c +++ b/apps/lib/cmp_mock_srv.c @@ -451,7 +451,7 @@ static int check_client_crl(const STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList, static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid, const OSSL_CMP_ITAV *req) { - OSSL_CMP_ITAV *rsp; + OSSL_CMP_ITAV *rsp = NULL; switch (req_nid) { case NID_id_it_caCerts: @@ -490,6 +490,48 @@ static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid, rsp = OSSL_CMP_ITAV_new_crls(res == 0 ? NULL : ctx->crlOut); } break; + case NID_id_it_certReqTemplate: + { + OSSL_CRMF_CERTTEMPLATE *reqtemp; + OSSL_CMP_ATAVS *keyspec = NULL; + X509_ALGOR *keyalg = NULL; + OSSL_CMP_ATAV *rsakeylen, *eckeyalg; + int ok = 0; + + if ((reqtemp = OSSL_CRMF_CERTTEMPLATE_new()) == NULL) + return NULL; + + if (!OSSL_CRMF_CERTTEMPLATE_fill(reqtemp, NULL, NULL, + X509_get_issuer_name(ctx->refCert), + NULL)) + goto crt_err; + + if ((keyalg = X509_ALGOR_new()) == NULL) + goto crt_err; + + (void)X509_ALGOR_set0(keyalg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), + V_ASN1_UNDEF, NULL); /* cannot fail */ + + eckeyalg = OSSL_CMP_ATAV_new_algId(keyalg); + rsakeylen = OSSL_CMP_ATAV_new_rsaKeyLen(4096); + ok = OSSL_CMP_ATAV_push1(&keyspec, eckeyalg) + && OSSL_CMP_ATAV_push1(&keyspec, rsakeylen); + OSSL_CMP_ATAV_free(eckeyalg); + OSSL_CMP_ATAV_free(rsakeylen); + X509_ALGOR_free(keyalg); + + if (!ok) + goto crt_err; + + rsp = OSSL_CMP_ITAV_new0_certReqTemplate(reqtemp, keyspec); + return rsp; + + crt_err: + OSSL_CRMF_CERTTEMPLATE_free(reqtemp); + OSSL_CMP_ATAVS_free(keyspec); + return NULL; + } + break; default: rsp = OSSL_CMP_ITAV_dup(req); } |