return NULL;
}
if (ctx->sendError) {
- CMPerr(0, CMP_R_ERROR_PROCESSING_MSG);
+ CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
return NULL;
}
if (ctx->sendError || ctx->certOut == NULL) {
- CMPerr(0, CMP_R_ERROR_PROCESSING_MSG);
+ CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
return 0;
}
if (ctx->sendError) {
- CMPerr(0, CMP_R_ERROR_PROCESSING_MSG);
+ CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE);
return 0;
}
if (sk_ASN1_UTF8STRING_num(errorDetails) <= 0) {
BIO_printf(bio_err, "errorDetails absent\n");
} else {
+ /* TODO could use sk_ASN1_UTF8STRING2text() if exported */
BIO_printf(bio_err, "errorDetails: ");
for (i = 0; i < sk_ASN1_UTF8STRING_num(errorDetails); i++) {
if (i > 0)
return 0;
}
if (ctx->sendError || ctx->certOut == NULL) {
- CMPerr(0, CMP_R_ERROR_PROCESSING_MSG);
+ CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE);
return 0;
}
}
if (ctx->sendError || ctx->certReq == NULL) {
*certReq = NULL;
- CMPerr(0, CMP_R_ERROR_PROCESSING_MSG);
+ CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE);
return 0;
}
LIBS=../../libcrypto
SOURCE[../../libcrypto]= cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \
cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c \
- cmp_server.c
+ cmp_server.c cmp_client.c
--- /dev/null
+/*
+ * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "cmp_local.h"
+#include "internal/cryptlib.h"
+
+/* explicit #includes not strictly needed since implied by the above: */
+#include <openssl/bio.h>
+#include <openssl/cmp.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/x509v3.h>
+
+#include "openssl/cmp_util.h"
+
+#define IS_CREP(t) ((t) == OSSL_CMP_PKIBODY_IP || (t) == OSSL_CMP_PKIBODY_CP \
+ || (t) == OSSL_CMP_PKIBODY_KUP)
+
+/*-
+ * Evaluate whether there's an exception (violating the standard) configured for
+ * handling negative responses without protection or with invalid protection.
+ * Returns 1 on acceptance, 0 on rejection, or -1 on (internal) error.
+ */
+static int unprotected_exception(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *rep,
+ int invalid_protection,
+ int expected_type /* ignored here */)
+{
+ int rcvd_type = ossl_cmp_msg_get_bodytype(rep /* may be NULL */);
+ const char *msg_type = NULL;
+
+ if (!ossl_assert(ctx != NULL && rep != NULL))
+ return -1;
+
+ if (!ctx->unprotectedErrors)
+ return 0;
+
+ switch (rcvd_type) {
+ case OSSL_CMP_PKIBODY_ERROR:
+ msg_type = "error response";
+ break;
+ case OSSL_CMP_PKIBODY_RP:
+ {
+ OSSL_CMP_PKISI *si =
+ ossl_cmp_revrepcontent_get_pkisi(rep->body->value.rp,
+ OSSL_CMP_REVREQSID);
+
+ if (si == NULL)
+ return -1;
+ if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_rejection)
+ msg_type = "revocation response message with rejection status";
+ break;
+ }
+ case OSSL_CMP_PKIBODY_PKICONF:
+ msg_type = "PKI Confirmation message";
+ break;
+ default:
+ if (IS_CREP(rcvd_type)) {
+ OSSL_CMP_CERTREPMESSAGE *crepmsg = rep->body->value.ip;
+ OSSL_CMP_CERTRESPONSE *crep =
+ ossl_cmp_certrepmessage_get0_certresponse(crepmsg,
+ -1 /* any rid */);
+
+ if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1)
+ return -1;
+ /* TODO: handle potentially multiple CertResponses in CertRepMsg */
+ if (crep == NULL)
+ return -1;
+ if (ossl_cmp_pkisi_get_status(crep->status)
+ == OSSL_CMP_PKISTATUS_rejection)
+ msg_type = "CertRepMessage with rejection status";
+ }
+ }
+ if (msg_type == NULL)
+ return 0;
+ ossl_cmp_log2(WARN, ctx, "ignoring %s protection of %s",
+ invalid_protection ? "invalid" : "missing", msg_type);
+ return 1;
+}
+
+
+/* Save error info from PKIStatusInfo field of a certresponse into ctx */
+static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si)
+{
+ int i;
+ OSSL_CMP_PKIFREETEXT *ss;
+
+ if (!ossl_assert(ctx != NULL && si != NULL))
+ return 0;
+
+ if ((ctx->status = ossl_cmp_pkisi_get_status(si)) < 0)
+ return 0;
+
+ ctx->failInfoCode = 0;
+ if (si->failInfo != NULL) {
+ for (i = 0; i <= OSSL_CMP_PKIFAILUREINFO_MAX; i++) {
+ if (ASN1_BIT_STRING_get_bit(si->failInfo, i))
+ ctx->failInfoCode |= (1 << i);
+ }
+ }
+
+ if (!ossl_cmp_ctx_set0_statusString(ctx, sk_ASN1_UTF8STRING_new_null())
+ || (ctx->statusString == NULL))
+ return 0;
+
+ ss = si->statusString; /* may be NULL */
+ for (i = 0; i < sk_ASN1_UTF8STRING_num(ss); i++) {
+ ASN1_UTF8STRING *str = sk_ASN1_UTF8STRING_value(ss, i);
+
+ if (!sk_ASN1_UTF8STRING_push(ctx->statusString, ASN1_STRING_dup(str)))
+ return 0;
+ }
+ return 1;
+}
+
+/*-
+ * Perform the generic aspects of sending a request and receiving a response.
+ * Returns 1 on success and provides the received PKIMESSAGE in *rep.
+ * Returns 0 on error.
+ * Regardless of success, caller is responsible for freeing *rep (unless NULL).
+ */
+static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
+ OSSL_CMP_MSG **rep, int expected_type)
+{
+ const char *req_type_str =
+ ossl_cmp_bodytype_to_string(ossl_cmp_msg_get_bodytype(req));
+ const char *expected_type_str = ossl_cmp_bodytype_to_string(expected_type);
+ int msg_timeout;
+ int bt;
+ time_t now = time(NULL);
+ int time_left;
+ OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb;
+
+ if (transfer_cb == NULL)
+ transfer_cb = NULL; /* TODO: will be OSSL_CMP_MSG_http_perform of chunk 10 */
+
+ *rep = NULL;
+ msg_timeout = ctx->msg_timeout; /* backup original value */
+ if ((IS_CREP(expected_type) || expected_type == OSSL_CMP_PKIBODY_POLLREP)
+ && ctx->total_timeout > 0 /* timeout is not infinite */) {
+ if (now >= ctx->end_time) {
+ CMPerr(0, CMP_R_TOTAL_TIMEOUT);
+ return 0;
+ }
+ if (!ossl_assert(ctx->end_time - time(NULL) < INT_MAX)) {
+ /* cannot really happen due to the assignment in do_certreq_seq() */
+ CMPerr(0, CMP_R_INVALID_ARGS);
+ return 0;
+ }
+ time_left = (int)(ctx->end_time - now);
+ if (ctx->msg_timeout == 0 || time_left < ctx->msg_timeout)
+ ctx->msg_timeout = time_left;
+ }
+
+ /* should print error queue since transfer_cb may call ERR_clear_error() */
+ OSSL_CMP_CTX_print_errors(ctx);
+
+ ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str);
+
+ *rep = (*transfer_cb)(ctx, req);
+ ctx->msg_timeout = msg_timeout; /* restore original value */
+
+ if (*rep == NULL) {
+ CMPerr(0, CMP_R_TRANSFER_ERROR); /* or receiving response */
+ ERR_add_error_data(1, req_type_str);
+ ERR_add_error_data(2, ", expected response: ", expected_type_str);
+ return 0;
+ }
+
+ bt = ossl_cmp_msg_get_bodytype(*rep);
+ /*
+ * The body type in the 'bt' variable is not yet verified.
+ * Still we use this preliminary value already for a progress report because
+ * the following msg verification may also produce log entries and may fail.
+ */
+ ossl_cmp_log1(INFO, ctx, "received %s", ossl_cmp_bodytype_to_string(bt));
+
+ if ((bt = ossl_cmp_msg_check_received(ctx, *rep, unprotected_exception,
+ expected_type)) < 0)
+ return 0;
+
+ if (bt == expected_type
+ /* as an answer to polling, there could be IP/CP/KUP: */
+ || (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP))
+ return 1;
+
+ /* received message type is not one of the expected ones (e.g., error) */
+ CMPerr(0, bt == OSSL_CMP_PKIBODY_ERROR ? CMP_R_RECEIVED_ERROR :
+ CMP_R_UNEXPECTED_PKIBODY); /* in next line for mkerr.pl */
+
+ if (bt != OSSL_CMP_PKIBODY_ERROR) {
+ ERR_add_error_data(3, "message type is '",
+ ossl_cmp_bodytype_to_string(bt), "'");
+ } else {
+ OSSL_CMP_ERRORMSGCONTENT *emc = (*rep)->body->value.error;
+ OSSL_CMP_PKISI *si = emc->pKIStatusInfo;
+ char buf[OSSL_CMP_PKISI_BUFLEN];
+
+ if (save_statusInfo(ctx, si)
+ && OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
+ ERR_add_error_data(1, buf);
+ if (emc->errorCode != NULL
+ && BIO_snprintf(buf, sizeof(buf), "; errorCode: %ld",
+ ASN1_INTEGER_get(emc->errorCode)) > 0)
+ ERR_add_error_data(1, buf);
+ if (emc->errorDetails != NULL) {
+ char *text = sk_ASN1_UTF8STRING2text(emc->errorDetails, ", ",
+ OSSL_CMP_PKISI_BUFLEN - 1);
+
+ if (text != NULL)
+ ERR_add_error_data(2, "; errorDetails: ", text);
+ OPENSSL_free(text);
+ }
+ if (ctx->status != OSSL_CMP_PKISTATUS_rejection) {
+ CMPerr(0, CMP_R_UNEXPECTED_PKISTATUS);
+ if (ctx->status == OSSL_CMP_PKISTATUS_waiting)
+ ctx->status = OSSL_CMP_PKISTATUS_rejection;
+ }
+ }
+ return 0;
+}
+
+/*-
+ * When a 'waiting' PKIStatus has been received, this function is used to
+ * poll, which should yield a pollRep or finally a CertRepMessage in ip/cp/kup.
+ * On receiving a pollRep, which includes a checkAfter value, it return this
+ * value if sleep == 0, else it sleeps as long as indicated and retries.
+ *
+ * A transaction timeout is enabled if ctx->total_timeout is > 0.
+ * In this case polling will continue until the timeout is reached and then
+ * polling is done a last time even if this is before the "checkAfter" time.
+ *
+ * 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).
+ */
+static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
+ OSSL_CMP_MSG **rep, int *checkAfter)
+{
+ OSSL_CMP_MSG *preq = NULL;
+ OSSL_CMP_MSG *prep = NULL;
+
+ ossl_cmp_info(ctx,
+ "received 'waiting' PKIStatus, starting to poll for response");
+ *rep = NULL;
+ for (;;) {
+ /* TODO: handle potentially multiple poll requests per message */
+ if ((preq = ossl_cmp_pollReq_new(ctx, rid)) == NULL)
+ goto err;
+
+ if (!send_receive_check(ctx, preq, &prep, OSSL_CMP_PKIBODY_POLLREP))
+ goto err;
+
+ /* handle potential pollRep */
+ if (ossl_cmp_msg_get_bodytype(prep) == OSSL_CMP_PKIBODY_POLLREP) {
+ OSSL_CMP_POLLREPCONTENT *prc = prep->body->value.pollRep;
+ OSSL_CMP_POLLREP *pollRep = NULL;
+ int64_t check_after;
+ char str[OSSL_CMP_PKISI_BUFLEN];
+ int len;
+
+ /* TODO: handle potentially multiple elements in pollRep */
+ if (sk_OSSL_CMP_POLLREP_num(prc) > 1) {
+ CMPerr(0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
+ goto err;
+ }
+ pollRep = ossl_cmp_pollrepcontent_get0_pollrep(prc, rid);
+ if (pollRep == NULL)
+ goto err;
+
+ if (!ASN1_INTEGER_get_int64(&check_after, pollRep->checkAfter)) {
+ CMPerr(0, CMP_R_BAD_CHECKAFTER_IN_POLLREP);
+ goto err;
+ }
+ if (check_after < 0 || (uint64_t)check_after
+ > (sleep ? ULONG_MAX / 1000 : INT_MAX)) {
+ CMPerr(0, CMP_R_CHECKAFTER_OUT_OF_RANGE);
+ if (BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN, "value = %ld",
+ check_after) >= 0)
+ ERR_add_error_data(1, str);
+ goto err;
+ }
+ if (ctx->total_timeout > 0) { /* timeout is not infinite */
+ const int exp = 5; /* expected max time per msg round trip */
+ int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL));
+
+ if (time_left <= 0) {
+ CMPerr(0, CMP_R_TOTAL_TIMEOUT);
+ goto err;
+ }
+ if (time_left < check_after)
+ check_after = time_left;
+ /* poll one last time just when timeout was reached */
+ }
+
+ if (pollRep->reason == NULL
+ || (len = BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN,
+ " with reason = '")) < 0) {
+ *str = '\0';
+ } else {
+ char *text = sk_ASN1_UTF8STRING2text(pollRep->reason, ", ",
+ sizeof(str) - len - 2);
+
+ if (text == NULL
+ || BIO_snprintf(str + len, sizeof(str) - len,
+ "%s'", text) < 0)
+ *str = '\0';
+ OPENSSL_free(text);
+ }
+ ossl_cmp_log2(INFO, ctx,
+ "received polling response%s; checkAfter = %ld seconds",
+ str, check_after);
+
+ OSSL_CMP_MSG_free(preq);
+ preq = NULL;
+ OSSL_CMP_MSG_free(prep);
+ prep = NULL;
+ if (sleep) {
+ ossl_sleep((unsigned long)(1000 * check_after));
+ } else {
+ if (checkAfter != NULL)
+ *checkAfter = (int)check_after;
+ return -1; /* exits the loop */
+ }
+ } else {
+ ossl_cmp_info(ctx, "received ip/cp/kup after polling");
+ /* any other body type has been rejected by send_receive_check() */
+ break;
+ }
+ }
+ if (prep == NULL)
+ goto err;
+
+ OSSL_CMP_MSG_free(preq);
+ *rep = prep;
+
+ return 1;
+ err:
+ OSSL_CMP_MSG_free(preq);
+ OSSL_CMP_MSG_free(prep);
+ return 0;
+}
+
+/* Send certConf for IR, CR or KUR sequences and check response */
+int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info,
+ const char *txt)
+{
+ OSSL_CMP_MSG *certConf;
+ OSSL_CMP_MSG *PKIconf = NULL;
+ int res = 0;
+
+ /* OSSL_CMP_certConf_new() also checks if all necessary options are set */
+ if ((certConf = ossl_cmp_certConf_new(ctx, fail_info, txt)) == NULL)
+ goto err;
+
+ res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
+
+ err:
+ OSSL_CMP_MSG_free(certConf);
+ OSSL_CMP_MSG_free(PKIconf);
+ return res;
+}
+
+/* Send given error and check response */
+int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
+ const char *txt, int errorCode, const char *details)
+{
+ OSSL_CMP_MSG *error = NULL;
+ OSSL_CMP_PKISI *si = NULL;
+ OSSL_CMP_MSG *PKIconf = NULL;
+ int res = 0;
+
+ if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt)) == NULL)
+ goto err;
+ /* ossl_cmp_error_new() also checks if all necessary options are set */
+ if ((error = ossl_cmp_error_new(ctx, si, errorCode, details, 0)) == NULL)
+ goto err;
+
+ res = send_receive_check(ctx, error, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
+
+ err:
+ OSSL_CMP_MSG_free(error);
+ OSSL_CMP_PKISI_free(si);
+ OSSL_CMP_MSG_free(PKIconf);
+ return res;
+}
+
+/*-
+ * Retrieve a copy of the certificate, if any, from the given CertResponse.
+ * Take into account PKIStatusInfo of CertResponse in ctx, report it on error.
+ * Returns NULL if not found or on error.
+ */
+static X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype,
+ OSSL_CMP_CERTRESPONSE *crep)
+{
+ char buf[OSSL_CMP_PKISI_BUFLEN];
+ X509 *crt = NULL;
+ EVP_PKEY *privkey;
+
+ if (!ossl_assert(ctx != NULL && crep != NULL))
+ return NULL;
+
+ privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
+ switch (ossl_cmp_pkisi_get_status(crep->status)) {
+ case OSSL_CMP_PKISTATUS_waiting:
+ ossl_cmp_err(ctx,
+ "received \"waiting\" status for cert when actually aiming to extract cert");
+ CMPerr(0, CMP_R_ENCOUNTERED_WAITING);
+ goto err;
+ case OSSL_CMP_PKISTATUS_grantedWithMods:
+ ossl_cmp_warn(ctx, "received \"grantedWithMods\" for certificate");
+ crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
+ break;
+ case OSSL_CMP_PKISTATUS_accepted:
+ crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
+ break;
+ /* get all information in case of a rejection before going to error */
+ case OSSL_CMP_PKISTATUS_rejection:
+ ossl_cmp_err(ctx, "received \"rejection\" status rather than cert");
+ CMPerr(0, CMP_R_REQUEST_REJECTED_BY_SERVER);
+ goto err;
+ case OSSL_CMP_PKISTATUS_revocationWarning:
+ ossl_cmp_warn(ctx,
+ "received \"revocationWarning\" - a revocation of the cert is imminent");
+ crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
+ break;
+ case OSSL_CMP_PKISTATUS_revocationNotification:
+ ossl_cmp_warn(ctx,
+ "received \"revocationNotification\" - a revocation of the cert has occurred");
+ crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
+ break;
+ case OSSL_CMP_PKISTATUS_keyUpdateWarning:
+ if (bodytype != OSSL_CMP_PKIBODY_KUR) {
+ CMPerr(0, CMP_R_ENCOUNTERED_KEYUPDATEWARNING);
+ goto err;
+ }
+ crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
+ break;
+ default:
+ ossl_cmp_log1(ERROR, ctx,
+ "received unsupported PKIStatus %d for certificate",
+ ctx->status);
+ CMPerr(0, CMP_R_UNKNOWN_PKISTATUS);
+ goto err;
+ }
+ if (crt == NULL) /* according to PKIStatus, we can expect a cert */
+ CMPerr(0, CMP_R_CERTIFICATE_NOT_FOUND);
+
+ return crt;
+
+ err:
+ if (OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
+ ERR_add_error_data(1, buf);
+ return NULL;
+}
+
+/*-
+ * Callback fn validating that the new certificate can be verified, using
+ * ctx->certConf_cb_arg, which has been initialized using opt_out_trusted, and
+ * ctx->untrusted_certs, which at this point already contains ctx->extraCertsIn.
+ * Returns 0 on acceptance, else a bit field reflecting PKIFailureInfo.
+ * Quoting from RFC 4210 section 5.1. Overall PKI Message:
+ * The extraCerts field can contain certificates that may be useful to
+ * the recipient. For example, this can be used by a CA or RA to
+ * present an end entity with certificates that it needs to verify its
+ * own new certificate (if, for example, the CA that issued the end
+ * entity's certificate is not a root CA for the end entity). Note that
+ * this field does not necessarily contain a certification path; the
+ * recipient may have to sort, select from, or otherwise process the
+ * extra certificates in order to use them.
+ * Note: While often handy, there is no hard requirement by CMP that
+ * an EE must be able to validate the certificates it gets enrolled.
+ */
+int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
+ const char **text)
+{
+ X509_STORE *out_trusted = OSSL_CMP_CTX_get_certConf_cb_arg(ctx);
+ (void)text; /* make (artificial) use of var to prevent compiler warning */
+
+ if (fail_info != 0) /* accept any error flagged by CMP core library */
+ return fail_info;
+
+ if (out_trusted != NULL
+ && !OSSL_CMP_validate_cert_path(ctx, out_trusted, cert))
+ fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
+
+ return fail_info;
+}
+
+/*-
+ * Perform the generic handling of certificate responses for IR/CR/KUR/P10CR.
+ * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
+ * Returns 1 on success and provides the received PKIMESSAGE in *resp.
+ * Returns 0 on error (which includes the case that timeout has been reached).
+ * Regardless of success, caller is responsible for freeing *resp (unless NULL).
+ */
+static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
+ OSSL_CMP_MSG **resp, int *checkAfter,
+ int req_type, int expected_type)
+{
+ EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx /* may be NULL */, 0);
+ int fail_info = 0; /* no failure */
+ const char *txt = NULL;
+ OSSL_CMP_CERTREPMESSAGE *crepmsg;
+ OSSL_CMP_CERTRESPONSE *crep;
+ X509 *cert;
+ char *subj = NULL;
+ int ret = 1;
+
+ retry:
+ crepmsg = (*resp)->body->value.ip; /* same for cp and kup */
+ if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) {
+ CMPerr(0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
+ return 0;
+ }
+ /* TODO: handle potentially multiple CertResponses in CertRepMsg */
+ crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
+ if (crep == NULL)
+ return 0;
+ if (!save_statusInfo(ctx, crep->status))
+ return 0;
+ if (rid == -1) {
+ /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */
+ rid = ossl_cmp_asn1_get_int(crep->certReqId);
+ if (rid == -1) {
+ CMPerr(0, CMP_R_BAD_REQUEST_ID);
+ return 0;
+ }
+ }
+
+ if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) {
+ OSSL_CMP_MSG_free(*resp);
+ *resp = NULL;
+ if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) {
+ if (ret == -1) /* at this point implies sleep == 0 */
+ return ret; /* waiting */
+ goto retry; /* got ip/cp/kup, which may still indicate 'waiting' */
+ } else {
+ CMPerr(0, CMP_R_POLLING_FAILED);
+ return 0;
+ }
+ }
+
+ cert = get1_cert_status(ctx, (*resp)->body->type, crep);
+ if (cert == NULL) {
+ ERR_add_error_data(1, "; cannot extract certificate from response");
+ return 0;
+ }
+ if (!ossl_cmp_ctx_set0_newCert(ctx, cert))
+ 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->caPubs != NULL
+ && !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs))
+ return 0;
+
+ /* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */
+ if (!ossl_cmp_ctx_set1_extraCertsIn(ctx, (*resp)->extraCerts))
+ return 0;
+
+ subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
+ if (rkey != NULL
+ /* X509_check_private_key() also works if rkey is just public key */
+ && !(X509_check_private_key(ctx->newCert, rkey))) {
+ fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
+ txt = "public key in new certificate does not match our enrollment key";
+ /*-
+ * not callling (void)ossl_cmp_exchange_error(ctx,
+ * OSSL_CMP_PKISTATUS_rejection, fail_info, txt)
+ * not throwing CMP_R_CERTIFICATE_NOT_ACCEPTED with txt
+ * not returning 0
+ * since we better leave this for any ctx->certConf_cb to decide
+ */
+ }
+
+ /*
+ * Execute the certification checking callback function possibly set in ctx,
+ * which can determine whether to accept a newly enrolled certificate.
+ * It may overrule the pre-decision reflected in 'fail_info' and '*txt'.
+ */
+ if (ctx->certConf_cb
+ && (fail_info = ctx->certConf_cb(ctx, ctx->newCert,
+ fail_info, &txt)) != 0) {
+ if (txt == NULL)
+ txt = "CMP client application did not accept it";
+ }
+ if (fail_info != 0) /* immediately log error before any certConf exchange */
+ ossl_cmp_log1(ERROR, ctx,
+ "rejecting newly enrolled cert with subject: %s", subj);
+
+ /*
+ * TODO: better move certConf exchange to do_certreq_seq() such that
+ * also more low-level errors with CertReqMessages get reported to server
+ */
+ if (!ctx->disableConfirm
+ && !ossl_cmp_hdr_has_implicitConfirm((*resp)->header)) {
+ if (!ossl_cmp_exchange_certConf(ctx, fail_info, txt))
+ ret = 0;
+ }
+
+ /* not throwing failure earlier as transfer_cb may call ERR_clear_error() */
+ if (fail_info != 0) {
+ CMPerr(0, CMP_R_CERTIFICATE_NOT_ACCEPTED);
+ ERR_add_error_data(2, "rejecting newly enrolled cert with subject: ",
+ subj);
+ if (txt != NULL)
+ ERR_add_error_txt("; ", txt);
+ ret = 0;
+ }
+ OPENSSL_free(subj);
+ return ret;
+}
+
+int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, int *checkAfter)
+{
+ OSSL_CMP_MSG *req = NULL;
+ OSSL_CMP_MSG *rep = NULL;
+ int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR;
+ int rid = is_p10 ? -1 : OSSL_CMP_CERTREQID;
+ int rep_type = is_p10 ? OSSL_CMP_PKIBODY_CP : req_type + 1;
+ int res = 0;
+
+ if (ctx == NULL) {
+ CMPerr(0, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */
+ ctx->status = -1;
+ if (!ossl_cmp_ctx_set0_newCert(ctx, NULL))
+ return 0;
+
+ if (ctx->total_timeout > 0) /* else ctx->end_time is not used */
+ ctx->end_time = time(NULL) + ctx->total_timeout;
+
+ req = ossl_cmp_certReq_new(ctx, req_type, 0 /* req_err */);
+ if (req == NULL) /* also checks if all necessary options are set */
+ return 0;
+
+ if (!send_receive_check(ctx, req, &rep, rep_type))
+ goto err;
+ } else {
+ if (req_type < 0)
+ return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection,
+ 0 /* TODO better fail_info value? */,
+ "polling aborted", 0 /* errorCode */,
+ "by application");
+ res = poll_for_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter);
+ if (res <= 0) /* waiting or error */
+ return res;
+ }
+ res = cert_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter,
+ req_type, rep_type);
+
+ err:
+ OSSL_CMP_MSG_free(req);
+ OSSL_CMP_MSG_free(rep);
+ return res;
+}
+
+/*-
+ * Do the full sequence CR/IR/KUR/P10CR, CP/IP/KUP/CP,
+ * certConf, PKIconf, and polling if required.
+ * Will sleep as long as indicated by the server (according to checkAfter).
+ * All enrollment options need to be present in the context.
+ * TODO: another function to request two certificates at once should be created.
+ * Returns pointer to received certificate, or NULL if none was received.
+ */
+static X509 *do_certreq_seq(OSSL_CMP_CTX *ctx, int req_type, int req_err,
+ int rep_type)
+{
+ OSSL_CMP_MSG *req = NULL;
+ OSSL_CMP_MSG *rep = NULL;
+ int rid = (req_type == OSSL_CMP_PKIBODY_P10CR) ? -1 : OSSL_CMP_CERTREQID;
+ X509 *result = NULL;
+
+ if (ctx == NULL) {
+ CMPerr(0, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ ctx->status = -1;
+ if (!ossl_cmp_ctx_set0_newCert(ctx, NULL))
+ return NULL;
+
+ if (ctx->total_timeout > 0) /* else ctx->end_time is not used */
+ ctx->end_time = time(NULL) + ctx->total_timeout;
+
+ /* OSSL_CMP_certreq_new() also checks if all necessary options are set */
+ if ((req = ossl_cmp_certReq_new(ctx, req_type, req_err)) == NULL)
+ goto err;
+
+ if (!send_receive_check(ctx, req, &rep, rep_type))
+ goto err;
+
+ if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type)
+ <= 0)
+ goto err;
+
+ result = ctx->newCert;
+ err:
+ OSSL_CMP_MSG_free(req);
+ OSSL_CMP_MSG_free(rep);
+ return result;
+}
+
+X509 *OSSL_CMP_exec_IR_ses(OSSL_CMP_CTX *ctx)
+{
+ return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_IR,
+ CMP_R_ERROR_CREATING_IR, OSSL_CMP_PKIBODY_IP);
+}
+
+X509 *OSSL_CMP_exec_CR_ses(OSSL_CMP_CTX *ctx)
+{
+ return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_CR,
+ CMP_R_ERROR_CREATING_CR, OSSL_CMP_PKIBODY_CP);
+}
+
+X509 *OSSL_CMP_exec_KUR_ses(OSSL_CMP_CTX *ctx)
+{
+ return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_KUR,
+ CMP_R_ERROR_CREATING_KUR, OSSL_CMP_PKIBODY_KUP);
+}
+
+X509 *OSSL_CMP_exec_P10CR_ses(OSSL_CMP_CTX *ctx)
+{
+ return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_P10CR,
+ CMP_R_ERROR_CREATING_P10CR, OSSL_CMP_PKIBODY_CP);
+}
+
+X509 *OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx)
+{
+ OSSL_CMP_MSG *rr = NULL;
+ OSSL_CMP_MSG *rp = NULL;
+ const int num_RevDetails = 1;
+ const int rsid = OSSL_CMP_REVREQSID;
+ OSSL_CMP_REVREPCONTENT *rrep = NULL;
+ OSSL_CMP_PKISI *si = NULL;
+ char buf[OSSL_CMP_PKISI_BUFLEN];
+ X509 *result = NULL;
+
+ if (ctx == NULL) {
+ CMPerr(0, CMP_R_INVALID_ARGS);
+ return 0;
+ }
+ ctx->status = -1;
+
+ /* OSSL_CMP_rr_new() also checks if all necessary options are set */
+ if ((rr = ossl_cmp_rr_new(ctx)) == NULL)
+ goto end;
+
+ if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
+ goto end;
+
+ rrep = rp->body->value.rp;
+ if (sk_OSSL_CMP_PKISI_num(rrep->status) != num_RevDetails) {
+ CMPerr(0, CMP_R_WRONG_RP_COMPONENT_COUNT);
+ goto end;
+ }
+
+ /* evaluate PKIStatus field */
+ si = ossl_cmp_revrepcontent_get_pkisi(rrep, rsid);
+ if (!save_statusInfo(ctx, si))
+ goto err;
+ switch (ossl_cmp_pkisi_get_status(si)) {
+ case OSSL_CMP_PKISTATUS_accepted:
+ ossl_cmp_info(ctx, "revocation accepted (PKIStatus=accepted)");
+ result = ctx->oldCert;
+ break;
+ case OSSL_CMP_PKISTATUS_grantedWithMods:
+ ossl_cmp_info(ctx, "revocation accepted (PKIStatus=grantedWithMods)");
+ result = ctx->oldCert;
+ break;
+ case OSSL_CMP_PKISTATUS_rejection:
+ CMPerr(0, CMP_R_REQUEST_REJECTED_BY_SERVER);
+ goto err;
+ case OSSL_CMP_PKISTATUS_revocationWarning:
+ ossl_cmp_info(ctx, "revocation accepted (PKIStatus=revocationWarning)");
+ result = ctx->oldCert;
+ break;
+ case OSSL_CMP_PKISTATUS_revocationNotification:
+ /* interpretation as warning or error depends on CA */
+ ossl_cmp_warn(ctx,
+ "revocation accepted (PKIStatus=revocationNotification)");
+ result = ctx->oldCert;
+ break;
+ case OSSL_CMP_PKISTATUS_waiting:
+ case OSSL_CMP_PKISTATUS_keyUpdateWarning:
+ CMPerr(0, CMP_R_UNEXPECTED_PKISTATUS);
+ goto err;
+ default:
+ CMPerr(0, CMP_R_UNKNOWN_PKISTATUS);
+ goto err;
+ }
+
+ /* check any present CertId in optional revCerts field */
+ if (rrep->revCerts != NULL) {
+ OSSL_CRMF_CERTID *cid;
+ OSSL_CRMF_CERTTEMPLATE *tmpl =
+ sk_OSSL_CMP_REVDETAILS_value(rr->body->value.rr, rsid)->certDetails;
+ const X509_NAME *issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl);
+ ASN1_INTEGER *serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
+
+ if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) != num_RevDetails) {
+ CMPerr(0, CMP_R_WRONG_RP_COMPONENT_COUNT);
+ result = NULL;
+ goto err;
+ }
+ if ((cid = ossl_cmp_revrepcontent_get_CertId(rrep, rsid)) == NULL) {
+ result = NULL;
+ goto err;
+ }
+ if (X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) {
+ CMPerr(0, CMP_R_WRONG_CERTID_IN_RP);
+ result = NULL;
+ goto err;
+ }
+ if (ASN1_INTEGER_cmp(serial,
+ OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) {
+ CMPerr(0, CMP_R_WRONG_SERIAL_IN_RP);
+ result = NULL;
+ goto err;
+ }
+ }
+
+ /* check number of any optionally present crls */
+ if (rrep->crls != NULL && sk_X509_CRL_num(rrep->crls) != num_RevDetails) {
+ CMPerr(0, CMP_R_WRONG_RP_COMPONENT_COUNT);
+ result = NULL;
+ goto err;
+ }
+
+ err:
+ if (result == NULL
+ && OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
+ ERR_add_error_data(1, buf);
+
+ end:
+ OSSL_CMP_MSG_free(rr);
+ OSSL_CMP_MSG_free(rp);
+ return result;
+}
+
+STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx)
+{
+ OSSL_CMP_MSG *genm;
+ OSSL_CMP_MSG *genp = NULL;
+ STACK_OF(OSSL_CMP_ITAV) *rcvd_itavs = NULL;
+
+ if (ctx == NULL) {
+ CMPerr(0, CMP_R_INVALID_ARGS);
+ return 0;
+ }
+
+ if ((genm = ossl_cmp_genm_new(ctx)) == NULL)
+ goto err;
+
+ if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
+ goto err;
+
+ /* received stack of itavs not to be freed with the genp */
+ rcvd_itavs = genp->body->value.genp;
+ genp->body->value.genp = NULL;
+
+ err:
+ OSSL_CMP_MSG_free(genm);
+ OSSL_CMP_MSG_free(genp);
+
+ return rcvd_itavs; /* recv_itavs == NULL indicates an error */
+}
ctx->serverPort = OSSL_CMP_DEFAULT_PORT;
ctx->proxyPort = OSSL_CMP_DEFAULT_PORT;
- ctx->msgtimeout = 2 * 60;
+ ctx->msg_timeout = 2 * 60;
if ((ctx->untrusted_certs = sk_X509_new_null()) == NULL)
goto err;
* it be rejected.
* Returns 1 on success, 0 on error
*/
-int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb)
+int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
* Set a callback function for error reporting and logging messages.
* Returns 1 on success, 0 on error
*/
-int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_log_cb_t cb)
+int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
* Set callback function for sending CMP request and receiving response.
* Returns 1 on success, 0 on error
*/
-int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_transfer_cb_t cb)
+int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
case OSSL_CMP_OPT_REVOCATION_REASON:
min_val = OCSP_REVOKED_STATUS_NOSTATUS;
break;
- case OSSL_CMP_OPT_POPOMETHOD:
+ case OSSL_CMP_OPT_POPO_METHOD:
min_val = OSSL_CRMF_POPO_NONE;
break;
default:
}
ctx->log_verbosity = val;
break;
- case OSSL_CMP_OPT_IMPLICITCONFIRM:
+ case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
ctx->implicitConfirm = val;
break;
- case OSSL_CMP_OPT_DISABLECONFIRM:
+ case OSSL_CMP_OPT_DISABLE_CONFIRM:
ctx->disableConfirm = val;
break;
case OSSL_CMP_OPT_UNPROTECTED_SEND:
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
ctx->unprotectedErrors = val;
break;
- case OSSL_CMP_OPT_VALIDITYDAYS:
+ case OSSL_CMP_OPT_VALIDITY_DAYS:
ctx->days = val;
break;
case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
ctx->ignore_keyusage = val;
break;
- case OSSL_CMP_OPT_POPOMETHOD:
+ case OSSL_CMP_OPT_POPO_METHOD:
if (val > OSSL_CRMF_POPO_KEYAGREE) {
CMPerr(0, CMP_R_INVALID_ARGS);
return 0;
case OSSL_CMP_OPT_MAC_ALGNID:
ctx->pbm_mac = val;
break;
- case OSSL_CMP_OPT_MSGTIMEOUT:
- ctx->msgtimeout = val;
+ case OSSL_CMP_OPT_MSG_TIMEOUT:
+ ctx->msg_timeout = val;
break;
- case OSSL_CMP_OPT_TOTALTIMEOUT:
- ctx->totaltimeout = val;
+ case OSSL_CMP_OPT_TOTAL_TIMEOUT:
+ ctx->total_timeout = val;
break;
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
ctx->permitTAInExtraCertsForIR = val;
switch (opt) {
case OSSL_CMP_OPT_LOG_VERBOSITY:
return ctx->log_verbosity;
- case OSSL_CMP_OPT_IMPLICITCONFIRM:
+ case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
return ctx->implicitConfirm;
- case OSSL_CMP_OPT_DISABLECONFIRM:
+ case OSSL_CMP_OPT_DISABLE_CONFIRM:
return ctx->disableConfirm;
case OSSL_CMP_OPT_UNPROTECTED_SEND:
return ctx->unprotectedSend;
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
return ctx->unprotectedErrors;
- case OSSL_CMP_OPT_VALIDITYDAYS:
+ case OSSL_CMP_OPT_VALIDITY_DAYS:
return ctx->days;
case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
return ctx->SubjectAltName_nodefault;
return ctx->setPoliciesCritical;
case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
return ctx->ignore_keyusage;
- case OSSL_CMP_OPT_POPOMETHOD:
+ case OSSL_CMP_OPT_POPO_METHOD:
return ctx->popoMethod;
case OSSL_CMP_OPT_DIGEST_ALGNID:
return ctx->digest;
return ctx->pbm_owf;
case OSSL_CMP_OPT_MAC_ALGNID:
return ctx->pbm_mac;
- case OSSL_CMP_OPT_MSGTIMEOUT:
- return ctx->msgtimeout;
- case OSSL_CMP_OPT_TOTALTIMEOUT:
- return ctx->totaltimeout;
+ case OSSL_CMP_OPT_MSG_TIMEOUT:
+ return ctx->msg_timeout;
+ case OSSL_CMP_OPT_TOTAL_TIMEOUT:
+ return ctx->total_timeout;
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
return ctx->permitTAInExtraCertsForIR;
case OSSL_CMP_OPT_REVOCATION_REASON:
static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ALGORITHM_NOT_SUPPORTED),
"algorithm not supported"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_CHECKAFTER_IN_POLLREP),
+ "bad checkafter in pollrep"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_REQUEST_ID), "bad request id"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTHASH_UNMATCHED), "certhash unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTID_NOT_FOUND), "certid not found"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_ACCEPTED),
+ "certificate not accepted"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_FOUND),
"certificate not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTREQMSG_NOT_FOUND),
"certresponse not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERT_AND_KEY_DO_NOT_MATCH),
"cert and key do not match"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CHECKAFTER_OUT_OF_RANGE),
+ "checkafter out of range"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_KEYUPDATEWARNING),
+ "encountered keyupdatewarning"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_WAITING),
+ "encountered waiting"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CALCULATING_PROTECTION),
"error calculating protection"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTCONF),
"error creating certconf"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTREP),
"error creating certrep"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CR), "error creating cr"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_ERROR),
"error creating error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENM),
"error creating genm"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENP),
"error creating genp"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_IR), "error creating ir"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_KUR), "error creating kur"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_P10CR),
"error creating p10cr"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_PKICONF),
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_RR), "error creating rr"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PARSING_PKISTATUS),
"error parsing pkistatus"},
- {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROCESSING_MSG),
- "error processing msg"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PARSING_PKISTATUS),
+ "error parsing pkistatus"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROCESSING_MESSAGE),
+ "error processing message"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROTECTING_MESSAGE),
"error protecting message"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_SETTING_CERTHASH),
"error setting certhash"},
- {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_TRANSFERRING_OUT),
- "error transferring out"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_UNEXPECTED_CERTCONF),
"error unexpected certconf"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_PROTECTION),
"missing trust store"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED),
"multiple requests not supported"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED),
+ "multiple responses not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_SAN_SOURCES),
"multiple san sources"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_STDIO), "no stdio"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKIBODY_ERROR), "pkibody error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKISTATUSINFO_NOT_FOUND),
"pkistatusinfo not found"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POLLING_FAILED), "polling failed"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE),
"potentially invalid certificate"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECEIVED_ERROR),
+ "received error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECIPNONCE_UNMATCHED),
"recipnonce unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_NOT_ACCEPTED),
"request not accepted"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_REJECTED_BY_SERVER),
+ "request rejected by server"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED),
"sender generalname type not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG),
"srvcert does not validate msg"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TOTAL_TIMEOUT), "total timeout"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSACTIONID_UNMATCHED),
"transactionid unmatched"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"},
{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_PVNO), "unexpected pvno"},
{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_PKISTATUS), "unknown pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_ALGORITHM),
"unsupported algorithm"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE),
"unsupported protection alg dhbasedmac"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_ALGORITHM_OID),
"wrong algorithm oid"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_CERTID_IN_RP), "wrong certid in rp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_PBM_VALUE), "wrong pbm value"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_RP_COMPONENT_COUNT),
+ "wrong rp component count"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_SERIAL_IN_RP), "wrong serial in rp"},
{0, NULL}
};
* this structure is used to store the context for CMP sessions
*/
struct ossl_cmp_ctx_st {
- OSSL_cmp_log_cb_t log_cb; /* log callback for error/debug/etc. output */
+ OSSL_CMP_log_cb_t log_cb; /* log callback for error/debug/etc. output */
OSSL_CMP_severity log_verbosity; /* level of verbosity of log output */
/* message transfer */
- OSSL_cmp_transfer_cb_t transfer_cb; /* default: OSSL_CMP_MSG_http_perform */
+ OSSL_CMP_transfer_cb_t transfer_cb; /* default: OSSL_CMP_MSG_http_perform */
void *transfer_cb_arg; /* allows to store optional argument to cb */
/* HTTP-based transfer */
char *serverPath;
int serverPort;
char *proxyName;
int proxyPort;
- int msgtimeout; /* max seconds to wait for each CMP message round trip */
- int totaltimeout; /* maximum number seconds an enrollment may take, incl. */
+ int msg_timeout; /* max seconds to wait for each CMP message round trip */
+ int total_timeout; /* max number of seconds an enrollment may take, incl. */
/* attempts polling for a response if a 'waiting' PKIStatus is received */
time_t end_time; /* session start time + totaltimeout */
OSSL_HTTP_bio_cb_t http_cb;
STACK_OF(X509) *extraCertsIn; /* extraCerts received from server */
/* certificate confirmation */
- OSSL_cmp_certConf_cb_t certConf_cb; /* callback for app checking new cert */
+ OSSL_CMP_certConf_cb_t certConf_cb; /* callback for app checking new cert */
void *certConf_cb_arg; /* allows to store an argument individual to cb */
} /* OSSL_CMP_CTX */;
ossl_cmp_allow_unprotected_cb_t cb, int cb_arg);
int ossl_cmp_verify_popo(const OSSL_CMP_MSG *msg, int accept_RAVerified);
+/* from cmp_client.c */
+int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info,
+ const char *txt);
+int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
+ const char *txt, int errorCode, const char *details);
+
#endif /* !defined(OSSL_CRYPTO_CMP_LOCAL_H) */
return msg;
err:
- CMPerr(0, err_code);
+ if (err_code != 0)
+ CMPerr(0, err_code);
OSSL_CRMF_MSG_free(crm);
OSSL_CMP_MSG_free(msg);
return NULL;
&certOut, &chainOut, &caPubs);
if (si == NULL)
goto err;
- /* set OSSL_CMP_OPT_IMPLICITCONFIRM if and only if transaction ends */
- if (!OSSL_CMP_CTX_set_option(srv_ctx->ctx, OSSL_CMP_OPT_IMPLICITCONFIRM,
+ /* set OSSL_CMP_OPT_IMPLICIT_CONFIRM if and only if transaction ends */
+ if (!OSSL_CMP_CTX_set_option(srv_ctx->ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM,
ossl_cmp_hdr_has_implicitConfirm(hdr)
&& srv_ctx->grantImplicitConfirm
/* do not set if polling starts: */
if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr,
OSSL_CMP_REVREQSID)) == NULL) {
- CMPerr(0, CMP_R_ERROR_PROCESSING_MSG);
+ CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
ccc = req->body->value.certConf;
num = sk_OSSL_CMP_CERTSTATUS_num(ccc);
- if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICITCONFIRM) == 1) {
+ if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 1) {
CMPerr(0, CMP_R_ERROR_UNEXPECTED_CERTCONF);
return NULL;
}
}
/*
- * Determines whether missing protection is allowed
+ * Determine whether missing/invalid protection of request message is allowed.
+ * Return 1 on acceptance, 0 on rejection, or -1 on (internal) error.
*/
static int unprotected_exception(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req,
int invalid_protection,
int accept_unprotected_requests)
{
+ if (!ossl_assert(ctx != NULL && req != NULL))
+ return -1;
+
if (accept_unprotected_requests) {
ossl_cmp_log1(WARN, ctx, "ignoring %s protection of request message",
invalid_protection ? "invalid" : "missing");
case OSSL_CMP_PKIBODY_CP:
case OSSL_CMP_PKIBODY_KUP:
case OSSL_CMP_PKIBODY_RP:
- if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICITCONFIRM) == 0)
+ if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 0)
break;
/* fall through */
}
if ((srv_ctx = OSSL_CMP_CTX_get_transfer_cb_arg(client_ctx)) == NULL) {
- CMPerr(0, CMP_R_ERROR_TRANSFERRING_OUT);
+ CMPerr(0, CMP_R_TRANSFER_ERROR);
return 0;
}
int i;
int res = 0;
- if (!ossl_assert(si != NULL && si->failInfo != NULL))
+ if (!ossl_assert(si != NULL))
return -1;
for (i = 0; i <= OSSL_CMP_PKIFAILUREINFO_MAX; i++)
if (ASN1_BIT_STRING_get_bit(si->failInfo, i))
#define ERR_PRINT_BUF_SIZE 4096
/* this is similar to ERR_print_errors_cb, but uses the CMP-specific cb type */
-void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn)
+void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn)
{
unsigned long err;
char msg[ERR_PRINT_BUF_SIZE];
char *sname = NULL;
char *skid_str = NULL;
const ASN1_OCTET_STRING *skid = msg->header->senderKID;
- OSSL_cmp_log_cb_t backup_log_cb = ctx->log_cb;
+ OSSL_CMP_log_cb_t backup_log_cb = ctx->log_cb;
int res = 0;
if (sender == NULL || msg->body == NULL)
*
* Ensures that:
* it has a valid body type
- * its protection is valid or absent (allowed only if callback function is
- * present and function yields non-zero result using also supplied argument)
+ * its protection is valid (or invalid/absent, but only if a callback function
+ * is present and yields a positive result using also the supplied argument)
* its transaction ID matches the previous transaction ID stored in ctx (if any)
* its recipNonce matches the previous senderNonce stored in the ctx (if any)
*
if (msg->header->protectionAlg != 0) {
/* detect explicitly permitted exceptions for invalid protection */
if (!OSSL_CMP_validate_msg(ctx, msg)
- && (cb == NULL || !(*cb)(ctx, msg, 1, cb_arg))) {
+ && (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) {
CMPerr(0, CMP_R_ERROR_VALIDATING_PROTECTION);
return -1;
}
} else {
/* detect explicitly permitted exceptions for missing protection */
- if (cb == NULL || !(*cb)(ctx, msg, 0, cb_arg)) {
+ if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) {
CMPerr(0, CMP_R_MISSING_PROTECTION);
return -1;
}
}
- /*
- * Store any provided extraCerts in ctx for future use,
- * such that they are available to ctx->certConf_cb and
- * the peer does not need to send them again in the same transaction.
- * For efficiency, the extraCerts are prepended so they get used first.
- */
- if (!ossl_cmp_sk_X509_add1_certs(ctx->untrusted_certs, msg->extraCerts,
- 0 /* this allows self-issued certs */,
- 1 /* no_dups */, 1 /* prepend */))
- return -1;
-
/* check CMP version number in header */
if (ossl_cmp_hdr_get_pvno(OSSL_CMP_MSG_get0_header(msg)) != OSSL_CMP_PVNO) {
CMPerr(0, CMP_R_UNEXPECTED_PVNO);
return -1;
}
+ if ((rcvd_type = ossl_cmp_msg_get_bodytype(msg)) < 0) {
+ CMPerr(0, CMP_R_PKIBODY_ERROR);
+ return -1;
+ }
+
/* compare received transactionID with the expected one in previous msg */
if (ctx->transactionID != NULL
&& (msg->header->transactionID == NULL
&& !OSSL_CMP_CTX_set1_transactionID(ctx, msg->header->transactionID))
return -1;
- if ((rcvd_type = ossl_cmp_msg_get_bodytype(msg)) < 0) {
- CMPerr(0, CMP_R_PKIBODY_ERROR);
+ /*
+ * Store any provided extraCerts in ctx for future use,
+ * such that they are available to ctx->certConf_cb and
+ * the peer does not need to send them again in the same transaction.
+ * For efficiency, the extraCerts are prepended so they get used first.
+ */
+ if (!ossl_cmp_sk_X509_add1_certs(ctx->untrusted_certs, msg->extraCerts,
+ 0 /* this allows self-issued certs */,
+ 1 /* no_dups */, 1 /* prepend */))
return -1;
- }
+
return rcvd_type;
}
BN_R_TOO_MANY_ITERATIONS:113:too many iterations
BN_R_TOO_MANY_TEMPORARY_VARIABLES:109:too many temporary variables
CMP_R_ALGORITHM_NOT_SUPPORTED:139:algorithm not supported
+CMP_R_BAD_CHECKAFTER_IN_POLLREP:167:bad checkafter in pollrep
CMP_R_BAD_REQUEST_ID:108:bad request id
CMP_R_CERTHASH_UNMATCHED:156:certhash unmatched
CMP_R_CERTID_NOT_FOUND:109:certid not found
+CMP_R_CERTIFICATE_NOT_ACCEPTED:169:certificate not accepted
CMP_R_CERTIFICATE_NOT_FOUND:112:certificate not found
CMP_R_CERTREQMSG_NOT_FOUND:157:certreqmsg not found
CMP_R_CERTRESPONSE_NOT_FOUND:113:certresponse not found
CMP_R_CERT_AND_KEY_DO_NOT_MATCH:114:cert and key do not match
+CMP_R_CHECKAFTER_OUT_OF_RANGE:181:checkafter out of range
+CMP_R_ENCOUNTERED_KEYUPDATEWARNING:176:encountered keyupdatewarning
+CMP_R_ENCOUNTERED_WAITING:162:encountered waiting
CMP_R_ERROR_CALCULATING_PROTECTION:115:error calculating protection
CMP_R_ERROR_CREATING_CERTCONF:116:error creating certconf
CMP_R_ERROR_CREATING_CERTREP:117:error creating certrep
+CMP_R_ERROR_CREATING_CR:163:error creating cr
CMP_R_ERROR_CREATING_ERROR:118:error creating error
CMP_R_ERROR_CREATING_GENM:119:error creating genm
CMP_R_ERROR_CREATING_GENP:120:error creating genp
+CMP_R_ERROR_CREATING_IR:164:error creating ir
+CMP_R_ERROR_CREATING_KUR:165:error creating kur
CMP_R_ERROR_CREATING_P10CR:121:error creating p10cr
CMP_R_ERROR_CREATING_PKICONF:122:error creating pkiconf
CMP_R_ERROR_CREATING_POLLREP:123:error creating pollrep
CMP_R_ERROR_CREATING_RP:125:error creating rp
CMP_R_ERROR_CREATING_RR:126:error creating rr
CMP_R_ERROR_PARSING_PKISTATUS:107:error parsing pkistatus
-CMP_R_ERROR_PROCESSING_MSG:158:error processing msg
+CMP_R_ERROR_PROCESSING_MESSAGE:158:error processing message
CMP_R_ERROR_PROTECTING_MESSAGE:127:error protecting message
CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash
-CMP_R_ERROR_TRANSFERRING_OUT:159:error transferring out
CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf
CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection
CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
CMP_R_MISSING_SENDER_IDENTIFICATION:111:missing sender identification
CMP_R_MISSING_TRUST_STORE:144:missing trust store
CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED:161:multiple requests not supported
+CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED:170:multiple responses not supported
CMP_R_MULTIPLE_SAN_SOURCES:102:multiple san sources
CMP_R_NO_STDIO:194:no stdio
CMP_R_NO_SUITABLE_SENDER_CERT:145:no suitable sender cert
CMP_R_NULL_ARGUMENT:103:null argument
CMP_R_PKIBODY_ERROR:146:pkibody error
CMP_R_PKISTATUSINFO_NOT_FOUND:132:pkistatusinfo not found
+CMP_R_POLLING_FAILED:172:polling failed
CMP_R_POTENTIALLY_INVALID_CERTIFICATE:147:potentially invalid certificate
+CMP_R_RECEIVED_ERROR:180:received error
CMP_R_RECIPNONCE_UNMATCHED:148:recipnonce unmatched
CMP_R_REQUEST_NOT_ACCEPTED:149:request not accepted
+CMP_R_REQUEST_REJECTED_BY_SERVER:182:request rejected by server
CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED:150:\
sender generalname type not supported
CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG:151:srvcert does not validate msg
+CMP_R_TOTAL_TIMEOUT:184:total timeout
CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
+CMP_R_TRANSFER_ERROR:159:transfer error
CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
+CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
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_PROTECTION_ALG_DHBASEDMAC:154:\
unsupported protection alg dhbasedmac
CMP_R_WRONG_ALGORITHM_OID:138:wrong algorithm oid
+CMP_R_WRONG_CERTID_IN_RP:187:wrong certid in rp
CMP_R_WRONG_PBM_VALUE:155:wrong pbm value
+CMP_R_WRONG_RP_COMPONENT_COUNT:188:wrong rp component count
+CMP_R_WRONG_SERIAL_IN_RP:173:wrong serial in rp
CMS_R_ADD_SIGNER_ERROR:99:add signer error
CMS_R_ATTRIBUTE_ERROR:161:attribute error
CMS_R_CERTIFICATE_ALREADY_PRESENT:175:certificate already present
--- /dev/null
+=pod
+
+=head1 NAME
+
+ossl_cmp_allow_unprotected_cb_t,
+ossl_cmp_msg_check_received
+- does all checks on a received CMP message that can be done generically
+
+=head1 SYNOPSIS
+
+ #include "cmp_local.h"
+
+ typedef int (*ossl_cmp_allow_unprotected_cb_t)(const OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *msg,
+ int invalid_protection, int arg);
+
+ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
+ ossl_cmp_allow_unprotected_cb_t cb, int cb_arg);
+
+=head1 DESCRIPTION
+
+ossl_cmp_msg_check_received() checks the given message B<msg>,
+which may be a server response or a request by some client.
+
+It is ensured for the B<msg> that
+
+=over 4
+
+=item it has a valid body type,
+
+=item its protection is present and valid (or a callback function B<cb>
+is present and indicates that a missing or invalid protection is acceptable),
+
+=item its recipNonce matches any previous senderNonce stored in B<ctx>, and
+
+=item its transaction ID matches any previous transaction ID stored in B<ctx>.
+
+=back
+
+In case no protection is present and B<cb> is not NULL then this callback
+function is called with its B<invalid_protection> parameter being 0, while in
+case an invalid protection is present the B<invalid_protection> parameter is 1.
+The callback is passed also the arguments B<ctx>, B<msg>, and <cb_arg>
+(which typically contains the expected message type).
+The callback should return 1 on acceptance, 0 on rejection, or -1 on error.
+It should not put and error on the error stack since this could be misleading.
+
+If all checks pass then ossl_cmp_msg_check_received()
+
+=over 4
+
+=item learns the senderNonce from the received message,
+
+=item learns the transaction ID if it is not yet in B<ctx>, and
+
+=item adds any extraCerts contained in the <msg> to the list of untrusted
+certificates in B<ctx> for future use, such that
+they are available already to the certificate confirmation callback and the
+peer does not need to send them again (at least not in the same transaction).
+For efficiency, the extraCerts are prepended to the list so they get used first.
+
+=back
+
+=head1 RETURN VALUES
+
+ossl_cmp_msg_check_received() returns the message body type (which is >= 0)
+on success, -1 on error.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_validate_msg(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
=head1 SEE ALSO
-L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_exec_IR_ses(3)>,
-L<OSSL_CMP_MSG_http_perform(3)>
+L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_exec_IR_ses(3)>
=head1 HISTORY
OSSL_CMP_CTX_set_http_cb,
OSSL_CMP_CTX_set_http_cb_arg,
OSSL_CMP_CTX_get_http_cb_arg,
-OSSL_cmp_transfer_cb_t,
+OSSL_CMP_transfer_cb_t,
OSSL_CMP_CTX_set_transfer_cb,
OSSL_CMP_CTX_set_transfer_cb_arg,
OSSL_CMP_CTX_get_transfer_cb_arg,
OSSL_CMP_CTX_set1_oldCert,
OSSL_CMP_CTX_set1_p10CSR,
OSSL_CMP_CTX_push0_genm_ITAV,
-OSSL_cmp_certConf_cb_t,
+OSSL_CMP_certConf_cb_t,
OSSL_CMP_CTX_set_certConf_cb,
OSSL_CMP_CTX_set_certConf_cb_arg,
OSSL_CMP_CTX_get_certConf_cb_arg,
int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt);
/* logging and error reporting: */
- int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_log_cb_t cb);
+ int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb);
#define OSSL_CMP_CTX_set_log_verbosity(ctx, level)
void OSSL_CMP_CTX_print_errors(OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, HTTP_bio_cb_t cb);
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx);
- typedef OSSL_CMP_MSG *(*OSSL_cmp_transfer_cb_t)(OSSL_CMP_CTX *ctx,
+ typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t)(OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req);
int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx,
- OSSL_cmp_transfer_cb_t cb);
+ OSSL_CMP_transfer_cb_t cb);
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
/* certificate confirmation: */
- typedef int (*OSSL_cmp_certConf_cb_t)(OSSL_CMP_CTX *ctx, X509 *cert,
+ typedef int (*OSSL_CMP_certConf_cb_t)(OSSL_CMP_CTX *ctx, X509 *cert,
int fail_info, const char **txt);
- int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb);
+ int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb);
int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx);
STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx);
STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx);
- /* for test purposes only: */
+ /* for testing and debugging purposes: */
int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *id);
int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
All other field values (i.e., CMP options) are retained for potential re-use.
OSSL_CMP_CTX_set_option() sets the given value for the given option
-(e.g., OSSL_CMP_OPT_IMPLICITCONFIRM) in the given OSSL_CMP_CTX structure.
+(e.g., OSSL_CMP_OPT_IMPLICIT_CONFIRM) in the given OSSL_CMP_CTX structure.
The following options can be set:
due to errors, warnings, general info, debugging, etc.
Default is OSSL_CMP_LOG_INFO. See also L<OSSL_CMP_log_open(3)>.
-=item B<OSSL_CMP_OPT_MSGTIMEOUT>
+=item B<OSSL_CMP_OPT_MSG_TIMEOUT>
Number of seconds (or 0 for infinite) a CMP message round trip is
allowed to take before a timeout error is returned. Default is 120.
-=item B<OSSL_CMP_OPT_TOTALTIMEOUT>
+=item B<OSSL_CMP_OPT_TOTAL_TIMEOUT>
Maximum total number of seconds an enrollment (including polling)
may take. Default is 0 (infinite).
-=item B<OSSL_CMP_OPT_VALIDITYDAYS>
+=item B<OSSL_CMP_OPT_VALIDITY_DAYS>
Number of days new certificates are asked to be valid for.
Demand that the given policies are flagged as critical.
-=item B<OSSL_CMP_OPT_POPOMETHOD>
+=item B<OSSL_CMP_OPT_POPO_METHOD>
Select the proof of possession method to use. Possible values are:
The reason code to be included in a Revocation Request (RR);
values: 0..10 (RFC 5210, 5.3.1) or -1 for none, which is the default.
-=item B<OSSL_CMP_OPT_IMPLICITCONFIRM>
+=item B<OSSL_CMP_OPT_IMPLICIT_CONFIRM>
Request server to enable implicit confirm mode, where the client
does not need to send confirmation upon receiving the
certificate. If the server does not enable implicit confirmation
in the return message, then confirmation is sent anyway.
-=item B<OSSL_CMP_OPT_DISABLECONFIRM>
+=item B<OSSL_CMP_OPT_DISABLE_CONFIRM>
Do not confirm enrolled certificates, to cope with broken servers
not supporting implicit confirmation correctly.
=back
OSSL_CMP_CTX_get_option() reads the current value of the given option
-(e.g., OSSL_CMP_OPT_IMPLICITCONFIRM) from the given OSSL_CMP_CTX structure.
+(e.g., OSSL_CMP_OPT_IMPLICIT_CONFIRM) from the given OSSL_CMP_CTX structure.
OSSL_CMP_CTX_set_log_cb() sets in B<ctx> the callback function C<cb>
for handling error queue entries and logging messages.
OSSL_CMP_CTX_set_transfer_cb() sets the message transfer callback function,
which has the type
- typedef OSSL_CMP_MSG *(*OSSL_cmp_transfer_cb_t) (OSSL_CMP_CTX *ctx,
+ typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t) (OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req);
Returns 1 on success, 0 on error.
Default is NULL, which implies the use of L<OSSL_CMP_MSG_http_perform(3)>.
The callback should send the CMP request message it obtains via the B<req>
-parameter and on success return the response.
+parameter and on success return the response, else it must return NULL.
The transfer callback may make use of a custom defined argument stored in
the ctx by means of OSSL_CMP_CTX_set_transfer_cb_arg(), which may be retrieved
again through OSSL_CMP_CTX_get_transfer_cb_arg().
enrolled certificate before the library sends, depending on its result,
a positive or negative certConf message to the server. The callback has type
- typedef int (*OSSL_cmp_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert,
+ typedef int (*OSSL_CMP_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert,
int fail_info, const char **txt);
and should inspect the certificate it obtains via the B<cert> parameter and may
CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+So far the CMP server implementation is limited to one request per CMP message
+(and consequently to at most one response component per CMP message).
+
=head1 RETURN VALUES
OSSL_CMP_SRV_CTX_new() returns a B<OSSL_CMP_SRV_CTX> structure on success,
--- /dev/null
+=pod
+
+=head1 NAME
+
+OSSL_CMP_exec_IR_ses,
+OSSL_CMP_exec_CR_ses,
+OSSL_CMP_exec_P10CR_ses,
+OSSL_CMP_exec_KUR_ses,
+OSSL_CMP_IR,
+OSSL_CMP_CR,
+OSSL_CMP_P10CR,
+OSSL_CMP_KUR,
+OSSL_CMP_try_certreq,
+OSSL_CMP_exec_RR_ses,
+OSSL_CMP_exec_GENM_ses,
+OSSL_CMP_certConf_cb
+- functions implementing CMP client transactions
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ X509 *OSSL_CMP_exec_IR_ses(OSSL_CMP_CTX *ctx);
+ X509 *OSSL_CMP_exec_CR_ses(OSSL_CMP_CTX *ctx);
+ X509 *OSSL_CMP_exec_P10CR_ses(OSSL_CMP_CTX *ctx);
+ X509 *OSSL_CMP_exec_KUR_ses(OSSL_CMP_CTX *ctx);
+ #define OSSL_CMP_IR
+ #define OSSL_CMP_CR
+ #define OSSL_CMP_P10CR
+ #define OSSL_CMP_KUR
+ int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, int *checkAfter);
+ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
+ const char **text);
+ X509 *OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx);
+ STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
+
+=head1 DESCRIPTION
+
+This is the OpenSSL API for doing CMP (Certificate Management Protocol)
+client-server transactions, i.e., sequences of CMP requests and responses.
+
+All functions take a populated OSSL_CMP_CTX structure as their first argument.
+Usually the server name, port, and path ("CMP alias") need to be set, as well as
+credentials the client can use for authenticating itself to the client.
+In order to authenticate the server the client typically needs a trust store.
+For performing certificate enrollment requests the certificate template needs
+to be sufficiently filled in, giving at least the subject name and key.
+The functions return their respective main results directly, while there are
+also accessor functions for retrieving various results and status information
+from the B<ctx>. See L<OSSL_CMP_CTX_new(3)> etc. for details.
+
+The default conveying protocol is HTTP.
+Timeout values may be given per request-response pair and per transaction.
+See L<OSSL_CMP_MSG_http_perform(3)> for details.
+
+OSSL_CMP_exec_IR_ses() requests an initial certificate from the given PKI.
+
+OSSL_CMP_exec_CR_ses() requests an additional certificate.
+
+OSSL_CMP_exec_P10CR_ses() conveys a legacy PKCS#10 CSR requesting a certificate.
+
+OSSL_CMP_exec_KUR_ses() obtains an updated certificate.
+
+All these four types of certificate enrollment may be blocked by sleeping until the
+CAs or an intermedate PKI component can fully process and answer the request.
+
+OSSL_CMP_try_certreq() is an alternative to these four functions that is
+more uniform regarding the type of the certificate request to use and
+more flexible regarding what to do after receiving a checkAfter value.
+When called for the first time (with no certificate request in progress for
+the given B<ctx>) it starts a new transaction by sending a certificate request
+of the given type,
+which may be IR, CR, P10CR, or KUR as specified by the B<req_type> parameter.
+Otherwise (when according to B<ctx> a 'waiting' status has been received before)
+it continues polling for the pending request
+unless the B<req_type> argument is < 0, which aborts the request.
+If the requested certificate is available the function returns 1 and the
+caller can use B<OSSL_CMP_CTX_get0_newCert()> to retrieve the new certificate.
+If no error occurred but no certificate is available yet then
+OSSL_CMP_try_certreq() remembers in the CMP context that it should be retried
+and returns -1 after assigning the received checkAfter value
+via the output pointer argument (unless it is NULL).
+The checkAfter value indicates the number of seconds the caller should let pass
+before trying again. The caller is free to sleep for the given number of seconds
+or for some other time and/or to do anything else before retrying by calling
+OSSL_CMP_try_certreq() again with the same parameter values as before.
+OSSL_CMP_try_certreq() then polls
+to see whether meanwhile the requested certificate is available.
+If the caller decides to abort the pending certificate request and provides
+a negative value as the B<req_type> argument then OSSL_CMP_try_certreq()
+aborts the CMP transaction by sending an error message to the server.
+
+OSSL_CMP_certConf_cb() is a basic certificate confirmation callback validating
+that the new certificate can be verified with the trusted/untrusted certificates
+in B<ctx>.
+As there is no requirement in RFC 4210 that the certificate can be
+validated by the client, this callback is not set by default in the context.
+
+OSSL_CMP_exec_RR_ses() requests the revocation of the certificate
+specified in the B<ctx> using L<OSSL_CMP_CTX_set1_oldCert(3)>.
+RFC 4210 is vague in which PKIStatus should be returned by the server.
+We take "accepted" and "grantedWithMods" as clear success and handle
+"revocationWarning" and "revocationNotification" just as warnings because CAs
+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.
+
+OSSL_CMP_exec_GENM_ses() sends a general message containing the sequence of
+infoType and infoValue pairs (InfoTypeAndValue; short: B<ITAV>)
+provided in the B<ctx> using L<OSSL_CMP_CTX_push0_genm_ITAV(3)>.
+It returns the list of B<ITAV>s received in the GenRep.
+This can be used, for instance, to poll for CRLs or CA Key Updates.
+See RFC 4210 section 5.3.19 and appendix E.5 for details.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+So far the CMP client implementation is limited to one request per CMP message
+(and consequently to at most one response component per CMP message).
+
+=head1 RETURN VALUES
+
+OSSL_CMP_exec_IR_ses(), OSSL_CMP_exec_CR_ses(),
+OSSL_CMP_exec_P10CR_ses(), and OSSL_CMP_exec_KUR_ses() return a
+pointer to the newly obtained X509 certificate on success, B<NULL> on error.
+This pointer will be freed implicitly by OSSL_CMP_CTX_free() or
+CSSL_CMP_CTX_reinit().
+
+OSSL_CMP_try_certreq() returns 1 if the requested certificate is available
+via B<OSSL_CMP_CTX_get0_newCert()>
+or on successfully aborting a pending certificate request, 0 on error, and -1
+in case a 'waiting' status has been received and checkAfter value is available.
+In the latter case B<OSSL_CMP_CTX_get0_newCert()> yields NULL
+and the output parameter B<checkAfter> has been used to
+assign the received value unless B<checkAfter> is NULL.
+
+OSSL_CMP_certConf_cb() returns B<fail_info> if it is not equal to B<0>,
+else B<0> on successful validation,
+or else a bit field with the B<OSSL_CMP_PKIFAILUREINFO_incorrectData> bit set.
+
+OSSL_CMP_exec_RR_ses() returns the
+pointer to the revoked certificate on success, B<NULL> on error.
+This pointer will be freed implicitly by OSSL_CMP_CTX_free().
+
+OSSL_CMP_exec_GENM_ses() returns a
+pointer to the received B<ITAV> sequence on success, B<NULL> on error.
+This pointer must be freed by the caller.
+
+=head1 EXAMPLES
+
+See OSSL_CMP_CTX for examples on how to prepare the context for these
+functions.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_MSG_http_perform(3)>
+
+=head1 HISTORY
+
+The OpenSSL CMP support was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
OSSL_CMP_LOG_NOTICE,
OSSL_CMP_LOG_INFO,
OSSL_CMP_LOG_DEBUG,
-OSSL_cmp_log_cb_t,
+OSSL_CMP_log_cb_t,
OSSL_CMP_print_to_bio,
OSSL_CMP_print_errors_cb
- functions for logging and error reporting
#define OSSL_CMP_LOG_INFO 6
#define OSSL_CMP_LOG_DEBUG 7
- typedef int (*OSSL_cmp_log_cb_t)(const char *component,
+ typedef int (*OSSL_CMP_log_cb_t)(const char *component,
const char *file, int line,
OSSL_CMP_severity level, const char *msg);
int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file,
int line, OSSL_CMP_severity level, const char *msg);
- void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn);
+ void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn);
=head1 DESCRIPTION
A CMP application can obtain this information by providing a callback function
with the following type:
- typedef int (*OSSL_cmp_log_cb_t)(const char *component,
+ typedef int (*OSSL_CMP_log_cb_t)(const char *component,
const char *file, int line,
OSSL_CMP_severity level, const char *msg);
int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx);
/* various CMP options: */
# define OSSL_CMP_OPT_LOG_VERBOSITY 0
-# define OSSL_CMP_OPT_MSGTIMEOUT 1
-# define OSSL_CMP_OPT_TOTALTIMEOUT 2
-# define OSSL_CMP_OPT_VALIDITYDAYS 3
+# define OSSL_CMP_OPT_MSG_TIMEOUT 1
+# define OSSL_CMP_OPT_TOTAL_TIMEOUT 2
+# define OSSL_CMP_OPT_VALIDITY_DAYS 3
# define OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT 4
# define OSSL_CMP_OPT_SUBJECTALTNAME_CRITICAL 5
# define OSSL_CMP_OPT_POLICIES_CRITICAL 6
-# define OSSL_CMP_OPT_POPOMETHOD 7
+# define OSSL_CMP_OPT_POPO_METHOD 7
# define OSSL_CMP_OPT_DIGEST_ALGNID 8
# define OSSL_CMP_OPT_OWF_ALGNID 9
# define OSSL_CMP_OPT_MAC_ALGNID 10
# define OSSL_CMP_OPT_REVOCATION_REASON 11
-# define OSSL_CMP_OPT_IMPLICITCONFIRM 12
-# define OSSL_CMP_OPT_DISABLECONFIRM 13
+# define OSSL_CMP_OPT_IMPLICIT_CONFIRM 12
+# define OSSL_CMP_OPT_DISABLE_CONFIRM 13
# define OSSL_CMP_OPT_UNPROTECTED_SEND 14
# define OSSL_CMP_OPT_UNPROTECTED_ERRORS 15
# define OSSL_CMP_OPT_IGNORE_KEYUSAGE 16
int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val);
int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt);
/* CMP-specific callback for logging and outputting the error queue: */
-int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_log_cb_t cb);
+int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb);
# define OSSL_CMP_CTX_set_log_verbosity(ctx, level) \
OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_LOG_VERBOSITY, level)
void OSSL_CMP_CTX_print_errors(OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb);
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx);
-typedef OSSL_CMP_MSG *(*OSSL_cmp_transfer_cb_t) (OSSL_CMP_CTX *ctx,
+typedef OSSL_CMP_MSG *(*OSSL_CMP_transfer_cb_t) (OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req);
-int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_transfer_cb_t cb);
+int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb);
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx);
/* server authentication: */
/* misc body contents: */
int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav);
/* certificate confirmation: */
-typedef int (*OSSL_cmp_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert,
+typedef int (*OSSL_CMP_certConf_cb_t) (OSSL_CMP_CTX *ctx, X509 *cert,
int fail_info, const char **txt);
-int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb);
+int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb);
int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg);
void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx);
/* result fetching: */
int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
int val);
+/* from cmp_client.c */
+X509 *OSSL_CMP_exec_IR_ses(OSSL_CMP_CTX *ctx);
+X509 *OSSL_CMP_exec_CR_ses(OSSL_CMP_CTX *ctx);
+X509 *OSSL_CMP_exec_P10CR_ses(OSSL_CMP_CTX *ctx);
+X509 *OSSL_CMP_exec_KUR_ses(OSSL_CMP_CTX *ctx);
+# define OSSL_CMP_IR OSSL_CMP_PKIBODY_IR
+# define OSSL_CMP_CR OSSL_CMP_PKIBODY_CR
+# define OSSL_CMP_P10CR OSSL_CMP_PKIBODY_P10CR
+# define OSSL_CMP_KUR OSSL_CMP_PKIBODY_KUR
+int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, int *checkAfter);
+int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
+ const char **text);
+X509 *OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx);
+STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx);
+
# ifdef __cplusplus
}
# endif
# define OSSL_CMP_LOG_NOTICE 5
# define OSSL_CMP_LOG_INFO 6
# define OSSL_CMP_LOG_DEBUG 7
-typedef int (*OSSL_cmp_log_cb_t)(const char *func, const char *file, int line,
+typedef int (*OSSL_CMP_log_cb_t)(const char *func, const char *file, int line,
OSSL_CMP_severity level, const char *msg);
int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file,
int line, OSSL_CMP_severity level, const char *msg);
/* use of the logging callback for outputting error queue */
-void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn);
+void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn);
# ifdef __cplusplus
}
* CMP reason codes.
*/
# define CMP_R_ALGORITHM_NOT_SUPPORTED 139
+# define CMP_R_BAD_CHECKAFTER_IN_POLLREP 167
# define CMP_R_BAD_REQUEST_ID 108
# define CMP_R_CERTHASH_UNMATCHED 156
# define CMP_R_CERTID_NOT_FOUND 109
+# define CMP_R_CERTIFICATE_NOT_ACCEPTED 169
# define CMP_R_CERTIFICATE_NOT_FOUND 112
# define CMP_R_CERTREQMSG_NOT_FOUND 157
# define CMP_R_CERTRESPONSE_NOT_FOUND 113
# define CMP_R_CERT_AND_KEY_DO_NOT_MATCH 114
+# define CMP_R_CHECKAFTER_OUT_OF_RANGE 181
+# define CMP_R_ENCOUNTERED_KEYUPDATEWARNING 176
+# define CMP_R_ENCOUNTERED_WAITING 162
# define CMP_R_ERROR_CALCULATING_PROTECTION 115
# define CMP_R_ERROR_CREATING_CERTCONF 116
# define CMP_R_ERROR_CREATING_CERTREP 117
+# define CMP_R_ERROR_CREATING_CR 163
# define CMP_R_ERROR_CREATING_ERROR 118
# define CMP_R_ERROR_CREATING_GENM 119
# define CMP_R_ERROR_CREATING_GENP 120
+# define CMP_R_ERROR_CREATING_IR 164
+# define CMP_R_ERROR_CREATING_KUR 165
# define CMP_R_ERROR_CREATING_P10CR 121
# define CMP_R_ERROR_CREATING_PKICONF 122
# define CMP_R_ERROR_CREATING_POLLREP 123
# define CMP_R_ERROR_CREATING_RP 125
# define CMP_R_ERROR_CREATING_RR 126
# define CMP_R_ERROR_PARSING_PKISTATUS 107
-# define CMP_R_ERROR_PROCESSING_MSG 158
+# define CMP_R_ERROR_PROCESSING_MESSAGE 158
# define CMP_R_ERROR_PROTECTING_MESSAGE 127
# define CMP_R_ERROR_SETTING_CERTHASH 128
-# define CMP_R_ERROR_TRANSFERRING_OUT 159
# define CMP_R_ERROR_UNEXPECTED_CERTCONF 160
# define CMP_R_ERROR_VALIDATING_PROTECTION 140
# define CMP_R_FAILED_EXTRACTING_PUBKEY 141
# define CMP_R_MISSING_SENDER_IDENTIFICATION 111
# define CMP_R_MISSING_TRUST_STORE 144
# define CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED 161
+# define CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED 170
# define CMP_R_MULTIPLE_SAN_SOURCES 102
# define CMP_R_NO_STDIO 194
# define CMP_R_NO_SUITABLE_SENDER_CERT 145
# define CMP_R_NULL_ARGUMENT 103
# define CMP_R_PKIBODY_ERROR 146
# define CMP_R_PKISTATUSINFO_NOT_FOUND 132
+# define CMP_R_POLLING_FAILED 172
# define CMP_R_POTENTIALLY_INVALID_CERTIFICATE 147
+# define CMP_R_RECEIVED_ERROR 180
# define CMP_R_RECIPNONCE_UNMATCHED 148
# define CMP_R_REQUEST_NOT_ACCEPTED 149
+# define CMP_R_REQUEST_REJECTED_BY_SERVER 182
# define CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED 150
# define CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG 151
+# define CMP_R_TOTAL_TIMEOUT 184
# define CMP_R_TRANSACTIONID_UNMATCHED 152
+# define CMP_R_TRANSFER_ERROR 159
# define CMP_R_UNEXPECTED_PKIBODY 133
+# define CMP_R_UNEXPECTED_PKISTATUS 185
# 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_PROTECTION_ALG_DHBASEDMAC 154
# define CMP_R_WRONG_ALGORITHM_OID 138
+# define CMP_R_WRONG_CERTID_IN_RP 187
# define CMP_R_WRONG_PBM_VALUE 155
+# define CMP_R_WRONG_RP_COMPONENT_COUNT 188
+# define CMP_R_WRONG_SERIAL_IN_RP 173
# endif
#endif
IF[{- !$disabled{cmp} -}]
PROGRAMS{noinst}=cmp_asn_test cmp_ctx_test cmp_status_test cmp_hdr_test \
cmp_protect_test cmp_msg_test cmp_vfy_test \
- cmp_server_test
+ cmp_server_test cmp_client_test
ENDIF
SOURCE[cmp_asn_test]=cmp_asn_test.c cmp_testlib.c
INCLUDE[cmp_server_test]=.. ../include ../apps/include
DEPEND[cmp_server_test]=../libcrypto.a libtestutil.a
+ SOURCE[cmp_client_test]=cmp_client_test.c cmp_testlib.c ../apps/cmp_mock_srv.c
+ INCLUDE[cmp_client_test]=.. ../include ../apps/include
+ DEPEND[cmp_client_test]=../libcrypto.a libtestutil.a
+
# Internal test programs. These are essentially a collection of internal
# test routines. Some of them need to reach internal symbols that aren't
# available through the shared library (at least on Linux, Solaris, Windows
--- /dev/null
+/*
+ * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright Nokia 2007-2019
+ * Copyright Siemens AG 2015-2019
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "cmp_testlib.h"
+
+#include "apps/cmp_mock_srv.h"
+
+#ifndef NDEBUG /* tests need mock server, which is available only if !NDEBUG */
+
+static const char *server_key_f;
+static const char *server_cert_f;
+static const char *client_key_f;
+static const char *client_cert_f;
+static const char *pkcs10_f;
+
+typedef struct test_fixture {
+ const char *test_case_name;
+ OSSL_CMP_CTX *cmp_ctx;
+ OSSL_CMP_SRV_CTX *srv_ctx;
+ int expected;
+ X509 *(*exec_cert_ses_cb) (OSSL_CMP_CTX *);
+ STACK_OF(X509) *caPubs;
+} CMP_SES_TEST_FIXTURE;
+
+static EVP_PKEY *server_key = NULL;
+static X509 *server_cert = NULL;
+static EVP_PKEY *client_key = NULL;
+static X509 *client_cert = NULL;
+static unsigned char ref[CMP_TEST_REFVALUE_LENGTH];
+
+/*
+ * For these unit tests, the client abandons message protection, and for
+ * error messages the mock server does so as well.
+ * Message protection and verification is tested in cmp_lib_test.c
+ */
+
+static void tear_down(CMP_SES_TEST_FIXTURE *fixture)
+{
+ OSSL_CMP_CTX_free(fixture->cmp_ctx);
+ ossl_cmp_mock_srv_free(fixture->srv_ctx);
+ sk_X509_free(fixture->caPubs);
+ OPENSSL_free(fixture);
+}
+
+static CMP_SES_TEST_FIXTURE *set_up(const char *const test_case_name)
+{
+ CMP_SES_TEST_FIXTURE *fixture;
+ OSSL_CMP_CTX *srv_cmp_ctx = NULL;
+ OSSL_CMP_CTX *ctx = NULL; /* for client */
+
+ if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture))))
+ return NULL;
+ fixture->test_case_name = test_case_name;
+ if (!TEST_ptr(fixture->srv_ctx = ossl_cmp_mock_srv_new())
+ || !OSSL_CMP_SRV_CTX_set_accept_unprotected(fixture->srv_ctx, 1)
+ || !ossl_cmp_mock_srv_set1_certOut(fixture->srv_ctx, client_cert)
+ || (srv_cmp_ctx =
+ OSSL_CMP_SRV_CTX_get0_cmp_ctx(fixture->srv_ctx)) == NULL
+ || !OSSL_CMP_CTX_set1_clCert(srv_cmp_ctx, server_cert)
+ || !OSSL_CMP_CTX_set1_pkey(srv_cmp_ctx, server_key))
+ goto err;
+ if (!TEST_ptr(fixture->cmp_ctx = ctx = OSSL_CMP_CTX_new())
+ || !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)
+ || !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)
+ || !OSSL_CMP_CTX_set1_srvCert(ctx, server_cert)
+ || !OSSL_CMP_CTX_set1_referenceValue(ctx, ref, sizeof(ref)))
+ goto err;
+ fixture->exec_cert_ses_cb = NULL;
+ return fixture;
+
+ err:
+ tear_down(fixture);
+ return NULL;
+}
+
+static int execute_exec_RR_ses_test(CMP_SES_TEST_FIXTURE *fixture)
+{
+ return TEST_int_eq(fixture->expected,
+ OSSL_CMP_exec_RR_ses(fixture->cmp_ctx) == client_cert);
+}
+
+static int execute_exec_GENM_ses_test(CMP_SES_TEST_FIXTURE *fixture)
+{
+ STACK_OF(OSSL_CMP_ITAV) *itavs = NULL;
+ if (!TEST_ptr(itavs = OSSL_CMP_exec_GENM_ses(fixture->cmp_ctx)))
+ return 0;
+ sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
+ /* TODO: check if the returned value is the expected one (same as sent) */
+ return 1;
+}
+
+static int execute_exec_certrequest_ses_test(CMP_SES_TEST_FIXTURE *fixture)
+{
+ X509 *res;
+
+ if (fixture->expected == 0)
+ return TEST_ptr_null(fixture->exec_cert_ses_cb(fixture->cmp_ctx));
+
+ if (!TEST_ptr(res = fixture->exec_cert_ses_cb(fixture->cmp_ctx))
+ || !TEST_int_eq(X509_cmp(res, client_cert), 0))
+ return 0;
+ /* TODO: check that cerfConf has been exchanged unless implicitConfirm */
+ if (fixture->caPubs != NULL) {
+ STACK_OF(X509) *caPubs = OSSL_CMP_CTX_get1_caPubs(fixture->cmp_ctx);
+ int ret = TEST_int_eq(STACK_OF_X509_cmp(fixture->caPubs, caPubs), 0);
+
+ sk_X509_pop_free(caPubs, X509_free);
+ return ret;
+ }
+ return 1;
+}
+
+static int test_exec_RR_ses(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->expected = 1;
+ EXECUTE_TEST(execute_exec_RR_ses_test, tear_down);
+ return result;
+}
+
+static int test_exec_RR_ses_receive_error(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ ossl_cmp_mock_srv_set_statusInfo(fixture->srv_ctx,
+ OSSL_CMP_PKISTATUS_rejection,
+ OSSL_CMP_CTX_FAILINFO_signerNotTrusted,
+ "test string");
+ ossl_cmp_mock_srv_set_send_error(fixture->srv_ctx, 1);
+ fixture->expected = 0;
+ EXECUTE_TEST(execute_exec_RR_ses_test, tear_down);
+ return result;
+}
+
+static int test_exec_IR_ses(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->exec_cert_ses_cb = OSSL_CMP_exec_IR_ses;
+ fixture->expected = 1;
+ fixture->caPubs = sk_X509_new_null();
+ sk_X509_push(fixture->caPubs, server_cert);
+ sk_X509_push(fixture->caPubs, server_cert);
+ ossl_cmp_mock_srv_set1_caPubsOut(fixture->srv_ctx, fixture->caPubs);
+ EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down);
+ return result;
+}
+
+static const int checkAfter = 1;
+static int test_exec_IR_ses_poll(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->exec_cert_ses_cb = OSSL_CMP_exec_IR_ses;
+ fixture->expected = 1;
+ ossl_cmp_mock_srv_set_pollCount(fixture->srv_ctx, 2);
+ ossl_cmp_mock_srv_set_checkAfterTime(fixture->srv_ctx, checkAfter);
+ EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down);
+ /* TODO: check that 2 rounds are done or session takes 2..3 seconds */
+ return result;
+}
+
+static int test_exec_IR_ses_poll_timeout(void)
+{
+ const int pollCount = 3;
+ const int tout = pollCount * checkAfter;
+
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->exec_cert_ses_cb = OSSL_CMP_exec_IR_ses;
+ fixture->expected = 0;
+ ossl_cmp_mock_srv_set_pollCount(fixture->srv_ctx, pollCount + 1);
+ ossl_cmp_mock_srv_set_checkAfterTime(fixture->srv_ctx, checkAfter);
+ OSSL_CMP_CTX_set_option(fixture->cmp_ctx, OSSL_CMP_OPT_TOTAL_TIMEOUT, tout);
+ EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down);
+ return result;
+}
+
+
+static int test_exec_CR_ses(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->exec_cert_ses_cb = OSSL_CMP_exec_CR_ses;
+ fixture->expected = 1;
+ EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down);
+ return result;
+}
+
+static int test_exec_CR_ses_implicit_confirm(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->exec_cert_ses_cb = OSSL_CMP_exec_CR_ses;
+ fixture->expected = 1;
+ OSSL_CMP_CTX_set_option(fixture->cmp_ctx,
+ OSSL_CMP_OPT_IMPLICIT_CONFIRM, 1);
+ OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(fixture->srv_ctx, 1);
+ EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down);
+ return result;
+}
+
+static int test_exec_KUR_ses(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->exec_cert_ses_cb = OSSL_CMP_exec_KUR_ses;
+ fixture->expected = 1;
+ EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down);
+ return result;
+}
+
+static int test_exec_P10CR_ses(void)
+{
+ X509_REQ *req = NULL;
+
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->exec_cert_ses_cb = OSSL_CMP_exec_P10CR_ses;
+ fixture->expected = 1;
+ if (!TEST_ptr(req = load_csr(pkcs10_f))
+ || !TEST_true(OSSL_CMP_CTX_set1_p10CSR(fixture->cmp_ctx, req))) {
+ tear_down(fixture);
+ fixture = NULL;
+ }
+ X509_REQ_free(req);
+ EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down);
+ return result;
+}
+
+static int execute_try_certreq_poll_test(CMP_SES_TEST_FIXTURE *fixture)
+{
+ OSSL_CMP_CTX *ctx = fixture->cmp_ctx;
+ int check_after;
+ const int CHECK_AFTER = 5;
+ const int TYPE = OSSL_CMP_KUR;
+
+ ossl_cmp_mock_srv_set_pollCount(fixture->srv_ctx, 3);
+ ossl_cmp_mock_srv_set_checkAfterTime(fixture->srv_ctx, CHECK_AFTER);
+ return TEST_int_eq(-1, OSSL_CMP_try_certreq(ctx, TYPE, &check_after))
+ && check_after == CHECK_AFTER
+ && TEST_ptr_eq(OSSL_CMP_CTX_get0_newCert(ctx), NULL)
+ && TEST_int_eq(-1, OSSL_CMP_try_certreq(ctx, TYPE, &check_after))
+ && check_after == CHECK_AFTER
+ && TEST_ptr_eq(OSSL_CMP_CTX_get0_newCert(ctx), NULL)
+ && TEST_int_eq(fixture->expected, OSSL_CMP_try_certreq(ctx, TYPE, NULL))
+ && TEST_int_eq(0, X509_cmp(OSSL_CMP_CTX_get0_newCert(ctx), client_cert));
+}
+
+static int test_try_certreq_poll(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->expected = 1;
+ EXECUTE_TEST(execute_try_certreq_poll_test, tear_down);
+ return result;
+}
+
+static int execute_try_certreq_poll_abort_test(CMP_SES_TEST_FIXTURE *fixture)
+{
+ OSSL_CMP_CTX *ctx = fixture->cmp_ctx;
+ int check_after;
+ const int CHECK_AFTER = INT_MAX;
+ const int TYPE = OSSL_CMP_CR;
+
+ ossl_cmp_mock_srv_set_pollCount(fixture->srv_ctx, 3);
+ ossl_cmp_mock_srv_set_checkAfterTime(fixture->srv_ctx, CHECK_AFTER);
+ return TEST_int_eq(-1, OSSL_CMP_try_certreq(ctx, TYPE, &check_after))
+ && check_after == CHECK_AFTER
+ && TEST_ptr_eq(OSSL_CMP_CTX_get0_newCert(ctx), NULL)
+ && TEST_int_eq(fixture->expected, OSSL_CMP_try_certreq(ctx, -1, NULL))
+ && TEST_ptr_eq(OSSL_CMP_CTX_get0_newCert(fixture->cmp_ctx), NULL);
+}
+
+static int test_try_certreq_poll_abort(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->expected = 1;
+ EXECUTE_TEST(execute_try_certreq_poll_abort_test, tear_down);
+ return result;
+}
+
+static int test_exec_GENM_ses(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ EXECUTE_TEST(execute_exec_GENM_ses_test, tear_down);
+ return result;
+}
+
+static int execute_exchange_certConf_test(CMP_SES_TEST_FIXTURE *fixture)
+{
+ int res =
+ ossl_cmp_exchange_certConf(fixture->cmp_ctx,
+ OSSL_CMP_PKIFAILUREINFO_addInfoNotAvailable,
+ "abcdefg");
+ return TEST_int_eq(fixture->expected, res);
+}
+
+static int execute_exchange_error_test(CMP_SES_TEST_FIXTURE *fixture)
+{
+ int res =
+ ossl_cmp_exchange_error(fixture->cmp_ctx,
+ OSSL_CMP_PKISTATUS_rejection,
+ 1 << OSSL_CMP_PKIFAILUREINFO_unsupportedVersion,
+ "foo_status", 999, "foo_details");
+
+ return TEST_int_eq(fixture->expected, res);
+}
+
+static int test_exchange_certConf(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->expected = 0; /* client should not send certConf immediately */
+ if (!ossl_cmp_ctx_set0_newCert(fixture->cmp_ctx, X509_dup(client_cert))) {
+ tear_down(fixture);
+ fixture = NULL;
+ }
+ EXECUTE_TEST(execute_exchange_certConf_test, tear_down);
+ return result;
+}
+
+static int test_exchange_error(void)
+{
+ SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up);
+ fixture->expected = 1; /* client may send error any time */
+ EXECUTE_TEST(execute_exchange_error_test, tear_down);
+ return result;
+}
+
+void cleanup_tests(void)
+{
+ X509_free(server_cert);
+ EVP_PKEY_free(server_key);
+ X509_free(client_cert);
+ EVP_PKEY_free(client_key);
+ return;
+}
+
+int setup_tests(void)
+{
+ if (!test_skip_common_options()) {
+ TEST_error("Error parsing test options\n");
+ return 0;
+ }
+
+ if (!TEST_ptr(server_key_f = test_get_argument(0))
+ || !TEST_ptr(server_cert_f = test_get_argument(1))
+ || !TEST_ptr(client_key_f = test_get_argument(2))
+ || !TEST_ptr(client_cert_f = test_get_argument(3))
+ || !TEST_ptr(pkcs10_f = test_get_argument(4))) {
+ TEST_error("usage: cmp_client_test server.key server.crt client.key client.crt client.csr\n");
+ return 0;
+ }
+
+ if (!TEST_ptr(server_key = load_pem_key(server_key_f))
+ || !TEST_ptr(server_cert = load_pem_cert(server_cert_f))
+ || !TEST_ptr(client_key = load_pem_key(client_key_f))
+ || !TEST_ptr(client_cert = load_pem_cert(client_cert_f))
+ || !TEST_int_eq(1, RAND_bytes(ref, sizeof(ref)))) {
+ cleanup_tests();
+ return 0;
+ }
+
+ ADD_TEST(test_exec_RR_ses);
+ ADD_TEST(test_exec_RR_ses_receive_error);
+ ADD_TEST(test_exec_CR_ses);
+ ADD_TEST(test_exec_CR_ses_implicit_confirm);
+ ADD_TEST(test_exec_IR_ses);
+ ADD_TEST(test_exec_IR_ses_poll);
+ ADD_TEST(test_exec_IR_ses_poll_timeout);
+ ADD_TEST(test_exec_KUR_ses);
+ ADD_TEST(test_exec_P10CR_ses);
+ ADD_TEST(test_try_certreq_poll);
+ ADD_TEST(test_try_certreq_poll_abort);
+ ADD_TEST(test_exec_GENM_ses);
+ ADD_TEST(test_exchange_certConf);
+ ADD_TEST(test_exchange_error);
+ return 1;
+}
+
+#else /* !defined (NDEBUG) */
+
+int setup_tests(void)
+{
+ TEST_note("CMP session tests are disabled in this build (NDEBUG).");
+ return 1;
+}
+
+#endif
STACK_OF(TYPE)*, NULL, IS_0, \
sk_##TYPE##_new_null(), sk_##TYPE##_free)
-typedef OSSL_HTTP_bio_cb_t OSSL_cmp_http_cb_t;
+typedef OSSL_HTTP_bio_cb_t OSSL_CMP_http_cb_t;
#define DEFINE_SET_CB_TEST(FIELD) \
- static OSSL_cmp_##FIELD##_t OSSL_CMP_CTX_get_##FIELD(const CMP_CTX *ctx) \
+ static OSSL_CMP_##FIELD##_t OSSL_CMP_CTX_get_##FIELD(const CMP_CTX *ctx) \
{ \
if (ctx == NULL) \
CMPerr(0, CMP_R_NULL_ARGUMENT); \
return ctx == NULL ? NULL /* cannot use ERR(NULL) here */ : ctx->FIELD;\
} \
DEFINE_SET_GET_BASE_TEST(OSSL_CMP_CTX, set, get, 0, FIELD, \
- OSSL_cmp_##FIELD##_t, NULL, IS_0, \
+ OSSL_CMP_##FIELD##_t, NULL, IS_0, \
test_##FIELD, DROP)
#define DEFINE_SET_GET_P_VOID_TEST(FIELD) \
DEFINE_SET_GET_BASE_TEST(OSSL_CMP_CTX, set, get, 0, FIELD, void *, \
fixture->expected = 0;
if (!TEST_true(OSSL_CMP_CTX_set1_pkey(fixture->cmp_ctx, newkey))
|| !TEST_true(SET_OPT_UNPROTECTED_SEND(fixture->cmp_ctx, 0))
+ /* newkey used by default for signing does not match cert: */
|| !TEST_true(OSSL_CMP_CTX_set1_clCert(fixture->cmp_ctx, cert))) {
tear_down(fixture);
fixture = NULL;
SETUP_TEST_FIXTURE(CMP_MSG_TEST_FIXTURE, set_up);
fixture->expected = 1;
iv = OSSL_CMP_ITAV_create(OBJ_nid2obj(NID_id_it_implicitConfirm), NULL);
- if (!TEST_true(SET_OPT_UNPROTECTED_SEND(fixture->cmp_ctx, 1))
- || !TEST_ptr(iv)
+ if (!TEST_ptr(iv)
|| !TEST_true(OSSL_CMP_CTX_push0_genm_ITAV(fixture->cmp_ctx, iv))) {
OSSL_CMP_ITAV_free(iv);
tear_down(fixture);
X509_free(cert); /* down-ref */
return res;
}
+
+int print_to_bio_out(const char *func, const char *file, int line,
+ OSSL_CMP_severity level, const char *msg)
+{
+ return OSSL_CMP_print_to_bio(bio_out, func, file, line, level, msg);
+}
EVP_PKEY *gen_rsa(void);
int STACK_OF_X509_cmp(const STACK_OF(X509) *sk1, const STACK_OF(X509) *sk2);
int STACK_OF_X509_push1(STACK_OF(X509) *sk, X509 *cert);
+int print_to_bio_out(const char *func, const char *file, int line,
+ OSSL_CMP_severity level, const char *msg);
# endif
#endif /* OSSL_TEST_CMP_TESTLIB_H */
OPENSSL_free(fixture);
}
-static int print_to_bio_out(const char *func, const char *file, int line,
- OSSL_CMP_severity level, const char *msg)
-{
- return OSSL_CMP_print_to_bio(bio_out, func, file, line, level, msg);
-}
-
static time_t test_time_valid = 0, test_time_after_expiration = 0;
static CMP_VFY_TEST_FIXTURE *set_up(const char *const test_case_name)
--- /dev/null
+#! /usr/bin/env perl
+# Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright Nokia 2007-2019
+# Copyright Siemens AG 2015-2019
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use OpenSSL::Test qw/:DEFAULT data_file/;
+use OpenSSL::Test::Utils;
+
+setup("test_cmp_client");
+
+plan skip_all => "This test is not supported in a no-cmp build"
+ if disabled("cmp");
+
+plan tests => 1;
+
+ok(run(test(["cmp_client_test",
+ data_file("server.key"),
+ data_file("server.crt"),
+ data_file("client.key"),
+ data_file("client.crt"),
+ data_file("client.csr")])));
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIB6DCCAUkCCQD6PZPVVOpOKTAKBggqhkjOPQQDAjA4MQswCQYDVQQGEwJERTET
+MBEGA1UECgwKU2llbWVucyBBRzEUMBIGA1UEAwwLdGVzdCBjbGllbnQwHhcNMTkw
+NzI2MTE1OTQyWhcNMTkwODI1MTE1OTQyWjA4MQswCQYDVQQGEwJERTETMBEGA1UE
+CgwKU2llbWVucyBBRzEUMBIGA1UEAwwLdGVzdCBjbGllbnQwgZswEAYHKoZIzj0C
+AQYFK4EEACMDgYYABAHClvNEi0aAVuM3CrR5Pwj3TFKHRXfd04MCSs/p9bzMFlMT
+l6SGCGbFh9ZbU+J2jXYGBtTSSs4O/27lqzXCS8DjQAHMrFq69i5VuUmGXe7jQcfY
+iyKIb+3It0GstBa0hDssxWvBUJADMd+p6R0pA/XjCG0ZqkkHwdzCxEby/oCZPp1g
+3jAKBggqhkjOPQQDAgOBjAAwgYgCQgEJiQwLbHH6E9dLpy+BsZ3m+nfwSvPulS/n
+DMm6ZRi57iItAey9eywxpsKV7DKT+SPjjlAt+l083Smz42Gwpdt+cAJCAXQ2NHqm
+hPYo8Qk5a+Y15PYqm5g5qZ1b5E2FtRHNK8EJzSMrQEzDiI3jO0sgcvzr7kwOsZ7X
+Z8y+DTE4HOoYo6oo
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIAyT6geQkerhMGSj1ZG0ZhFa1Q5kYEBtnEE/bs5Gdm9L3v0OukExzm
+Nx1XJATGBnCyOM5IzPw1TWXT+BNhSxJYtvOgBwYFK4EEACOhgYkDgYYABAHClvNE
+i0aAVuM3CrR5Pwj3TFKHRXfd04MCSs/p9bzMFlMTl6SGCGbFh9ZbU+J2jXYGBtTS
+Ss4O/27lqzXCS8DjQAHMrFq69i5VuUmGXe7jQcfYiyKIb+3It0GstBa0hDssxWvB
+UJADMd+p6R0pA/XjCG0ZqkkHwdzCxEby/oCZPp1g3g==
+-----END EC PRIVATE KEY-----
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIICpTCCAY2gAwIBAgIBATANBgkqhkiG9w0BAQUFADAWMRQwEgYDVQQKDAtvcGVu
+c3NsX2NtcDAeFw0xNzEyMjAxMzA0MDBaFw0xODEyMjAxMzA0MDBaMBYxFDASBgNV
+BAoMC29wZW5zc2xfY21wMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+4ckRrH0UWmIJFj99kBqvCipGjJRAaPkdvWjdDQLglTpI3eZAJHnq0ypW/PZccrWj
+o7mxuvAStEYWF+5Jx6ZFmAsC1K0NNebSAZQoLWYZqiOzkfVVpLicMnItNFElfCoh
+BzPCYmF5UlC5yp9PSUEfNwPJqDIRMtw+IlVUV3AJw9TJ3uuWq/vWW9r96/gBKKdd
+mj/q2gGT8RC6LxEaolTbhfPbHaA1DFpv1WQFb3oAV3Wq14SOZf9bH1olBVsmBMsU
+shFEw5MXVrNCv2moM4HtITMyjvZe7eIwHzSzf6dvQjERG6GvZ/i5KOhaqgJCnRKd
+HHzijz9cLec5p9NSOuC1OwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQDGUXpFCBkV
+WgPrBfZyBwt6VCjWB/e67q4IdcKMfDa4hwSquah1AyXHI0PlC/qitnoSx2+7f7pY
+TEOay/3eEPUl1J5tdPF2Vg56Dw8jdhSkMwO7bXKDEE3R6o6jaa4ECgxwQtdGHmNU
+A41PgKX76yEXku803ptO39/UR7i7Ye3MbyAmWE+PvixJYUbxd3fqz5fsaJqTCzAy
+AT9hrr4uu8J7m3LYaYXo4LVL4jw5UsP5bIYtpmmEBfy9GhpUqH5/LzBNij7y3ziE
+T59wHkzawAQDHsBPuCe07DFtlzqWWvaih0TQAw9MZ2tbyK9jt7P80Rqt9CwpM/i9
+jQYqSl/ix5hn
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA4ckRrH0UWmIJFj99kBqvCipGjJRAaPkdvWjdDQLglTpI3eZA
+JHnq0ypW/PZccrWjo7mxuvAStEYWF+5Jx6ZFmAsC1K0NNebSAZQoLWYZqiOzkfVV
+pLicMnItNFElfCohBzPCYmF5UlC5yp9PSUEfNwPJqDIRMtw+IlVUV3AJw9TJ3uuW
+q/vWW9r96/gBKKddmj/q2gGT8RC6LxEaolTbhfPbHaA1DFpv1WQFb3oAV3Wq14SO
+Zf9bH1olBVsmBMsUshFEw5MXVrNCv2moM4HtITMyjvZe7eIwHzSzf6dvQjERG6Gv
+Z/i5KOhaqgJCnRKdHHzijz9cLec5p9NSOuC1OwIDAQABAoIBAGiYVO+rIfqc38jG
+sMxJED2NSBFnvE7k2LoeEgktBA0daxQgziYXtIkOXC3jkwAw1RXLuGH5RTDuJt3/
+LX6nsCW3NCCB6lTGERNaJyKg4dLHpzA+juY3/2P/MKHD1bGncpV7jNk2fpV7gBY1
+pu0wld1Oi+S3DPCaxs3w6Zl39Y4Z7oSNf6DRO5lGN3Asc8TSVjIOWpAl8LIg+P2B
+ZvFeHRANVXaV9YmF2uEi7iMgH4vGrK2svsmM9VThVO4ArGcTRTvGYn7aw3/H4Pt+
+lYuhERdpkKBT0tCgIpO5IJXMl4/5RSDTtcBwiJcReN5IHUAItBIPSHcMflNSKG/I
+aQf4u0ECgYEA8+PAyzn096Y2UrKzE75yuadCveLjsUWx2NN5ZMohQru99F4k7Pab
+/Te4qOe5zlxHAPK3LRwvbwUWo5mLfs45wFrSgZoRlYcCuL+JaX0y2oXMMF9E+UkY
+tljMt/HpLo1SfSjN2Sae4LVhC7rWJ43LtyRepptzBPGqd26eLPGAMr8CgYEA7P8u
+RGkMOrMzEKAb0A9smrzq2xW88T1VejqEt6R8mUcNt8PFHMgjuzVU4zDysrlb7G/0
+VSkQWnJxBh1yNGc1Av7YgwicIgApr4ty0hZhLcnKX2VrNw+L/sSe/cnwVAc6RtPK
+RR6xQubuLlrCGcbYXmyn5Jv+nlY0S3uCyDFHqIUCgYAwtpLxhJf7RwWeqva9wNJl
+ZpUcHE9iPwtwxXx/tyfBjoI4Zv11HyS1BQYrJm2kXCYKeHBB4FlREXEeKDMGluZO
+F1XocP+GIDtY71jg6xLXNtY76yt5pzH6ae4p53WtyKhrO1UyRFaDh3bkwuK3b8j6
+wZbuLCpjGGn2BPAvBeWXPQKBgEewKN6op/pZmmi9Bay5/bAQ1TnQKYcPdnuyl9K0
+/ruespeTsFw0bhqC11qhw8gsKZIri0z3TusNEwM2hQU08uQlEnkQcaoXQoTHOcQy
+4NJo575Tf0r4ePBnqXA7VWcViJtEFTszPYtvLzz2VyBU9b4aP+73AN4EVW0/vx+v
+SG3BAoGBAMzESFA2TXwUFmozK5zowIszc995Xqpi7mXKk77WESOpoS1dQ1wF1dSg
+XOwxzFoYovLxcc1K9lqOrod8BV+qGuEfc/PIJ2aiXjvEDeZYX2eWaANNmj4OSLoJ
+MNYj9tZxbq56slD7snf7AgUBnwKz0Pj6H6UsbE3gdJqZWCDyw/bB
+-----END RSA PRIVATE KEY-----
OSSL_CMP_CTX_set1_senderNonce ? 3_0_0 EXIST::FUNCTION:CMP
OSSL_CMP_log_open ? 3_0_0 EXIST::FUNCTION:CMP
OSSL_CMP_log_close ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_print_to_bio ? 3_0_0 EXIST::FUNCTION:CMP
OSSL_CMP_print_errors_cb ? 3_0_0 EXIST::FUNCTION:CMP
OSSL_CRMF_CERTID_get0_issuer ? 3_0_0 EXIST::FUNCTION:CRMF
OSSL_CRMF_CERTID_get0_serialNumber ? 3_0_0 EXIST::FUNCTION:CRMF
X509_STORE_get1_all_certs ? 3_0_0 EXIST::FUNCTION:
OSSL_CMP_validate_msg ? 3_0_0 EXIST::FUNCTION:CMP
OSSL_CMP_validate_cert_path ? 3_0_0 EXIST::FUNCTION:CMP
-OSSL_CMP_print_to_bio ? 3_0_0 EXIST::FUNCTION:CMP
EVP_PKEY_CTX_set_ecdh_cofactor_mode ? 3_0_0 EXIST::FUNCTION:EC
EVP_PKEY_CTX_get_ecdh_cofactor_mode ? 3_0_0 EXIST::FUNCTION:EC
EVP_PKEY_CTX_set_ecdh_kdf_type ? 3_0_0 EXIST::FUNCTION:EC
OSSL_CMP_SRV_CTX_set_accept_unprotected ? 3_0_0 EXIST::FUNCTION:CMP
OSSL_CMP_SRV_CTX_set_accept_raverified ? 3_0_0 EXIST::FUNCTION:CMP
OSSL_CMP_SRV_CTX_set_grant_implicit_confirm ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_exec_IR_ses ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_exec_CR_ses ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_exec_P10CR_ses ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_exec_KUR_ses ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_try_certreq ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_certConf_cb ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_exec_RR_ses ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_exec_GENM_ses ? 3_0_0 EXIST::FUNCTION:CMP
EVP_PKEY_gen ? 3_0_0 EXIST::FUNCTION:
EVP_PKEY_CTX_set_rsa_keygen_bits ? 3_0_0 EXIST::FUNCTION:RSA
EVP_PKEY_CTX_set_rsa_keygen_pubexp ? 3_0_0 EXIST::FUNCTION:RSA
OPENSSL_uni2utf8(3)
OPENSSL_utf82uni(3)
OSSL_CMP_MSG_http_perform(3)
-OSSL_CMP_exec_GENM_ses(3)
-OSSL_CMP_exec_IR_ses(3)
-OSSL_CMP_exec_KUR_ses(3)
OSSL_SERIALIZER-DH(7)
OSSL_SERIALIZER-DSA(7)
OSSL_SERIALIZER-EC(7)
OpenSSL_add_all_digests define deprecated 1.1.0
OpenSSL_add_ssl_algorithms define
OSSL_CMP_CTX_set_log_verbosity define
+OSSL_CMP_CR define
OSSL_CMP_DEFAULT_PORT define
+OSSL_CMP_IR define
+OSSL_CMP_KUR define
OSSL_CMP_LOG_ALERT define
OSSL_CMP_LOG_CRIT define
OSSL_CMP_LOG_DEBUG define
OSSL_CMP_LOG_WARNING define
OSSL_CMP_MSTR_HELPER define
OSSL_CMP_MSTR define
+OSSL_CMP_P10CR define
+ossl_cmp_allow_unprotected_cb_t datatype
+OSSL_CMP_certConf_cb_t datatype
+OSSL_CMP_log_cb_t datatype
OSSL_CMP_severity datatype
-OSSL_cmp_certConf_cb_t datatype
-OSSL_cmp_log_cb_t datatype
-OSSL_cmp_transfer_cb_t datatype
+OSSL_CMP_transfer_cb_t datatype
OSSL_CMP_SRV_cert_request_cb_t datatype
OSSL_CMP_SRV_rr_cb_t datatype
OSSL_CMP_SRV_certConf_cb_t datatype