aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorRajeev Ranjan <ranjan.rajeev@siemens.com>2024-05-15 13:11:09 +0200
committerDr. David von Oheimb <dev@ddvo.net>2024-06-20 13:38:13 +0200
commit6a3579e190fd52f49b1e5eafb4d002684eb0ff42 (patch)
tree7041c8caf1fb6a5e0b640f084ad9fad312fdf84c /apps
parente2a4d68a03b8a3576b0fe917a602b3a283d105a5 (diff)
downloadopenssl-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.c177
-rw-r--r--apps/lib/cmp_mock_srv.c44
2 files changed, 220 insertions, 1 deletions
diff --git a/apps/cmp.c b/apps/cmp.c
index 8d880c5..dc2a1c3 100644
--- a/apps/cmp.c
+++ b/apps/cmp.c
@@ -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, &paramtype, &param, 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);
}