summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>2020-04-29 18:06:43 +0200
committerDr. David von Oheimb <David.von.Oheimb@siemens.com>2020-05-13 19:42:00 +0200
commit143be4748e49ff0181964affcbf422a895c48e85 (patch)
tree5da63b523b5cafbe7a84c26b2edd14e95743622d
parent6b326fc396d203d84f5461a0025495dfef88e1e8 (diff)
Add -reqin_new_tid option to apps/cmp.c and OSSL_CMP_MSG_update_transactionID()
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> (Merged from https://github.com/openssl/openssl/pull/11470)
-rw-r--r--apps/cmp.c46
-rw-r--r--crypto/cmp/cmp_asn.c9
-rw-r--r--crypto/cmp/cmp_client.c5
-rw-r--r--crypto/cmp/cmp_hdr.c38
-rw-r--r--crypto/cmp/cmp_local.h9
-rw-r--r--crypto/cmp/cmp_msg.c18
-rw-r--r--crypto/cmp/cmp_protect.c130
-rw-r--r--crypto/cmp/cmp_server.c3
-rw-r--r--doc/internal/man3/ossl_cmp_msg_protect.pod4
-rw-r--r--doc/man1/openssl-cmp.pod.in8
-rw-r--r--doc/man3/OSSL_CMP_MSG_get0_header.pod15
-rw-r--r--include/openssl/cmp.h17
-rw-r--r--util/libcrypto.num1
13 files changed, 170 insertions, 133 deletions
diff --git a/apps/cmp.c b/apps/cmp.c
index 1e4642d466..cf36d67fef 100644
--- a/apps/cmp.c
+++ b/apps/cmp.c
@@ -314,6 +314,7 @@ static char *opt_tls_host = NULL;
static int opt_batch = 0;
static int opt_repeat = 1;
static char *opt_reqin = NULL;
+static int opt_reqin_new_tid = 0;
static char *opt_reqout = NULL;
static char *opt_rspin = NULL;
static char *opt_rspout = NULL;
@@ -391,7 +392,7 @@ typedef enum OPTION_choice {
OPT_TLS_EXTRA, OPT_TLS_TRUSTED, OPT_TLS_HOST,
OPT_BATCH, OPT_REPEAT,
- OPT_REQIN, OPT_REQOUT, OPT_RSPIN, OPT_RSPOUT,
+ OPT_REQIN, OPT_REQIN_NEW_TID, OPT_REQOUT, OPT_RSPIN, OPT_RSPOUT,
OPT_USE_MOCK_SRV, OPT_PORT, OPT_MAX_MSGS,
OPT_SRV_REF, OPT_SRV_SECRET,
@@ -594,6 +595,8 @@ const OPTIONS cmp_options[] = {
{"repeat", OPT_REPEAT, 'n',
"Invoke the transaction the given number of times. Default 1"},
{"reqin", OPT_REQIN, 's', "Take sequence of CMP requests from file(s)"},
+ {"reqin_new_tid", OPT_REQIN_NEW_TID, '-',
+ "Use fresh transactionID for CMP requests read from -reqin"},
{"reqout", OPT_REQOUT, 's', "Save sequence of CMP requests to file(s)"},
{"rspin", OPT_RSPIN, 's',
"Process sequence of CMP responses provided in file(s), skipping server"},
@@ -706,7 +709,8 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
{&opt_tls_extra}, {&opt_tls_trusted}, {&opt_tls_host},
{(char **)&opt_batch}, {(char **)&opt_repeat},
- {&opt_reqin}, {&opt_reqout}, {&opt_rspin}, {&opt_rspout},
+ {&opt_reqin}, {(char **)&opt_reqin_new_tid},
+ {&opt_reqout}, {&opt_rspin}, {&opt_rspout},
{(char **)&opt_use_mock_srv}, {&opt_port}, {(char **)&opt_max_msgs},
{&opt_srv_ref}, {&opt_srv_secret},
@@ -1161,26 +1165,17 @@ static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx,
if (req != NULL && opt_reqout != NULL
&& !write_PKIMESSAGE(req, &opt_reqout))
goto err;
- if (opt_reqin != NULL) {
- if (opt_rspin != NULL) {
- CMP_warn("-reqin is ignored since -rspin is present");
- } else {
- if ((req_new = read_PKIMESSAGE(&opt_reqin)) == NULL)
- goto err;
- /*-
- * The transaction ID in req_new may not be fresh.
- * In this case the Insta Demo CA correctly complains:
- * "Transaction id already in use."
- * The following workaround unfortunately requires re-protection.
- * See also https://github.com/mpeylo/cmpossl/issues/8
- */
-#if defined(USE_TRANSACTIONID_WORKAROUND)
- hdr = OSSL_CMP_MSG_get0_header(req_new);
- if (!OSSL_CMP_CTX_set1_transactionID(hdr, NULL)
- || !ossl_cmp_msg_protect(ctx, req_new))
- goto err;
-#endif
- }
+ if (opt_reqin != NULL && opt_rspin == NULL) {
+ if ((req_new = read_PKIMESSAGE(&opt_reqin)) == NULL)
+ goto err;
+ /*-
+ * The transaction ID in req_new read from opt_reqin may not be fresh.
+ * In this case the server may complain "Transaction id already in use."
+ * The following workaround unfortunately requires re-protection.
+ */
+ if (opt_reqin_new_tid
+ && !OSSL_CMP_MSG_update_transactionID(ctx, req_new))
+ goto err;
}
if (opt_rspin != NULL) {
@@ -2325,6 +2320,10 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *e)
(void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_TOTAL_TIMEOUT,
opt_total_timeout);
+ if (opt_reqin != NULL && opt_rspin != NULL)
+ CMP_warn("-reqin is ignored since -rspin is present");
+ if (opt_reqin_new_tid && opt_reqin == NULL)
+ CMP_warn("-reqin_new_tid is ignored since -reqin is not present");
if (opt_reqin != NULL || opt_reqout != NULL
|| opt_rspin != NULL || opt_rspout != NULL || opt_use_mock_srv)
(void)OSSL_CMP_CTX_set_transfer_cb(ctx, read_write_req_resp);
@@ -2899,6 +2898,9 @@ static int get_opts(int argc, char **argv)
case OPT_REQIN:
opt_reqin = opt_str("reqin");
break;
+ case OPT_REQIN_NEW_TID:
+ opt_reqin_new_tid = 1;
+ break;
case OPT_REQOUT:
opt_reqout = opt_str("reqout");
break;
diff --git a/crypto/cmp/cmp_asn.c b/crypto/cmp/cmp_asn.c
index 703bd8cded..f109af0502 100644
--- a/crypto/cmp/cmp_asn.c
+++ b/crypto/cmp/cmp_asn.c
@@ -70,7 +70,8 @@ ASN1_SEQUENCE(OSSL_CMP_ERRORMSGCONTENT) = {
* so it is used directly
*
*/
- ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ERRORMSGCONTENT, errorDetails, ASN1_UTF8STRING)
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ERRORMSGCONTENT, errorDetails,
+ ASN1_UTF8STRING)
} ASN1_SEQUENCE_END(OSSL_CMP_ERRORMSGCONTENT)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ERRORMSGCONTENT)
@@ -352,8 +353,10 @@ ASN1_CHOICE(OSSL_CMP_PKIBODY) = {
ASN1_EXP(OSSL_CMP_PKIBODY, value.cr, OSSL_CRMF_MSGS, 2),
ASN1_EXP(OSSL_CMP_PKIBODY, value.cp, OSSL_CMP_CERTREPMESSAGE, 3),
ASN1_EXP(OSSL_CMP_PKIBODY, value.p10cr, X509_REQ, 4),
- ASN1_EXP(OSSL_CMP_PKIBODY, value.popdecc, OSSL_CMP_POPODECKEYCHALLCONTENT, 5),
- ASN1_EXP(OSSL_CMP_PKIBODY, value.popdecr, OSSL_CMP_POPODECKEYRESPCONTENT, 6),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.popdecc,
+ OSSL_CMP_POPODECKEYCHALLCONTENT, 5),
+ ASN1_EXP(OSSL_CMP_PKIBODY, value.popdecr,
+ OSSL_CMP_POPODECKEYRESPCONTENT, 6),
ASN1_EXP(OSSL_CMP_PKIBODY, value.kur, OSSL_CRMF_MSGS, 7),
ASN1_EXP(OSSL_CMP_PKIBODY, value.kup, OSSL_CMP_CERTREPMESSAGE, 8),
ASN1_EXP(OSSL_CMP_PKIBODY, value.krr, OSSL_CRMF_MSGS, 9),
diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c
index f561f72eb1..d309f84a78 100644
--- a/crypto/cmp/cmp_client.c
+++ b/crypto/cmp/cmp_client.c
@@ -176,7 +176,7 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
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, "request sent: ", req_type_str);
ERR_add_error_data(2, ", expected response: ", expected_type_str);
return 0;
}
@@ -211,7 +211,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
char buf[OSSL_CMP_PKISI_BUFLEN];
if (save_statusInfo(ctx, si)
- && OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
+ && 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",
diff --git a/crypto/cmp/cmp_hdr.c b/crypto/cmp/cmp_hdr.c
index c2493420f8..157247d47e 100644
--- a/crypto/cmp/cmp_hdr.c
+++ b/crypto/cmp/cmp_hdr.c
@@ -41,7 +41,8 @@ int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr)
return (int)pvno;
}
-ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const OSSL_CMP_PKIHEADER *hdr)
+ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const
+ OSSL_CMP_PKIHEADER *hdr)
{
if (hdr == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
@@ -266,6 +267,25 @@ int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
return 0;
}
+/*
+ * set ctx->transactionID in CMP header
+ * if ctx->transactionID is NULL, a random one is created with 128 bit
+ * according to section 5.1.1:
+ *
+ * It is RECOMMENDED that the clients fill the transactionID field with
+ * 128 bits of (pseudo-) random data for the start of a transaction to
+ * reduce the probability of having the transactionID in use at the server.
+ */
+int ossl_cmp_hdr_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
+{
+ if (ctx->transactionID == NULL
+ && !set1_aostr_else_random(&ctx->transactionID, NULL,
+ OSSL_CMP_TRANSACTIONID_LENGTH))
+ return 0;
+ return ossl_cmp_asn1_octet_string_set1(&hdr->transactionID,
+ ctx->transactionID);
+}
+
/* 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)
{
@@ -316,21 +336,7 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
ctx->recipNonce))
return 0;
- /*
- * set ctx->transactionID in CMP header
- * if ctx->transactionID is NULL, a random one is created with 128 bit
- * according to section 5.1.1:
- *
- * It is RECOMMENDED that the clients fill the transactionID field with
- * 128 bits of (pseudo-) random data for the start of a transaction to
- * reduce the probability of having the transactionID in use at the server.
- */
- if (ctx->transactionID == NULL
- && !set1_aostr_else_random(&ctx->transactionID, NULL,
- OSSL_CMP_TRANSACTIONID_LENGTH))
- return 0;
- if (!ossl_cmp_asn1_octet_string_set1(&hdr->transactionID,
- ctx->transactionID))
+ if (!ossl_cmp_hdr_set_transactionID(ctx, hdr))
return 0;
/*-
diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h
index 9acafbae89..62d7dbd1d4 100644
--- a/crypto/cmp/cmp_local.h
+++ b/crypto/cmp/cmp_local.h
@@ -790,7 +790,7 @@ int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
/* from cmp_status.c */
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 *s);
int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si);
int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int index);
@@ -814,6 +814,7 @@ int ossl_cmp_hdr_set_implicitConfirm(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_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
/* from cmp_msg.c */
@@ -885,13 +886,13 @@ OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
int64_t poll_after);
OSSL_CMP_PKISI *
ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid);
-OSSL_CRMF_CERTID *ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep,
+OSSL_CRMF_CERTID *ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rc,
int rsid);
OSSL_CMP_POLLREP *
ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
int rid);
OSSL_CMP_CERTRESPONSE *
-ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crepmsg,
+ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
int rid);
X509 *ossl_cmp_certresponse_get1_certificate(EVP_PKEY *privkey,
const OSSL_CMP_CERTRESPONSE *crep);
@@ -916,6 +917,6 @@ int ossl_cmp_verify_popo(const OSSL_CMP_MSG *msg, int accept_RAVerified);
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);
+ const char *txt, int errorCode, const char *detail);
#endif /* !defined(OSSL_CRYPTO_CMP_LOCAL_H) */
diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c
index dc11b54d2b..0534cae0ae 100644
--- a/crypto/cmp/cmp_msg.c
+++ b/crypto/cmp/cmp_msg.c
@@ -584,9 +584,9 @@ int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
return 0;
for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) {
- if ((itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i))) == NULL)
- return 0;
- if (!ossl_cmp_msg_gen_push0_ITAV(msg, itav)) {
+ itav = OSSL_CMP_ITAV_dup(sk_OSSL_CMP_ITAV_value(itavs, i));
+ if (itav == NULL
+ || !ossl_cmp_msg_gen_push0_ITAV(msg, itav)) {
OSSL_CMP_ITAV_free(itav);
return 0;
}
@@ -982,6 +982,18 @@ X509 *ossl_cmp_certresponse_get1_certificate(EVP_PKEY *privkey,
return crt;
}
+int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
+{
+ if (ctx == NULL || msg == NULL) {
+ CMPerr(0, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if (!ossl_cmp_hdr_set_transactionID(ctx, msg->header))
+ return 0;
+ return msg->header->protectionAlg == NULL
+ || ossl_cmp_msg_protect(ctx, msg);
+}
+
OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file)
{
OSSL_CMP_MSG *msg = NULL;
diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c
index 3e0c22bb80..0b87acd804 100644
--- a/crypto/cmp/cmp_protect.c
+++ b/crypto/cmp/cmp_protect.c
@@ -145,21 +145,18 @@ int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
&& (msg->extraCerts = sk_X509_new_null()) == NULL)
return 0;
- if (ctx->clCert != NULL) {
- /* Make sure that our own cert gets sent, in the first position */
- if (!X509_up_ref(ctx->clCert))
+ if (ctx->clCert != NULL && ctx->pkey != NULL) {
+ /* make sure that our own cert is included in the first position */
+ if (!ossl_cmp_sk_X509_add1_cert(msg->extraCerts, ctx->clCert, 1, 1))
return 0;
- if (!sk_X509_push(msg->extraCerts, ctx->clCert)) {
- X509_free(ctx->clCert);
- return 0;
- }
- /* if we have untrusted store, try to add intermediate certs */
+ /* if we have untrusted certs, try to add intermediate certs */
if (ctx->untrusted_certs != NULL) {
STACK_OF(X509) *chain =
ossl_cmp_build_cert_chain(ctx->untrusted_certs, ctx->clCert);
int res = ossl_cmp_sk_X509_add1_certs(msg->extraCerts, chain,
1 /* no self-issued */,
1 /* no duplicates */, 0);
+
sk_X509_pop_free(chain, X509_free);
if (res == 0)
return 0;
@@ -227,6 +224,15 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
if (!ossl_assert(ctx != NULL && msg != NULL))
return 0;
+ /*
+ * For the case of re-protection remove pre-existing protection.
+ * TODO: Consider also removing any pre-existing extraCerts.
+ */
+ X509_ALGOR_free(msg->header->protectionAlg);
+ msg->header->protectionAlg = NULL;
+ ASN1_BIT_STRING_free(msg->protection);
+ msg->protection = NULL;
+
if (ctx->unprotectedSend)
return 1;
@@ -238,84 +244,70 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
&& !ossl_cmp_hdr_set1_senderKID(msg->header,
ctx->referenceValue))
goto err;
-
- /*
- * add any additional certificates from ctx->extraCertsOut
- * while not needed to validate the signing cert, the option to do
- * this might be handy for certain use cases
- */
- if (!ossl_cmp_msg_add_extraCerts(ctx, msg))
- goto err;
-
- if ((msg->protection =
- ossl_cmp_calc_protection(msg, ctx->secretValue, NULL)) == NULL)
- goto err;
- } else {
+ } else if (ctx->clCert != NULL && ctx->pkey != NULL) {
/*
* use MSG_SIG_ALG according to 5.1.3.3 if client Certificate and
* private key is given
*/
- if (ctx->clCert != NULL && ctx->pkey != NULL) {
- const ASN1_OCTET_STRING *subjKeyIDStr = NULL;
- int algNID = 0;
- ASN1_OBJECT *alg = NULL;
-
- /* make sure that key and certificate match */
- if (!X509_check_private_key(ctx->clCert, ctx->pkey)) {
- CMPerr(0, CMP_R_CERT_AND_KEY_DO_NOT_MATCH);
- goto err;
- }
-
- if (msg->header->protectionAlg == NULL)
- if ((msg->header->protectionAlg = X509_ALGOR_new()) == NULL)
- goto err;
+ const ASN1_OCTET_STRING *subjKeyIDStr = NULL;
+ int algNID = 0;
+ ASN1_OBJECT *alg = NULL;
- if (!OBJ_find_sigid_by_algs(&algNID, ctx->digest,
- EVP_PKEY_id(ctx->pkey))) {
- CMPerr(0, CMP_R_UNSUPPORTED_KEY_TYPE);
- goto err;
- }
- if ((alg = OBJ_nid2obj(algNID)) == NULL)
- goto err;
- if (!X509_ALGOR_set0(msg->header->protectionAlg,
- alg, V_ASN1_UNDEF, NULL)) {
- ASN1_OBJECT_free(alg);
- goto err;
- }
-
- /*
- * set senderKID to keyIdentifier of the used certificate according
- * 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;
+ /* make sure that key and certificate match */
+ if (!X509_check_private_key(ctx->clCert, ctx->pkey)) {
+ CMPerr(0, CMP_R_CERT_AND_KEY_DO_NOT_MATCH);
+ goto err;
+ }
- /*
- * Add ctx->clCert followed, if possible, by its chain built
- * from ctx->untrusted_certs, and then ctx->extraCertsOut
- */
- if (!ossl_cmp_msg_add_extraCerts(ctx, msg))
+ if (msg->header->protectionAlg == NULL)
+ if ((msg->header->protectionAlg = X509_ALGOR_new()) == NULL)
goto err;
- if ((msg->protection =
- ossl_cmp_calc_protection(msg, NULL, ctx->pkey)) == NULL)
- goto err;
- } else {
- CMPerr(0, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
+ if (!OBJ_find_sigid_by_algs(&algNID, ctx->digest,
+ EVP_PKEY_id(ctx->pkey))) {
+ CMPerr(0, CMP_R_UNSUPPORTED_KEY_TYPE);
goto err;
}
+ if ((alg = OBJ_nid2obj(algNID)) == NULL)
+ goto err;
+ if (!X509_ALGOR_set0(msg->header->protectionAlg, alg,
+ V_ASN1_UNDEF, NULL)) {
+ ASN1_OBJECT_free(alg);
+ goto err;
+ }
+
+ /*
+ * set senderKID to keyIdentifier of the used certificate according
+ * 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;
+ } else {
+ CMPerr(0, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
+ goto err;
}
+ if ((msg->protection =
+ ossl_cmp_calc_protection(msg, ctx->secretValue, ctx->pkey)) == NULL)
+ goto err;
+
+ /*
+ * If present, add ctx->clCert followed by its chain as far as possible.
+ * Finally add any additional certificates from ctx->extraCertsOut;
+ * even if not needed to validate the protection
+ * the option to do this might be handy for certain use cases.
+ */
+ if (!ossl_cmp_msg_add_extraCerts(ctx, msg))
+ goto err;
/*
* 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);
diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c
index 8bd3b56a26..b805dc8bcb 100644
--- a/crypto/cmp/cmp_server.c
+++ b/crypto/cmp/cmp_server.c
@@ -221,7 +221,8 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
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,
+ 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: */
diff --git a/doc/internal/man3/ossl_cmp_msg_protect.pod b/doc/internal/man3/ossl_cmp_msg_protect.pod
index a931d3caf2..7c5e10baa7 100644
--- a/doc/internal/man3/ossl_cmp_msg_protect.pod
+++ b/doc/internal/man3/ossl_cmp_msg_protect.pod
@@ -15,9 +15,9 @@ ossl_cmp_msg_add_extraCerts
=head1 DESCRIPTION
-ossl_cmp_msg_protect() protects the given message B<msg> using an algorithm
+ossl_cmp_msg_protect() (re-)protects the given message B<msg> using an algorithm
depending on the available context information given in the B<ctx>.
-If there is a secretValue it selects PBMAC. Else if there is a clCert
+If there is a secretValue it selects PBMAC, else if there is a clCert
it selects Signature and uses B<ossl_cmp_msg_add_extraCerts()>.
It also sets the protectionAlg field in the message header accordingly.
diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in
index a99391ac6d..cf7f6aa418 100644
--- a/doc/man1/openssl-cmp.pod.in
+++ b/doc/man1/openssl-cmp.pod.in
@@ -85,6 +85,7 @@ B<openssl> B<cmp>
[B<-batch>]
[B<-repeat> I<number>]
[B<-reqin>] I<filenames>
+[B<-reqin_new_tid>]
[B<-reqout>] I<filenames>
[B<-rspin>] I<filenames>
[B<-rspout>] I<filenames>
@@ -798,6 +799,13 @@ Multiple filenames may be given, separated by commas and/or whitespace
(where in the latter case the whole argument must be enclosed in "...").
As many files are read as needed for a complete transaction.
+=item B<-reqin_new_tid>
+
+Use a fresh transactionID for CMP request messages read using B<-reqin>,
+which requires re-protecting them as far as they were protected before.
+This may be needed in case the sequence of requests is reused
+and the CMP server complains that the transaction ID has already been used.
+
=item B<-reqout> I<filenames>
Save sequence of CMP requests to file(s).
diff --git a/doc/man3/OSSL_CMP_MSG_get0_header.pod b/doc/man3/OSSL_CMP_MSG_get0_header.pod
index bd51eb5598..3ab76c14df 100644
--- a/doc/man3/OSSL_CMP_MSG_get0_header.pod
+++ b/doc/man3/OSSL_CMP_MSG_get0_header.pod
@@ -3,6 +3,7 @@
=head1 NAME
OSSL_CMP_MSG_get0_header,
+OSSL_CMP_MSG_update_transactionID,
d2i_OSSL_CMP_MSG_bio,
i2d_OSSL_CMP_MSG_bio
- function(s) manipulating CMP messages
@@ -12,17 +13,22 @@ i2d_OSSL_CMP_MSG_bio
#include <openssl/cmp.h>
OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
+ int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg);
int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg);
=head1 DESCRIPTION
-OSSL_CMP_MSG_get0_header returns the header of the given CMP message.
+OSSL_CMP_MSG_get0_header() returns the header of the given CMP message.
-d2i_OSSL_CMP_MSG_bio parses an ASN.1-encoded OSSL_CMP_MSG from the BIO I<bio>.
+OSSL_CMP_MSG_update_transactionID() updates the transactionID field
+in the header of the given message according to the CMP_CTX.
+This requires re-protecting the message (if it was protected).
+
+d2i_OSSL_CMP_MSG_bio() parses an ASN.1-encoded OSSL_CMP_MSG from the BIO I<bio>.
It assigns a pointer to the new structure to I<*msg> if I<msg> is not NULL.
-i2d_OSSL_CMP_MSG_bio writes the OSSL_CMP_MSG I<msg> in ASN.1 encoding
+i2d_OSSL_CMP_MSG_bio() writes the OSSL_CMP_MSG I<msg> in ASN.1 encoding
to BIO I<bio>.
=head1 NOTES
@@ -36,7 +42,8 @@ or NULL if the respective entry does not exist and on error.
d2i_OSSL_CMP_MSG_bio() returns the parsed message or NULL on error.
-i2d_OSSL_CMP_MSG_bio() returns 1 on success or 0 on error.
+i2d_OSSL_CMP_MSG_bio() and OSSL_CMP_MSG_update_transactionID()
+return 1 on success, 0 on error.
=head1 HISTORY
diff --git a/include/openssl/cmp.h b/include/openssl/cmp.h
index 66e3f40860..57416067f7 100644
--- a/include/openssl/cmp.h
+++ b/include/openssl/cmp.h
@@ -310,7 +310,8 @@ int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey);
EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv);
int OSSL_CMP_CTX_set1_issuer(OSSL_CMP_CTX *ctx, const X509_NAME *name);
int OSSL_CMP_CTX_set1_subjectName(OSSL_CMP_CTX *ctx, const X509_NAME *name);
-int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx, const GENERAL_NAME *name);
+int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
+ const GENERAL_NAME *name);
int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts);
int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx);
int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo);
@@ -346,11 +347,13 @@ OSSL_CMP_PKISI *
OSSL_CMP_STATUSINFO_new(int status, int fail_info, const char *text);
/* from cmp_hdr.c */
-ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const OSSL_CMP_PKIHEADER *hdr);
+ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const
+ OSSL_CMP_PKIHEADER *hdr);
ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr);
/* from cmp_msg.c */
OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
+int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg);
int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg);
@@ -387,7 +390,7 @@ typedef void (*OSSL_CMP_SRV_error_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req,
const OSSL_CMP_PKISI *statusInfo,
const ASN1_INTEGER *errorCode,
- const OSSL_CMP_PKIFREETEXT *errorDetails);
+ const OSSL_CMP_PKIFREETEXT *errDetails);
typedef int (*OSSL_CMP_SRV_certConf_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req,
int certReqId,
@@ -418,10 +421,10 @@ X509 *OSSL_CMP_exec_IR_ses(OSSL_CMP_CTX *ctx);
X509 *OSSL_CMP_exec_CR_ses(OSSL_CMP_CTX *ctx);
X509 *OSSL_CMP_exec_P10CR_ses(OSSL_CMP_CTX *ctx);
X509 *OSSL_CMP_exec_KUR_ses(OSSL_CMP_CTX *ctx);
-# define OSSL_CMP_IR OSSL_CMP_PKIBODY_IR
-# define OSSL_CMP_CR OSSL_CMP_PKIBODY_CR
-# define OSSL_CMP_P10CR OSSL_CMP_PKIBODY_P10CR
-# define OSSL_CMP_KUR OSSL_CMP_PKIBODY_KUR
+# define OSSL_CMP_IR OSSL_CMP_PKIBODY_IR
+# define OSSL_CMP_CR OSSL_CMP_PKIBODY_CR
+# define OSSL_CMP_P10CR OSSL_CMP_PKIBODY_P10CR
+# define OSSL_CMP_KUR OSSL_CMP_PKIBODY_KUR
int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, int *checkAfter);
int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
const char **text);
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 590157fe8b..dd69168ecc 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4902,6 +4902,7 @@ i2d_X509_PUBKEY_bio ? 3_0_0 EXIST::FUNCTION:
RSA_get0_pss_params ? 3_0_0 EXIST::FUNCTION:DEPRECATEDIN_3_0,RSA
X509_cmp_timeframe ? 3_0_0 EXIST::FUNCTION:
OSSL_CMP_MSG_get0_header ? 3_0_0 EXIST::FUNCTION:CMP
+OSSL_CMP_MSG_update_transactionID ? 3_0_0 EXIST::FUNCTION:CMP
BIO_f_prefix ? 3_0_0 EXIST::FUNCTION:
EVP_PKEY_CTX_new_from_name ? 3_0_0 EXIST::FUNCTION:
EVP_PKEY_CTX_new_from_pkey ? 3_0_0 EXIST::FUNCTION: