Skip to content

Commit

Permalink
add test case of crlStatusList
Browse files Browse the repository at this point in the history
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

review

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
  • Loading branch information
rajeev-0 committed Mar 7, 2024
1 parent 2418203 commit ea75c30
Show file tree
Hide file tree
Showing 25 changed files with 303 additions and 139 deletions.
93 changes: 57 additions & 36 deletions apps/cmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ 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;

Expand Down Expand Up @@ -238,7 +239,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_CRLCERT, 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 @@ -268,9 +269,9 @@ 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_CRL, OPT_RSP_EXTRACERTS,
OPT_RSP_CAPUBS, OPT_RSP_NEWWITHNEW, OPT_RSP_NEWWITHOLD,
OPT_RSP_OLDWITHNEW, OPT_POLL_COUNT, OPT_CHECK_AFTER,
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,
OPT_PKISTATUS, OPT_FAILURE,
OPT_FAILUREBITS, OPT_STATUSSTRING,
Expand Down Expand Up @@ -429,6 +430,8 @@ 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 CRL update for in genm of type crlStatusList"},
{ "oldcrl", OPT_OLDCRL, 's',
"CRL to request update for in genm of type crlStatusList"},
{ "crlout", OPT_CRLOUT, 's',
Expand Down Expand Up @@ -628,7 +631,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_crlcert}, {&opt_oldcrl}, {&opt_crlout},

{&opt_ref}, {&opt_secret},
{&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
Expand Down Expand Up @@ -658,9 +661,9 @@ 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_crl}, {&opt_rsp_extracerts},
{&opt_rsp_capubs}, {&opt_rsp_newwithnew}, {&opt_rsp_newwithold},
{&opt_rsp_oldwithnew},
{&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},
{(char **)&opt_grant_implicitconf},
Expand Down Expand Up @@ -1009,9 +1012,7 @@ static int setup_certs(char *files, const char *desc, void *ctx,
return ok;
}

typedef int (*add_X509_CRL_fn_t)(void *ctx, const X509_CRL *crl);
static int setup_crl(void *ctx, const char *file, const char *desc,
add_X509_CRL_fn_t set1_fn)
static int setup_mock_crlout(void *ctx, const char *file, const char *desc)
{
X509_CRL *crl;
int ok;
Expand All @@ -1020,7 +1021,7 @@ static int setup_crl(void *ctx, const char *file, const char *desc,
return 1;
if ((crl = load_crl(file, FORMAT_UNDEF, 0, desc)) == NULL)
return 0;
ok = (*set1_fn)(ctx, crl);
ok = ossl_cmp_mock_srv_set1_crlOut(ctx, crl);
X509_CRL_free(crl);
return ok;
}
Expand Down Expand Up @@ -1166,8 +1167,8 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
(add_X509_fn_t)ossl_cmp_mock_srv_set1_certOut))
goto err;
}
if (!setup_crl(srv_ctx, opt_rsp_crl, "CRL the mock server returns",
(add_X509_CRL_fn_t)ossl_cmp_mock_srv_set1_crlOut))
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,
Expand Down Expand Up @@ -1849,8 +1850,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 && opt_infotype != NID_id_it_crlStatusList) {
CMP_warn("-oldcert option is ignored for 'genm' command except with -infotype crlStatusList");
if (opt_cmd == CMP_GENM) {
CMP_warn("-oldcert option is ignored for 'genm' command");
} else {
if (!setup_cert(ctx, opt_oldcert, opt_keypass,
/* needed if opt_oldcert is encrypted PKCS12 file */
Expand Down Expand Up @@ -2219,14 +2220,14 @@ static int write_cert(BIO *bio, X509 *cert)

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",
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;
return 0;
}

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

/*
Expand Down Expand Up @@ -2289,8 +2290,8 @@ static int save_free_crl(X509_CRL *crl,

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);
CMP_err2("could not open file '%s' for writing %s CRL",
file, desc);
goto end;
}

Expand Down Expand Up @@ -2345,7 +2346,7 @@ static int save_crl_or_delete(X509_CRL *crl, const char *file, const char *desc)
if (crl == NULL) {
char desc_crl[80];

BIO_snprintf(desc_crl, sizeof(desc_crl), "%s CRL", desc);
BIO_snprintf(desc_crl, sizeof(desc_crl), "%s", desc);
return delete_file(file, desc_crl);
} else {
return save_free_crl(crl, file, desc);
Expand Down Expand Up @@ -2751,6 +2752,9 @@ 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;
Expand Down Expand Up @@ -3172,39 +3176,56 @@ static int do_genm(OSSL_CMP_CTX *ctx)
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_oldcert == NULL) {
CMP_err("Missing -oldcrl and no -oldcert given for -infotype crlStatusList");
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) {
CMP_warn("No -crlcert given, will use data from -oldcrl");
} else {
crlcert = load_cert_pwd(opt_crlcert, opt_otherpass,
"Cert for genm with -infotype crlStatusList");
if (crlcert == NULL)
goto end_crlupd;
}

if (opt_oldcrl == NULL) {
CMP_warn("No -oldcrl given, will use data from -oldcert");
CMP_warn("No -oldcrl given, will use data from -crlcert");
} 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))

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;

const char *desc = "CRL from genp of type 'crls'";
if (crl == NULL) {
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)) {
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;
Expand Down
50 changes: 36 additions & 14 deletions apps/lib/cmp_mock_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,25 +408,41 @@ static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
return OSSL_CMP_PKISI_dup(ctx->statusOut);
}

/* return -1 for error, 0 for no update available */
static int check_client_crl(const STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList,
const X509_CRL *crl)
{
OSSL_CMP_CRLSTATUS *crlstatus;
DIST_POINT_NAME *distpoint;
GENERAL_NAMES *gen;
ASN1_TIME *thisupd;
ASN1_TIME *thisupd = NULL;

if (crlStatusList == NULL || crl == NULL)
return 0;
if (sk_OSSL_CMP_CRLSTATUS_num(crlStatusList) != 1)
if (sk_OSSL_CMP_CRLSTATUS_num(crlStatusList) != 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CRLSTATUSLIST);
return -1;
}
if (crl == NULL)
return 0;

crlstatus = sk_OSSL_CMP_CRLSTATUS_value(crlStatusList, 0);
if (!OSSL_CMP_CRLSTATUS_get0(crlstatus, &distpoint, &gen, &thisupd))
return 0;
if (ASN1_TIME_compare(thisupd, X509_CRL_get0_lastUpdate(crl)) >= 0)
return 0;
return -1;

return 1;
if (gen != NULL) {
GENERAL_NAME *gn = sk_GENERAL_NAME_value(gen, 0);

if (gn != NULL && gn->type == GEN_DIRNAME) {
X509_NAME *gen_name = gn->d.dirn;

if (X509_NAME_cmp(gen_name, X509_CRL_get_issuer(crl)) != 0) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CRL_ISSUER);
return -1;
}
}
}

return thisupd == NULL
|| ASN1_TIME_compare(thisupd, X509_CRL_get0_lastUpdate(crl)) < 0;
}

static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
Expand All @@ -446,12 +462,18 @@ static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
case NID_id_it_crlStatusList:
{
STACK_OF(OSSL_CMP_CRLSTATUS) *crlstatuslist;

rsp = OSSL_CMP_ITAV_get0_crlStatusList(req, &crlstatuslist)
? check_client_crl(crlstatuslist, ctx->crlOut)
? OSSL_CMP_ITAV_new_crls(ctx->crlOut)
: OSSL_CMP_ITAV_new_crls(NULL)
: OSSL_CMP_ITAV_new_crls(NULL);
int res = 0;

if (!OSSL_CMP_ITAV_get0_crlStatusList(req, &crlstatuslist))
return NULL;

res = check_client_crl(crlstatuslist, ctx->crlOut);
if (res < 0)
rsp = NULL;
else if (res == 0)
rsp = OSSL_CMP_ITAV_new_crls(NULL);
else
rsp = OSSL_CMP_ITAV_new_crls(ctx->crlOut);
}
break;
default:
Expand Down
29 changes: 14 additions & 15 deletions crypto/cmp/cmp_asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,6 @@ ASN1_SEQUENCE(OSSL_CMP_CRLSTATUS) = {
} ASN1_SEQUENCE_END(OSSL_CMP_CRLSTATUS)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CRLSTATUS)

IMPLEMENT_ASN1_DUP_FUNCTION(DIST_POINT_NAME)

OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value)
{
OSSL_CMP_ITAV *itav;
Expand Down Expand Up @@ -429,7 +427,7 @@ static GENERAL_NAMES *gennames_new(const X509_NAME *nm)

if ((names = sk_GENERAL_NAME_new_reserve(NULL, 1)) == NULL)
return NULL;
if (!GENERAL_NAME_create(&name, nm)) {
if (!GENERAL_NAME_set1_X509_NAME(&name, nm)) {
sk_GENERAL_NAME_free(names);
return NULL;
}
Expand Down Expand Up @@ -461,11 +459,11 @@ OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl,
int i, NID_akid = NID_authority_key_identifier;

/*
* Note: X509{,_CRL}_get_ext_d2i(..., NID, &i, ...) return the 1st extension
* with the given NID that is available, if any. There might be more such.
* Note: X509{,_CRL}_get_ext_d2i(..., NID, ..., NULL) return the 1st extension
* with the given NID that is available, if any. If there are more, this is an error.
*/
if (cert != NULL) {
crldps = X509_get_ext_d2i(cert, NID_crl_distribution_points, &i, NULL);
crldps = X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL);
/* if available, take the first suitable element */
for (i = 0; i < sk_DIST_POINT_num(crldps); i++) {
DIST_POINT *dp = sk_DIST_POINT_value(crldps, i);
Expand All @@ -486,21 +484,21 @@ OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl,
return NULL;
}
idp = X509_CRL_get_ext_d2i(crl,
NID_issuing_distribution_point, &i, NULL);
NID_issuing_distribution_point, NULL, NULL);
if (idp != NULL && idp->distpoint != NULL)
dpn = idp->distpoint;
}

if (dpn == NULL && CRLissuer == NULL) {
if (cert != NULL) {
akid = X509_get_ext_d2i(cert, NID_akid, &i, NULL);
akid = X509_get_ext_d2i(cert, NID_akid, NULL, NULL);
if (akid != NULL && gennames_allowed(akid->issuer, only_DN))
CRLissuer = akid->issuer;
else
CRLissuer = issuers = gennames_new(X509_get_issuer_name(cert));
}
if (CRLissuer == NULL && crl != NULL) {
akid = X509_CRL_get_ext_d2i(crl, NID_akid, &i, NULL);
akid = X509_CRL_get_ext_d2i(crl, NID_akid, NULL, NULL);
if (akid != NULL && gennames_allowed(akid->issuer, only_DN))
CRLissuer = akid->issuer;
else
Expand Down Expand Up @@ -558,11 +556,12 @@ OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crl)
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;
if (crl != NULL) {
if ((crls = sk_X509_CRL_new_reserve(NULL, 1)) == NULL
|| (crl_copy = X509_CRL_dup(crl)) == NULL)
goto err;
(void)sk_X509_CRL_push(crls, crl_copy); /* cannot fail */
}

itav->infoType = OBJ_nid2obj(NID_id_it_crls);
itav->infoValue.crls = crls;
Expand All @@ -588,7 +587,7 @@ int OSSL_CMP_ITAV_get0_crls(const OSSL_CMP_ITAV *itav, STACK_OF(X509_CRL) **out)
return 1;
}

/* get ASN.1 encoded integer, return -1 on error */
/* get ASN.1 encoded integer, return -2 on error; -1 is valid for certReqId */
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
{
int64_t res;
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 @@ -150,6 +150,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNCLEAN_CTX), "unclean ctx"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CERTPROFILE),
"unexpected certprofile"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CRLSTATUSLIST),
"unexpected crlstatuslist"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
"unexpected pkistatus"},
Expand All @@ -159,6 +161,7 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
"unknown algorithm id"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CRL_ISSUER), "unknown crl issuer"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_PKISTATUS), "unknown pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_ALGORITHM),
"unsupported algorithm"},
Expand Down
Loading

0 comments on commit ea75c30

Please sign in to comment.