Skip to content
cms.c 42.7 KiB
Newer Older
Rich Salz's avatar
Rich Salz committed
 * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
Dr. Stephen Henson's avatar
Dr. Stephen Henson committed
 *
Rich Salz's avatar
Rich Salz committed
 * Licensed under the OpenSSL license (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
Dr. Stephen Henson's avatar
Dr. Stephen Henson committed
 */

/* CMS utility function */

#include <stdio.h>
#include <string.h>
#include "apps.h"

#ifndef OPENSSL_NO_CMS

# include <openssl/crypto.h>
# include <openssl/pem.h>
# include <openssl/err.h>
# include <openssl/x509_vfy.h>
# include <openssl/x509v3.h>
# include <openssl/cms.h>
Dr. Stephen Henson's avatar
Dr. Stephen Henson committed

static int save_certs(char *signerfile, STACK_OF(X509) *signers);
static int cms_cb(int ok, X509_STORE_CTX *ctx);
static void receipt_request_print(CMS_ContentInfo *cms);
static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
                                                *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
                                                *rr_from);
static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
                              STACK_OF(OPENSSL_STRING) *param);

# define SMIME_OP        0x10
# define SMIME_IP        0x20
# define SMIME_SIGNERS   0x40
# define SMIME_ENCRYPT           (1 | SMIME_OP)
# define SMIME_DECRYPT           (2 | SMIME_IP)
# define SMIME_SIGN              (3 | SMIME_OP | SMIME_SIGNERS)
# define SMIME_VERIFY            (4 | SMIME_IP)
# define SMIME_CMSOUT            (5 | SMIME_IP | SMIME_OP)
# define SMIME_RESIGN            (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
# define SMIME_DATAOUT           (7 | SMIME_IP)
# define SMIME_DATA_CREATE       (8 | SMIME_OP)
# define SMIME_DIGEST_VERIFY     (9 | SMIME_IP)
# define SMIME_DIGEST_CREATE     (10 | SMIME_OP)
# define SMIME_UNCOMPRESS        (11 | SMIME_IP)
# define SMIME_COMPRESS          (12 | SMIME_OP)
# define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
# define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP)
# define SMIME_SIGN_RECEIPT      (15 | SMIME_IP | SMIME_OP)
# define SMIME_VERIFY_RECEIPT    (16 | SMIME_IP)
static int verify_err = 0;
typedef struct cms_key_param_st cms_key_param;

struct cms_key_param_st {
    int idx;
    STACK_OF(OPENSSL_STRING) *param;
    cms_key_param *next;
};
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_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,
    OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT,
    OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS,
    OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID,
    OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF,
    OPT_NOINDEF, OPT_NOOLDMIME, 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_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE,
    OPT_RAND, 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_V_ENUM,
    OPT_CIPHER
} OPTION_CHOICE;

OPTIONS cms_options[] = {
    {OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"},
    {OPT_HELP_STR, 1, '-',
        "  cert.pem... recipient certs for encryption\n"},
    {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
    {"help", OPT_HELP, '-', "Display this summary"},
    {"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
    {"outform", OPT_OUTFORM, 'c',
     "Output format SMIME (default), PEM or DER"},
    {"in", OPT_IN, '<', "Input file"},
    {"out", OPT_OUT, '>', "Output file"},
    {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
    {"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"},
    {"sign", OPT_SIGN, '-', "Sign message"},
    {"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"},
    {"resign", OPT_RESIGN, '-'},
    {"verify", OPT_VERIFY, '-', "Verify signed message"},
    {"verify_retcode", OPT_VERIFY_RETCODE, '-'},
    {"verify_receipt", OPT_VERIFY_RECEIPT, '<'},
    {"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, '-'},
    {"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
    {"asciicrlf", OPT_ASCIICRLF, '-'},
    {"nointern", OPT_NOINTERN, '-',
     "Don't search certificates in message for signer"},
    {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
    {"nocerts", OPT_NOCERTS, '-',
     "Don't include signers certificate when signing"},
    {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
    {"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
    {"nosmimecap", OPT_NOSMIMECAP, '-'},
    {"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, '-'},
    {"stream", OPT_INDEF, '-'},
    {"indef", OPT_INDEF, '-'},
    {"noindef", OPT_NOINDEF, '-'},
    {"nooldmime", OPT_NOOLDMIME, '-'},
    {"crlfeol", OPT_CRLFEOL, '-'},
    {"noout", OPT_NOOUT, '-', "For the -cmsout operation do not output the parsed CMS structure"},
    {"receipt_request_print", OPT_RR_PRINT, '-'},
    {"receipt_request_all", OPT_RR_ALL, '-'},
    {"receipt_request_first", OPT_RR_FIRST, '-'},
    {"rctform", OPT_RCTFORM, 'F'},
    {"certfile", OPT_CERTFILE, '<', "Other certificates file"},
    {"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
    {"CApath", OPT_CAPATH, '/', "trusted certificates directory"},
    {"no-CAfile", OPT_NOCAFILE, '-',
     "Do not load the default certificates file"},
    {"no-CApath", OPT_NOCAPATH, '-',
     "Do not load certificates from the default certificates directory"},
    {"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"},
    {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
    {"to", OPT_TO, 's', "To address"},
    {"from", OPT_FROM, 's', "From address"},
    {"subject", OPT_SUBJECT, 's', "Subject"},
    {"signer", OPT_SIGNER, 's', "Signer certificate file"},
    {"recip", OPT_RECIP, '<', "Recipient cert file for decryption"},
    {"certsout", OPT_CERTSOUT, '>', "Certificate output file"},
    {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"},
    {"inkey", OPT_INKEY, 's',
     "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'},
    {"", OPT_CIPHER, '-', "Any supported cipher"},
    OPT_V_OPTIONS,
    {"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
    {"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"},
    {"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"},
# ifndef OPENSSL_NO_DES
    {"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"},
# endif
# ifndef OPENSSL_NO_ENGINE
    {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
# endif
int cms_main(int argc, char **argv)
    ASN1_OBJECT *econtent_type = NULL;
    BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
    CMS_ContentInfo *cms = NULL, *rcms = NULL;
    CMS_ReceiptRequest *rr = NULL;
    ENGINE *e = NULL;
    EVP_PKEY *key = NULL;
    const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
    const EVP_MD *sign_md = NULL;
    STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
    STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
    STACK_OF(X509) *encerts = NULL, *other = NULL;
    X509 *cert = NULL, *recip = NULL, *signer = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
Loading
Loading full blame…