Latest update.
This commit is contained in:
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user