Skip to content

Commit

Permalink
CMP: add support for requesting cert template using genm/genp
Browse files Browse the repository at this point in the history
  • Loading branch information
rajeev-0 committed May 15, 2024
1 parent 57bb112 commit efefa2a
Show file tree
Hide file tree
Showing 22 changed files with 826 additions and 43 deletions.
166 changes: 166 additions & 0 deletions apps/cmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -2176,6 +2184,14 @@ 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);
}

if (!setup_verification_ctx(ctx))
goto err;
Expand Down Expand Up @@ -2420,6 +2436,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;
Expand Down Expand Up @@ -2845,6 +2912,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();
Expand Down Expand Up @@ -3154,6 +3227,68 @@ 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;

if (keySpec == NULL)
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);

int i, n = sk_OSSL_CMP_ATAV_num(keySpec);
for (i = 0; i < n; 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 bit\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);

const char *p;
long 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 */
Expand Down Expand Up @@ -3300,6 +3435,37 @@ 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;
return 1;
}
if (!save_template(opt_template, certTemplate))
goto tmpl_end;

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;
}
print_keyspec(keySpec);
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;
Expand Down
37 changes: 36 additions & 1 deletion apps/lib/cmp_mock_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -490,6 +490,41 @@ 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;

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 ((keyspec = OSSL_CMP_ATAVS_new()) == 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 */

if (!sk_OSSL_CMP_ATAV_push(keyspec, OSSL_CMP_ATAV_new_algId(keyalg))
|| !sk_OSSL_CMP_ATAV_push(keyspec, OSSL_CMP_ATAV_new_rsaKeyLen(4096)))
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);
X509_ALGOR_free(keyalg);
return NULL;
}
break;
default:
rsp = OSSL_CMP_ITAV_dup(req);
}
Expand Down
Loading

0 comments on commit efefa2a

Please sign in to comment.