OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx,
const char *propq);
void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);
+OSSL_CMP_MSG *ossl_cmp_mock_server_perform(OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req);
int ossl_cmp_mock_srv_set1_refCert(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status,
int fail_info, const char *text);
int ossl_cmp_mock_srv_set_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype);
+int ossl_cmp_mock_srv_set_useBadProtection(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype);
int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count);
int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec);
#include "apps.h"
#include "cmp_mock_srv.h"
+#include "../../crypto/cmp/cmp_local.h" /* for access to msg->protection */
#include <openssl/cmp.h>
#include <openssl/err.h>
X509 *oldWithNew; /* to return in oldWithNew of rootKeyUpdate */
OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */
int sendError; /* send error response on given request type */
+ int useBadProtection; /* use bad protection on given response type */
OSSL_CMP_MSG *req; /* original request message during polling */
int pollCount; /* number of polls before actual cert response */
int curr_pollCount; /* number of polls so far for current request */
goto err;
ctx->sendError = -1;
+ ctx->useBadProtection = -1;
/* all other elements are initialized to 0 or NULL, respectively */
return ctx;
return 1;
}
+int ossl_cmp_mock_srv_set_useBadProtection(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype)
+{
+ mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ /* might check bodytype, but this would require exporting all body types */
+ ctx->useBadProtection = bodytype;
+ return 1;
+}
+
int ossl_cmp_mock_srv_set_pollCount(OSSL_CMP_SRV_CTX *srv_ctx, int count)
{
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
return 1;
}
+OSSL_CMP_MSG *ossl_cmp_mock_server_perform(OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_SRV_CTX *srv_ctx = OSSL_CMP_CTX_get_transfer_cb_arg(ctx);
+ OSSL_CMP_MSG *rsp = OSSL_CMP_CTX_server_perform(ctx, req);
+
+ if (srv_ctx != NULL && rsp != NULL) {
+ mock_srv_ctx *mock_ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+ if (mock_ctx != NULL && OSSL_CMP_MSG_get_bodytype(rsp) == mock_ctx->useBadProtection) {
+ ASN1_BIT_STRING *prot = rsp->protection;
+
+ if (prot != NULL && prot->length != 0 && prot->data != NULL)
+ prot->data[0] ^= 0x80; /* flip most significant bit of the first byte */
+ }
+ }
+ return rsp;
+}
+
OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq)
{
OSSL_CMP_SRV_CTX *srv_ctx = OSSL_CMP_SRV_CTX_new(libctx, propq);
int time_left;
OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb;
+ ctx->status = OSSL_CMP_PKISTATUS_trans;
#ifndef OPENSSL_NO_HTTP
if (transfer_cb == NULL)
transfer_cb = OSSL_CMP_MSG_http_perform;
/* should print error queue since transfer_cb may call ERR_clear_error() */
OSSL_CMP_CTX_print_errors(ctx);
- if (ctx->server != NULL)
+ if (ctx->server != NULL || ctx->transfer_cb != NULL)
ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str);
*rep = (*transfer_cb)(ctx, req);
return 0;
}
+ ctx->status = OSSL_CMP_PKISTATUS_checking_response;
bt = OSSL_CMP_MSG_get_bodytype(*rep);
/*
* The body type in the 'bt' variable is not yet verified.
"received 'waiting' PKIStatus, starting to poll for response");
*rep = NULL;
for (;;) {
+ int bak = ctx->status;
+
+ ctx->status = OSSL_CMP_PKISTATUS_request;
if ((preq = ossl_cmp_pollReq_new(ctx, rid)) == NULL)
goto err;
if (!send_receive_check(ctx, preq, &prep, OSSL_CMP_PKIBODY_POLLREP))
goto err;
+ ctx->status = bak;
/* handle potential pollRep */
if (OSSL_CMP_MSG_get_bodytype(prep) == OSSL_CMP_PKIBODY_POLLREP) {
int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL));
if (time_left <= 0) {
+ ctx->status = OSSL_CMP_PKISTATUS_trans;
ERR_raise(ERR_LIB_CMP, CMP_R_TOTAL_TIMEOUT);
goto err;
}
OSSL_CMP_MSG *certConf;
OSSL_CMP_MSG *PKIconf = NULL;
int res = 0;
+ int bak = ctx->status;
+ ctx->status = OSSL_CMP_PKISTATUS_request;
/* OSSL_CMP_certConf_new() also checks if all necessary options are set */
certConf = ossl_cmp_certConf_new(ctx, certReqId, fail_info, txt);
if (certConf == NULL)
res = send_receive_also_delayed(ctx, certConf, &PKIconf,
OSSL_CMP_PKIBODY_PKICONF);
+ if (res)
+ ctx->status = bak;
+
err:
OSSL_CMP_MSG_free(certConf);
OSSL_CMP_MSG_free(PKIconf);
OSSL_CMP_MSG *PKIconf = NULL;
int res = 0;
+ ctx->status = OSSL_CMP_PKISTATUS_request;
/* not overwriting ctx->status on error exchange */
if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt)) == NULL)
goto err;
res = send_receive_also_delayed(ctx, error,
&PKIconf, OSSL_CMP_PKIBODY_PKICONF);
+ ctx->status = OSSL_CMP_PKISTATUS_rejected_by_client;
err:
OSSL_CMP_MSG_free(error);
ERR_raise_data(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_ACCEPTED,
"rejecting newly enrolled cert with subject: %s; %s",
subj, txt);
- ctx->status = OSSL_CMP_PKISTATUS_rejection;
+ ctx->status = OSSL_CMP_PKISTATUS_rejected_by_client;
ret = 0;
}
OPENSSL_free(subj);
if ((req = ossl_cmp_certreq_new(ctx, req_type, crm)) == NULL)
return 0;
- ctx->status = OSSL_CMP_PKISTATUS_trans;
res = send_receive_check(ctx, req, p_rep, rep_type);
OSSL_CMP_MSG_free(req);
return res;
if ((rr = ossl_cmp_rr_new(ctx)) == NULL)
goto end;
- ctx->status = OSSL_CMP_PKISTATUS_trans;
if (!send_receive_also_delayed(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
goto end;
if ((genm = ossl_cmp_genm_new(ctx)) == NULL)
goto err;
- ctx->status = OSSL_CMP_PKISTATUS_trans;
if (!send_receive_also_delayed(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
goto err;
ctx->status = OSSL_CMP_PKISTATUS_accepted;
return valid;
}
+/* checks protection of msg but not cert revocation nor cert chain */
static int check_msg_given_cert(const OSSL_CMP_CTX *ctx, X509 *cert,
const OSSL_CMP_MSG *msg)
{
return cert_acceptable(ctx, "previously validated", "sender cert",
- cert, NULL, NULL, msg)
- && (check_cert_path(ctx, ctx->trusted, cert)
- || check_cert_path_3gpp(ctx, msg, cert));
+ cert, NULL, NULL, msg);
}
/*-
(void)ERR_set_mark();
ctx->log_cb = NULL; /* temporarily disable logging */
- /*
- * try first cached scrt, used successfully earlier in same transaction,
- * for validating this and any further msgs where extraCerts may be left out
- */
if (scrt != NULL) {
+ /*-
+ * try first using cached message sender cert (in 'scrt' variable),
+ * which was used successfully earlier in the same transaction
+ * (assuming that the certificate itself was not revoked meanwhile and
+ * is a good guess for use in validating also the current message)
+ */
if (check_msg_given_cert(ctx, scrt, msg)) {
ctx->log_cb = backup_log_cb;
(void)ERR_pop_to_mark();
=item B<-no_cache_extracerts>
Do not cache certificates in the extraCerts field of CMP messages received.
-By default, they are kept as they may be helful for validating further messages.
+By default, they are kept as they may be helpful for validating further messages.
This option applies to both CMP clients and the mock server.
+In any case, after successfully validating an incoming message, its protection
+certificate (if any) is cached for reuse with validation of subsequent messages.
+This is done not only for efficiency but also
+to eliminate the need for the sender to include its certificate and related chain
+in the extraCerts field of subsequent messages of the same transaction.
+
=item B<-srvcertout> I<filename>
The file where to save the successfully validated certificate, if any,
Do not cache certificates received in the extraCerts CMP message field.
Otherwise they are stored to potentially help validate further messages.
+In any case, after successfully validating an incoming message, its protection
+certificate (if any) is cached for reuse with validation of subsequent messages.
+This is done not only for efficiency but also
+to eliminate the need for the sender to include its certificate and related chain
+in the extraCerts field of subsequent messages of the same transaction.
+
=back
OSSL_CMP_CTX_get_option() reads the current value of the given option
* -- CertReqMsg
* }
*/
+#define OSSL_CMP_PKISTATUS_rejected_by_client -5
+#define OSSL_CMP_PKISTATUS_checking_response -4
#define OSSL_CMP_PKISTATUS_request -3
#define OSSL_CMP_PKISTATUS_trans -2
#define OSSL_CMP_PKISTATUS_unspecified -1
static X509 *server_cert = NULL;
static EVP_PKEY *client_key = NULL;
static X509 *client_cert = NULL;
-static unsigned char ref[CMP_TEST_REFVALUE_LENGTH];
+static unsigned char ref[CMP_TEST_REFVALUE_LENGTH]; /* not actually used */
/*
* For these unit tests, the client abandons message protection, and for
OPENSSL_free(fixture);
}
+static int set_simple_trust(OSSL_CMP_CTX *ctx, X509 *trusted)
+{
+ X509_STORE *ts = X509_STORE_new();
+ X509_VERIFY_PARAM *vpm;
+
+ /*
+ * not simply using OSSL_CMP_CTX_set1_srvCert() (to pin the server cert)
+ * in order to make sure that validated server cert gets cached,
+ * which is needed for the negative test case test_exec_KUR_bad_pkiConf_protection
+ */
+ if (ts == NULL || !X509_STORE_add_cert(ts, trusted))
+ goto err;
+
+ vpm = X509_STORE_get0_param(ts);
+ if (!X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME | X509_V_FLAG_PARTIAL_CHAIN)
+ || !OSSL_CMP_CTX_set0_trusted(ctx, ts))
+ goto err;
+
+ return 1;
+err:
+ X509_STORE_free(ts);
+ return 0;
+}
+
static CMP_SES_TEST_FIXTURE *set_up(const char *const test_case_name)
{
CMP_SES_TEST_FIXTURE *fixture;
goto err;
if (!TEST_ptr(fixture->cmp_ctx = ctx = OSSL_CMP_CTX_new(libctx, NULL))
|| !OSSL_CMP_CTX_set_log_cb(fixture->cmp_ctx, print_to_bio_out)
- || !OSSL_CMP_CTX_set_transfer_cb(ctx, OSSL_CMP_CTX_server_perform)
+ /* using default verbosity: OSSL_CMP_LOG_INFO */
+ || !OSSL_CMP_CTX_set_transfer_cb(ctx, ossl_cmp_mock_server_perform)
|| !OSSL_CMP_CTX_set_transfer_cb_arg(ctx, fixture->srv_ctx)
|| !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_SEND, 1)
- || !OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1)
|| !OSSL_CMP_CTX_set1_oldCert(ctx, client_cert)
|| !OSSL_CMP_CTX_set1_pkey(ctx, client_key)
/* client_key is by default used also for newPkey */
- || !OSSL_CMP_CTX_set1_srvCert(ctx, server_cert)
- || !OSSL_CMP_CTX_set1_referenceValue(ctx, ref, sizeof(ref)))
+ || !set_simple_trust(ctx, server_cert)
+ || !OSSL_CMP_CTX_set1_referenceValue(ctx, ref, sizeof(ref))) /* not actually needed */
goto err;
fixture->req_type = -1;
return fixture;
int status = OSSL_CMP_CTX_get_status(ctx);
print_errors_PKIStatusInfo(ctx);
- if (!TEST_int_eq(status, fixture->expected)
- && !(fixture->expected == OSSL_CMP_PKISTATUS_waiting
- && TEST_int_eq(status, OSSL_CMP_PKISTATUS_trans)))
+ if (!TEST_int_eq(status, fixture->expected))
return 0;
if (fixture->expected != OSSL_CMP_PKISTATUS_accepted)
return TEST_ptr_null(res);
static int test_exec_IR_ses_poll_total_timeout(void)
{
- return !test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter,
+ return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter,
3 /* pollCount */, checkAfter + 4,
- OSSL_CMP_PKISTATUS_waiting);
+ OSSL_CMP_PKISTATUS_trans);
}
static int test_exec_CR_ses(int implicit_confirm, int granted, int reject)
&& test_exec_CR_ses(1, 1 /* granted */, 0);
}
-static int test_exec_KUR_ses(int transfer_error, int pubkey, int raverified)
+/* the KUR transactions include certConf/pkiConf */
+static int test_exec_KUR_ses(int transfer_error, int server_use_bad_protection,
+ int pubkey, int raverified)
{
SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
fixture->req_type = OSSL_CMP_PKIBODY_KUR;
if (transfer_error)
OSSL_CMP_CTX_set_transfer_cb_arg(fixture->cmp_ctx, NULL);
+ (void)ossl_cmp_mock_srv_set_useBadProtection(fixture->srv_ctx, server_use_bad_protection);
+
if (pubkey) {
EVP_PKEY *key = raverified /* wrong key */ ? server_key : client_key;
if (pubkey || raverified)
OSSL_CMP_CTX_set_option(fixture->cmp_ctx, OSSL_CMP_OPT_POPO_METHOD,
OSSL_CRMF_POPO_RAVERIFIED);
- fixture->expected = transfer_error ? OSSL_CMP_PKISTATUS_trans : raverified ? OSSL_CMP_PKISTATUS_rejection
+ fixture->expected = transfer_error ? OSSL_CMP_PKISTATUS_trans : raverified ? (pubkey ? OSSL_CMP_PKISTATUS_rejected_by_client : OSSL_CMP_PKISTATUS_rejection)
+ : server_use_bad_protection != -1 ? OSSL_CMP_PKISTATUS_checking_response
: OSSL_CMP_PKISTATUS_accepted;
EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down);
return result;
static int test_exec_KUR_ses_ok(void)
{
- return test_exec_KUR_ses(0, 0, 0);
+ return test_exec_KUR_ses(0, -1, 0, 0);
}
static int test_exec_KUR_ses_transfer_error(void)
{
- return test_exec_KUR_ses(1, 0, 0);
+ return test_exec_KUR_ses(1, -1, 0, 0);
+}
+
+static int test_exec_KUR_bad_pkiConf_protection(void)
+{
+ return test_exec_KUR_ses(0, OSSL_CMP_PKIBODY_PKICONF, 0, 0);
}
static int test_exec_KUR_ses_wrong_popo(void)
{
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* cf ossl_cmp_verify_popo() */
- return test_exec_KUR_ses(0, 0, 1);
+ return test_exec_KUR_ses(0, -1, 0, 1);
#else
return 1;
#endif
static int test_exec_KUR_ses_pub(void)
{
- return test_exec_KUR_ses(0, 1, 0);
+ return test_exec_KUR_ses(0, -1, 1, 0);
}
static int test_exec_KUR_ses_wrong_pub(void)
{
- return test_exec_KUR_ses(0, 1, 1);
+ return test_exec_KUR_ses(0, -1, 1, 1);
}
static int test_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
fixture->req_type = OSSL_CMP_PKIBODY_P10CR;
- fixture->expected = reject ? OSSL_CMP_PKISTATUS_rejection
+ fixture->expected = reject ? OSSL_CMP_PKISTATUS_rejected_by_client
: OSSL_CMP_PKISTATUS_accepted;
ctx = fixture->cmp_ctx;
if (!TEST_ptr(csr = load_csr_der(pkcs10_f, libctx))
{
return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter,
3 /* pollCount */, checkAfter + 2,
- OSSL_CMP_PKISTATUS_waiting);
+ OSSL_CMP_PKISTATUS_trans);
}
static int test_exec_GENM_ses(int transfer_error, int total_timeout, int expect)
|| !TEST_ptr(server_cert = load_cert_pem(server_cert_f, libctx))
|| !TEST_ptr(client_key = load_pkey_pem(client_key_f, libctx))
|| !TEST_ptr(client_cert = load_cert_pem(client_cert_f, libctx))
- || !TEST_int_eq(1, RAND_bytes_ex(libctx, ref, sizeof(ref), 0))) {
+ || !TEST_int_eq(1, RAND_bytes_ex(libctx, ref, sizeof(ref), 0))) { /* not actually used */
cleanup_tests();
return 0;
}
ADD_TEST(test_exec_IR_ses_poll_total_timeout);
ADD_TEST(test_exec_KUR_ses_ok);
ADD_TEST(test_exec_KUR_ses_transfer_error);
+ ADD_TEST(test_exec_KUR_bad_pkiConf_protection);
ADD_TEST(test_exec_KUR_ses_wrong_popo);
ADD_TEST(test_exec_KUR_ses_pub);
ADD_TEST(test_exec_KUR_ses_wrong_pub);
0,using popo 1 with -centralkeygen, -section,, -cmd,cr,, -centralkeygen, -popo,1, -newkeyout,_RESULT_DIR/newkeyout.pem
1, using popo -1 redundantly with -centralkeygen, -section,, -cmd,cr,, -centralkeygen, -popo,-1, -newkeyout,_RESULT_DIR/newkeyout2.pem
1, using popo -1 alternatively to -centralkeygen, -section,, -cmd,cr,, -popo,-1, -newkeyout,_RESULT_DIR/newkeyout3.pem, -newkeypass,pass:12345, -certout,_RESULT_DIR/test.cert3.pem
-1, using centrally generated key (and cert) , -section,, -cmd,cr,,-cert,_RESULT_DIR/test.cert3.pem, -key,_RESULT_DIR/newkeyout3.pem, -keypass,pass:12345
+1, using centrally generated key (and cert) with existing chain, -section,, -cmd,cr,,-cert,_RESULT_DIR/test.cert3.pem, -key,_RESULT_DIR/newkeyout3.pem, -keypass,pass:12345, -extracerts, issuing.crt
+1, using centrally generated key (and cert) without giving chain (requires sender cert caching), -section,, -cmd,cr,,-cert,_RESULT_DIR/test.cert3.pem, -key,_RESULT_DIR/newkeyout3.pem, -keypass,pass:12345, -extracerts, ""
0, using centrally generated key with wrong password, -section,, -cmd,cr,,-cert,_RESULT_DIR/test.cert3.pem, -key,_RESULT_DIR/newkeyout3.pem, -keypass,pass:wrong
0, using popo -1 (instead of -centralkeygen) without -newkeyout, -section,, -cmd,cr,, -popo,-1,,BLANK,,BLANK,,BLANK,,BLANK