Latest update.

This commit is contained in:
2020-04-15 18:45:34 +09:00
parent be29e7bcc6
commit 2015c00c43
573 changed files with 22943 additions and 6714 deletions
+2 -1
View File
@@ -1,3 +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_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c \
cmp_server.c cmp_client.c cmp_http.c
+881
View File
@@ -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 <openssl/bio.h>
#include <openssl/cmp.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
#include "openssl/cmp_util.h"
#define IS_CREP(t) ((t) == OSSL_CMP_PKIBODY_IP || (t) == OSSL_CMP_PKIBODY_CP \
|| (t) == OSSL_CMP_PKIBODY_KUP)
/*-
* Evaluate whether there's an exception (violating the standard) configured for
* handling negative responses without protection or with invalid protection.
* Returns 1 on acceptance, 0 on rejection, or -1 on (internal) error.
*/
static int unprotected_exception(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *rep,
int invalid_protection,
int expected_type /* ignored here */)
{
int rcvd_type = ossl_cmp_msg_get_bodytype(rep /* may be NULL */);
const char *msg_type = NULL;
if (!ossl_assert(ctx != NULL && rep != NULL))
return -1;
if (!ctx->unprotectedErrors)
return 0;
switch (rcvd_type) {
case OSSL_CMP_PKIBODY_ERROR:
msg_type = "error response";
break;
case OSSL_CMP_PKIBODY_RP:
{
OSSL_CMP_PKISI *si =
ossl_cmp_revrepcontent_get_pkisi(rep->body->value.rp,
OSSL_CMP_REVREQSID);
if (si == NULL)
return -1;
if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_rejection)
msg_type = "revocation response message with rejection status";
break;
}
case OSSL_CMP_PKIBODY_PKICONF:
msg_type = "PKI Confirmation message";
break;
default:
if (IS_CREP(rcvd_type)) {
OSSL_CMP_CERTREPMESSAGE *crepmsg = rep->body->value.ip;
OSSL_CMP_CERTRESPONSE *crep =
ossl_cmp_certrepmessage_get0_certresponse(crepmsg,
-1 /* any rid */);
if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1)
return -1;
/* TODO: handle potentially multiple CertResponses in CertRepMsg */
if (crep == NULL)
return -1;
if (ossl_cmp_pkisi_get_status(crep->status)
== OSSL_CMP_PKISTATUS_rejection)
msg_type = "CertRepMessage with rejection status";
}
}
if (msg_type == NULL)
return 0;
ossl_cmp_log2(WARN, ctx, "ignoring %s protection of %s",
invalid_protection ? "invalid" : "missing", msg_type);
return 1;
}
/* Save error info from PKIStatusInfo field of a certresponse into ctx */
static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si)
{
int i;
OSSL_CMP_PKIFREETEXT *ss;
if (!ossl_assert(ctx != NULL && si != NULL))
return 0;
if ((ctx->status = ossl_cmp_pkisi_get_status(si)) < 0)
return 0;
ctx->failInfoCode = 0;
if (si->failInfo != NULL) {
for (i = 0; i <= OSSL_CMP_PKIFAILUREINFO_MAX; i++) {
if (ASN1_BIT_STRING_get_bit(si->failInfo, i))
ctx->failInfoCode |= (1 << i);
}
}
if (!ossl_cmp_ctx_set0_statusString(ctx, sk_ASN1_UTF8STRING_new_null())
|| (ctx->statusString == NULL))
return 0;
ss = si->statusString; /* may be NULL */
for (i = 0; i < sk_ASN1_UTF8STRING_num(ss); i++) {
ASN1_UTF8STRING *str = sk_ASN1_UTF8STRING_value(ss, i);
if (!sk_ASN1_UTF8STRING_push(ctx->statusString, ASN1_STRING_dup(str)))
return 0;
}
return 1;
}
/*-
* Perform the generic aspects of sending a request and receiving a response.
* Returns 1 on success and provides the received PKIMESSAGE in *rep.
* Returns 0 on error.
* Regardless of success, caller is responsible for freeing *rep (unless NULL).
*/
static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
OSSL_CMP_MSG **rep, int expected_type)
{
const char *req_type_str =
ossl_cmp_bodytype_to_string(ossl_cmp_msg_get_bodytype(req));
const char *expected_type_str = ossl_cmp_bodytype_to_string(expected_type);
int msg_timeout;
int bt;
time_t now = time(NULL);
int time_left;
OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb;
if (transfer_cb == NULL)
transfer_cb = OSSL_CMP_MSG_http_perform;
*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 = %jd",
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 */
}
+59 -170
View File
@@ -20,9 +20,7 @@
#include <openssl/crmf.h>
#include <openssl/err.h>
/*
* Get current certificate store containing trusted root CA certs
*/
/* Get current certificate store containing trusted root CA certs */
X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
@@ -36,7 +34,6 @@ X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
* Set certificate store containing trusted (root) CA certs and possibly CRLs
* and a cert verification callback function used for CMP server authentication.
* Any already existing store entry is freed. Given NULL, the entry is reset.
* returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
{
@@ -49,9 +46,7 @@ int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
return 1;
}
/*
* Get current list of non-trusted intermediate certs
*/
/* Get current list of non-trusted intermediate certs */
STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted_certs(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
@@ -64,7 +59,6 @@ STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted_certs(const OSSL_CMP_CTX *ctx)
/*
* Set untrusted certificates for path construction in authentication of
* the CMP server and potentially others (TLS server, newly enrolled cert).
* returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set1_untrusted_certs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs)
{
@@ -101,9 +95,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(void)
ctx->status = -1;
ctx->failInfoCode = -1;
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;
@@ -125,9 +117,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(void)
return NULL;
}
/*
* Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX
*/
/* Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX */
int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
@@ -148,17 +138,16 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
&& ossl_cmp_ctx_set1_recipNonce(ctx, NULL);
}
/*
* Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new()
*/
/* Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new() */
void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
{
if (ctx == NULL)
return;
OPENSSL_free(ctx->serverPath);
OPENSSL_free(ctx->serverName);
OPENSSL_free(ctx->proxyName);
OPENSSL_free(ctx->server);
OPENSSL_free(ctx->proxy);
OPENSSL_free(ctx->no_proxy);
X509_free(ctx->srvCert);
X509_free(ctx->validatedSrvCert);
@@ -252,12 +241,8 @@ int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert)
return 1;
}
/*
* Set callback function for checking if the cert is ok or should
* 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)
/* Set callback function for checking if the cert is ok or should be rejected */
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);
@@ -270,7 +255,6 @@ int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb)
/*
* Set argument, respectively a pointer to a structure containing arguments,
* optionally to be used by the certConf callback.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
{
@@ -380,11 +364,8 @@ int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
return res;
}
/*
* 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)
/* Set a callback function for error reporting and logging messages */
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);
@@ -411,7 +392,6 @@ void OSSL_CMP_CTX_print_errors(OSSL_CMP_CTX *ctx)
/*
* Set or clear the reference value to be used for identification
* (i.e., the user name) when using PBMAC.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
const unsigned char *ref, int len)
@@ -424,10 +404,7 @@ int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
len);
}
/*
* Set or clear the password to be used for protecting messages with PBMAC.
* Returns 1 on success, 0 on error
*/
/* Set or clear the password to be used for protecting messages with PBMAC */
int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
const int len)
{
@@ -465,7 +442,6 @@ STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx)
/*
* Copies any given stack of inbound X509 certificates to extraCertsIn
* of the OSSL_CMP_CTX structure so that they may be retrieved later.
* Returns 1 on success, 0 on error.
*/
int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
STACK_OF(X509) *extraCertsIn)
@@ -483,7 +459,6 @@ int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
/*
* Duplicate and set the given stack as the new stack of X509
* certificates to send out in the extraCerts field.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
STACK_OF(X509) *extraCertsOut)
@@ -503,7 +478,6 @@ int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
/*
* Add the given policy info object
* to the X509_EXTENSIONS of the requested certificate template.
* Returns 1 on success, 0 on error.
*/
int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo)
{
@@ -519,9 +493,7 @@ int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo)
return sk_POLICYINFO_push(ctx->policies, pinfo);
}
/*
* Add an ITAV for geninfo of the PKI message header
*/
/* Add an ITAV for geninfo of the PKI message header */
int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
{
if (ctx == NULL) {
@@ -531,9 +503,7 @@ int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
return OSSL_CMP_ITAV_push0_stack_item(&ctx->geninfo_ITAVs, itav);
}
/*
* Add an itav for the body of outgoing general messages
*/
/* Add an itav for the body of outgoing general messages */
int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
{
if (ctx == NULL) {
@@ -562,7 +532,6 @@ STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx)
/*
* Duplicate and copy the given stack of certificates to the given
* OSSL_CMP_CTX structure so that they may be retrieved later.
* Returns 1 on success, 0 on error
*/
int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs)
{
@@ -614,39 +583,25 @@ int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \
* Pins the server certificate to be directly trusted (even if it is expired)
* for verifying response messages.
* Cert pointer is not consumed. It may be NULL to clear the entry.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1_up_ref(srvCert, X509)
/*
* Set the X509 name of the recipient. Set in the PKIHeader.
* returns 1 on success, 0 on error
*/
/* Set the X509 name of the recipient. Set in the PKIHeader */
DEFINE_OSSL_CMP_CTX_set1(recipient, X509_NAME)
/*
* Store the X509 name of the expected sender in the PKIHeader of responses.
* Returns 1 on success, 0 on error
*/
/* Store the X509 name of the expected sender in the PKIHeader of responses */
DEFINE_OSSL_CMP_CTX_set1(expected_sender, X509_NAME)
/*
* Set the X509 name of the issuer. Set in the PKIHeader.
* Returns 1 on success, 0 on error
*/
/* Set the X509 name of the issuer. Set in the PKIHeader */
DEFINE_OSSL_CMP_CTX_set1(issuer, X509_NAME)
/*
* Set the subject name that will be placed in the certificate
* request. This will be the subject name on the received certificate.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1(subjectName, X509_NAME)
/*
* Set the X.509v3 certificate request extensions to be used in IR/CR/KUR.
* Returns 1 on success, 0 on error
*/
/* Set the X.509v3 certificate request extensions to be used in IR/CR/KUR */
int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts)
{
if (ctx == NULL) {
@@ -680,7 +635,6 @@ int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx)
/*
* Add a GENERAL_NAME structure that will be added to the CRMF
* request's extensions field to request subject alternative names.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
const GENERAL_NAME *name)
@@ -712,7 +666,6 @@ int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
/*
* Set our own client certificate, used for example in KUR and when
* doing the IR with existing certificate.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1_up_ref(clCert, X509)
@@ -721,19 +674,14 @@ DEFINE_OSSL_CMP_CTX_set1_up_ref(clCert, X509)
* or the certificate to be revoked in RR, respectively.
* Also used as reference cert (defaulting to clCert) for deriving subject DN
* and SANs. Its issuer is used as default recipient in the CMP message header.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1_up_ref(oldCert, X509)
/*
* Set the PKCS#10 CSR to be sent in P10CR.
* Returns 1 on success, 0 on error
*/
/* Set the PKCS#10 CSR to be sent in P10CR */
DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ)
/*
* Sets the (newly received in IP/KUP/CP) certificate in the context.
* Returns 1 on success, 0 on error
* Set the (newly received in IP/KUP/CP) certificate in the context.
* TODO: this only permits for one cert to be enrolled at a time.
*/
int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert)
@@ -759,16 +707,10 @@ X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx)
return ctx->newCert;
}
/*
* Set the client's current private key.
* Returns 1 on success, 0 on error
*/
/* Set the client's current private key */
DEFINE_OSSL_CMP_CTX_set1_up_ref(pkey, EVP_PKEY)
/*
* Set new key pair. Used e.g. when doing Key Update.
* Returns 1 on success, 0 on error
*/
/* Set new key pair. Used e.g. when doing Key Update */
int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey)
{
if (ctx == NULL) {
@@ -782,9 +724,7 @@ int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey)
return 1;
}
/*
* gets the private/public key to use for certificate enrollment, NULL on error
*/
/* Get the private/public key to use for cert enrollment, or NULL on error */
EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv)
{
if (ctx == NULL) {
@@ -799,10 +739,7 @@ EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv)
return ctx->pkey; /* may be NULL */
}
/*
* Sets the given transactionID to the context.
* Returns 1 on success, 0 on error
*/
/* Set the given transactionID to the context */
int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *id)
{
@@ -813,11 +750,7 @@ int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
return ossl_cmp_asn1_octet_string_set1(&ctx->transactionID, id);
}
/*
* sets the given nonce to be used for the recipNonce in the next message to be
* created.
* returns 1 on success, 0 on error
*/
/* Set the nonce to be used for the recipNonce in the message created next */
int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce)
{
@@ -826,10 +759,7 @@ int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
return ossl_cmp_asn1_octet_string_set1(&ctx->recipNonce, nonce);
}
/*
* Stores the given nonce as the last senderNonce sent out.
* Returns 1 on success, 0 on error
*/
/* Stores the given nonce as the last senderNonce sent out */
int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce)
{
@@ -840,36 +770,16 @@ int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
return ossl_cmp_asn1_octet_string_set1(&ctx->senderNonce, nonce);
}
/*
* Set the host name of the (HTTP) proxy server to use for all connections
* returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1(proxyName, char)
/* Set the proxy server to use for HTTP(S) connections */
DEFINE_OSSL_CMP_CTX_set1(proxy, char)
/*
* Set the (HTTP) host name of the CA server.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1(serverName, char)
/* Set the (HTTP) host name of the CMP server */
DEFINE_OSSL_CMP_CTX_set1(server, char)
/*
* Sets the (HTTP) proxy port to be used.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set_proxyPort(OSSL_CMP_CTX *ctx, int port)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->proxyPort = port;
return 1;
}
/* Set the server exclusion list of the HTTP proxy server */
DEFINE_OSSL_CMP_CTX_set1(no_proxy, char)
/*
* sets the http connect/disconnect callback function to be used for HTTP(S)
* returns 1 on success, 0 on error
*/
/* Set the http connect/disconnect callback function to be used for HTTP(S) */
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb)
{
if (ctx == NULL) {
@@ -880,10 +790,7 @@ int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb)
return 1;
}
/*
* Set argument optionally to be used by the http connect/disconnect callback.
* Returns 1 on success, 0 on error
*/
/* Set argument optionally to be used by the http connect/disconnect callback */
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
{
if (ctx == NULL) {
@@ -907,11 +814,8 @@ void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx)
return ctx->http_cb_arg;
}
/*
* 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)
/* Set callback function for sending CMP request and receiving response */
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);
@@ -921,10 +825,7 @@ int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_transfer_cb_t cb)
return 1;
}
/*
* Set argument optionally to be used by the transfer callback.
* Returns 1 on success, 0 on error
*/
/* Set argument optionally to be used by the transfer callback */
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
{
if (ctx == NULL) {
@@ -948,10 +849,7 @@ void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx)
return ctx->transfer_cb_arg;
}
/*
* Sets the (HTTP) server port to be used.
* Returns 1 on success, 0 on error
*/
/** Set the HTTP server port to be used */
int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port)
{
if (ctx == NULL) {
@@ -962,16 +860,10 @@ int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port)
return 1;
}
/*
* Sets the HTTP path to be used on the server (e.g "pkix/").
* Returns 1 on success, 0 on error
*/
/* Set the HTTP path to be used on the server (e.g "pkix/") */
DEFINE_OSSL_CMP_CTX_set1(serverPath, char)
/*
* Set the failInfo error code as bit encoding in OSSL_CMP_CTX.
* Returns 1 on success, 0 on error
*/
/* Set the failInfo error code as bit encoding in OSSL_CMP_CTX */
int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info)
{
if (!ossl_assert(ctx != NULL))
@@ -993,10 +885,7 @@ int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx)
return ctx->failInfoCode;
}
/*
* Sets a Boolean or integer option of the context to the "val" arg.
* Returns 1 on success, 0 on error
*/
/* Set a Boolean or integer option of the context to the "val" arg */
int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
{
int min_val;
@@ -1010,7 +899,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 +919,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 +931,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 +946,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 +962,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 +1000,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 +1018,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 +1026,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:
+40 -1
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 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
@@ -16,26 +16,44 @@
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),
"certreqmsg not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTRESPONSE_NOT_FOUND),
"certresponse not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERT_AND_KEY_DO_NOT_MATCH),
"cert and key do not match"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CHECKAFTER_OUT_OF_RANGE),
"checkafter out of range"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE),
"checking pbm no secret available"},
{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),
@@ -48,10 +66,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_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_UNEXPECTED_CERTCONF),
"error unexpected certconf"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_PROTECTION),
"error validating protection"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY),
@@ -72,6 +94,10 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
"missing sender identification"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_TRUST_STORE),
"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"},
@@ -81,23 +107,32 @@ 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),
@@ -106,7 +141,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}
};
+27 -41
View File
@@ -63,31 +63,42 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr)
return hdr->recipNonce;
}
int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name)
{
X509_NAME *null = X509_NAME_new();
int res = name == NULL || null == NULL
|| (name->type == GEN_DIRNAME
&& X509_NAME_cmp(name->d.directoryName, null) == 0);
X509_NAME_free(null);
return res;
}
/* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */
static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src)
{
GENERAL_NAME *gen;
GENERAL_NAME *name;
if (!ossl_assert(tgt != NULL))
return 0;
if ((gen = GENERAL_NAME_new()) == NULL)
if ((name = GENERAL_NAME_new()) == NULL)
goto err;
gen->type = GEN_DIRNAME;
name->type = GEN_DIRNAME;
if (src == NULL) { /* NULL-DN */
if ((gen->d.directoryName = X509_NAME_new()) == NULL)
if ((name->d.directoryName = X509_NAME_new()) == NULL)
goto err;
} else if (!X509_NAME_set(&gen->d.directoryName, src)) {
} else if (!X509_NAME_set(&name->d.directoryName, src)) {
goto err;
}
GENERAL_NAME_free(*tgt);
*tgt = gen;
*tgt = name;
return 1;
err:
GENERAL_NAME_free(gen);
GENERAL_NAME_free(name);
return 0;
}
@@ -153,25 +164,6 @@ int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr,
}
/* push the given text string to the given PKIFREETEXT ft */
int ossl_cmp_pkifreetext_push_str(OSSL_CMP_PKIFREETEXT *ft, const char *text)
{
ASN1_UTF8STRING *utf8string;
if (!ossl_assert(ft != NULL && text != NULL))
return 0;
if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
return 0;
if (!ASN1_STRING_set(utf8string, text, -1))
goto err;
if (!sk_ASN1_UTF8STRING_push(ft, utf8string))
goto err;
return 1;
err:
ASN1_UTF8STRING_free(utf8string);
return 0;
}
int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
{
if (!ossl_assert(hdr != NULL && text != NULL))
@@ -193,7 +185,8 @@ int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
&& (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL)
return 0;
return ossl_cmp_pkifreetext_push_str(hdr->freeText, (char *)text->data);
return
ossl_cmp_sk_ASN1_UTF8STRING_push_str(hdr->freeText, (char *)text->data);
}
int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
@@ -205,7 +198,7 @@ int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
}
int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr,
STACK_OF(OSSL_CMP_ITAV) *itavs)
const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
int i;
OSSL_CMP_ITAV *itav;
@@ -250,7 +243,7 @@ int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr)
}
/* return 1 if implicitConfirm in the generalInfo field of the header is set */
int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
{
int itavCount;
int i;
@@ -273,8 +266,8 @@ int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
/* fill in all fields of the hdr according to the info given in ctx */
int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
{
X509_NAME *sender;
X509_NAME *rcp = NULL;
const X509_NAME *sender;
const X509_NAME *rcp = NULL;
if (!ossl_assert(ctx != NULL && hdr != NULL))
return 0;
@@ -283,19 +276,12 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
if (!ossl_cmp_hdr_set_pvno(hdr, OSSL_CMP_PVNO))
return 0;
sender = ctx->clCert != NULL ?
X509_get_subject_name(ctx->clCert) : ctx->subjectName;
/*
* The sender name is copied from the subject of the client cert, if any,
* or else from the the subject name provided for certification requests.
* As required by RFC 4210 section 5.1.1., if the sender name is not known
* to the client it set to NULL-DN. In this case for identification at least
* the senderKID must be set, which we take from any referenceValue given.
* or else from the subject name provided for certification requests.
*/
if (sender == NULL && ctx->referenceValue == NULL) {
CMPerr(0, CMP_R_MISSING_SENDER_IDENTIFICATION);
return 0;
}
sender = ctx->clCert != NULL ?
X509_get_subject_name(ctx->clCert) : ctx->subjectName;
if (!ossl_cmp_hdr_set1_sender(hdr, sender))
return 0;
+66
View File
@@ -0,0 +1,66 @@
/*
* 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 <string.h>
#include <stdio.h>
#include <openssl/asn1t.h>
#include <openssl/http.h>
#include "internal/sockets.h"
#include "openssl/cmp.h"
#include "cmp_local.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/cmp.h>
#include <openssl/err.h>
/*
* Send the PKIMessage req and on success return the response, else NULL.
* Any previous error queue entries will likely be removed by ERR_clear_error().
*/
OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req)
{
char server_port[32] = { '\0' };
STACK_OF(CONF_VALUE) *headers = NULL;
const char *const content_type_pkix = "application/pkixcmp";
OSSL_CMP_MSG *res;
if (ctx == NULL || req == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
if (!X509V3_add_value("Pragma", "no-cache", &headers))
return NULL;
if (ctx->serverPort != 0)
BIO_snprintf(server_port, sizeof(server_port), "%d", ctx->serverPort);
res = (OSSL_CMP_MSG *)
OSSL_HTTP_post_asn1(ctx->server, server_port, ctx->serverPath,
OSSL_CMP_CTX_get_http_cb_arg(ctx) != NULL,
ctx->proxy, ctx->no_proxy, NULL, NULL,
ctx->http_cb, OSSL_CMP_CTX_get_http_cb_arg(ctx),
headers, content_type_pkix,
(ASN1_VALUE *)req, ASN1_ITEM_rptr(OSSL_CMP_MSG),
0, 0, ctx->msg_timeout, content_type_pkix,
ASN1_ITEM_rptr(OSSL_CMP_MSG));
sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
return res;
}
+42 -49
View File
@@ -28,20 +28,20 @@
* 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;
char *serverName;
char *server;
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. */
char *proxy;
char *no_proxy;
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;
@@ -56,7 +56,7 @@ struct ossl_cmp_ctx_st {
int unprotectedErrors;
X509 *srvCert; /* certificate used to identify the server */
X509 *validatedSrvCert; /* caches any already validated server cert */
X509_NAME *expected_sender; /* expected sender in pkiheader of response */
X509_NAME *expected_sender; /* expected sender in header of response */
X509_STORE *trusted; /* trust store maybe w CRLs and cert verify callback */
STACK_OF(X509) *untrusted_certs; /* untrusted (intermediate) certs */
int ignore_keyusage; /* ignore key usage entry when validating certs */
@@ -95,7 +95,7 @@ struct ossl_cmp_ctx_st {
int newPkey_priv; /* flag indicating if newPkey contains private key */
X509_NAME *issuer; /* issuer name to used in cert template */
int days; /* Number of days new certificates are asked to be valid for */
X509_NAME *subjectName; /* subject name to be used in the cert template */
X509_NAME *subjectName; /* subject name to be used in cert template */
STACK_OF(GENERAL_NAME) *subjectAltNames; /* to add to the cert template */
int SubjectAltName_nodefault;
int setSubjectAltNameCritical;
@@ -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 */;
@@ -246,7 +246,6 @@ struct ossl_cmp_itav_st {
} infoValue;
} /* OSSL_CMP_ITAV */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ITAV)
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
typedef struct ossl_cmp_certorenccert_st {
int type;
@@ -284,8 +283,6 @@ struct ossl_cmp_pkisi_st {
OSSL_CMP_PKIFREETEXT *statusString;
OSSL_CMP_PKIFAILUREINFO *failInfo;
} /* OSSL_CMP_PKISI */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI)
DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID)
/*-
@@ -296,10 +293,11 @@ DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID)
* crlEntryDetails Extensions OPTIONAL
* }
*/
typedef struct ossl_cmp_revdetails_st {
struct ossl_cmp_revdetails_st {
OSSL_CRMF_CERTTEMPLATE *certDetails;
X509_EXTENSIONS *crlEntryDetails;
} OSSL_CMP_REVDETAILS;
} /* OSSL_CMP_REVDETAILS */;
typedef struct ossl_cmp_revdetails_st OSSL_CMP_REVDETAILS;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVDETAILS)
DEFINE_STACK_OF(OSSL_CMP_REVDETAILS)
@@ -375,7 +373,6 @@ struct ossl_cmp_certstatus_st {
OSSL_CMP_PKISI *statusInfo;
} /* OSSL_CMP_CERTSTATUS */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS)
typedef STACK_OF(OSSL_CMP_CERTSTATUS) OSSL_CMP_CERTCONFIRMCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTCONFIRMCONTENT)
@@ -670,7 +667,6 @@ struct ossl_cmp_msg_st {
STACK_OF(X509) *extraCerts; /* 1 */
} /* OSSL_CMP_MSG */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_MSG)
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_MSG)
/*-
* ProtectedPart ::= SEQUENCE {
@@ -728,17 +724,6 @@ DECLARE_ASN1_FUNCTIONS(CMP_PROTECTEDPART)
* }
*/
/*
* constants
*/
/* certReqId for the first - and so far only - certificate request */
# define OSSL_CMP_CERTREQID 0
/* sequence id for the first - and so far only - revocation request */
# define OSSL_CMP_REVREQSID 0
/*
* functions
*/
/* from cmp_asn.c */
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
@@ -755,6 +740,9 @@ int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
int no_self_issued, int no_dups, int prepend);
int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
int only_self_issued);
STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store);
int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
const char *text);
int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
const ASN1_OCTET_STRING *src);
int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
@@ -800,32 +788,30 @@ int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce);
/* from cmp_status.c */
OSSL_CMP_PKISI *
ossl_cmp_statusinfo_new(int status, int fail_info, const char *text);
int ossl_cmp_pkisi_get_pkistatus(const OSSL_CMP_PKISI *statusInfo);
int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si);
const char *ossl_cmp_PKIStatus_to_string(int status);
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusstring(const OSSL_CMP_PKISI *si);
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si);
int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si);
int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index);
int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int index);
/* from cmp_hdr.c */
int ossl_cmp_hdr_set_pvno(OSSL_CMP_PKIHEADER *hdr, int pvno);
int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr);
ASN1_OCTET_STRING *ossl_cmp_hdr_get0_senderNonce(const OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name);
int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr,
const ASN1_OCTET_STRING *senderKID);
int ossl_cmp_pkifreetext_push_str(OSSL_CMP_PKIFREETEXT *ft, const char *text);
int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
OSSL_CMP_ITAV *itav);
int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr,
STACK_OF(OSSL_CMP_ITAV) *itavs);
const STACK_OF(OSSL_CMP_ITAV) *itavs);
int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr);
# define OSSL_CMP_TRANSACTIONID_LENGTH 16
# define OSSL_CMP_SENDERNONCE_LENGTH 16
int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
@@ -860,6 +846,10 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
# define OSSL_CMP_PKIBODY_POLLREQ 25
# define OSSL_CMP_PKIBODY_POLLREP 26
# define OSSL_CMP_PKIBODY_TYPE_MAX OSSL_CMP_PKIBODY_POLLREP
/* certReqId for the first - and so far only - certificate request */
# define OSSL_CMP_CERTREQID 0
/* sequence id for the first - and so far only - revocation request */
# define OSSL_CMP_REVREQSID 0
const char *ossl_cmp_bodytype_to_string(int type);
int ossl_cmp_msg_set_bodytype(OSSL_CMP_MSG *msg, int type);
int ossl_cmp_msg_get_bodytype(const OSSL_CMP_MSG *msg);
@@ -875,24 +865,26 @@ OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
OSSL_CRMF_CERTID *certId, int unprot_err);
OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
int64_t poll_after);
int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav);
int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
STACK_OF(OSSL_CMP_ITAV) *itavs);
const STACK_OF(OSSL_CMP_ITAV) *itavs);
OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
const STACK_OF(OSSL_CMP_ITAV) *itavs);
OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
int errorCode,
OSSL_CMP_PKIFREETEXT *errorDetails,
int unprotected);
int ossl_cmp_certstatus_set_certHash(OSSL_CMP_CERTSTATUS *certStatus,
const X509 *cert);
const char *details, int unprotected);
int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
ASN1_OCTET_STRING *hash);
OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
const char *text);
OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid);
OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
int64_t poll_after);
OSSL_CMP_PKISI *
ossl_cmp_revrepcontent_get_pkistatusinfo(OSSL_CMP_REVREPCONTENT *rrep, int rsid);
ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid);
OSSL_CRMF_CERTID *ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep,
int rsid);
OSSL_CMP_POLLREP *
@@ -904,11 +896,6 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crepmsg
X509 *ossl_cmp_certresponse_get1_certificate(EVP_PKEY *privkey,
const OSSL_CMP_CERTRESPONSE *crep);
OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file);
/* BIO definitions */
# define OSSL_d2i_CMP_MSG_bio(bp, p) \
ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new, d2i_OSSL_CMP_MSG, bp, p)
# define OSSL_i2d_CMP_MSG_bio(bp, o) \
ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bp, o)
/* from cmp_protect.c */
ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_MSG *msg,
@@ -925,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);
#endif /* !defined OSSL_CRYPTO_CMP_LOCAL_H */
/* 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) */
+70 -72
View File
@@ -185,8 +185,8 @@ OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype)
(sk_GENERAL_NAME_num((ctx)->subjectAltNames) > 0 \
|| OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1)
static X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert,
int bodytype)
static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert,
int bodytype)
{
if (ctx->subjectName != NULL)
return ctx->subjectName;
@@ -205,18 +205,20 @@ static X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert,
* Create CRMF certificate request message for IR/CR/KUR
* returns a pointer to the OSSL_CRMF_MSG on success, NULL on error
*/
static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype,
int rid, EVP_PKEY *rkey)
static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype, int rid)
{
OSSL_CRMF_MSG *crm = NULL;
X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->clCert;
/* refcert defaults to current client cert */
EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0);
STACK_OF(GENERAL_NAME) *default_sans = NULL;
X509_NAME *subject = determine_subj(ctx, refcert, bodytype);
const X509_NAME *subject = determine_subj(ctx, refcert, bodytype);
int crit = ctx->setSubjectAltNameCritical || subject == NULL;
/* RFC5280: subjectAltName MUST be critical if subject is null */
X509_EXTENSIONS *exts = NULL;
if (rkey == NULL)
rkey = ctx->pkey; /* default is independent of ctx->oldClCert */
if (rkey == NULL
|| (bodytype == OSSL_CMP_PKIBODY_KUR && refcert == NULL)) {
CMPerr(0, CMP_R_INVALID_ARGS);
@@ -300,19 +302,12 @@ static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype,
OSSL_CMP_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int type, int err_code)
{
EVP_PKEY *rkey;
EVP_PKEY *privkey;
OSSL_CMP_MSG *msg;
OSSL_CRMF_MSG *crm = NULL;
if (!ossl_assert(ctx != NULL))
return NULL;
rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0);
if (rkey == NULL)
return NULL;
privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
if (type != OSSL_CMP_PKIBODY_IR && type != OSSL_CMP_PKIBODY_CR
&& type != OSSL_CMP_PKIBODY_KUR && type != OSSL_CMP_PKIBODY_P10CR) {
CMPerr(0, CMP_R_INVALID_ARGS);
@@ -329,15 +324,19 @@ OSSL_CMP_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int type, int err_code)
/* body */
/* For P10CR the content has already been set in OSSL_CMP_MSG_create */
if (type != OSSL_CMP_PKIBODY_P10CR) {
EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
if (privkey == NULL)
privkey = ctx->pkey; /* default is independent of ctx->oldCert */
if (ctx->popoMethod == OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) {
CMPerr(0, CMP_R_MISSING_PRIVATE_KEY);
goto err;
}
if ((crm = crm_new(ctx, type, OSSL_CMP_CERTREQID, rkey)) == NULL
|| !OSSL_CRMF_MSG_create_popo(crm, privkey, ctx->digest,
ctx->popoMethod)
/* value.ir is same for cr and kur */
|| !sk_OSSL_CRMF_MSG_push(msg->body->value.ir, crm))
if ((crm = crm_new(ctx, type, OSSL_CMP_CERTREQID)) == NULL
|| !OSSL_CRMF_MSG_create_popo(crm, privkey, ctx->digest,
ctx->popoMethod)
/* value.ir is same for cr and kur */
|| !sk_OSSL_CRMF_MSG_push(msg->body->value.ir, crm))
goto err;
crm = NULL;
/* TODO: here optional 2nd certreqmsg could be pushed to the stack */
@@ -349,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;
@@ -385,7 +385,7 @@ OSSL_CMP_MSG *ossl_cmp_certRep_new(OSSL_CMP_CTX *ctx, int bodytype,
|| !ASN1_INTEGER_set(resp->certReqId, certReqId))
goto err;
status = ossl_cmp_pkisi_get_pkistatus(resp->status);
status = ossl_cmp_pkisi_get_status(resp->status);
if (status != OSSL_CMP_PKISTATUS_rejection
&& status != OSSL_CMP_PKISTATUS_waiting && cert != NULL) {
if (encrypted) {
@@ -416,7 +416,7 @@ OSSL_CMP_MSG *ossl_cmp_certRep_new(OSSL_CMP_CTX *ctx, int bodytype,
goto err;
if (!unprotectedErrors
|| ossl_cmp_pkisi_get_pkistatus(si) != OSSL_CMP_PKISTATUS_rejection)
|| ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
@@ -511,7 +511,7 @@ OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
}
if (!unprot_err
|| ossl_cmp_pkisi_get_pkistatus(si) != OSSL_CMP_PKISTATUS_rejection)
|| ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
@@ -560,7 +560,7 @@ int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav)
}
int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
STACK_OF(OSSL_CMP_ITAV) *itavs)
const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
int i;
OSSL_CMP_ITAV *itav = NULL;
@@ -583,7 +583,9 @@ int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
* Creates a new General Message/Response with an empty itav stack
* returns a pointer to the PKIMessage on success, NULL on error
*/
static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, int body_type, int err_code)
static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx,
const STACK_OF(OSSL_CMP_ITAV) *itavs,
int body_type, int err_code)
{
OSSL_CMP_MSG *msg = NULL;
@@ -594,7 +596,7 @@ static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, int body_type, int err_code)
return NULL;
if (ctx->genm_ITAVs != NULL
&& !ossl_cmp_msg_gen_push1_ITAVs(msg, ctx->genm_ITAVs))
&& !ossl_cmp_msg_gen_push1_ITAVs(msg, itavs))
goto err;
if (!ossl_cmp_msg_protect(ctx, msg))
@@ -610,20 +612,23 @@ static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, int body_type, int err_code)
OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx)
{
return gen_new(ctx, OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM);
return gen_new(ctx, ctx->genm_ITAVs,
OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM);
}
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx)
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
return gen_new(ctx, OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP);
return gen_new(ctx, itavs,
OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP);
}
OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
int errorCode,
OSSL_CMP_PKIFREETEXT *errorDetails,
int unprotected)
const char *details, int unprotected)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_PKIFREETEXT *ft;
if (!ossl_assert(ctx != NULL && si != NULL))
return NULL;
@@ -641,11 +646,13 @@ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
if (!ASN1_INTEGER_set(msg->body->value.error->errorCode, errorCode))
goto err;
}
if (errorDetails != NULL)
if ((msg->body->value.error->errorDetails =
sk_ASN1_UTF8STRING_deep_copy(errorDetails, ASN1_STRING_dup,
ASN1_STRING_free)) == NULL)
if (details != NULL) {
if ((ft = sk_ASN1_UTF8STRING_new_null()) == NULL)
goto err;
msg->body->value.error->errorDetails = ft;
if (!ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details))
goto err;
}
if (!unprotected && !ossl_cmp_msg_protect(ctx, msg))
goto err;
@@ -658,44 +665,18 @@ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
}
/*
* OSSL_CMP_CERTSTATUS_set_certHash() calculates a hash of the certificate,
* using the same hash algorithm as is used to create and verify the
* certificate signature, and places the hash into the certHash field of a
* OSSL_CMP_CERTSTATUS structure. This is used in the certConf message,
* for example, to confirm that the certificate was received successfully.
* Set the certHash field of a OSSL_CMP_CERTSTATUS structure.
* This is used in the certConf message, for example,
* to confirm that the certificate was received successfully.
*/
int ossl_cmp_certstatus_set_certHash(OSSL_CMP_CERTSTATUS *certStatus,
const X509 *cert)
int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
ASN1_OCTET_STRING *hash)
{
unsigned int len;
unsigned char hash[EVP_MAX_MD_SIZE];
int md_NID;
const EVP_MD *md = NULL;
if (!ossl_assert(certStatus != NULL && cert != NULL))
if (!ossl_assert(certStatus != NULL))
return 0;
/*-
* select hash algorithm, as stated in Appendix F. Compilable ASN.1 defs:
* the hash of the certificate, using the same hash algorithm
* as is used to create and verify the certificate signature
*/
if (OBJ_find_sigid_algs(X509_get_signature_nid(cert), &md_NID, NULL)
&& (md = EVP_get_digestbynid(md_NID)) != NULL) {
if (!X509_digest(cert, md, hash, &len))
goto err;
if (!ossl_cmp_asn1_octet_string_set1_bytes(&certStatus->certHash, hash,
len))
goto err;
} else {
CMPerr(0, CMP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
ASN1_OCTET_STRING_free(certStatus->certHash);
certStatus->certHash = hash;
return 1;
err:
CMPerr(0, CMP_R_ERROR_SETTING_CERTHASH);
return 0;
}
/*
@@ -707,6 +688,7 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_CERTSTATUS *certStatus = NULL;
ASN1_OCTET_STRING *certHash = NULL;
OSSL_CMP_PKISI *sinfo;
if (!ossl_assert(ctx != NULL && ctx->newCert != NULL))
@@ -732,8 +714,12 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
* the hash of the certificate, using the same hash algorithm
* as is used to create and verify the certificate signature
*/
if (!ossl_cmp_certstatus_set_certHash(certStatus, ctx->newCert))
if ((certHash = X509_digest_sig(ctx->newCert)) == NULL)
goto err;
if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash))
goto err;
certHash = NULL;
/*
* For any particular CertStatus, omission of the statusInfo field
* indicates ACCEPTANCE of the specified certificate. Alternatively,
@@ -742,8 +728,8 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
* the CA/RA.
*/
sinfo = fail_info != 0 ?
ossl_cmp_statusinfo_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) :
ossl_cmp_statusinfo_new(OSSL_CMP_PKISTATUS_accepted, 0, text);
OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) :
OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_accepted, 0, text);
if (sinfo == NULL)
goto err;
certStatus->statusInfo = sinfo;
@@ -756,6 +742,7 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
err:
CMPerr(0, CMP_R_ERROR_CREATING_CERTCONF);
OSSL_CMP_MSG_free(msg);
ASN1_OCTET_STRING_free(certHash);
return NULL;
}
@@ -827,7 +814,7 @@ OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
* returns NULL on error
*/
OSSL_CMP_PKISI *
ossl_cmp_revrepcontent_get_pkistatusinfo(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
{
OSSL_CMP_PKISI *status;
@@ -990,7 +977,18 @@ OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file)
if ((bio = BIO_new_file(file, "rb")) == NULL)
return NULL;
msg = OSSL_d2i_CMP_MSG_bio(bio, NULL);
msg = d2i_OSSL_CMP_MSG_bio(bio, NULL);
BIO_free(bio);
return msg;
}
OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg)
{
return ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new,
d2i_OSSL_CMP_MSG, bio, msg);
}
int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg)
{
return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg);
}
+14 -1
View File
@@ -286,6 +286,8 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
* to section 5.1.1
*/
subjKeyIDStr = X509_get0_subject_key_id(ctx->clCert);
if (subjKeyIDStr == NULL)
subjKeyIDStr = ctx->referenceValue; /* fallback */
if (subjKeyIDStr != NULL
&& !ossl_cmp_hdr_set1_senderKID(msg->header, subjKeyIDStr))
goto err;
@@ -306,7 +308,18 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
}
}
return 1;
/*
* As required by RFC 4210 section 5.1.1., if the sender name is not known
* to the client it set to NULL-DN. In this case for identification at least
* the senderKID must be set, where we took the referenceValue as fallback.
*/
if (ossl_cmp_general_name_is_NULL_DN(msg->header->sender)
&& msg->header->senderKID == NULL)
CMPerr(0, CMP_R_MISSING_SENDER_IDENTIFICATION);
else
return 1;
err:
CMPerr(0, CMP_R_ERROR_PROTECTING_MESSAGE);
return 0;
+619
View File
@@ -0,0 +1,619 @@
/*
* 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
*/
/* general CMP server functions */
#include <openssl/asn1t.h>
#include "cmp_local.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/cmp.h>
#include <openssl/err.h>
/* the context for the generic CMP server */
struct ossl_cmp_srv_ctx_st
{
OSSL_CMP_CTX *ctx; /* Client CMP context, partly reused for srv */
void *custom_ctx; /* pointer to specific server context */
OSSL_CMP_SRV_cert_request_cb_t process_cert_request;
OSSL_CMP_SRV_rr_cb_t process_rr;
OSSL_CMP_SRV_genm_cb_t process_genm;
OSSL_CMP_SRV_error_cb_t process_error;
OSSL_CMP_SRV_certConf_cb_t process_certConf;
OSSL_CMP_SRV_pollReq_cb_t process_pollReq;
int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */
int acceptUnprotected; /* Accept requests with no/invalid prot. */
int acceptRAVerified; /* Accept ir/cr/kur with POPO RAVerified */
int grantImplicitConfirm; /* Grant implicit confirmation if requested */
}; /* OSSL_CMP_SRV_CTX */
void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL)
return;
OSSL_CMP_CTX_free(srv_ctx->ctx);
OPENSSL_free(srv_ctx);
}
OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(void)
{
OSSL_CMP_SRV_CTX *ctx = OPENSSL_zalloc(sizeof(OSSL_CMP_SRV_CTX));
if (ctx == NULL)
goto err;
if ((ctx->ctx = OSSL_CMP_CTX_new()) == NULL)
goto err;
/* all other elements are initialized to 0 or NULL, respectively */
return ctx;
err:
OSSL_CMP_SRV_CTX_free(ctx);
return NULL;
}
int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
OSSL_CMP_SRV_rr_cb_t process_rr,
OSSL_CMP_SRV_genm_cb_t process_genm,
OSSL_CMP_SRV_error_cb_t process_error,
OSSL_CMP_SRV_certConf_cb_t process_certConf,
OSSL_CMP_SRV_pollReq_cb_t process_pollReq)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->custom_ctx = custom_ctx;
srv_ctx->process_cert_request = process_cert_request;
srv_ctx->process_rr = process_rr;
srv_ctx->process_genm = process_genm;
srv_ctx->process_error = process_error;
srv_ctx->process_certConf = process_certConf;
srv_ctx->process_pollReq = process_pollReq;
return 1;
}
OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
return srv_ctx->ctx;
}
void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
return srv_ctx->custom_ctx;
}
int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx,
int val)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->sendUnprotectedErrors = val != 0;
return 1;
}
int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->acceptUnprotected = val != 0;
return 1;
}
int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->acceptRAVerified = val != 0;
return 1;
}
int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
int val)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->grantImplicitConfirm = val != 0;
return 1;
}
/*
* Processes an ir/cr/p10cr/kur and returns a certification response.
* Only handles the first certification request contained in req
* returns an ip/cp/kup on success and NULL on error
*/
static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_PKISI *si = NULL;
X509 *certOut = NULL;
STACK_OF(X509) *chainOut = NULL, *caPubs = NULL;
const OSSL_CRMF_MSG *crm = NULL;
const X509_REQ *p10cr = NULL;
int bodytype;
int certReqId;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
switch (ossl_cmp_msg_get_bodytype(req)) {
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_CR:
bodytype = OSSL_CMP_PKIBODY_CP;
break;
case OSSL_CMP_PKIBODY_IR:
bodytype = OSSL_CMP_PKIBODY_IP;
break;
case OSSL_CMP_PKIBODY_KUR:
bodytype = OSSL_CMP_PKIBODY_KUP;
break;
default:
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
return NULL;
}
if (ossl_cmp_msg_get_bodytype(req) == OSSL_CMP_PKIBODY_P10CR) {
certReqId = OSSL_CMP_CERTREQID;
p10cr = req->body->value.p10cr;
} else {
OSSL_CRMF_MSGS *reqs = req->body->value.ir; /* same for cr and kur */
if (sk_OSSL_CRMF_MSG_num(reqs) != 1) { /* TODO: handle case > 1 */
CMPerr(0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
if ((crm = sk_OSSL_CRMF_MSG_value(reqs, OSSL_CMP_CERTREQID)) == NULL) {
CMPerr(0, CMP_R_CERTREQMSG_NOT_FOUND);
return NULL;
}
certReqId = OSSL_CRMF_MSG_get_certReqId(crm);
}
if (!ossl_cmp_verify_popo(req, srv_ctx->acceptRAVerified)) {
/* Proof of possession could not be verified */
si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection,
1 << OSSL_CMP_PKIFAILUREINFO_badPOP,
ERR_reason_error_string(ERR_peek_error()));
if (si == NULL)
return NULL;
} else {
OSSL_CMP_PKIHEADER *hdr = OSSL_CMP_MSG_get0_header(req);
si = srv_ctx->process_cert_request(srv_ctx, req, certReqId, crm, p10cr,
&certOut, &chainOut, &caPubs);
if (si == NULL)
goto err;
/* 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: */
&& certOut != NULL))
goto err;
}
msg = ossl_cmp_certRep_new(srv_ctx->ctx, bodytype, certReqId, si,
certOut, chainOut, caPubs, 0 /* encrypted */,
srv_ctx->sendUnprotectedErrors);
/*
* TODO when implemented in ossl_cmp_certrep_new():
* in case OSSL_CRMF_POPO_KEYENC, set encrypted
*/
if (msg == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_CERTREP);
err:
OSSL_CMP_PKISI_free(si);
X509_free(certOut);
sk_X509_pop_free(chainOut, X509_free);
sk_X509_pop_free(caPubs, X509_free);
return msg;
}
static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_REVDETAILS *details;
OSSL_CRMF_CERTID *certId;
OSSL_CRMF_CERTTEMPLATE *tmpl;
const X509_NAME *issuer;
ASN1_INTEGER *serial;
OSSL_CMP_PKISI *si;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
if (sk_OSSL_CMP_REVDETAILS_num(req->body->value.rr) != 1) {
/* TODO: handle multiple elements if multiple requests have been sent */
CMPerr(0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr,
OSSL_CMP_REVREQSID)) == NULL) {
CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
tmpl = details->certDetails;
issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl);
serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
/* here issuer and serial may safely be NULL */
if ((certId = OSSL_CRMF_CERTID_gen(issuer, serial)) == NULL)
return NULL;
if ((si = srv_ctx->process_rr(srv_ctx, req, issuer, serial)) == NULL)
goto err;
if ((msg = ossl_cmp_rp_new(srv_ctx->ctx, si, certId,
srv_ctx->sendUnprotectedErrors)) == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_RR);
err:
OSSL_CRMF_CERTID_free(certId);
OSSL_CMP_PKISI_free(si);
return msg;
}
/*
* Processes genm and creates a genp message mirroring the contents of the
* incoming message
*/
static OSSL_CMP_MSG *process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_GENMSGCONTENT *itavs;
OSSL_CMP_MSG *msg;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
if (!srv_ctx->process_genm(srv_ctx, req, req->body->value.genm, &itavs))
return NULL;
msg = ossl_cmp_genp_new(srv_ctx->ctx, itavs);
sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
return msg;
}
static OSSL_CMP_MSG *process_error(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_ERRORMSGCONTENT *errorContent;
OSSL_CMP_MSG *msg;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
errorContent = req->body->value.error;
srv_ctx->process_error(srv_ctx, req, errorContent->pKIStatusInfo,
errorContent->errorCode, errorContent->errorDetails);
if ((msg = ossl_cmp_pkiconf_new(srv_ctx->ctx)) == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_PKICONF);
return msg;
}
static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_CTX *ctx;
OSSL_CMP_CERTCONFIRMCONTENT *ccc;
int num;
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_CERTSTATUS *status = NULL;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
ctx = srv_ctx->ctx;
ccc = req->body->value.certConf;
num = sk_OSSL_CMP_CERTSTATUS_num(ccc);
if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 1) {
CMPerr(0, CMP_R_ERROR_UNEXPECTED_CERTCONF);
return NULL;
}
if (num == 0) {
ossl_cmp_err(ctx, "certificate rejected by client");
} else {
if (num > 1)
ossl_cmp_warn(ctx, "All CertStatus but the first will be ignored");
status = sk_OSSL_CMP_CERTSTATUS_value(ccc, OSSL_CMP_CERTREQID);
}
if (status != NULL) {
int certReqId = ossl_cmp_asn1_get_int(status->certReqId);
ASN1_OCTET_STRING *certHash = status->certHash;
OSSL_CMP_PKISI *si = status->statusInfo;
if (!srv_ctx->process_certConf(srv_ctx, req, certReqId, certHash, si))
return NULL; /* reason code may be: CMP_R_CERTHASH_UNMATCHED */
if (si != NULL && ossl_cmp_pkisi_get_status(si)
!= OSSL_CMP_PKISTATUS_accepted) {
int pki_status = ossl_cmp_pkisi_get_status(si);
const char *str = ossl_cmp_PKIStatus_to_string(pki_status);
ossl_cmp_log2(INFO, ctx, "certificate rejected by client %s %s",
str == NULL ? "without" : "with",
str == NULL ? "PKIStatus" : str);
}
}
if ((msg = ossl_cmp_pkiconf_new(ctx)) == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_PKICONF);
return msg;
}
static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_POLLREQCONTENT *prc;
OSSL_CMP_POLLREQ *pr;
int certReqId;
OSSL_CMP_MSG *certReq;
int64_t check_after = 0;
OSSL_CMP_MSG *msg = NULL;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
prc = req->body->value.pollReq;
if (sk_OSSL_CMP_POLLREQ_num(prc) != 1) { /* TODO: handle case > 1 */
CMPerr(0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
pr = sk_OSSL_CMP_POLLREQ_value(prc, 0);
certReqId = ossl_cmp_asn1_get_int(pr->certReqId);
if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId,
&certReq, &check_after))
return NULL;
if (certReq != NULL) {
msg = process_cert_request(srv_ctx, certReq);
OSSL_CMP_MSG_free(certReq);
} else {
if ((msg = ossl_cmp_pollRep_new(srv_ctx->ctx, certReqId,
check_after)) == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_POLLREP);
}
return msg;
}
/*
* 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");
return 1;
}
if (ossl_cmp_msg_get_bodytype(req) == OSSL_CMP_PKIBODY_ERROR
&& OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS) == 1) {
ossl_cmp_warn(ctx, "ignoring missing protection of error message");
return 1;
}
return 0;
}
/*
* returns created message and NULL on internal error
*/
OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_CTX *ctx;
OSSL_CMP_PKIHEADER *hdr;
int req_type, rsp_type;
OSSL_CMP_MSG *rsp = NULL;
if (srv_ctx == NULL || srv_ctx->ctx == NULL
|| req == NULL || req->body == NULL
|| (hdr = OSSL_CMP_MSG_get0_header(req)) == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx = srv_ctx->ctx;
if (hdr->sender->type != GEN_DIRNAME) {
CMPerr(0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
goto err;
}
if (!OSSL_CMP_CTX_set1_recipient(ctx, hdr->sender->d.directoryName))
goto err;
req_type = ossl_cmp_msg_get_bodytype(req);
switch (req_type) {
case OSSL_CMP_PKIBODY_IR:
case OSSL_CMP_PKIBODY_CR:
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_KUR:
case OSSL_CMP_PKIBODY_RR:
case OSSL_CMP_PKIBODY_GENM:
case OSSL_CMP_PKIBODY_ERROR:
if (ctx->transactionID != NULL) {
char *tid;
tid = OPENSSL_buf2hexstr(ctx->transactionID->data,
ctx->transactionID->length);
ossl_cmp_log1(WARN, ctx,
"Assuming that last transaction with ID=%s got aborted",
tid);
OPENSSL_free(tid);
}
/* start of a new transaction, set transactionID and senderNonce */
if (!OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID)
|| !ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce))
goto err;
break;
default:
/* transactionID should be already initialized */
if (ctx->transactionID == NULL) {
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
/* ignore any (extra) error in next two function calls: */
(void)OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID);
(void)ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce);
goto err;
}
}
if (ossl_cmp_msg_check_received(ctx, req, unprotected_exception,
srv_ctx->acceptUnprotected) < 0)
goto err;
switch (req_type) {
case OSSL_CMP_PKIBODY_IR:
case OSSL_CMP_PKIBODY_CR:
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_KUR:
if (srv_ctx->process_cert_request == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_cert_request(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_RR:
if (srv_ctx->process_rr == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_rr(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_GENM:
if (srv_ctx->process_genm == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_genm(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_ERROR:
if (srv_ctx->process_error == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_error(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_CERTCONF:
if (srv_ctx->process_certConf == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_certConf(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_POLLREQ:
if (srv_ctx->process_pollReq == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_pollReq(srv_ctx, req);
break;
default:
/* TODO possibly support further request message types */
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
}
err:
if (rsp == NULL) {
/* on error, try to respond with CMP error message to client */
const char *data = NULL;
int flags = 0;
unsigned long err = ERR_peek_error_data(&data, &flags);
int fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_badRequest;
/* TODO fail_info could be more specific */
OSSL_CMP_PKISI *si = NULL;
if ((si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection,
fail_info, NULL)) == NULL)
return 0;
if (err != 0 && (flags & ERR_TXT_STRING) != 0)
data = ERR_reason_error_string(err);
rsp = ossl_cmp_error_new(srv_ctx->ctx, si,
err != 0 ? ERR_GET_REASON(err) : -1,
data, srv_ctx->sendUnprotectedErrors);
OSSL_CMP_PKISI_free(si);
}
/* possibly close the transaction */
rsp_type =
rsp != NULL ? ossl_cmp_msg_get_bodytype(rsp) : OSSL_CMP_PKIBODY_ERROR;
switch (rsp_type) {
case OSSL_CMP_PKIBODY_IP:
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_IMPLICIT_CONFIRM) == 0)
break;
/* fall through */
case OSSL_CMP_PKIBODY_PKICONF:
case OSSL_CMP_PKIBODY_GENP:
case OSSL_CMP_PKIBODY_ERROR:
/* TODO possibly support further terminating response message types */
(void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL); /* ignore any error */
default: /* not closing transaction in other cases */
break;
}
return rsp;
}
/*
* Server interface that may substitute OSSL_CMP_MSG_http_perform at the client.
* The OSSL_CMP_SRV_CTX must be set as client_ctx->transfer_cb_arg.
* returns received message on success, else NULL and pushes an element on the
* error stack.
*/
OSSL_CMP_MSG * OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_SRV_CTX *srv_ctx = NULL;
if (client_ctx == NULL || req == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
if ((srv_ctx = OSSL_CMP_CTX_get_transfer_cb_arg(client_ctx)) == NULL) {
CMPerr(0, CMP_R_TRANSFER_ERROR);
return 0;
}
return OSSL_CMP_SRV_process_request(srv_ctx, req);
}
+56 -44
View File
@@ -28,17 +28,13 @@
/* CMP functions related to PKIStatus */
int ossl_cmp_pkisi_get_pkistatus(const OSSL_CMP_PKISI *si)
int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si)
{
if (!ossl_assert(si != NULL && si->status != NULL))
return -1;
return ossl_cmp_asn1_get_int(si->status);
}
/*
* return the declared identifier and a short explanation for the PKIStatus
* value as specified in RFC4210, Appendix F.
*/
const char *ossl_cmp_PKIStatus_to_string(int status)
{
switch (status) {
@@ -67,27 +63,19 @@ const char *ossl_cmp_PKIStatus_to_string(int status)
}
}
/*
* returns a pointer to the statusString contained in a PKIStatusInfo
* returns NULL on error
*/
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusstring(const OSSL_CMP_PKISI *si)
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si)
{
if (!ossl_assert(si != NULL))
return NULL;
return si->statusString;
}
/*
* returns the FailureInfo bits of the given PKIStatusInfo
* returns -1 on error
*/
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))
@@ -95,12 +83,9 @@ int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si)
return res;
}
/*
* internal function
/*-
* convert PKIFailureInfo number to human-readable string
*
* returns pointer to static string
* returns NULL on error
* returns pointer to static string, or NULL on error
*/
static const char *CMP_PKIFAILUREINFO_to_string(int number)
{
@@ -164,11 +149,7 @@ static const char *CMP_PKIFAILUREINFO_to_string(int number)
}
}
/*
* checks PKIFailureInfo bits in a given PKIStatusInfo
* returns 1 if a given bit is set, 0 if not, -1 on error
*/
int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index)
int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int bit_index)
{
if (!ossl_assert(si != NULL && si->failInfo != NULL))
return -1;
@@ -180,16 +161,17 @@ int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index)
return ASN1_BIT_STRING_get_bit(si->failInfo, bit_index);
}
/*
/*-
* place human-readable error string created from PKIStatusInfo in given buffer
* returns pointer to the same buffer containing the string, or NULL on error
*/
char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
size_t bufsize)
static
char *snprint_PKIStatusInfo_parts(int status, int fail_info,
const OSSL_CMP_PKIFREETEXT *status_strings,
char *buf, size_t bufsize)
{
int status, failure, fail_info;
int failure;
const char *status_string, *failure_string;
OSSL_CMP_PKIFREETEXT *status_strings;
ASN1_UTF8STRING *text;
int i;
int printed_chars;
@@ -197,22 +179,22 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
int n_status_strings;
char *write_ptr = buf;
#define ADVANCE_BUFFER \
if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \
return NULL; \
write_ptr += printed_chars; \
bufsize -= printed_chars;
if (ctx == NULL
|| buf == NULL
|| (status = OSSL_CMP_CTX_get_status(ctx)) < 0
if (buf == NULL
|| status < 0
|| (status_string = ossl_cmp_PKIStatus_to_string(status)) == NULL)
return NULL;
#define ADVANCE_BUFFER \
if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \
return NULL; \
write_ptr += printed_chars; \
bufsize -= printed_chars;
printed_chars = BIO_snprintf(write_ptr, bufsize, "%s", status_string);
ADVANCE_BUFFER;
/* failInfo is optional and may be empty */
if ((fail_info = OSSL_CMP_CTX_get_failInfoCode(ctx)) > 0) {
if (fail_info != 0) {
printed_chars = BIO_snprintf(write_ptr, bufsize, "; PKIFailureInfo: ");
ADVANCE_BUFFER;
for (failure = 0; failure <= OSSL_CMP_PKIFAILUREINFO_MAX; failure++) {
@@ -220,7 +202,7 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
failure_string = CMP_PKIFAILUREINFO_to_string(failure);
if (failure_string != NULL) {
printed_chars = BIO_snprintf(write_ptr, bufsize, "%s%s",
failure > 0 ? ", " : "",
failinfo_found ? ", " : "",
failure_string);
ADVANCE_BUFFER;
failinfo_found = 1;
@@ -235,7 +217,6 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
}
/* statusString sequence is optional and may be empty */
status_strings = OSSL_CMP_CTX_get0_statusString(ctx);
n_status_strings = sk_ASN1_UTF8STRING_num(status_strings);
if (n_status_strings > 0) {
printed_chars = BIO_snprintf(write_ptr, bufsize, "; StatusString%s: ",
@@ -253,13 +234,44 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
return buf;
}
/*
char *OSSL_CMP_snprint_PKIStatusInfo(const OSSL_CMP_PKISI *statusInfo,
char *buf, size_t bufsize)
{
int failure_info;
if (statusInfo == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
failure_info = ossl_cmp_pkisi_get_pkifailureinfo(statusInfo);
return snprint_PKIStatusInfo_parts(ASN1_INTEGER_get(statusInfo->status),
failure_info,
statusInfo->statusString, buf, bufsize);
}
char *OSSL_CMP_CTX_snprint_PKIStatus(const OSSL_CMP_CTX *ctx, char *buf,
size_t bufsize)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
return snprint_PKIStatusInfo_parts(OSSL_CMP_CTX_get_status(ctx),
OSSL_CMP_CTX_get_failInfoCode(ctx),
OSSL_CMP_CTX_get0_statusString(ctx),
buf, bufsize);
}
/*-
* Creates a new PKIStatusInfo structure and fills it in
* returns a pointer to the structure on success, NULL on error
* note: strongly overlaps with TS_RESP_CTX_set_status_info()
* and TS_RESP_CTX_add_failure_info() in ../ts/ts_rsp_sign.c
*/
OSSL_CMP_PKISI *ossl_cmp_statusinfo_new(int status, int fail_info,
OSSL_CMP_PKISI *OSSL_CMP_STATUSINFO_new(int status, int fail_info,
const char *text)
{
OSSL_CMP_PKISI *si = OSSL_CMP_PKISI_new();
+21 -1
View File
@@ -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];
@@ -320,6 +320,26 @@ STACK_OF(X509) *ossl_cmp_build_cert_chain(STACK_OF(X509) *certs, X509 *cert)
return result;
}
int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
const char *text)
{
ASN1_UTF8STRING *utf8string;
if (!ossl_assert(sk != NULL && text != NULL))
return 0;
if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
return 0;
if (!ASN1_STRING_set(utf8string, text, -1))
goto err;
if (!sk_ASN1_UTF8STRING_push(sk, utf8string))
goto err;
return 1;
err:
ASN1_UTF8STRING_free(utf8string);
return 0;
}
int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
const ASN1_OCTET_STRING *src)
{
+107 -67
View File
@@ -167,6 +167,8 @@ int OSSL_CMP_validate_cert_path(OSSL_CMP_CTX *ctx, X509_STORE *trusted_store,
CMPerr(0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE);
err:
/* directly output any fresh errors, needed for check_msg_find_cert() */
OSSL_CMP_CTX_print_errors(ctx);
X509_STORE_CTX_free(csc);
return valid;
}
@@ -250,17 +252,22 @@ static int cert_acceptable(OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg)
{
X509_STORE *ts = ctx->trusted;
char *sub, *iss;
int self_issued = X509_check_issued(cert, cert) == X509_V_OK;
char *str;
X509_VERIFY_PARAM *vpm = ts != NULL ? X509_STORE_get0_param(ts) : NULL;
int time_cmp;
ossl_cmp_log2(INFO, ctx, " considering %s %s with..", desc1, desc2);
if ((sub = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL)
ossl_cmp_log1(INFO, ctx, " subject = %s", sub);
if ((iss = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0)) != NULL)
ossl_cmp_log1(INFO, ctx, " issuer = %s", iss);
OPENSSL_free(iss);
OPENSSL_free(sub);
ossl_cmp_log3(INFO, ctx, " considering %s%s %s with..",
self_issued ? "self-issued ": "", desc1, desc2);
if ((str = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL)
ossl_cmp_log1(INFO, ctx, " subject = %s", str);
OPENSSL_free(str);
if (!self_issued) {
str = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
if (str != NULL)
ossl_cmp_log1(INFO, ctx, " issuer = %s", str);
OPENSSL_free(str);
}
if (already_checked(cert, already_checked1)
|| already_checked(cert, already_checked2)) {
@@ -284,7 +291,7 @@ static int cert_acceptable(OSSL_CMP_CTX *ctx,
if (!check_kid(ctx, cert, msg->header->senderKID))
return 0;
/* acceptable also if there is no senderKID in msg header */
ossl_cmp_info(ctx, " cert is acceptable");
ossl_cmp_info(ctx, " cert seems acceptable");
return 1;
}
@@ -295,38 +302,49 @@ static int check_msg_valid_cert(OSSL_CMP_CTX *ctx, X509_STORE *store,
ossl_cmp_warn(ctx, "msg signature verification failed");
return 0;
}
if (!OSSL_CMP_validate_cert_path(ctx, store, scrt)) {
ossl_cmp_warn(ctx, "cert path validation failed");
return 0;
}
return 1;
if (OSSL_CMP_validate_cert_path(ctx, store, scrt))
return 1;
ossl_cmp_warn(ctx,
"msg signature validates but cert path validation failed");
return 0;
}
/*
* Exceptional handling for 3GPP TS 33.310 [3G/LTE Network Domain Security
* (NDS); Authentication Framework (AF)], only to use for IP and if the ctx
* option is explicitly set: use self-issued certificates from extraCerts as
* trust anchor to validate sender cert and msg -
* (NDS); Authentication Framework (AF)], only to use for IP messages
* and if the ctx option is explicitly set: use self-issued certificates
* from extraCerts as trust anchor to validate sender cert and msg -
* provided it also can validate the newly enrolled certificate
*/
static int check_msg_valid_cert_3gpp(OSSL_CMP_CTX *ctx, X509 *scrt,
const OSSL_CMP_MSG *msg)
{
int valid = 0;
X509_STORE *store = X509_STORE_new();
X509_STORE *store;
if (store != NULL /* store does not include CRLs */
&& ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts,
1 /* self-issued only */))
valid = check_msg_valid_cert(ctx, store, scrt, msg);
if (valid) {
if (!ctx->permitTAInExtraCertsForIR)
return 0;
if ((store = X509_STORE_new()) == NULL
|| !ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts,
1 /* self-issued only */))
goto err;
/* store does not include CRLs */
valid = OSSL_CMP_validate_cert_path(ctx, store, scrt);
if (!valid) {
ossl_cmp_warn(ctx,
"also exceptional 3GPP mode cert path validation failed");
} else {
/*
* verify that the newly enrolled certificate (which is assumed to have
* rid == 0) can also be validated with the same trusted store
* verify that the newly enrolled certificate (which assumed rid ==
* OSSL_CMP_CERTREQID) can also be validated with the same trusted store
*/
EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
OSSL_CMP_CERTRESPONSE *crep =
ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip, 0);
ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip,
OSSL_CMP_CERTREQID);
X509 *newcrt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
/*
* maybe better use get_cert_status() from cmp_client.c, which catches
@@ -335,6 +353,8 @@ static int check_msg_valid_cert_3gpp(OSSL_CMP_CTX *ctx, X509 *scrt,
valid = OSSL_CMP_validate_cert_path(ctx, store, newcrt);
X509_free(newcrt);
}
err:
X509_STORE_free(store);
return valid;
}
@@ -393,8 +413,13 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
{
int ret = 0;
if (mode_3gpp
&& ((!ctx->permitTAInExtraCertsForIR
|| ossl_cmp_msg_get_bodytype(msg) != OSSL_CMP_PKIBODY_IP)))
return 0;
ossl_cmp_info(ctx,
mode_3gpp ? "failed; trying now 3GPP mode trusting extraCerts"
mode_3gpp ? "normal mode failed; trying now 3GPP mode trusting extraCerts"
: "trying first normal mode using trust store");
if (check_msg_with_certs(ctx, msg->extraCerts, "extraCerts",
NULL, NULL, msg, mode_3gpp))
@@ -418,6 +443,12 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
return ret;
}
static int no_log_cb(const char *func, const char *file, int line,
OSSL_CMP_severity level, const char *msg)
{
return 1;
}
/* verify message signature with any acceptable and valid candidate cert */
static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
{
@@ -426,7 +457,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)
@@ -436,49 +467,52 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
return 0;
}
/* dump any hitherto errors to avoid confusion when printing further ones */
OSSL_CMP_CTX_print_errors(ctx);
/*
* try first cached scrt, used successfully earlier in same transaction,
* for validating this and any further msgs where extraCerts may be left out
*/
(void)ERR_set_mark();
if (scrt != NULL
&& cert_acceptable(ctx, "previously validated", "sender cert", scrt,
NULL, NULL, msg)
&& (check_msg_valid_cert(ctx, ctx->trusted, scrt, msg)
if (scrt != NULL) {
(void)ERR_set_mark();
ossl_cmp_info(ctx,
"trying to verify msg signature with previously validated cert");
if (cert_acceptable(ctx, "previously validated", "sender cert", scrt,
NULL, NULL, msg)
&& (check_msg_valid_cert(ctx, ctx->trusted, scrt, msg)
|| check_msg_valid_cert_3gpp(ctx, scrt, msg))) {
(void)ERR_pop_to_mark();
return 1;
}
(void)ERR_pop_to_mark();
return 1;
/* cached sender cert has shown to be no more successfully usable */
(void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL);
}
(void)ERR_pop_to_mark();
/* release any cached sender cert that proved no more successfully usable */
(void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL);
/* enable clearing irrelevant errors in attempts to validate sender certs */
(void)ERR_set_mark();
ctx->log_cb = NULL; /* temporarily disable logging diagnostic info */
if (check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */)
|| check_msg_all_certs(ctx, msg, 1 /* 3gpp */)) {
/* discard any diagnostic info on trying to use certs */
ctx->log_cb = backup_log_cb; /* restore any logging */
ctx->log_cb = no_log_cb; /* temporarily disable logging */
res = check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */)
|| check_msg_all_certs(ctx, msg, 1 /* 3gpp */);
ctx->log_cb = backup_log_cb;
if (res) {
/* discard any diagnostic information on trying to use certs */
(void)ERR_pop_to_mark();
res = 1;
goto end;
}
/* failed finding a sender cert that verifies the message signature */
ctx->log_cb = backup_log_cb; /* restore any logging */
(void)ERR_clear_last_mark();
sname = X509_NAME_oneline(sender->d.directoryName, NULL, 0);
skid_str = skid == NULL ? NULL
: OPENSSL_buf2hexstr(skid->data, skid->length);
if (ctx->log_cb != NULL) {
ossl_cmp_info(ctx, "verifying msg signature with valid cert that..");
ossl_cmp_info(ctx, "trying to verify msg signature with a valid cert that..");
if (sname != NULL)
ossl_cmp_log1(INFO, ctx, "matches msg sender name = %s", sname);
ossl_cmp_log1(INFO, ctx, "matches msg sender = %s", sname);
if (skid_str != NULL)
ossl_cmp_log1(INFO, ctx, "matches msg senderKID = %s", skid_str);
ossl_cmp_log1(INFO, ctx, "matches msg senderKID = %s", skid_str);
else
ossl_cmp_info(ctx, "while msg header does not contain senderKID");
/* re-do the above checks (just) for adding diagnostic information */
@@ -543,6 +577,11 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
switch (nid) {
/* 5.1.3.1. Shared Secret Information */
case NID_id_PasswordBasedMAC:
if (ctx->secretValue == 0) {
CMPerr(0, CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE);
break;
}
if (verify_PBMAC(msg, ctx->secretValue)) {
/*
* RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is
@@ -633,8 +672,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 +699,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 +753,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;
}