]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
CMP add: fix -reqin option, which requires adding OSSL_CMP_MSG_update_recipNonce()
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Fri, 3 Feb 2023 09:31:19 +0000 (10:31 +0100)
committerDr. David von Oheimb <dev@ddvo.net>
Sat, 25 Mar 2023 08:55:26 +0000 (09:55 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/20204)

apps/cmp.c
crypto/cmp/cmp_msg.c
crypto/cmp/cmp_protect.c
doc/internal/man3/ossl_cmp_msg_protect.pod
doc/man1/openssl-cmp.pod.in
doc/man3/OSSL_CMP_MSG_get0_header.pod
include/openssl/cmp.h.in
util/libcrypto.num

index 41d9e79606495c17c33e5e5235cce9d7b0fe5049..8112e6d5b16c515328fd223a1ee10d14cab8a1f0 100644 (file)
@@ -787,6 +787,13 @@ static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx,
         if (opt_reqin_new_tid
                 && !OSSL_CMP_MSG_update_transactionID(ctx, req_new))
             goto err;
+
+        /*
+         * Except for first request, need to satisfy recipNonce check by server.
+         * Unfortunately requires re-protection if protection is required.
+         */
+        if (!OSSL_CMP_MSG_update_recipNonce(ctx, req_new))
+            goto err;
     }
 
     if (opt_rspin != NULL) {
@@ -802,7 +809,7 @@ static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx,
         goto err;
 
     if (req_new != NULL || prev_opt_rspin != NULL) {
-        /* need to satisfy nonce and transactionID checks */
+        /* need to satisfy nonce and transactionID checks by client */
         ASN1_OCTET_STRING *nonce;
         ASN1_OCTET_STRING *tid;
 
index 64c83d6e34e75e4d4775da2dd56ab5bae84bb4d8..f9cffcc3b9eebf41097c759b164c0bb2b838effe 100644 (file)
@@ -1096,6 +1096,20 @@ int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
             || ossl_cmp_msg_protect(ctx, msg);
 }
 
+int OSSL_CMP_MSG_update_recipNonce(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
+{
+    if (ctx == NULL || msg == NULL || msg->header == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+    if (ctx->recipNonce == NULL) /* nothing to do for 1st msg in transaction */
+        return 1;
+    if (!ossl_cmp_asn1_octet_string_set1(&msg->header->recipNonce,
+                                         ctx->recipNonce))
+        return 0;
+    return msg->header->protectionAlg == NULL || ossl_cmp_msg_protect(ctx, msg);
+}
+
 OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx,
                                 const char *propq)
 {
index 76b9e55d3df9b677c5884e37dd5893f7303743d5..3d633bef79385c9862df34b3d8970fb225ed29d7 100644 (file)
@@ -129,6 +129,7 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
     }
 }
 
+/* ctx is not const just because ctx->chain may get adapted */
 int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
 {
     if (!ossl_assert(ctx != NULL && msg != NULL))
@@ -235,6 +236,7 @@ static int set_senderKID(const OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg,
     return id == NULL || ossl_cmp_hdr_set1_senderKID(msg->header, id);
 }
 
+/* ctx is not const just because ctx->chain may get adapted */
 int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
 {
     if (!ossl_assert(ctx != NULL && msg != NULL))
index ae7771280763e31fedda14b02e5350a4e0608612..04da21fd9f9b6d9fa87d32efe3923a419541a343 100644 (file)
@@ -25,7 +25,7 @@ using the credentials, library context, and property criteria in the I<ctx>.
 ossl_cmp_msg_protect() (re-)protects the given message I<msg> using an algorithm
 depending on the available context information given in the I<ctx>.
 If there is a secretValue it selects PBMAC, else if there is a protection cert
-it selects Signature and uses L<ossl_cmp_msg_add_extraCerts(3)>.
+it selects Signature and uses ossl_cmp_msg_add_extraCerts (see below).
 It also sets the protectionAlg field in the message header accordingly.
 
 ossl_cmp_msg_add_extraCerts() adds elements to the extraCerts field in I<msg>.
@@ -40,6 +40,10 @@ of the chain, i.e, the trust anchor (unless it is part of extraCertsOut).
 
 CMP is defined in RFC 4210 (and CRMF in RFC 4211).
 
+The I<ctx> parameter of ossl_cmp_msg_add_extraCerts()
+and thus also of ossl_cmp_msg_protect() cannot be made I<const>
+because I<ctx->chain> may get adapted to cache the chain of the CMP signer cert.
+
 =head1 RETURN VALUES
 
 ossl_cmp_calc_protection() returns the protection on success, else NULL.
index 900d87c0c44c4544c71a3a735b173c7d7bf78218..3de21e742e1562e56f480640fd6a13d8330609ef 100644 (file)
@@ -885,6 +885,9 @@ Default is one invocation.
 Take the sequence of CMP requests to send to the server from file(s).
 This option is ignored if the B<-rspin> option is given
 because in the latter case no requests are actually sent.
+Except for first request, the client needs to update the recipNonce field in any
+further request in order to satisfy the checks to be performed by the server.
+This causes re-protection (if protecting requests is required).
 
 Multiple filenames may be given, separated by commas and/or whitespace
 (where in the latter case the whole argument must be enclosed in "...").
@@ -893,7 +896,7 @@ 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.
+which causes their reprotection (if protecting requests is required).
 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.
 
index c3297a3577ac9dce0f2ea933002ba147a9c7d0bc..ff94fca973d3502e3ad743a7afa0318c8a2bc0d6 100644 (file)
@@ -5,6 +5,7 @@
 OSSL_CMP_MSG_get0_header,
 OSSL_CMP_MSG_get_bodytype,
 OSSL_CMP_MSG_update_transactionID,
+OSSL_CMP_MSG_update_recipNonce,
 OSSL_CMP_CTX_setup_CRM,
 OSSL_CMP_MSG_read,
 OSSL_CMP_MSG_write,
@@ -19,6 +20,7 @@ i2d_OSSL_CMP_MSG_bio
   OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
   int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg);
   int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+  int OSSL_CMP_MSG_update_recipNonce(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
   OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid);
   OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx, const char *propq);
   int OSSL_CMP_MSG_write(const char *file, const OSSL_CMP_MSG *msg);
@@ -33,7 +35,12 @@ OSSL_CMP_MSG_get_bodytype() returns the body type of the given CMP message.
 
 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).
+If I<ctx> does not contain a transaction ID, a fresh one is created before.
+The message gets re-protected (if protecting requests is required).
+
+OSSL_CMP_MSG_update_recipNonce() updates the recipNonce field
+in the header of the given message according to the CMP_CTX.
+The message gets re-protected (if protecting requests is required).
 
 OSSL_CMP_CTX_setup_CRM() creates a CRMF certificate request message
 from various information provided in the CMP context argument I<ctx>
@@ -121,8 +128,9 @@ return the parsed CMP message or NULL on error.
 OSSL_CMP_MSG_write() returns the number of bytes successfully encoded or a
 negative value if an error occurs.
 
-i2d_OSSL_CMP_MSG_bio() and OSSL_CMP_MSG_update_transactionID() return 1 on
-success, 0 on error.
+i2d_OSSL_CMP_MSG_bio(), OSSL_CMP_MSG_update_transactionID(),
+and OSSL_CMP_MSG_update_recipNonce()
+return 1 on success, 0 on error.
 
 =head1 SEE ALSO
 
@@ -135,6 +143,8 @@ L<OSSL_CMP_CTX_push1_subjectAltName(3)>, L<OSSL_CMP_CTX_push0_policy(3)>
 
 The OpenSSL CMP support was added in OpenSSL 3.0.
 
+OSSL_CMP_MSG_update_recipNonce() was added in OpenSSL 3.0.9.
+
 =head1 COPYRIGHT
 
 Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
index 32360120c2e1feb128bf8131c88d295ec29d85bf..4e14200d82d9e1f3a0ffc4279e5fae85d9b4132f 100644 (file)
@@ -391,6 +391,7 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr);
 OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg);
 int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg);
 int OSSL_CMP_MSG_update_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
+int OSSL_CMP_MSG_update_recipNonce(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
 OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid);
 OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx,
                                 const char *propq);
index 78fd4813ee45b72eadd903756e59a9ecd058d409..311f0c205f36fe4f9c59e5bf3b6ceac3f0969a9d 100644 (file)
@@ -5449,6 +5449,7 @@ OSSL_CMP_CTX_get0_libctx                ? 3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_CTX_get0_propq                 ?      3_2_0   EXIST::FUNCTION:CMP
 OSSL_CMP_CTX_reset_geninfo_ITAVs        ?      3_0_8   EXIST::FUNCTION:CMP
 OSSL_CMP_CTX_get0_validatedSrvCert      ?      3_2_0   EXIST::FUNCTION:CMP
+OSSL_CMP_MSG_update_recipNonce          ?      3_0_9   EXIST::FUNCTION:CMP
 OSSL_CRMF_CERTTEMPLATE_get0_publicKey   ?      3_2_0   EXIST::FUNCTION:CRMF
 CMS_final_digest                        ?      3_2_0   EXIST::FUNCTION:CMS
 CMS_EnvelopedData_it                    ?      3_2_0   EXIST::FUNCTION:CMS