From: Dr. David von Oheimb Date: Wed, 29 Apr 2020 16:06:43 +0000 (+0200) Subject: Add -reqin_new_tid option to apps/cmp.c and OSSL_CMP_MSG_update_transactionID() X-Git-Tag: openssl-3.0.0-alpha2~31 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=143be4748e49ff0181964affcbf422a895c48e85;p=oweals%2Fopenssl.git Add -reqin_new_tid option to apps/cmp.c and OSSL_CMP_MSG_update_transactionID() Reviewed-by: Matt Caswell Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/11470) --- 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 using an algorithm +ossl_cmp_msg_protect() (re-)protects the given message B using an algorithm depending on the available context information given in the B. -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. 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 B [B<-batch>] [B<-repeat> I] [B<-reqin>] I +[B<-reqin_new_tid>] [B<-reqout>] I [B<-rspin>] I [B<-rspout>] I @@ -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 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 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. +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. It assigns a pointer to the new structure to I<*msg> if I is not NULL. -i2d_OSSL_CMP_MSG_bio writes the OSSL_CMP_MSG I in ASN.1 encoding +i2d_OSSL_CMP_MSG_bio() writes the OSSL_CMP_MSG I in ASN.1 encoding to BIO I. =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: