crypto/cmp/,apps/lib/cmp_mock_srv.c: various improvements on delayed delivery

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/20727)
This commit is contained in:
Dr. David von Oheimb 2023-04-28 13:45:21 +02:00 committed by Dr. David von Oheimb
parent 192bfec487
commit bedffe1731
16 changed files with 163 additions and 134 deletions

View File

@ -43,6 +43,7 @@ OpenSSL 3.3
* Added several new features of CMPv3 defined in RFC 9480 and RFC 9483:
- `certProfile` request message header and respective `-profile` CLI option
- support for delayed delivery of all types of response messages
*David von Oheimb*

View File

@ -183,15 +183,15 @@ int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec)
return 1;
}
static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
/* determine whether to delay response to (non-polling) request */
static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
int req_type = OSSL_CMP_MSG_get_bodytype(req);
if (ctx == NULL || req == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
return -1;
}
/*
@ -211,11 +211,10 @@ static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx,
if (ctx->req != NULL) { /* TODO: move this check to cmp_server.c */
/* already in polling mode */
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
return 0;
return -1;
}
if ((ctx->req = OSSL_CMP_MSG_dup(req)) == NULL)
return -1;
return 1;
}
return 0;
@ -236,17 +235,17 @@ static int refcert_cmp(const X509 *refcert,
&& (ref_serial == NULL || ASN1_INTEGER_cmp(serial, ref_serial) == 0);
}
/* Reset dynamic variable in case of incomplete tansaction */
static int reset_transaction(OSSL_CMP_SRV_CTX *srv_ctx)
/* reset the state that belongs to a transaction */
static int clean_transaction(OSSL_CMP_SRV_CTX *srv_ctx,
ossl_unused const ASN1_OCTET_STRING *id)
{
mock_srv_ctx *ctx = NULL;
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
if (srv_ctx == NULL) {
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
ctx->curr_pollCount = 0;
OSSL_CMP_MSG_free(ctx->req);
ctx->req = NULL;
@ -533,6 +532,7 @@ static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
return 1;
}
/* return 0 on failure, 1 on success, setting *req or otherwise *check_after */
static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *pollReq,
ossl_unused int certReqId,
@ -540,21 +540,21 @@ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
if (req != NULL)
*req = NULL;
if (ctx == NULL || pollReq == NULL
|| req == NULL || check_after == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
if (ctx->sendError == 1
|| ctx->sendError == OSSL_CMP_MSG_get_bodytype(pollReq)) {
*req = NULL;
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return 0;
}
if (ctx->req == NULL) { /* TODO: move this check to cmp_server.c */
/* not currently in polling mode */
*req = NULL;
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
if (ctx->req == NULL) { /* not currently in polling mode */
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_POLLREQ);
return 0;
}
@ -564,7 +564,6 @@ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
ctx->req = NULL;
*check_after = 0;
} else {
*req = NULL;
*check_after = ctx->checkAfterTime;
}
return 1;
@ -579,8 +578,8 @@ OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq)
&& OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request,
process_rr, process_genm, process_error,
process_certConf, process_pollReq)
&& OSSL_CMP_SRV_CTX_setup_polling(srv_ctx, reset_transaction,
delayed_delivery))
&& OSSL_CMP_SRV_CTX_init_trans(srv_ctx,
delayed_delivery, clean_transaction))
return srv_ctx;
mock_srv_ctx_free(ctx);

View File

@ -113,7 +113,7 @@ static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si)
return 1;
}
static int is_crep_with_waiting(OSSL_CMP_MSG *resp, int rid)
static int is_crep_with_waiting(const OSSL_CMP_MSG *resp, int rid)
{
OSSL_CMP_CERTREPMESSAGE *crepmsg;
OSSL_CMP_CERTRESPONSE *crep;
@ -210,11 +210,11 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
return 0;
/*
* 'rep' can have the expected response type, which during polling is
* pollRep. When polling, also any other non-error response (the final
* response) is fine here. When not yet polling, delayed delivery may
* be started by an error with 'waiting' status (while it may also be
* started by an expected response type ip/cp/kup).
* rep can have the expected response type, which during polling is pollRep.
* When polling, also any other non-error response (the final response)
* is fine here. When not yet polling, delayed delivery may be initiated
* by the server returning an error message with 'waiting' status (or a
* response message of expected type ip/cp/kup with 'waiting' status).
*/
if (bt == expected_type
|| (expected_type == OSSL_CMP_PKIBODY_POLLREP
@ -272,8 +272,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
* Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
* Returns 1 on success and provides the received PKIMESSAGE in *rep.
* In this case the caller is responsible for freeing *rep.
* Returns 0 on error (which includes the case that timeout has been reached or
* received response with waiting status).
* Returns 0 on error (which includes the cases that timeout has been reached
* or a response with 'waiting' status has been received).
*/
static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
OSSL_CMP_MSG **rep, int *checkAfter)
@ -364,7 +364,7 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
}
} else if (is_crep_with_waiting(prep, rid)
|| ossl_cmp_is_error_with_waiting(prep)) {
/* status cannot be 'waiting' at this point */
/* received status must not be 'waiting' */
(void)ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection,
OSSL_CMP_CTX_FAILINFO_badRequest,
"polling already started",
@ -393,12 +393,12 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
}
static int save_senderNonce_if_waiting(OSSL_CMP_CTX *ctx,
OSSL_CMP_MSG *rep, int rid)
const OSSL_CMP_MSG *rep, int rid)
{
/*
* LWCMP section 4.4 states: the senderNonce of the preceding request
* message because this value will be needed for checking the recipNonce
* of the final response to be received after polling.
* Lightweight CMP Profile section 4.4 states: the senderNonce of the
* preceding request message because this value will be needed for checking
* the recipNonce of the final response to be received after polling.
*/
if ((is_crep_with_waiting(rep, rid)
|| ossl_cmp_is_error_with_waiting(rep))
@ -409,8 +409,8 @@ static int save_senderNonce_if_waiting(OSSL_CMP_CTX *ctx,
}
/*
* send request and get response possibly with polling initiated by error msg.
* Polling for ip/cp/kup/ with 'waiting' status is handled elsewhere.
* Send request and get response possibly with polling initiated by error msg.
* Polling for ip/cp/kup/ with 'waiting' status is handled by cert_response().
*/
static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
OSSL_CMP_MSG **rep, int expected_type)
@ -420,12 +420,9 @@ static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
return 0;
if (ossl_cmp_is_error_with_waiting(*rep)) {
if (!save_senderNonce_if_waiting(ctx, *rep, -1 /* rid */))
if (!save_senderNonce_if_waiting(ctx, *rep, OSSL_CMP_CERTREQID_NONE))
return 0;
/*
* not modifying ctx->status during the certConf & error exchange,
* because these additional exchanges should not change the status.
*/
/* not modifying ctx->status during certConf and error exchanges */
if (expected_type != OSSL_CMP_PKIBODY_PKICONF
&& !save_statusInfo(ctx, (*rep)->body->value.error->pKIStatusInfo))
return 0;
@ -433,7 +430,7 @@ static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
OSSL_CMP_MSG_free(*rep);
*rep = NULL;
if (poll_for_response(ctx, 1 /* can sleep */, -1 /* rid */,
if (poll_for_response(ctx, 1 /* can sleep */, OSSL_CMP_CERTREQID_NONE,
rep, NULL /* checkAfter */) <= 0) {
ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED);
return 0;
@ -462,8 +459,8 @@ int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId,
if (certConf == NULL)
goto err;
res = send_receive_also_delayed(ctx, certConf,
&PKIconf, OSSL_CMP_PKIBODY_PKICONF);
res = send_receive_also_delayed(ctx, certConf, &PKIconf,
OSSL_CMP_PKIBODY_PKICONF);
err:
OSSL_CMP_MSG_free(certConf);
@ -683,10 +680,10 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
return 0;
si = crep->status;
if (rid == OSSL_CMP_CERTREQID_NONE) {
if (rid == OSSL_CMP_CERTREQID_NONE) {
/* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */
rid = ossl_cmp_asn1_get_int(crep->certReqId);
if (rid == OSSL_CMP_CERTREQID_NONE) {
if (rid != OSSL_CMP_CERTREQID_NONE) {
ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
return 0;
}
@ -702,7 +699,11 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
return 0;
if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting) {
/* here we allow different flavor of ip/cp/kup & error with waiting */
/*
* Here we allow both and error message with waiting indication
* as well as a certificate response with waiting indication, where
* its flavor (ip, cp, or kup) may not strictly match ir/cr/p10cr/kur.
*/
OSSL_CMP_MSG_free(*resp);
*resp = NULL;
if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) {
@ -715,12 +716,12 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
}
}
/* at this point, ip/cp/kup or error without waiting */
/* at this point, we have received ip/cp/kup/error without waiting */
if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) {
ERR_raise(ERR_LIB_CMP, CMP_R_RECEIVED_ERROR);
return 0;
}
/* here we are strict on the flavor of ip/cp/kup */
/* here we are strict on the flavor of ip/cp/kup: must match request */
if (rcvd_type != expected_type) {
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
return 0;
@ -738,8 +739,7 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
* if the CMP server returned certificates in the caPubs field, copy them
* to the context so that they can be retrieved if necessary
*/
if (crepmsg != NULL
&& crepmsg->caPubs != NULL
if (crepmsg != NULL && crepmsg->caPubs != NULL
&& !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs))
return 0;

View File

@ -76,6 +76,7 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
"error validating protection"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_SIGNATURE),
"error validating signature"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_EXPECTED_POLLREQ), "expected pollreq"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_BUILDING_OWN_CHAIN),
"failed building own chain"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY),
@ -149,6 +150,7 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
"unexpected pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_POLLREQ), "unexpected pollreq"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
"unknown algorithm id"},
@ -158,6 +160,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
"unsupported algorithm"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE),
"unsupported key type"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PKIBODY),
"unsupported pkibody"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC),
"unsupported protection alg dhbasedmac"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_VALUE_TOO_LARGE), "value too large"},

View File

@ -984,8 +984,7 @@ static int suitable_rid(const ASN1_INTEGER *certReqId, int rid)
return 1;
trid = ossl_cmp_asn1_get_int(certReqId);
if (trid == OSSL_CMP_CERTREQID_NONE) {
if (trid < OSSL_CMP_CERTREQID_NONE) {
ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
return 0;
}

View File

@ -22,9 +22,9 @@
/* the context for the generic CMP server */
struct ossl_cmp_srv_ctx_st
{
void *custom_ctx; /* pointer to application-specific server context */
OSSL_CMP_CTX *ctx; /* Client CMP context, reusing transactionID etc. */
int certReqId; /* id of last ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */
OSSL_CMP_CTX *ctx; /* CMP client context reused for transactionID etc. */
void *custom_ctx; /* application-specific server context */
int certReqId; /* of ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */
OSSL_CMP_SRV_cert_request_cb_t process_cert_request;
OSSL_CMP_SRV_rr_cb_t process_rr;
@ -32,8 +32,8 @@ struct ossl_cmp_srv_ctx_st
OSSL_CMP_SRV_error_cb_t process_error;
OSSL_CMP_SRV_certConf_cb_t process_certConf;
OSSL_CMP_SRV_pollReq_cb_t process_pollReq;
OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction;
OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery;
OSSL_CMP_SRV_clean_transaction_cb_t clean_transaction;
int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */
int acceptUnprotected; /* Accept requests with no/invalid prot. */
@ -91,16 +91,16 @@ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
return 1;
}
int OSSL_CMP_SRV_CTX_setup_polling(OSSL_CMP_SRV_CTX *srv_ctx,
OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction,
OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery)
int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx,
OSSL_CMP_SRV_delayed_delivery_cb_t delay,
OSSL_CMP_SRV_clean_transaction_cb_t clean)
{
if (srv_ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->reset_transaction = reset_transaction;
srv_ctx->delayed_delivery = delayed_delivery;
srv_ctx->delayed_delivery = delay;
srv_ctx->clean_transaction = clean;
return 1;
}
@ -164,13 +164,13 @@ int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
return 1;
}
/* Return error msg with waiting status if polling is initiated, else NULL. */
/* return error msg with waiting status if polling is initiated, else NULL */
static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_PKISI *si = NULL;
int ret;
OSSL_CMP_PKISI *si;
OSSL_CMP_MSG *msg;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL
&& srv_ctx->delayed_delivery != NULL))
@ -180,8 +180,8 @@ static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx,
if (ret == 0 || !ossl_assert(ret != -1))
return NULL;
if ((si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL))
== NULL)
si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL);
if (si == NULL)
return NULL;
msg = ossl_cmp_error_new(srv_ctx->ctx, si, 0,
@ -236,15 +236,14 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
if ((crm = sk_OSSL_CRMF_MSG_value(reqs, OSSL_CMP_CERTREQID)) == NULL) {
if ((crm = sk_OSSL_CRMF_MSG_value(reqs, 0)) == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND);
return NULL;
}
certReqId = OSSL_CRMF_MSG_get_certReqId(crm);
if (certReqId != OSSL_CMP_CERTREQID) {
if (certReqId != OSSL_CMP_CERTREQID) { /* so far, only possible value */
ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
return 0;
return NULL;
}
}
srv_ctx->certReqId = certReqId;
@ -306,9 +305,8 @@ static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr,
OSSL_CMP_REVREQSID)) == NULL) {
details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr, 0);
if (details == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
@ -397,7 +395,7 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
} else {
if (num > 1)
ossl_cmp_warn(ctx, "All CertStatus but the first will be ignored");
status = sk_OSSL_CMP_CERTSTATUS_value(ccc, OSSL_CMP_CERTREQID);
status = sk_OSSL_CMP_CERTSTATUS_value(ccc, 0);
}
if (status != NULL) {
@ -428,7 +426,7 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
return msg;
}
/* pollreq should be handled separately, to avoid recursive call */
/* pollReq is handled separately, to avoid recursive call */
static OSSL_CMP_MSG *process_non_polling_request(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
@ -444,38 +442,41 @@ static OSSL_CMP_MSG *process_non_polling_request(OSSL_CMP_SRV_CTX *srv_ctx,
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_KUR:
if (srv_ctx->process_cert_request == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
else
rsp = process_cert_request(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_RR:
if (srv_ctx->process_rr == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
else
rsp = process_rr(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_GENM:
if (srv_ctx->process_genm == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
else
rsp = process_genm(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_ERROR:
if (srv_ctx->process_error == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
else
rsp = process_error(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_CERTCONF:
if (srv_ctx->process_certConf == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
else
rsp = process_certConf(srv_ctx, req);
break;
default:
/* Other request message types are not supported */
case OSSL_CMP_PKIBODY_POLLREQ:
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
break;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
break;
}
return rsp;
@ -500,12 +501,8 @@ static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
return NULL;
}
pr = sk_OSSL_CMP_POLLREQ_value(prc, OSSL_CMP_CERTREQID);
pr = sk_OSSL_CMP_POLLREQ_value(prc, 0);
certReqId = ossl_cmp_asn1_get_int(pr->certReqId);
if (certReqId != srv_ctx->certReqId) {
ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
return NULL;
}
if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId,
&orig_req, &check_after))
return NULL;
@ -604,8 +601,11 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
|| !OSSL_CMP_CTX_set1_senderNonce(ctx, NULL))
goto err;
if (srv_ctx->reset_transaction != NULL)
(void)srv_ctx->reset_transaction(srv_ctx);
if (srv_ctx->clean_transaction != NULL
&& !srv_ctx->clean_transaction(srv_ctx, NULL)) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
goto err;
}
break;
default:
@ -628,7 +628,7 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
if (req_type == OSSL_CMP_PKIBODY_POLLREQ) {
if (srv_ctx->process_pollReq == NULL)
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
else
rsp = process_pollReq(srv_ctx, req);
} else {
@ -693,8 +693,7 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
/* fall through */
case OSSL_CMP_PKIBODY_ERROR:
if (rsp != NULL
&& ossl_cmp_is_error_with_waiting(rsp))
if (rsp != NULL && ossl_cmp_is_error_with_waiting(rsp))
break;
/* fall through */
@ -702,12 +701,13 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
case OSSL_CMP_PKIBODY_PKICONF:
case OSSL_CMP_PKIBODY_GENP:
/* Other terminating response message types are not supported */
srv_ctx->certReqId = OSSL_CMP_CERTREQID_INVALID;
/* Prepare for next transaction, ignoring any errors here: */
if (srv_ctx->clean_transaction != NULL)
(void)srv_ctx->clean_transaction(srv_ctx, ctx->transactionID);
(void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL);
(void)OSSL_CMP_CTX_set1_senderNonce(ctx, NULL);
ctx->status = OSSL_CMP_PKISTATUS_unspecified; /* transaction closed */
if (srv_ctx->reset_transaction != NULL)
(void)srv_ctx->reset_transaction(srv_ctx);
default: /* not closing transaction in other cases */
break;

View File

@ -787,8 +787,8 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
return 0;
/*
* enable clearing irrelevant errors in attempts to validate recipient nonce
* in case of delayed delivery.
* enable clearing irrelevant errors
* in attempts to validate recipient nonce in case of delayed delivery.
*/
(void)ERR_set_mark();
/* compare received nonce with the one we sent */
@ -805,7 +805,6 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
return 0;
}
}
/* discard any intermediate error while trying to check recipient nonce */
(void)ERR_pop_to_mark();
/* if not yet present, learn transactionID */

View File

@ -227,6 +227,7 @@ CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash
CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf
CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection
CMP_R_ERROR_VALIDATING_SIGNATURE:171:error validating signature
CMP_R_EXPECTED_POLLREQ:104:expected pollreq
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
@ -275,12 +276,14 @@ CMP_R_UNCLEAN_CTX:191:unclean ctx
CMP_R_UNEXPECTED_CERTPROFILE:196:unexpected certprofile
CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
CMP_R_UNEXPECTED_POLLREQ:105:unexpected pollreq
CMP_R_UNEXPECTED_PVNO:153:unexpected pvno
CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus
CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm
CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type
CMP_R_UNSUPPORTED_PKIBODY:101:unsupported pkibody
CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\
unsupported protection alg dhbasedmac
CMP_R_VALUE_TOO_LARGE:175:value too large

View File

@ -12,10 +12,10 @@ OSSL_CMP_SRV_certConf_cb_t,
OSSL_CMP_SRV_genm_cb_t,
OSSL_CMP_SRV_error_cb_t,
OSSL_CMP_SRV_pollReq_cb_t,
OSSL_CMP_SRV_reset_transaction_cb_t,
OSSL_CMP_SRV_delayed_delivery_cb_t,
OSSL_CMP_SRV_CTX_init,
OSSL_CMP_SRV_CTX_setup_polling,
OSSL_CMP_SRV_delayed_delivery_cb_t,
OSSL_CMP_SRV_clean_transaction_cb_t,
OSSL_CMP_SRV_CTX_init_trans,
OSSL_CMP_SRV_CTX_get0_cmp_ctx,
OSSL_CMP_SRV_CTX_get0_custom_ctx,
OSSL_CMP_SRV_CTX_set_send_unprotected_errors,
@ -67,9 +67,6 @@ OSSL_CMP_SRV_CTX_set_grant_implicit_confirm
int certReqId,
OSSL_CMP_MSG **certReq,
int64_t *check_after);
typedef int (*OSSL_CMP_SRV_reset_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx);
typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req);
int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
OSSL_CMP_SRV_rr_cb_t process_rr,
@ -77,9 +74,13 @@ OSSL_CMP_SRV_CTX_set_grant_implicit_confirm
OSSL_CMP_SRV_error_cb_t process_error,
OSSL_CMP_SRV_certConf_cb_t process_certConf,
OSSL_CMP_SRV_pollReq_cb_t process_pollReq);
int OSSL_CMP_SRV_CTX_setup_polling(OSSL_CMP_SRV_CTX *srv_ctx,
OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction,
OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery);
typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req);
typedef int (*OSSL_CMP_SRV_clean_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const ASN1_OCTET_STRING *id);
int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx,
OSSL_CMP_SRV_delayed_delivery_cb_t delay,
OSSL_CMP_SRV_clean_transaction_cb_t clean);
OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
@ -122,8 +123,19 @@ All arguments except I<srv_ctx> may be NULL.
If a callback for some message type is not given this means that the respective
type of CMP message is not supported by the server.
OSSL_CMP_SRV_CTX_setup_polling() sets in the given I<srv_ctx> callback functions
for reseting transaction and intitiating delayed delivery.
OSSL_CMP_SRV_CTX_init_trans() sets in I<srv_ctx> the optional callback
functions for initiating delayed delivery and cleaning up a transaction.
If the <delay> function is NULL then delivery of responses is never delayed.
Otherwise I<delay> takes a custom server context and a request message as input.
It must return 1 if delivery of the respecive response shall be delayed,
0 if not, and -1 on error.
If the <clean> function is NULL then no specific cleanup is performed.
Otherwise I<clean> takes a custom server context and a transaction ID pointer
as input, where the pointer is NULL in case a new transaction is being started
and otherwise provides the ID of the transaction being terminated.
The <clean> function should reset the respective portions of the state
and free related memory.
It must return 1 on success and 0 on error.
OSSL_CMP_SRV_CTX_get0_cmp_ctx() returns the B<OSSL_CMP_CTX> from the I<srv_ctx>.
@ -168,6 +180,10 @@ All other functions return 1 on success, 0 on error.
The OpenSSL CMP support was added in OpenSSL 3.0.
OSSL_CMP_SRV_CTX_init_trans()
supporting delayed delivery of all types of response messages
was added in OpenSSL 3.3.
=head1 COPYRIGHT
Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.

View File

@ -78,8 +78,8 @@ Typically I<crm> is NULL, then the template ingredients are taken from I<ctx>
and need to be filled in using L<OSSL_CMP_CTX_set1_subjectName(3)>,
L<OSSL_CMP_CTX_set0_newPkey(3)>, L<OSSL_CMP_CTX_set1_oldCert(3)>, etc.
For P10CR, L<OSSL_CMP_CTX_set1_p10CSR(3)> needs to be used instead.
The enrollment session may be blocked by sleeping until the addressed
CA (or an intermediate PKI component) can fully process and answer the request.
The enrollment session may be blocked (with polling and sleeping in between)
until the server side can fully process and ultimately answer the request.
OSSL_CMP_try_certreq() is an alternative to the above functions that is
more flexible regarding what to do after receiving a checkAfter value.
@ -118,11 +118,15 @@ We take "accepted" and "grantedWithMods" as clear success and handle
typically return them as an indication that the certificate was already revoked.
"rejection" is a clear error. The values "waiting" and "keyUpdateWarning"
make no sense for revocation and thus are treated as an error as well.
The revocation session may be blocked (with polling and sleeping in between)
until the server can fully process and ultimately answer the request.
OSSL_CMP_exec_GENM_ses() sends a genm general message containing the sequence of
infoType and infoValue pairs (InfoTypeAndValue; short: B<ITAV>)
optionally provided in the I<ctx> using L<OSSL_CMP_CTX_push0_genm_ITAV(3)>.
On success it records in I<ctx> the status B<OSSL_CMP_PKISTATUS_accepted>
The message exchange may be blocked (with polling and sleeping in between)
until the server can fully process and ultimately answer the request.
On success the function records in I<ctx> status B<OSSL_CMP_PKISTATUS_accepted>
and returns the list of B<ITAV>s received in a genp response message.
This can be used, for instance,
with infoType C<signKeyPairTypes> to obtain the set of signature
@ -216,6 +220,9 @@ The OpenSSL CMP support was added in OpenSSL 3.0.
OSSL_CMP_get1_caCerts() and OSSL_CMP_get1_rootCaKeyUpdate()
were added in OpenSSL 3.2.
Support for delayed delivery of all types of response messages
was added in OpenSSL 3.3.
=head1 COPYRIGHT
Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.

View File

@ -155,13 +155,14 @@ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
return 0;
}
static int reset_transaction(OSSL_CMP_SRV_CTX *srv_ctx)
static int clean_transaction(ossl_unused OSSL_CMP_SRV_CTX *srv_ctx,
ossl_unused const ASN1_OCTET_STRING *id)
{
return 1;
}
static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
static int delayed_delivery(ossl_unused OSSL_CMP_SRV_CTX *srv_ctx,
ossl_unused const OSSL_CMP_MSG *req)
{
return 0;
}
@ -195,8 +196,8 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
&& OSSL_CMP_SRV_CTX_init(srv_ctx, NULL, process_cert_request,
process_rr, process_genm, process_error,
process_certConf, process_pollReq)
&& OSSL_CMP_SRV_CTX_setup_polling(srv_ctx, reset_transaction,
delayed_delivery))
&& OSSL_CMP_SRV_CTX_init_trans(srv_ctx, delayed_delivery,
clean_transaction))
OSSL_CMP_MSG_free(OSSL_CMP_SRV_process_request(srv_ctx, msg));
OSSL_CMP_CTX_free(client_ctx);

View File

@ -469,9 +469,6 @@ typedef int (*OSSL_CMP_SRV_pollReq_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req, int certReqId,
OSSL_CMP_MSG **certReq,
int64_t *check_after);
typedef int (*OSSL_CMP_SRV_reset_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx);
typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req);
int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
OSSL_CMP_SRV_rr_cb_t process_rr,
@ -479,9 +476,13 @@ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
OSSL_CMP_SRV_error_cb_t process_error,
OSSL_CMP_SRV_certConf_cb_t process_certConf,
OSSL_CMP_SRV_pollReq_cb_t process_pollReq);
int OSSL_CMP_SRV_CTX_setup_polling(OSSL_CMP_SRV_CTX *srv_ctx,
OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction,
OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery);
typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req);
typedef int (*OSSL_CMP_SRV_clean_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const ASN1_OCTET_STRING *id);
int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx,
OSSL_CMP_SRV_delayed_delivery_cb_t delay,
OSSL_CMP_SRV_clean_transaction_cb_t clean);
OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx);
int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx,

View File

@ -55,6 +55,7 @@
# define CMP_R_ERROR_UNEXPECTED_CERTCONF 160
# define CMP_R_ERROR_VALIDATING_PROTECTION 140
# define CMP_R_ERROR_VALIDATING_SIGNATURE 171
# define CMP_R_EXPECTED_POLLREQ 104
# define CMP_R_FAILED_BUILDING_OWN_CHAIN 164
# define CMP_R_FAILED_EXTRACTING_PUBKEY 141
# define CMP_R_FAILURE_OBTAINING_RANDOM 110
@ -101,12 +102,14 @@
# define CMP_R_UNEXPECTED_CERTPROFILE 196
# define CMP_R_UNEXPECTED_PKIBODY 133
# define CMP_R_UNEXPECTED_PKISTATUS 185
# define CMP_R_UNEXPECTED_POLLREQ 105
# define CMP_R_UNEXPECTED_PVNO 153
# define CMP_R_UNKNOWN_ALGORITHM_ID 134
# define CMP_R_UNKNOWN_CERT_TYPE 135
# define CMP_R_UNKNOWN_PKISTATUS 186
# define CMP_R_UNSUPPORTED_ALGORITHM 136
# define CMP_R_UNSUPPORTED_KEY_TYPE 137
# define CMP_R_UNSUPPORTED_PKIBODY 101
# define CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC 154
# define CMP_R_VALUE_TOO_LARGE 175
# define CMP_R_VALUE_TOO_SMALL 177

View File

@ -194,7 +194,7 @@ static int test_exec_IR_ses(void)
return result;
}
static int test_exec_any_ses_poll(int req_type, int check_after,
static int test_exec_REQ_ses_poll(int req_type, int check_after,
int poll_count, int total_timeout,
int expect)
{
@ -206,14 +206,10 @@ static int test_exec_any_ses_poll(int req_type, int check_after,
OSSL_CMP_CTX_set_option(fixture->cmp_ctx,
OSSL_CMP_OPT_TOTAL_TIMEOUT, total_timeout);
if (req_type == OSSL_CMP_PKIBODY_IR || req_type == OSSL_CMP_PKIBODY_CR
|| req_type == OSSL_CMP_PKIBODY_KUR
|| req_type == OSSL_CMP_PKIBODY_P10CR) {
if (req_type == OSSL_CMP_PKIBODY_IR) {
EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down);
} else if (req_type == OSSL_CMP_PKIBODY_GENM) {
EXECUTE_TEST(execute_exec_GENM_ses_test, tear_down);
} else {
result = 0;
}
return result;
}
@ -221,20 +217,20 @@ static int test_exec_any_ses_poll(int req_type, int check_after,
static int checkAfter = 1;
static int test_exec_IR_ses_poll_ok(void)
{
return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, 2, 0,
return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, 2, 0,
OSSL_CMP_PKISTATUS_accepted);
}
static int test_exec_IR_ses_poll_no_timeout(void)
{
return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter,
return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter,
2 /* pollCount */, checkAfter + 4,
OSSL_CMP_PKISTATUS_accepted);
}
static int test_exec_IR_ses_poll_total_timeout(void)
{
return !test_exec_any_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter + 1,
return !test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter + 1,
3 /* pollCount */, checkAfter + 6,
OSSL_CMP_PKISTATUS_waiting);
}
@ -419,20 +415,20 @@ static int test_try_certreq_poll_abort(void)
static int test_exec_GENM_ses_poll_ok(void)
{
return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter, 2, 0,
return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter, 2, 0,
OSSL_CMP_PKISTATUS_accepted);
}
static int test_exec_GENM_ses_poll_no_timeout(void)
{
return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter,
return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter,
1 /* pollCount */, checkAfter + 1,
OSSL_CMP_PKISTATUS_accepted);
}
static int test_exec_GENM_ses_poll_total_timeout(void)
{
return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter + 1,
return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter + 1,
3 /* pollCount */, checkAfter + 2,
OSSL_CMP_PKISTATUS_waiting);
}

View File

@ -76,7 +76,7 @@ static int execute_test_handle_request(CMP_SRV_TEST_FIXTURE *fixture)
if (!TEST_true(OSSL_CMP_SRV_CTX_init(ctx, dummy_custom_ctx,
process_cert_request, NULL, NULL,
NULL, NULL, NULL))
|| !TEST_true(OSSL_CMP_SRV_CTX_setup_polling(ctx, NULL, NULL))
|| !TEST_true(OSSL_CMP_SRV_CTX_init_trans(ctx, NULL, NULL))
|| !TEST_ptr(custom_ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(ctx))
|| !TEST_int_eq(strcmp(custom_ctx, dummy_custom_ctx), 0))
goto end;

View File

@ -5540,6 +5540,6 @@ OSSL_CMP_CTX_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_HDR_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_ITAV_new0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_ITAV_get0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_SRV_CTX_setup_polling ? 3_3_0 EXIST::FUNCTION:CMP
OSSL_CMP_SRV_CTX_init_trans ? 3_3_0 EXIST::FUNCTION:CMP
EVP_DigestSqueeze ? 3_3_0 EXIST::FUNCTION:
ERR_pop ? 3_3_0 EXIST::FUNCTION: