]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Introduce cms kekcipher option to select cipher for pwri
authorJakub Zelenka <jakub.openssl@gmail.com>
Thu, 6 Feb 2025 18:07:28 +0000 (19:07 +0100)
committerTomas Mraz <tomas@openssl.org>
Tue, 1 Jul 2025 17:04:53 +0000 (19:04 +0200)
This is useful for AEAD ciphers where it is not possible to use AEAD
cipher (currently only AES GCM supported) for password recipient info
because the same cipher is used for encrypting the password and it is
not possible to store tag for this purpose so different cipher (e.g.
AES CBC) needs to be selected.

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26871)

apps/cms.c
crypto/cms/cms_pwri.c
doc/man1/openssl-cms.pod.in
test/recipes/80-test_cms.t

index 8c7feed431280f995af4d48e21dd6d6f04b2b83b..0a2ce7f571f7f949ae99bc4ace72d5f2c9245481 100644 (file)
@@ -84,7 +84,7 @@ typedef enum OPTION_choice {
     OPT_R_ENUM,
     OPT_PROV_ENUM, OPT_CONFIG,
     OPT_V_ENUM,
-    OPT_CIPHER,
+    OPT_CIPHER, OPT_KEKCIPHER,
     OPT_ORIGINATOR
 } OPTION_CHOICE;
 
@@ -164,6 +164,8 @@ const OPTIONS cms_options[] = {
      "Recipient certs (optional; used only when encrypting)"},
     {"", OPT_CIPHER, '-',
      "The encryption algorithm to use (any supported cipher)"},
+    {"kekcipher", OPT_KEKCIPHER, 's',
+     "The key encryption algorithm to use"},
     {"wrap", OPT_WRAP, 's',
      "Key wrap algorithm to use when encrypting with key agreement"},
     {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
@@ -288,7 +290,7 @@ int cms_main(int argc, char **argv)
     CMS_ReceiptRequest *rr = NULL;
     ENGINE *e = NULL;
     EVP_PKEY *key = NULL;
-    EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
+    EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL, *kekcipher = NULL;
     EVP_MD *sign_md = NULL;
     STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
     STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
@@ -305,7 +307,8 @@ int cms_main(int argc, char **argv)
     long digestlen = 0;
     char *infile = NULL, *outfile = NULL, *rctfile = NULL;
     char *passinarg = NULL, *passin = NULL, *signerfile = NULL;
-    char *originatorfile = NULL, *recipfile = NULL, *ciphername = NULL;
+    char *originatorfile = NULL, *recipfile = NULL;
+    char *ciphername = NULL, *kekciphername = NULL;
     char *to = NULL, *from = NULL, *subject = NULL, *prog;
     cms_key_param *key_first = NULL, *key_param = NULL;
     int flags = CMS_DETACHED, binary_files = 0;
@@ -653,6 +656,9 @@ int cms_main(int argc, char **argv)
         case OPT_CIPHER:
             ciphername = opt_unknown();
             break;
+        case OPT_KEKCIPHER:
+            kekciphername = opt_arg();
+            break;
         case OPT_KEYOPT:
             keyidx = -1;
             if (operation == SMIME_ENCRYPT) {
@@ -724,6 +730,8 @@ int cms_main(int argc, char **argv)
     }
     if (!opt_cipher_any(ciphername, &cipher))
         goto end;
+    if (kekciphername != NULL && !opt_cipher_any(kekciphername, &kekcipher))
+        goto end;
     if (wrapname != NULL) {
         if (!opt_cipher_any(wrapname, &wrap_cipher))
             goto end;
@@ -1033,9 +1041,8 @@ int cms_main(int argc, char **argv)
             pwri_tmp = (unsigned char *)OPENSSL_strdup((char *)pwri_pass);
             if (pwri_tmp == NULL)
                 goto end;
-            if (CMS_add0_recipient_password(cms,
-                                            -1, NID_undef, NID_undef,
-                                            pwri_tmp, -1, NULL) == NULL)
+            if (CMS_add0_recipient_password(cms, -1, NID_undef, NID_undef,
+                                            pwri_tmp, -1, kekcipher) == NULL)
                 goto end;
             pwri_tmp = NULL;
         }
@@ -1315,6 +1322,7 @@ int cms_main(int argc, char **argv)
     X509_free(originator);
     EVP_PKEY_free(key);
     EVP_CIPHER_free(cipher);
+    EVP_CIPHER_free(kekcipher);
     EVP_CIPHER_free(wrap_cipher);
     EVP_MD_free(sign_md);
     CMS_ContentInfo_free(cms);
index d907ad9a57ae465dff1204453a03965ea3a1a9a7..efed89a017a99b8f5a1e8bf724a4851d02857574 100644 (file)
@@ -71,6 +71,10 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
         ERR_raise(ERR_LIB_CMS, CMS_R_NO_CIPHER);
         return NULL;
     }
+    if ((EVP_CIPHER_get_flags(kekciph) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) {
+        ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEK_ALGORITHM);
+        return NULL;
+    }
     if (wrap_nid != NID_id_alg_PWRI_KEK) {
         ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
         return NULL;
index 36f1b3e4a82c03d66f97a4550933c8e7762b3851..30e7734d0f5839a16f2f6ad33a6a082a7ffcfee0 100644 (file)
@@ -68,6 +68,7 @@ Encryption options:
 [B<-recip> I<file>]
 [I<recipient-cert> ...]
 [B<-I<cipher>>]
+[B<-kekcipher> I<cipher>]
 [B<-wrap> I<cipher>]
 [B<-aes128-wrap>]
 [B<-aes192-wrap>]
@@ -426,6 +427,13 @@ algorithms.
 If not specified, AES-256-CBC is used as the default. Only used with B<-encrypt> and
 B<-EncryptedData_create> commands.
 
+=item B<-kekcipher> I<cipher>
+
+Cipher algorithm to use for password key encryption. This option is relevant
+when a password for password recipient information is provided using
+B<-pwri_password>, and an AEAD encryption algorithm is selected. In such cases,
+a non-AEAD algorithm should be specified using this option.
+
 =item B<-wrap> I<cipher>
 
 Cipher algorithm to use for key wrap when encrypting the message using Key
index 6e3508dac8fb2e4776627abc292b15dd75686276..3feea1e48e15ed2f7904edb6b413826b3b9a0de5 100644 (file)
@@ -346,6 +346,17 @@ my @smime_cms_tests = (
       \&final_compare
     ],
 
+    [ "enveloped content test streaming PEM format, AES-128-GCM cipher and AES-128-CBC KEK cipher, password",
+      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes-128-gcm",
+        "-kekcipher", "aes-128-cbc",
+        "-stream", "-out", "{output}.cms",
+        "-pwri_password", "test" ],
+      [ "{cmd2}", "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
+        "-inform", "PEM",
+        "-pwri_password", "test" ],
+      \&final_compare
+    ],
+
     [ "enveloped content test streaming PEM format, KEK, key only",
       [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
         "-stream", "-out", "{output}.cms",