X509_LOOKUP_store: Add CHANGES note
[openssl.git] / apps / cms.c
index 25ee7e85247a732409bce9a14254c58e0fc0ea86..468820f3cf6ee97080061871c78e97f4d6bd71f4 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Copyright 2008-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * 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
@@ -12,6 +12,7 @@
 #include <stdio.h>
 #include <string.h>
 #include "apps.h"
+#include "progs.h"
 
 #ifndef OPENSSL_NO_CMS
 
@@ -64,7 +65,7 @@ struct cms_key_param_st {
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT,
-    OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN,
+    OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN,
     OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT,
     OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY,
     OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
@@ -74,12 +75,14 @@ typedef enum OPTION_choice {
     OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF,
     OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT,
     OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE,
-    OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT,
+    OPT_CAPATH, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
+    OPT_CONTENT, OPT_PRINT,
     OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE,
-    OPT_RAND, OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP,
+    OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP,
     OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM,
     OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
     OPT_3DES_WRAP, OPT_ENGINE,
+    OPT_R_ENUM,
     OPT_V_ENUM,
     OPT_CIPHER
 } OPTION_CHOICE;
@@ -100,21 +103,31 @@ const OPTIONS cms_options[] = {
     {"sign", OPT_SIGN, '-', "Sign message"},
     {"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"},
     {"resign", OPT_RESIGN, '-', "Resign a signed message"},
+    {"cades", OPT_CADES, '-', "Include signer certificate digest"},
     {"verify", OPT_VERIFY, '-', "Verify signed message"},
-    {"verify_retcode", OPT_VERIFY_RETCODE, '-'},
-    {"verify_receipt", OPT_VERIFY_RECEIPT, '<'},
+    {"verify_retcode", OPT_VERIFY_RETCODE, '-',
+        "Exit non-zero on verification failure"},
+    {"verify_receipt", OPT_VERIFY_RECEIPT, '<',
+        "Verify receipts; exit if receipt signatures do not verify"},
     {"cmsout", OPT_CMSOUT, '-', "Output CMS structure"},
-    {"data_out", OPT_DATA_OUT, '-'},
-    {"data_create", OPT_DATA_CREATE, '-'},
-    {"digest_verify", OPT_DIGEST_VERIFY, '-'},
-    {"digest_create", OPT_DIGEST_CREATE, '-'},
-    {"compress", OPT_COMPRESS, '-'},
-    {"uncompress", OPT_UNCOMPRESS, '-'},
-    {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-'},
-    {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-'},
-    {"debug_decrypt", OPT_DEBUG_DECRYPT, '-'},
+    {"data_out", OPT_DATA_OUT, '-', "Copy CMS \"Data\" object to output"},
+    {"data_create", OPT_DATA_CREATE, '-', "Create a CMS \"Data\" object"},
+    {"digest_verify", OPT_DIGEST_VERIFY, '-',
+        "Verify a CMS \"DigestedData\" object and output it"},
+    {"digest_create", OPT_DIGEST_CREATE, '-',
+        "Create a CMS \"DigestedData\" object"},
+    {"compress", OPT_COMPRESS, '-', "Create a CMS \"CompressedData\" object"},
+    {"uncompress", OPT_UNCOMPRESS, '-', "Uncompress a CMS \"CompressedData\" object"},
+    {"EncryptedData_decrypt", OPT_ED_DECRYPT, '-',
+        "Decrypt CMS \"EncryptedData\" object using symmetric key"},
+    {"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-',
+        "Create CMS \"EncryptedData\" object using symmetric key"},
+    {"debug_decrypt", OPT_DEBUG_DECRYPT, '-',
+        "Disable MMA protection and return an error if no recipient found"
+        " (see documentation)"},
     {"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
-    {"asciicrlf", OPT_ASCIICRLF, '-'},
+    {"asciicrlf", OPT_ASCIICRLF, '-',
+        "Perform CRLF canonicalisation when signing"},
     {"nointern", OPT_NOINTERN, '-',
      "Don't search certificates in message for signer"},
     {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
@@ -126,34 +139,42 @@ const OPTIONS cms_options[] = {
     {"binary", OPT_BINARY, '-', "Don't translate message to text"},
     {"keyid", OPT_KEYID, '-', "Use subject key identifier"},
     {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
-    {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-'},
-    {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-'},
+    {"no_content_verify", OPT_NO_CONTENT_VERIFY, '-',
+        "Do not verify signed content signatures"},
+    {"no_attr_verify", OPT_NO_ATTR_VERIFY, '-',
+        "Do not verify signed attribute signatures"},
     {"stream", OPT_INDEF, '-', "Enable CMS streaming"},
     {"indef", OPT_INDEF, '-', "Same as -stream"},
     {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
     {"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only" },
     {"noout", OPT_NOOUT, '-', "For the -cmsout operation do not output the parsed CMS structure"},
     {"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" },
-    {"receipt_request_all", OPT_RR_ALL, '-'},
-    {"receipt_request_first", OPT_RR_FIRST, '-'},
+    {"receipt_request_all", OPT_RR_ALL, '-',
+        "When signing, create a receipt request for all recipients"},
+    {"receipt_request_first", OPT_RR_FIRST, '-',
+        "When signing, create a receipt request for first recipient"},
     {"rctform", OPT_RCTFORM, 'F', "Receipt file format"},
     {"certfile", OPT_CERTFILE, '<', "Other certificates file"},
     {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
     {"CApath", OPT_CAPATH, '/', "trusted certificates directory"},
+    {"CAstore", OPT_CASTORE, ':', "trusted certificates store URI"},
     {"no-CAfile", OPT_NOCAFILE, '-',
      "Do not load the default certificates file"},
     {"no-CApath", OPT_NOCAPATH, '-',
      "Do not load certificates from the default certificates directory"},
+    {"no-CAstore", OPT_NOCASTORE, '-',
+     "Do not load certificates from the default certificates store"},
     {"content", OPT_CONTENT, '<',
      "Supply or override content for detached signature"},
     {"print", OPT_PRINT, '-',
      "For the -cmsout operation print out all fields of the CMS structure"},
-    {"secretkey", OPT_SECRETKEY, 's'},
-    {"secretkeyid", OPT_SECRETKEYID, 's'},
-    {"pwri_password", OPT_PWRI_PASSWORD, 's'},
-    {"econtent_type", OPT_ECONTENT_TYPE, 's'},
-    {"rand", OPT_RAND, 's',
-     "Load the file(s) into the random number generator"},
+    {"secretkey", OPT_SECRETKEY, 's',
+        "Use specified hex-encoded key to decrypt/encrypt recipients or content"},
+    {"secretkeyid", OPT_SECRETKEYID, 's',
+        "Identity of the -secretkey for CMS \"KEKRecipientInfo\" object"},
+    {"pwri_password", OPT_PWRI_PASSWORD, 's',
+        "Specific password for recipient"},
+    {"econtent_type", OPT_ECONTENT_TYPE, 's', "OID for external content"},
     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
     {"to", OPT_TO, 's', "To address"},
     {"from", OPT_FROM, 's', "From address"},
@@ -166,9 +187,12 @@ const OPTIONS cms_options[] = {
      "Input private key (if not signer or recipient)"},
     {"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"},
     {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"},
-    {"receipt_request_from", OPT_RR_FROM, 's'},
-    {"receipt_request_to", OPT_RR_TO, 's'},
+    {"receipt_request_from", OPT_RR_FROM, 's',
+        "Create signed receipt request with specified email address"},
+    {"receipt_request_to", OPT_RR_TO, 's',
+        "Create signed receipt targeted to specified address"},
     {"", OPT_CIPHER, '-', "Any supported cipher"},
+    OPT_R_OPTIONS,
     OPT_V_OPTIONS,
     {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
     {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"},
@@ -199,19 +223,16 @@ int cms_main(int argc, char **argv)
     X509_STORE *store = NULL;
     X509_VERIFY_PARAM *vpm = NULL;
     char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
-    const char *CAfile = NULL, *CApath = NULL;
+    const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL;
     char *certsoutfile = NULL;
-    int noCAfile = 0, noCApath = 0;
-    char *infile = NULL, *outfile = NULL, *rctfile = NULL, *inrand = NULL;
-    char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile =
-        NULL;
+    int noCAfile = 0, noCApath = 0, noCAstore = 0;
+    char *infile = NULL, *outfile = NULL, *rctfile = NULL;
+    char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL;
     char *to = NULL, *from = NULL, *subject = NULL, *prog;
     cms_key_param *key_first = NULL, *key_param = NULL;
-    int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched =
-        0;
+    int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 0;
     int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
-    int need_rand = 0, operation = 0, ret = 1, rr_print = 0, rr_allorfirst =
-        -1;
+    int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1;
     int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
     size_t secret_keylen = 0, secret_keyidlen = 0;
     unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
@@ -328,6 +349,9 @@ int cms_main(int argc, char **argv)
         case OPT_BINARY:
             flags |= CMS_BINARY;
             break;
+        case OPT_CADES:
+            flags |= CMS_CADES;
+            break;
         case OPT_KEYID:
             flags |= CMS_USE_KEYID;
             break;
@@ -381,12 +405,18 @@ int cms_main(int argc, char **argv)
         case OPT_CAPATH:
             CApath = opt_arg();
             break;
+        case OPT_CASTORE:
+            CAstore = opt_arg();
+            break;
         case OPT_NOCAFILE:
             noCAfile = 1;
             break;
         case OPT_NOCAPATH:
             noCApath = 1;
             break;
+        case OPT_NOCASTORE:
+            noCAstore = 1;
+            break;
         case OPT_IN:
             infile = opt_arg();
             break;
@@ -449,10 +479,6 @@ int cms_main(int argc, char **argv)
                 goto opthelp;
             }
             break;
-        case OPT_RAND:
-            inrand = opt_arg();
-            need_rand = 1;
-            break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
@@ -568,6 +594,10 @@ int cms_main(int argc, char **argv)
                 goto end;
             vpmtouched++;
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         case OPT_3DES_WRAP:
 # ifndef OPENSSL_NO_DES
             wrap_cipher = EVP_des_ede3_wrap();
@@ -601,6 +631,14 @@ int cms_main(int argc, char **argv)
         goto opthelp;
     }
 
+    if (flags & CMS_CADES) {
+        if (flags & CMS_NOATTR) {
+            BIO_puts(bio_err, "Incompatible options: "
+                     "CAdES required signed attributes\n");
+            goto opthelp;
+        }
+    }
+
     if (operation & SMIME_SIGNERS) {
         if (keyfile != NULL && signerfile == NULL) {
             BIO_puts(bio_err, "Illegal -inkey without -signer\n");
@@ -624,7 +662,6 @@ int cms_main(int argc, char **argv)
         }
         signerfile = NULL;
         keyfile = NULL;
-        need_rand = 1;
     } else if (operation == SMIME_DECRYPT) {
         if (recipfile == NULL && keyfile == NULL
             && secret_key == NULL && pwri_pass == NULL) {
@@ -638,8 +675,8 @@ int cms_main(int argc, char **argv)
             BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
             goto opthelp;
         }
-        need_rand = 1;
     } else if (!operation) {
+        BIO_printf(bio_err, "No operation option (-encrypt|-decrypt|-sign|-verify|...) specified.\n");
         goto opthelp;
     }
 
@@ -648,13 +685,6 @@ int cms_main(int argc, char **argv)
         goto end;
     }
 
-    if (need_rand) {
-        app_RAND_load_file(NULL, (inrand != NULL));
-        if (inrand != NULL)
-            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
-                       app_RAND_load_files(inrand));
-    }
-
     ret = 2;
 
     if (!(operation & SMIME_SIGNERS))
@@ -805,7 +835,8 @@ int cms_main(int argc, char **argv)
         goto end;
 
     if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) {
-        if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
+        if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
+                                  CAstore, noCAstore)) == NULL)
             goto end;
         X509_STORE_set_verify_cb(store, cms_cb);
         if (vpmtouched)
@@ -933,11 +964,15 @@ int cms_main(int argc, char **argv)
             keyfile = sk_OPENSSL_STRING_value(skkeys, i);
 
             signer = load_cert(signerfile, FORMAT_PEM, "signer certificate");
-            if (signer == NULL)
+            if (signer == NULL) {
+                ret = 2;
                 goto end;
+            }
             key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
-            if (key == NULL)
+            if (key == NULL) {
+                ret = 2;
                 goto end;
+            }
             for (kparam = key_first; kparam; kparam = kparam->next) {
                 if (kparam->idx == i) {
                     tflags |= CMS_KEY_PARAM;
@@ -1083,8 +1118,6 @@ int cms_main(int argc, char **argv)
  end:
     if (ret)
         ERR_print_errors(bio_err);
-    if (need_rand)
-        app_RAND_write_file(NULL);
     sk_X509_pop_free(encerts, X509_free);
     sk_X509_pop_free(other, X509_free);
     X509_VERIFY_PARAM_free(vpm);
@@ -1117,7 +1150,7 @@ int cms_main(int argc, char **argv)
     BIO_free(indata);
     BIO_free_all(out);
     OPENSSL_free(passin);
-    return (ret);
+    return ret;
 }
 
 static int save_certs(char *signerfile, STACK_OF(X509) *signers)