From: Dr. David von Oheimb Date: Tue, 10 Mar 2020 16:32:57 +0000 (+0100) Subject: Chunk 9 of CMP contribution to OpenSSL: CMP client and related tests X-Git-Tag: openssl-3.0.0-alpha1~214 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=7e765f46a6b3a5b2fc48e10657bea7016e5c5e4b;p=oweals%2Fopenssl.git Chunk 9 of CMP contribution to OpenSSL: CMP client and related tests Certificate Management Protocol (CMP, RFC 4210) extension to OpenSSL Also includes CRMF (RFC 4211) and HTTP transfer (RFC 6712). Adds the CMP and CRMF API to libcrypto and the "cmp" app to the CLI. Adds extensive documentation and tests. Reviewed-by: Matt Caswell Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/11300) --- diff --git a/apps/cmp_mock_srv.c b/apps/cmp_mock_srv.c index 2e02104884..8ffe4ca5a8 100644 --- a/apps/cmp_mock_srv.c +++ b/apps/cmp_mock_srv.c @@ -187,7 +187,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, return NULL; } if (ctx->sendError) { - CMPerr(0, CMP_R_ERROR_PROCESSING_MSG); + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); return NULL; } @@ -238,7 +238,7 @@ static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, return NULL; } if (ctx->sendError || ctx->certOut == NULL) { - CMPerr(0, CMP_R_ERROR_PROCESSING_MSG); + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); return NULL; } @@ -264,7 +264,7 @@ static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx, return 0; } if (ctx->sendError) { - CMPerr(0, CMP_R_ERROR_PROCESSING_MSG); + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); return 0; } @@ -306,6 +306,7 @@ static void process_error(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *error, 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) @@ -332,7 +333,7 @@ static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, return 0; } if (ctx->sendError || ctx->certOut == NULL) { - CMPerr(0, CMP_R_ERROR_PROCESSING_MSG); + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); return 0; } @@ -366,7 +367,7 @@ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, } if (ctx->sendError || ctx->certReq == NULL) { *certReq = NULL; - CMPerr(0, CMP_R_ERROR_PROCESSING_MSG); + CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE); return 0; } diff --git a/crypto/cmp/build.info b/crypto/cmp/build.info index 1667334e2a..d3fbae2452 100644 --- a/crypto/cmp/build.info +++ b/crypto/cmp/build.info @@ -1,4 +1,4 @@ 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 diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c new file mode 100644 index 0000000000..394358c5e3 --- /dev/null +++ b/crypto/cmp/cmp_client.c @@ -0,0 +1,881 @@ +/* + * 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 +#include +#include +#include +#include + +#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 */ +} diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c index 714157a964..873d69320e 100644 --- a/crypto/cmp/cmp_ctx.c +++ b/crypto/cmp/cmp_ctx.c @@ -103,7 +103,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(void) 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; @@ -257,7 +257,7 @@ int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert) * 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); @@ -384,7 +384,7 @@ int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx, * 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); @@ -911,7 +911,7 @@ void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx) * 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); @@ -1010,7 +1010,7 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) 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: @@ -1030,10 +1030,10 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) } 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: @@ -1042,7 +1042,7 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) 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: @@ -1057,7 +1057,7 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) 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; @@ -1073,11 +1073,11 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) 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; @@ -1111,15 +1111,15 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt) 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; @@ -1129,7 +1129,7 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt) 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; @@ -1137,10 +1137,10 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt) 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: diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c index 0d311a8ddf..d64d60bf1d 100644 --- a/crypto/cmp/cmp_err.c +++ b/crypto/cmp/cmp_err.c @@ -16,9 +16,13 @@ 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), @@ -27,18 +31,27 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "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), @@ -51,14 +64,14 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { {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), @@ -83,6 +96,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "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"}, @@ -92,23 +107,33 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { {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), @@ -117,7 +142,11 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "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} }; diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h index 688ccabd7c..220e93e2ce 100644 --- a/crypto/cmp/cmp_local.h +++ b/crypto/cmp/cmp_local.h @@ -28,11 +28,11 @@ * 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; @@ -40,8 +40,8 @@ struct ossl_cmp_ctx_st { 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; @@ -122,7 +122,7 @@ struct ossl_cmp_ctx_st { 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 */; @@ -912,4 +912,10 @@ 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); 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) */ diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c index e4a4f1f3b3..7fc51596b9 100644 --- a/crypto/cmp/cmp_msg.c +++ b/crypto/cmp/cmp_msg.c @@ -348,7 +348,8 @@ OSSL_CMP_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int type, int err_code) 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; diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c index ce532b3110..c5c57fc8b7 100644 --- a/crypto/cmp/cmp_server.c +++ b/crypto/cmp/cmp_server.c @@ -215,8 +215,8 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, &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: */ @@ -264,7 +264,7 @@ static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, 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; } @@ -341,7 +341,7 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, 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; } @@ -415,13 +415,17 @@ static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, } /* - * 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"); @@ -574,7 +578,7 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, 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 */ @@ -607,7 +611,7 @@ OSSL_CMP_MSG * OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx, } 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; } diff --git a/crypto/cmp/cmp_status.c b/crypto/cmp/cmp_status.c index 6232239237..9192cf5e4d 100644 --- a/crypto/cmp/cmp_status.c +++ b/crypto/cmp/cmp_status.c @@ -75,7 +75,7 @@ int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si) 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)) diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c index 70c060166a..121b6a173a 100644 --- a/crypto/cmp/cmp_util.c +++ b/crypto/cmp/cmp_util.c @@ -144,7 +144,7 @@ int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file, #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]; diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 437bc3298f..73f93360d6 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -426,7 +426,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) 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) @@ -633,8 +633,8 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) * * 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) * @@ -660,35 +660,29 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, 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 @@ -720,10 +714,17 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, && !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; } diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 50fb57baee..cb106e23b1 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2078,19 +2078,27 @@ BN_R_P_IS_NOT_PRIME:112:p is not prime 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 @@ -2098,10 +2106,9 @@ CMP_R_ERROR_CREATING_POLLREQ:124:error creating pollreq 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 @@ -2116,29 +2123,40 @@ CMP_R_MISSING_PROTECTION:143:missing protection 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 diff --git a/doc/internal/man3/ossl_cmp_msg_check_received.pod b/doc/internal/man3/ossl_cmp_msg_check_received.pod new file mode 100644 index 0000000000..3fc7882c5a --- /dev/null +++ b/doc/internal/man3/ossl_cmp_msg_check_received.pod @@ -0,0 +1,86 @@ +=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, +which may be a server response or a request by some client. + +It is ensured for the B that + +=over 4 + +=item it has a valid body type, + +=item its protection is present and valid (or a callback function B +is present and indicates that a missing or invalid protection is acceptable), + +=item its recipNonce matches any previous senderNonce stored in B, and + +=item its transaction ID matches any previous transaction ID stored in B. + +=back + +In case no protection is present and B is not NULL then this callback +function is called with its B parameter being 0, while in +case an invalid protection is present the B parameter is 1. +The callback is passed also the arguments B, B, and +(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, and + +=item adds any extraCerts contained in the to the list of untrusted +certificates in B 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 + +=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. + +=cut diff --git a/doc/internal/man3/ossl_cmp_msg_create.pod b/doc/internal/man3/ossl_cmp_msg_create.pod index 7498a1d6fd..ebc08f7ef1 100644 --- a/doc/internal/man3/ossl_cmp_msg_create.pod +++ b/doc/internal/man3/ossl_cmp_msg_create.pod @@ -62,8 +62,7 @@ See the individual functions above. =head1 SEE ALSO -L, L, -L +L, L =head1 HISTORY diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod index 032ef817c0..016d851ddc 100644 --- a/doc/man3/OSSL_CMP_CTX_new.pod +++ b/doc/man3/OSSL_CMP_CTX_new.pod @@ -19,7 +19,7 @@ OSSL_CMP_DEFAULT_PORT, 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, @@ -47,7 +47,7 @@ OSSL_CMP_CTX_push0_policy, 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, @@ -72,7 +72,7 @@ OSSL_CMP_CTX_set1_senderNonce 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); @@ -86,10 +86,10 @@ OSSL_CMP_CTX_set1_senderNonce 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); @@ -134,9 +134,9 @@ OSSL_CMP_CTX_set1_senderNonce 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); @@ -149,7 +149,7 @@ OSSL_CMP_CTX_set1_senderNonce 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, @@ -172,7 +172,7 @@ from the last executed transaction. 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: @@ -184,17 +184,17 @@ The following options can be set: due to errors, warnings, general info, debugging, etc. Default is OSSL_CMP_LOG_INFO. See also L. -=item B +=item B 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 +=item B Maximum total number of seconds an enrollment (including polling) may take. Default is 0 (infinite). -=item B +=item B Number of days new certificates are asked to be valid for. @@ -211,7 +211,7 @@ The following options can be set: Demand that the given policies are flagged as critical. -=item B +=item B Select the proof of possession method to use. Possible values are: @@ -247,14 +247,14 @@ The following options can be set: 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 +=item B 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 +=item B Do not confirm enrolled certificates, to cope with broken servers not supporting implicit confirmation correctly. @@ -290,7 +290,7 @@ RFC 4210. =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 the callback function C for handling error queue entries and logging messages. @@ -350,14 +350,14 @@ OSSL_CMP_CTX_set_http_cb_arg() or NULL if unset. 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. The callback should send the CMP request message it obtains via the B -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(). @@ -512,7 +512,7 @@ OSSL_CMP_CTX_set_certConf_cb() sets the callback used for evaluating the newly 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 parameter and may diff --git a/doc/man3/OSSL_CMP_SRV_CTX_new.pod b/doc/man3/OSSL_CMP_SRV_CTX_new.pod index 45ac0174b7..2b7ce7fa2b 100644 --- a/doc/man3/OSSL_CMP_SRV_CTX_new.pod +++ b/doc/man3/OSSL_CMP_SRV_CTX_new.pod @@ -128,6 +128,9 @@ confirmation of newly enrolled certificates if requested. 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 structure on success, diff --git a/doc/man3/OSSL_CMP_exec_IR_ses.pod b/doc/man3/OSSL_CMP_exec_IR_ses.pod new file mode 100644 index 0000000000..24913d5b80 --- /dev/null +++ b/doc/man3/OSSL_CMP_exec_IR_ses.pod @@ -0,0 +1,172 @@ +=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 + + 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. See L etc. for details. + +The default conveying protocol is HTTP. +Timeout values may be given per request-response pair and per transaction. +See L 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) 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 parameter. +Otherwise (when according to B a 'waiting' status has been received before) +it continues polling for the pending request +unless the B argument is < 0, which aborts the request. +If the requested certificate is available the function returns 1 and the +caller can use B 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 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. +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 using L. +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) +provided in the B using L. +It returns the list of Bs 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 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 +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 yields NULL +and the output parameter B has been used to +assign the received value unless B is NULL. + +OSSL_CMP_certConf_cb() returns B if it is not equal to B<0>, +else B<0> on successful validation, +or else a bit field with the B bit set. + +OSSL_CMP_exec_RR_ses() returns the +pointer to the revoked certificate on success, B 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 sequence on success, B 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, L + +=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. + +=cut diff --git a/doc/man3/OSSL_CMP_log_open.pod b/doc/man3/OSSL_CMP_log_open.pod index 9f204d6ec1..78d51ee780 100644 --- a/doc/man3/OSSL_CMP_log_open.pod +++ b/doc/man3/OSSL_CMP_log_open.pod @@ -13,7 +13,7 @@ OSSL_CMP_LOG_WARNING, 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 @@ -36,12 +36,12 @@ OSSL_CMP_print_errors_cb #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 @@ -56,7 +56,7 @@ should be provided for user information, debugging, and auditing purposes. 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); diff --git a/include/openssl/cmp.h b/include/openssl/cmp.h index fcdd44b40c..21d16cc94d 100644 --- a/include/openssl/cmp.h +++ b/include/openssl/cmp.h @@ -248,19 +248,19 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx); 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 @@ -268,7 +268,7 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx); 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); @@ -282,9 +282,9 @@ int OSSL_CMP_CTX_set_proxyPort(OSSL_CMP_CTX *ctx, int port); 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: */ @@ -320,9 +320,9 @@ int OSSL_CMP_CTX_set1_p10CSR(OSSL_CMP_CTX *ctx, const X509_REQ *csr); /* 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: */ @@ -410,6 +410,21 @@ int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val); 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 diff --git a/include/openssl/cmp_util.h b/include/openssl/cmp_util.h index 6b6025b6ce..831b65ec1c 100644 --- a/include/openssl/cmp_util.h +++ b/include/openssl/cmp_util.h @@ -39,13 +39,13 @@ typedef int OSSL_CMP_severity; # 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 } diff --git a/include/openssl/cmperr.h b/include/openssl/cmperr.h index f868cc104f..c11f372ab5 100644 --- a/include/openssl/cmperr.h +++ b/include/openssl/cmperr.h @@ -34,19 +34,27 @@ int ERR_load_CMP_strings(void); * 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 @@ -54,10 +62,9 @@ int ERR_load_CMP_strings(void); # 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 @@ -71,27 +78,38 @@ int ERR_load_CMP_strings(void); # 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 diff --git a/test/build.info b/test/build.info index 6f00d1a141..bc1f3f2f86 100644 --- a/test/build.info +++ b/test/build.info @@ -442,7 +442,7 @@ IF[{- !$disabled{tests} -}] 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 @@ -477,6 +477,10 @@ IF[{- !$disabled{tests} -}] 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 diff --git a/test/cmp_client_test.c b/test/cmp_client_test.c new file mode 100644 index 0000000000..057d079f73 --- /dev/null +++ b/test/cmp_client_test.c @@ -0,0 +1,393 @@ +/* + * 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 diff --git a/test/cmp_ctx_test.c b/test/cmp_ctx_test.c index 6da9863179..bbbd056ba5 100644 --- a/test/cmp_ctx_test.c +++ b/test/cmp_ctx_test.c @@ -535,16 +535,16 @@ static X509_STORE *X509_STORE_new_1(void) 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 *, \ diff --git a/test/cmp_msg_test.c b/test/cmp_msg_test.c index 3919480610..2111a2127d 100644 --- a/test/cmp_msg_test.c +++ b/test/cmp_msg_test.c @@ -162,6 +162,7 @@ static int test_cmp_create_ir_protection_fails(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; @@ -357,8 +358,7 @@ static int test_cmp_create_genm(void) 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); diff --git a/test/cmp_testlib.c b/test/cmp_testlib.c index 6c696eafaa..12ef4f3514 100644 --- a/test/cmp_testlib.c +++ b/test/cmp_testlib.c @@ -126,3 +126,9 @@ int STACK_OF_X509_push1(STACK_OF(X509) *sk, X509 *cert) 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); +} diff --git a/test/cmp_testlib.h b/test/cmp_testlib.h index f1bc55c118..e5f1af8f04 100644 --- a/test/cmp_testlib.h +++ b/test/cmp_testlib.h @@ -30,6 +30,8 @@ int valid_asn1_encoding(const OSSL_CMP_MSG *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 */ diff --git a/test/cmp_vfy_test.c b/test/cmp_vfy_test.c index f0b9b50b01..9fca675ef1 100644 --- a/test/cmp_vfy_test.c +++ b/test/cmp_vfy_test.c @@ -44,12 +44,6 @@ static void tear_down(CMP_VFY_TEST_FIXTURE *fixture) 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) diff --git a/test/recipes/65-test_cmp_client.t b/test/recipes/65-test_cmp_client.t new file mode 100644 index 0000000000..52019942f6 --- /dev/null +++ b/test/recipes/65-test_cmp_client.t @@ -0,0 +1,27 @@ +#! /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")]))); diff --git a/test/recipes/65-test_cmp_client_data/client.crt b/test/recipes/65-test_cmp_client_data/client.crt new file mode 100644 index 0000000000..c74d52e965 --- /dev/null +++ b/test/recipes/65-test_cmp_client_data/client.crt @@ -0,0 +1,13 @@ +-----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----- diff --git a/test/recipes/65-test_cmp_client_data/client.csr b/test/recipes/65-test_cmp_client_data/client.csr new file mode 100644 index 0000000000..c9b6ad4cfb Binary files /dev/null and b/test/recipes/65-test_cmp_client_data/client.csr differ diff --git a/test/recipes/65-test_cmp_client_data/client.key b/test/recipes/65-test_cmp_client_data/client.key new file mode 100644 index 0000000000..56ad079927 --- /dev/null +++ b/test/recipes/65-test_cmp_client_data/client.key @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIAyT6geQkerhMGSj1ZG0ZhFa1Q5kYEBtnEE/bs5Gdm9L3v0OukExzm +Nx1XJATGBnCyOM5IzPw1TWXT+BNhSxJYtvOgBwYFK4EEACOhgYkDgYYABAHClvNE +i0aAVuM3CrR5Pwj3TFKHRXfd04MCSs/p9bzMFlMTl6SGCGbFh9ZbU+J2jXYGBtTS +Ss4O/27lqzXCS8DjQAHMrFq69i5VuUmGXe7jQcfYiyKIb+3It0GstBa0hDssxWvB +UJADMd+p6R0pA/XjCG0ZqkkHwdzCxEby/oCZPp1g3g== +-----END EC PRIVATE KEY----- diff --git a/test/recipes/65-test_cmp_client_data/server.crt b/test/recipes/65-test_cmp_client_data/server.crt new file mode 100644 index 0000000000..ed1d43333e --- /dev/null +++ b/test/recipes/65-test_cmp_client_data/server.crt @@ -0,0 +1,17 @@ +-----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----- diff --git a/test/recipes/65-test_cmp_client_data/server.key b/test/recipes/65-test_cmp_client_data/server.key new file mode 100644 index 0000000000..2324266798 --- /dev/null +++ b/test/recipes/65-test_cmp_client_data/server.key @@ -0,0 +1,27 @@ +-----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----- diff --git a/util/libcrypto.num b/util/libcrypto.num index ba27450084..4d57cad19e 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4802,6 +4802,7 @@ OSSL_CMP_CTX_set1_transactionID ? 3_0_0 EXIST::FUNCTION:CMP 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 @@ -4937,7 +4938,6 @@ X509_STORE_CTX_print_verify_cb ? 3_0_0 EXIST::FUNCTION: 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 @@ -4985,6 +4985,14 @@ OSSL_CMP_SRV_CTX_set_send_unprotected_errors ? 3_0_0 EXIST::FUNCTION:CMP 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 diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index 4c3af107d9..cf56fae0a6 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -912,9 +912,6 @@ OPENSSL_uni2asc(3) 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) diff --git a/util/other.syms b/util/other.syms index 1d2a2689ef..508653f86b 100644 --- a/util/other.syms +++ b/util/other.syms @@ -352,7 +352,10 @@ OpenSSL_add_all_ciphers define deprecated 1.1.0 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 @@ -363,10 +366,12 @@ OSSL_CMP_LOG_NOTICE 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