Skip to content

Commit

Permalink
CMP: add support for genm with crlStatusList and genp with crls
Browse files Browse the repository at this point in the history
cmp.c: save CRL to file

add option -rsp_crl for Mock server

add test case of crlStatusList

OSSL_CMP_exec_certreq.pod: add OSSL_CMP_get1_crlUpdate()

add documentation for GENERAL_NAME_create()

add OSSL_CMP_CTX_get0_oldCert()

add issuer check and generate warning

add error CMP_R_UNKNOWN_CRL_ISSUER

Fix OSSL_CMP_get1_crlUpdate parameter in cmp_genm.c

add -crlcert option for genm with infotype crlStatusList

cmp.c: Refactor CRL update logic

Remove OSSL_CMP_CTX_get0_oldCert() function

Add options for specifying CRL issuer and saving received CRLs

Update test_commands.csv with new crlcert and old crl

Add new functions and rearrange existing functions in libcrypto.num

Refactor setup_crl function to use setup_mock_crlout

Add support for requesting CRL in CMP
  • Loading branch information
DDvO authored and rajeev-0 committed Mar 8, 2024
1 parent 8d8866a commit bda4e53
Show file tree
Hide file tree
Showing 27 changed files with 918 additions and 62 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ OpenSSL 3.3

*Neil Horman*

* Added support for requesting CRL in CMP.

*Rajeev Ranjan, Siemens AG*

* Added `-set_issuer` and `-set_subject` options to `openssl x509` to
override the Issuer and Subject when creating a certificate. The `-subj`
option now is an alias for `-set_subject`.
Expand Down
163 changes: 159 additions & 4 deletions apps/cmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ static char *opt_oldwithold = NULL;
static char *opt_newwithnew = NULL;
static char *opt_newwithold = NULL;
static char *opt_oldwithnew = NULL;
static char *opt_crlcert = NULL;
static char *opt_oldcrl = NULL;
static char *opt_crlout = NULL;

/* client authentication */
static char *opt_ref = NULL;
Expand Down Expand Up @@ -143,6 +146,8 @@ static int opt_revreason = CRL_REASON_NONE;
/* credentials format */
static char *opt_certform_s = "PEM";
static int opt_certform = FORMAT_PEM;
static char *opt_crlform_s = "DER";
static int opt_crlform = FORMAT_ASN1;
static char *opt_keyform_s = NULL;
static int opt_keyform = FORMAT_UNDEF;
static char *opt_otherpass = NULL;
Expand Down Expand Up @@ -187,6 +192,7 @@ static char *opt_srv_trusted = NULL;
static char *opt_srv_untrusted = NULL;
static char *opt_ref_cert = NULL;
static char *opt_rsp_cert = NULL;
static char *opt_rsp_crl = NULL;
static char *opt_rsp_extracerts = NULL;
static char *opt_rsp_capubs = NULL;
static char *opt_rsp_newwithnew = NULL;
Expand Down Expand Up @@ -237,12 +243,13 @@ typedef enum OPTION_choice {
OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, OPT_NO_CACHE_EXTRACERTS,
OPT_SRVCERTOUT, OPT_EXTRACERTSOUT, OPT_CACERTSOUT,
OPT_OLDWITHOLD, OPT_NEWWITHNEW, OPT_NEWWITHOLD, OPT_OLDWITHNEW,
OPT_CRLCERT, OPT_OLDCRL, OPT_CRLOUT,

OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS,
OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
OPT_UNPROTECTED_REQUESTS,

OPT_CERTFORM, OPT_KEYFORM,
OPT_CERTFORM, OPT_CRLFORM, OPT_KEYFORM,
OPT_OTHERPASS,
#ifndef OPENSSL_NO_ENGINE
OPT_ENGINE,
Expand All @@ -267,7 +274,7 @@ typedef enum OPTION_choice {
OPT_SRV_REF, OPT_SRV_SECRET,
OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS,
OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED,
OPT_REF_CERT, OPT_RSP_CERT, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
OPT_REF_CERT, OPT_RSP_CERT, OPT_RSP_CRL, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
OPT_RSP_NEWWITHNEW, OPT_RSP_NEWWITHOLD, OPT_RSP_OLDWITHNEW,
OPT_POLL_COUNT, OPT_CHECK_AFTER,
OPT_GRANT_IMPLICITCONF,
Expand Down Expand Up @@ -428,6 +435,12 @@ const OPTIONS cmp_options[] = {
"File to save NewWithOld cert received in genp of type rootCaKeyUpdate"},
{ "oldwithnew", OPT_OLDWITHNEW, 's',
"File to save OldWithNew cert received in genp of type rootCaKeyUpdate"},
{ "crlcert", OPT_CRLCERT, 's',
"certificate to request a CRL for in genm of type crlStatusList"},
{ "oldcrl", OPT_OLDCRL, 's',
"CRL to request update for in genm of type crlStatusList"},
{ "crlout", OPT_CRLOUT, 's',
"File to save new CRL received in genp of type 'crls'"},

OPT_SECTION("Client authentication"),
{"ref", OPT_REF, 's',
Expand Down Expand Up @@ -459,6 +472,8 @@ const OPTIONS cmp_options[] = {
OPT_SECTION("Credentials format"),
{"certform", OPT_CERTFORM, 's',
"Format (PEM or DER) to use when saving a certificate to a file. Default PEM"},
{"crlform", OPT_CRLFORM, 's',
"Format (PEM or DER) to use when saving a CRL to a file. Default DER"},
{"keyform", OPT_KEYFORM, 's',
"Format of the key input (ENGINE, other values ignored)"},
{"otherpass", OPT_OTHERPASS, 's',
Expand Down Expand Up @@ -544,6 +559,8 @@ const OPTIONS cmp_options[] = {
"Certificate to be expected for rr and any oldCertID in kur messages"},
{"rsp_cert", OPT_RSP_CERT, 's',
"Certificate to be returned as mock enrollment result"},
{"rsp_crl", OPT_RSP_CRL, 's',
"CRL to be returned in genp of type crls"},
{"rsp_extracerts", OPT_RSP_EXTRACERTS, 's',
"Extra certificates to be included in mock certification responses"},
{"rsp_capubs", OPT_RSP_CAPUBS, 's',
Expand Down Expand Up @@ -623,13 +640,14 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
{(char **)&opt_no_cache_extracerts},
{&opt_srvcertout}, {&opt_extracertsout}, {&opt_cacertsout},
{&opt_oldwithold}, {&opt_newwithnew}, {&opt_newwithold}, {&opt_oldwithnew},
{&opt_crlcert}, {&opt_oldcrl}, {&opt_crlout},

{&opt_ref}, {&opt_secret},
{&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
{&opt_digest}, {&opt_mac}, {&opt_extracerts},
{(char **)&opt_unprotected_requests},

{&opt_certform_s}, {&opt_keyform_s},
{&opt_certform_s}, {&opt_crlform_s}, {&opt_keyform_s},
{&opt_otherpass},
#ifndef OPENSSL_NO_ENGINE
{&opt_engine},
Expand All @@ -652,7 +670,8 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
{&opt_srv_ref}, {&opt_srv_secret},
{&opt_srv_cert}, {&opt_srv_key}, {&opt_srv_keypass},
{&opt_srv_trusted}, {&opt_srv_untrusted},
{&opt_ref_cert}, {&opt_rsp_cert}, {&opt_rsp_extracerts}, {&opt_rsp_capubs},
{&opt_ref_cert}, {&opt_rsp_cert}, {&opt_rsp_crl},
{&opt_rsp_extracerts}, {&opt_rsp_capubs},
{&opt_rsp_newwithnew}, {&opt_rsp_newwithold}, {&opt_rsp_oldwithnew},

{(char **)&opt_poll_count}, {(char **)&opt_check_after},
Expand Down Expand Up @@ -1010,6 +1029,19 @@ static int setup_certs(char *files, const char *desc, void *ctx,
return ok;
}

static int setup_mock_crlout(void *ctx, const char *file, const char *desc)
{
X509_CRL *crl;
int ok;

if (file == NULL)
return 1;
if ((crl = load_crl(file, FORMAT_UNDEF, 0, desc)) == NULL)
return 0;
ok = ossl_cmp_mock_srv_set1_crlOut(ctx, crl);
X509_CRL_free(crl);
return ok;
}
/*
* parse and transform some options, checking their syntax.
* Returns 1 on success, 0 on error
Expand Down Expand Up @@ -1057,6 +1089,11 @@ static int transform_opts(void)
CMP_err("unknown option given for certificate storing format");
return 0;
}
if (opt_crlform_s != NULL
&& !opt_format(opt_crlform_s, OPT_FMT_PEMDER, &opt_crlform)) {
CMP_err("unknown option given for CRL storing format");
return 0;
}

return 1;
}
Expand Down Expand Up @@ -1152,6 +1189,9 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
(add_X509_fn_t)ossl_cmp_mock_srv_set1_certOut))
goto err;
}
if (!setup_mock_crlout(srv_ctx, opt_rsp_crl,
"CRL to be returned by the mock server"))
goto err;
if (!setup_certs(opt_rsp_extracerts,
"CMP extra certificates for mock server", srv_ctx,
(add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_chainOut))
Expand Down Expand Up @@ -2248,6 +2288,18 @@ static int write_cert(BIO *bio, X509 *cert)
return 0;
}

static int write_crl(BIO *bio, X509_CRL *crl)
{
if (opt_crlform != FORMAT_PEM && opt_crlform != FORMAT_ASN1) {
BIO_printf(bio_err, "error: unsupported type '%s' for writing CRLs\n",
opt_crlform_s);
return 0;
}

return opt_crlform == FORMAT_PEM ? PEM_write_bio_X509_CRL(bio, crl)
: i2d_X509_CRL_bio(bio, crl);
}

/*
* If file != NULL writes out a stack of certs to the given file.
* If certs is NULL, the file is emptied.
Expand Down Expand Up @@ -2295,6 +2347,35 @@ static int save_free_certs(STACK_OF(X509) *certs,
return n;
}

static int save_crl(X509_CRL *crl,
const char *file, const char *desc)
{
BIO *bio = NULL;
int res = 0;

if (file == NULL)
return 1;
if (crl != NULL)
CMP_info2("received %s, saving to file '%s'", desc, file);

if ((bio = BIO_new(BIO_s_file())) == NULL
|| !BIO_write_filename(bio, (char *)file)) {
CMP_err2("could not open file '%s' for writing %s",
file, desc);
goto end;
}

if (!write_crl(bio, crl)) {
CMP_err2("cannot write %s to file '%s'", desc, file);
goto end;
}
res = 1;

end:
BIO_free(bio);
return res;
}

static int delete_file(const char *file, const char *desc)
{
if (file == NULL)
Expand Down Expand Up @@ -2328,6 +2409,13 @@ static int save_cert_or_delete(X509 *cert, const char *file, const char *desc)
}
}

static int save_crl_or_delete(X509_CRL *crl, const char *file, const char *desc)
{
if (file == NULL)
return 1;
return (crl == NULL) ? delete_file(file, desc) : save_crl(crl, file, desc);
}

static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
int i, ret = 1;
Expand Down Expand Up @@ -2727,6 +2815,15 @@ static int get_opts(int argc, char **argv)
case OPT_OLDWITHNEW:
opt_oldwithnew = opt_str();
break;
case OPT_CRLCERT:
opt_crlcert = opt_str();
break;
case OPT_OLDCRL:
opt_oldcrl = opt_str();
break;
case OPT_CRLOUT:
opt_crlout = opt_str();
break;

case OPT_V_CASES:
if (!opt_verify(o, vpm))
Expand Down Expand Up @@ -2822,6 +2919,9 @@ static int get_opts(int argc, char **argv)
case OPT_CERTFORM:
opt_certform_s = opt_str();
break;
case OPT_CRLFORM:
opt_crlform_s = opt_str();
break;
case OPT_KEYFORM:
opt_keyform_s = opt_str();
break;
Expand Down Expand Up @@ -2905,6 +3005,9 @@ static int get_opts(int argc, char **argv)
case OPT_RSP_CERT:
opt_rsp_cert = opt_str();
break;
case OPT_RSP_CRL:
opt_rsp_crl = opt_str();
break;
case OPT_RSP_EXTRACERTS:
opt_rsp_extracerts = opt_str();
break;
Expand Down Expand Up @@ -3141,6 +3244,58 @@ static int do_genm(OSSL_CMP_CTX *ctx)
end_upd:
X509_free(oldwithold);
return res;
} else if (opt_infotype == NID_id_it_crlStatusList) {
X509_CRL *oldcrl = NULL, *crl = NULL;
X509 *crlcert = NULL;
int res = 0;
const char *desc = "CRL from genp of type 'crls'";

if (opt_oldcrl == NULL && opt_crlcert == NULL) {
CMP_err("Missing -oldcrl and no -crlcert given for -infotype crlStatusList");
return 0;
}
if (opt_crlout == NULL) {
CMP_err("Missing -crlout for -infotype crlStatusList");
return 0;
}

if (opt_crlcert != NULL) {
crlcert = load_cert_pwd(opt_crlcert, opt_otherpass,
"Cert for genm with -infotype crlStatusList");
if (crlcert == NULL)
goto end_crlupd;
}

if (opt_oldcrl != NULL) {
oldcrl = load_crl(opt_oldcrl, FORMAT_UNDEF, 0,
"CRL for genm with -infotype crlStatusList");
if (oldcrl == NULL)
goto end_crlupd;
}

if (opt_oldcrl != NULL && opt_crlcert != NULL) {
if (X509_NAME_cmp(X509_CRL_get_issuer(oldcrl),
X509_get_issuer_name(crlcert))
!= 0)
CMP_warn("-oldcrl and -crlcert have different issuer");
}

if (!OSSL_CMP_get1_crlUpdate(ctx, crlcert, oldcrl, &crl))
goto end_crlupd;

if (crl == NULL)
CMP_info("no CRL update available");
if (!save_crl_or_delete(crl, opt_crlout, desc))
goto end_crlupd;

res = 1;

end_crlupd:
X509_free(crlcert);
X509_CRL_free(oldcrl);
X509_CRL_free(crl);
return res;

} else {
OSSL_CMP_ITAV *req;
STACK_OF(OSSL_CMP_ITAV) *itavs;
Expand Down
1 change: 1 addition & 0 deletions apps/include/cmp_mock_srv.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);

int ossl_cmp_mock_srv_set1_refCert(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
int ossl_cmp_mock_srv_set1_crlOut(OSSL_CMP_SRV_CTX *srv_ctx, X509_CRL *crl);
int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
STACK_OF(X509) *chain);
int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
Expand Down
Loading

0 comments on commit bda4e53

Please sign in to comment.