* 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*
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;
}
/*
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;
&& (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;
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,
{
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;
}
ctx->req = NULL;
*check_after = 0;
} else {
- *req = NULL;
*check_after = ctx->checkAfterTime;
}
return 1;
&& 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);
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;
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
* 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)
}
} 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",
}
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))
}
/*
- * 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)
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;
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;
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);
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;
}
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) {
}
}
- /* 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;
* 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;
"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),
{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"},
"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"},
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;
}
/* 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;
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. */
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;
}
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))
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,
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;
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;
}
} 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) {
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)
{
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;
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;
|| !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:
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 {
/* 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 */
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;
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 */
return 0;
}
}
- /* discard any intermediate error while trying to check recipient nonce */
(void)ERR_pop_to_mark();
/* if not yet present, learn transactionID */
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
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
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,
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,
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);
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>.
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.
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.
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
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.
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;
}
&& 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);
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,
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,
# 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
# 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
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)
{
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;
}
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);
}
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);
}
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;
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: