Skip to content

Commit

Permalink
cmp.c: save CRL to file
Browse files Browse the repository at this point in the history
  • Loading branch information
rajeev-0 committed Mar 7, 2024
1 parent 8dc4a4c commit 6719c7d
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 25 deletions.
149 changes: 128 additions & 21 deletions apps/cmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ static char *opt_oldwithold = NULL;
static char *opt_newwithnew = NULL;
static char *opt_newwithold = NULL;
static char *opt_oldwithnew = NULL;
static char *opt_oldcrl = NULL;
static char *opt_crlout = NULL;

/* client authentication */
static char *opt_ref = NULL;
Expand Down Expand Up @@ -235,6 +237,7 @@ 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_OLDCRL, OPT_CRLOUT,

OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS,
OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
Expand Down Expand Up @@ -425,6 +428,10 @@ 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"},
{ "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 @@ -618,6 +625,7 @@ 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_oldcrl}, {&opt_crlout},

{&opt_ref}, {&opt_secret},
{&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
Expand Down Expand Up @@ -1130,7 +1138,7 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
if (!setup_cert(srv_ctx, opt_ref_cert, opt_otherpass,
"reference cert to be expected by the mock server",
(add_X509_fn_t)ossl_cmp_mock_srv_set1_refCert))
goto err;
goto err;
if (opt_rsp_cert == NULL) {
CMP_warn("no -rsp_cert given for mock server");
} else {
Expand Down Expand Up @@ -1574,8 +1582,8 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
&& opt_popo != OSSL_CRMF_POPO_RAVERIFIED) {
if (opt_csr != NULL) {
CMP_err1("no -newkey option given with private key for POPO, -csr option only provides public key%s",
opt_key == NULL ? "" :
", and -key option superseded by -csr");
opt_key == NULL ? "" :
", and -key option superseded by -csr");
return 0;
}
if (opt_key == NULL) {
Expand Down Expand Up @@ -1819,8 +1827,8 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POPO_METHOD, opt_popo);

if (opt_oldcert != NULL) {
if (opt_cmd == CMP_GENM) {
CMP_warn("-oldcert option is ignored for 'genm' command");
if (opt_cmd == CMP_GENM && opt_infotype != NID_id_it_crlStatusList) {
CMP_warn("-oldcert option is ignored for 'genm' command except with -infotype crlStatusList");
} else {
if (!setup_cert(ctx, opt_oldcert, opt_keypass,
/* needed if opt_oldcert is encrypted PKCS12 file */
Expand Down Expand Up @@ -1854,20 +1862,20 @@ static int add_certProfile(OSSL_CMP_CTX *ctx, const char *name)

if ((sk = sk_ASN1_UTF8STRING_new_reserve(NULL, 1)) == NULL)
return 0;
if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
goto err;
if (!ASN1_STRING_set(utf8string, name, (int)strlen(name))) {
ASN1_STRING_free(utf8string);
goto err;
}
/* Due to sk_ASN1_UTF8STRING_new_reserve(NULL, 1), this surely succeeds: */
(void)sk_ASN1_UTF8STRING_push(sk, utf8string);
if ((itav = OSSL_CMP_ITAV_new0_certProfile(sk)) == NULL)
goto err;
if (OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav))
return 1;
OSSL_CMP_ITAV_free(itav);
return 0;
if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
goto err;
if (!ASN1_STRING_set(utf8string, name, (int)strlen(name))) {
ASN1_STRING_free(utf8string);
goto err;
}
/* Due to sk_ASN1_UTF8STRING_new_reserve(NULL, 1), this surely succeeds: */
(void)sk_ASN1_UTF8STRING_push(sk, utf8string);
if ((itav = OSSL_CMP_ITAV_new0_certProfile(sk)) == NULL)
goto err;
if (OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav))
return 1;
OSSL_CMP_ITAV_free(itav);
return 0;

err:
sk_ASN1_UTF8STRING_pop_free(sk, ASN1_UTF8STRING_free);
Expand Down Expand Up @@ -1912,7 +1920,7 @@ static int handle_opt_geninfo(OSSL_CMP_CTX *ctx)
if (*ptr != '\0') {
if (*ptr != ',') {
CMP_err1("Missing ',' or end of -geninfo arg after int at %.40s",
ptr);
ptr);
goto err;
}
ptr++;
Expand Down Expand Up @@ -2187,6 +2195,18 @@ static int write_cert(BIO *bio, X509 *cert)
return 0;
}

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

/*
* 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 @@ -2234,6 +2254,35 @@ static int save_free_certs(STACK_OF(X509) *certs,
return n;
}

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

if (file == NULL)
goto end;
if (crl != NULL)
CMP_info2("received %s CRL, saving to file '%s'", desc, file);

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

if (!write_crl(bio, crl)) {
CMP_err2("cannot write %s crl 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 @@ -2267,6 +2316,20 @@ 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;
if (crl == NULL) {
char desc_crl[80];

BIO_snprintf(desc_crl, sizeof(desc_crl), "%s CRL", desc);
return delete_file(file, desc_crl);
} else {
return save_free_crl(crl, file, desc);
}
}

static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
int i, ret = 1;
Expand Down Expand Up @@ -2666,7 +2729,12 @@ static int get_opts(int argc, char **argv)
case OPT_OLDWITHNEW:
opt_oldwithnew = 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))
goto opthelp;
Expand Down Expand Up @@ -3077,6 +3145,45 @@ 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;
int res = 0;

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

if (opt_oldcrl == NULL) {
CMP_warn("No -oldcrl given, will use data from -oldcert");
} else {
oldcrl = load_crl(opt_oldcrl, FORMAT_UNDEF, 0,
"CRL for genm with -infotype crlStatusList");
if (oldcrl == NULL)
goto end_crlupd;
}
if (!OSSL_CMP_get1_crlUpdate(ctx, oldcrl, &crl))
goto end_crlupd;

const char *desc = "CRL from genp of type 'crls'";
if (crl == NULL) {
CMP_info("no CRL update available");
if (!delete_file(opt_crlout, desc))
goto end_crlupd;
} else if (!save_crl_or_delete(crl, opt_crlout, desc)) {
goto end_crlupd;
}
res = 1;

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

} else {
OSSL_CMP_ITAV *req;
STACK_OF(OSSL_CMP_ITAV) *itavs;
Expand Down
29 changes: 25 additions & 4 deletions crypto/cmp/cmp_asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,9 +384,6 @@ OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn,
const GENERAL_NAMES *issuer,
const ASN1_TIME *thisUpdate)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
return dpn == NULL && issuer == NULL && thisUpdate == NULL ? NULL : NULL;
#else
OSSL_CMP_CRLSOURCE *crlsource;
OSSL_CMP_CRLSTATUS *crlstatus;

Expand Down Expand Up @@ -423,7 +420,6 @@ OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn,
err:
OSSL_CMP_CRLSTATUS_free(crlstatus);
return NULL;
#endif
}

static GENERAL_NAMES *gennames_new(const X509_NAME *nm)
Expand Down Expand Up @@ -553,6 +549,31 @@ int OSSL_CMP_CRLSTATUS_get0(const OSSL_CMP_CRLSTATUS *crlstatus,
return 1;
}

OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crl)
{
OSSL_CMP_ITAV *itav;
X509_CRL *crl_copy = NULL;
STACK_OF(X509_CRL) *crls = NULL;

if ((itav = OSSL_CMP_ITAV_new()) == NULL)
return NULL;

if (crl != NULL
&& ((crls = sk_X509_CRL_new_reserve(NULL, 1)) == NULL
|| (crl_copy = X509_CRL_dup(crl)) == NULL
|| !sk_X509_CRL_push(crls, crl_copy)))
goto err;

itav->infoType = OBJ_nid2obj(NID_id_it_crls);
itav->infoValue.crls = crls;
return itav;

err:
sk_X509_CRL_free(crls);
OSSL_CMP_ITAV_free(itav);
return NULL;
}

OSSL_CMP_ITAV *OSSL_CMP_ITAV_new0_crls(STACK_OF(X509_CRL) *crls)
{
OSSL_CMP_ITAV *itav;
Expand Down
3 changes: 3 additions & 0 deletions crypto/cmp/cmp_err.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
"failure obtaining random"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAIL_INFO_OUT_OF_RANGE),
"fail info out of range"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GENERATE_CRLSTATUS),
"error creating crlstatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GETTING_GENP), "getting genp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GET_ITAV), "get itav"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_GENP), "invalid genp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
Expand Down
62 changes: 62 additions & 0 deletions crypto/cmp/cmp_genm.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,65 @@ int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
X509_free(oldWithOld_copy);
return res;
}

int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509_CRL *last_crl,
X509_CRL **crl)
{
OSSL_CMP_CRLSTATUS *status = NULL;
STACK_OF(OSSL_CMP_CRLSTATUS) *list = NULL;
OSSL_CMP_ITAV *req = NULL, *itav = NULL;
STACK_OF(X509_CRL) *crls;
int res = 0;

if (crl == NULL) {
ERR_raise_data(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT,
"No crl output parameter given");
return 0;
}
*crl = NULL;

if ((status = OSSL_CMP_CRLSTATUS_create(last_crl, ctx->oldCert, 1)) == NULL) {
ERR_raise_data(ERR_LIB_CMP, CMP_R_GENERATE_CRLSTATUS,
"Cannot set up CRLStatus structure");
goto end;
}
if ((list = sk_OSSL_CMP_CRLSTATUS_new_reserve(NULL, 1)) == NULL) {
ERR_raise_data(ERR_LIB_CMP, CMP_R_GENERATE_CRLSTATUS,
"Cannot set up CRLStatus list");
goto end;
}
(void)sk_OSSL_CMP_CRLSTATUS_push(list, status); /* cannot fail */

if ((req = OSSL_CMP_ITAV_new0_crlStatusList(list)) == NULL)
goto end;

status = NULL;
list = NULL;

itav = get_genm_itav(ctx, req, NID_id_it_crls, "crl");
if (itav == NULL)
goto end;

if (!OSSL_CMP_ITAV_get0_crls(itav, &crls))
goto end;

if (crls == NULL) /* no CRL update available */
goto end;
if (sk_X509_CRL_num(crls) != 1) {
ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_GENP,
"Unexpected number of CRLs in genp: %d",
sk_X509_CRL_num(crls));
goto end;
}

if ((*crl = sk_X509_CRL_value(crls, 0)) == NULL || !X509_CRL_up_ref(*crl)) {
*crl = NULL;
goto end;
}
res = 1;
end:
OSSL_CMP_CRLSTATUS_free(status);
sk_OSSL_CMP_CRLSTATUS_free(list);
OSSL_CMP_ITAV_free(itav);
return res;
}
2 changes: 2 additions & 0 deletions crypto/err/openssl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain
CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
CMP_R_FAIL_INFO_OUT_OF_RANGE:129:fail info out of range
CMP_R_GENERATE_CRLSTATUS:198:error creating crlstatus
CMP_R_GETTING_GENP:192:getting genp
CMP_R_GET_ITAV:199:get itav
CMP_R_INVALID_ARGS:100:invalid args
CMP_R_INVALID_GENP:193:invalid genp
CMP_R_INVALID_OPTION:174:invalid option
Expand Down
Loading

0 comments on commit 6719c7d

Please sign in to comment.