[BACK]Return to cms.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / openssl

Annotation of src/usr.bin/openssl/cms.c, Revision 1.34

1.34    ! tb          1: /* $OpenBSD: cms.c,v 1.33 2023/03/06 14:32:05 tb Exp $ */
1.1       jsing       2: /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
                      3:  * project.
                      4:  */
                      5: /* ====================================================================
                      6:  * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  *
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  *
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in
                     17:  *    the documentation and/or other materials provided with the
                     18:  *    distribution.
                     19:  *
                     20:  * 3. All advertising materials mentioning features or use of this
                     21:  *    software must display the following acknowledgment:
                     22:  *    "This product includes software developed by the OpenSSL Project
                     23:  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
                     24:  *
                     25:  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
                     26:  *    endorse or promote products derived from this software without
                     27:  *    prior written permission. For written permission, please contact
                     28:  *    licensing@OpenSSL.org.
                     29:  *
                     30:  * 5. Products derived from this software may not be called "OpenSSL"
                     31:  *    nor may "OpenSSL" appear in their names without prior written
                     32:  *    permission of the OpenSSL Project.
                     33:  *
                     34:  * 6. Redistributions of any form whatsoever must retain the following
                     35:  *    acknowledgment:
                     36:  *    "This product includes software developed by the OpenSSL Project
                     37:  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
                     38:  *
                     39:  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
                     40:  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     41:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     42:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
                     43:  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     44:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     45:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     46:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     47:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     48:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     49:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
                     50:  * OF THE POSSIBILITY OF SUCH DAMAGE.
                     51:  * ====================================================================
                     52:  */
                     53:
                     54: /* CMS utility function */
                     55:
                     56: #include <stdio.h>
                     57: #include <string.h>
                     58:
                     59: #include "apps.h"
                     60:
                     61: #ifndef OPENSSL_NO_CMS
                     62:
                     63: #include <openssl/crypto.h>
                     64: #include <openssl/err.h>
                     65: #include <openssl/pem.h>
                     66: #include <openssl/x509_vfy.h>
                     67: #include <openssl/x509v3.h>
1.10      jsing      68:
                     69: #include <openssl/cms.h>
1.1       jsing      70:
1.12      jsing      71: static int save_certs(char *signerfile, STACK_OF(X509) *signers);
                     72: static void receipt_request_print(BIO *out, CMS_ContentInfo *cms);
                     73: static CMS_ReceiptRequest *make_receipt_request(
                     74:     STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
                     75:     STACK_OF(OPENSSL_STRING) *rr_from);
1.14      inoguchi   76: static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
                     77:     STACK_OF(OPENSSL_STRING) *param);
1.1       jsing      78:
                     79: #define SMIME_OP       0x10
                     80: #define SMIME_IP       0x20
                     81: #define SMIME_SIGNERS  0x40
                     82: #define SMIME_ENCRYPT          (1 | SMIME_OP)
                     83: #define SMIME_DECRYPT          (2 | SMIME_IP)
                     84: #define SMIME_SIGN             (3 | SMIME_OP | SMIME_SIGNERS)
                     85: #define SMIME_VERIFY           (4 | SMIME_IP)
                     86: #define SMIME_CMSOUT           (5 | SMIME_IP | SMIME_OP)
                     87: #define SMIME_RESIGN           (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
                     88: #define SMIME_DATAOUT          (7 | SMIME_IP)
                     89: #define SMIME_DATA_CREATE      (8 | SMIME_OP)
                     90: #define SMIME_DIGEST_VERIFY    (9 | SMIME_IP)
                     91: #define SMIME_DIGEST_CREATE    (10 | SMIME_OP)
                     92: #define SMIME_UNCOMPRESS       (11 | SMIME_IP)
                     93: #define SMIME_COMPRESS         (12 | SMIME_OP)
                     94: #define SMIME_ENCRYPTED_DECRYPT        (13 | SMIME_IP)
                     95: #define SMIME_ENCRYPTED_ENCRYPT        (14 | SMIME_OP)
                     96: #define SMIME_SIGN_RECEIPT     (15 | SMIME_IP | SMIME_OP)
                     97: #define SMIME_VERIFY_RECEIPT   (16 | SMIME_IP)
                     98:
                     99: int verify_err = 0;
                    100:
1.15      inoguchi  101: struct cms_key_param {
1.14      inoguchi  102:        int idx;
                    103:        STACK_OF(OPENSSL_STRING) *param;
1.15      inoguchi  104:        struct cms_key_param *next;
1.14      inoguchi  105: };
                    106:
1.19      inoguchi  107: static struct {
                    108:        char *CAfile;
                    109:        char *CApath;
                    110:        X509 *cert;
                    111:        char *certfile;
                    112:        char *certsoutfile;
                    113:        const EVP_CIPHER *cipher;
                    114:        char *contfile;
                    115:        ASN1_OBJECT *econtent_type;
                    116:        STACK_OF(X509) *encerts;
                    117:        int flags;
                    118:        char *from;
                    119:        char *infile;
                    120:        int informat;
                    121:        struct cms_key_param *key_first;
                    122:        struct cms_key_param *key_param;
                    123:        char *keyfile;
                    124:        int keyform;
                    125:        int noout;
                    126:        int operation;
                    127:        char *outfile;
                    128:        int outformat;
                    129:        char *passargin;
                    130:        int print;
                    131:        unsigned char *pwri_pass;
                    132:        int rr_allorfirst;
                    133:        STACK_OF(OPENSSL_STRING) *rr_from;
                    134:        int rr_print;
                    135:        STACK_OF(OPENSSL_STRING) *rr_to;
                    136:        char *rctfile;
                    137:        int rctformat;
                    138:        char *recipfile;
                    139:        unsigned char *secret_key;
                    140:        unsigned char *secret_keyid;
                    141:        size_t secret_keyidlen;
                    142:        size_t secret_keylen;
                    143:        const EVP_MD *sign_md;
                    144:        char *signerfile;
                    145:        STACK_OF(OPENSSL_STRING) *skkeys;
                    146:        STACK_OF(OPENSSL_STRING) *sksigners;
                    147:        char *subject;
                    148:        char *to;
                    149:        int verify_retcode;
                    150:        X509_VERIFY_PARAM *vpm;
1.33      tb        151: } cfg;
1.19      inoguchi  152:
                    153: static const EVP_CIPHER *
                    154: get_cipher_by_name(char *name)
                    155: {
                    156:        if (name == NULL || strcmp(name, "") == 0)
                    157:                return (NULL);
                    158: #ifndef OPENSSL_NO_AES
                    159:        else if (strcmp(name, "aes128") == 0)
                    160:                return EVP_aes_128_cbc();
                    161:        else if (strcmp(name, "aes192") == 0)
                    162:                return EVP_aes_192_cbc();
                    163:        else if (strcmp(name, "aes256") == 0)
                    164:                return EVP_aes_256_cbc();
                    165: #endif
                    166: #ifndef OPENSSL_NO_CAMELLIA
                    167:        else if (strcmp(name, "camellia128") == 0)
                    168:                return EVP_camellia_128_cbc();
                    169:        else if (strcmp(name, "camellia192") == 0)
                    170:                return EVP_camellia_192_cbc();
                    171:        else if (strcmp(name, "camellia256") == 0)
                    172:                return EVP_camellia_256_cbc();
                    173: #endif
                    174: #ifndef OPENSSL_NO_DES
                    175:        else if (strcmp(name, "des") == 0)
                    176:                return EVP_des_cbc();
                    177:        else if (strcmp(name, "des3") == 0)
                    178:                return EVP_des_ede3_cbc();
                    179: #endif
                    180: #ifndef OPENSSL_NO_RC2
                    181:        else if (!strcmp(name, "rc2-40"))
                    182:                return EVP_rc2_40_cbc();
                    183:        else if (!strcmp(name, "rc2-64"))
                    184:                return EVP_rc2_64_cbc();
                    185:        else if (!strcmp(name, "rc2-128"))
                    186:                return EVP_rc2_cbc();
                    187: #endif
                    188:        else
                    189:                return (NULL);
                    190: }
                    191:
                    192: static int
                    193: cms_opt_cipher(int argc, char **argv, int *argsused)
                    194: {
                    195:        char *name = argv[0];
                    196:
                    197:        if (*name++ != '-')
                    198:                return (1);
                    199:
1.33      tb        200:        if ((cfg.cipher = get_cipher_by_name(name)) == NULL)
                    201:                if ((cfg.cipher = EVP_get_cipherbyname(name)) == NULL)
1.19      inoguchi  202:                        return (1);
                    203:
                    204:        *argsused = 1;
                    205:        return (0);
                    206: }
                    207:
                    208: static int
                    209: cms_opt_econtent_type(char *arg)
                    210: {
1.33      tb        211:        ASN1_OBJECT_free(cfg.econtent_type);
1.27      inoguchi  212:
1.33      tb        213:        if ((cfg.econtent_type = OBJ_txt2obj(arg, 0)) == NULL) {
1.19      inoguchi  214:                BIO_printf(bio_err, "Invalid OID %s\n", arg);
                    215:                return (1);
                    216:        }
                    217:        return (0);
                    218: }
                    219:
                    220: static int
                    221: cms_opt_inkey(char *arg)
                    222: {
1.33      tb        223:        if (cfg.keyfile == NULL) {
                    224:                cfg.keyfile = arg;
1.20      inoguchi  225:                return (0);
                    226:        }
1.32      tb        227:
1.33      tb        228:        if (cfg.signerfile == NULL) {
1.20      inoguchi  229:                BIO_puts(bio_err, "Illegal -inkey without -signer\n");
                    230:                return (1);
                    231:        }
                    232:
1.33      tb        233:        if (cfg.sksigners == NULL)
                    234:                cfg.sksigners = sk_OPENSSL_STRING_new_null();
                    235:        if (cfg.sksigners == NULL)
1.20      inoguchi  236:                return (1);
1.33      tb        237:        if (!sk_OPENSSL_STRING_push(cfg.sksigners, cfg.signerfile))
1.20      inoguchi  238:                return (1);
1.19      inoguchi  239:
1.33      tb        240:        cfg.signerfile = NULL;
1.19      inoguchi  241:
1.33      tb        242:        if (cfg.skkeys == NULL)
                    243:                cfg.skkeys = sk_OPENSSL_STRING_new_null();
                    244:        if (cfg.skkeys == NULL)
1.20      inoguchi  245:                return (1);
1.33      tb        246:        if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile))
1.20      inoguchi  247:                return (1);
1.19      inoguchi  248:
1.33      tb        249:        cfg.keyfile = arg;
1.19      inoguchi  250:        return (0);
                    251: }
                    252:
                    253: static int
                    254: cms_opt_keyopt(char *arg)
                    255: {
                    256:        int keyidx = -1;
                    257:
1.33      tb        258:        if (cfg.operation == SMIME_ENCRYPT) {
                    259:                if (cfg.encerts != NULL)
                    260:                        keyidx += sk_X509_num(cfg.encerts);
1.19      inoguchi  261:        } else {
1.33      tb        262:                if (cfg.keyfile != NULL || cfg.signerfile != NULL)
1.19      inoguchi  263:                        keyidx++;
1.33      tb        264:                if (cfg.skkeys != NULL)
                    265:                        keyidx += sk_OPENSSL_STRING_num(cfg.skkeys);
1.19      inoguchi  266:        }
                    267:
                    268:        if (keyidx < 0) {
                    269:                BIO_printf(bio_err, "No key specified\n");
                    270:                return (1);
                    271:        }
                    272:
1.33      tb        273:        if (cfg.key_param == NULL ||
                    274:            cfg.key_param->idx != keyidx) {
1.19      inoguchi  275:                struct cms_key_param *nparam;
                    276:
1.21      inoguchi  277:                if ((nparam = calloc(1, sizeof(struct cms_key_param))) == NULL)
1.19      inoguchi  278:                        return (1);
                    279:
                    280:                nparam->idx = keyidx;
                    281:                if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL) {
                    282:                        free(nparam);
                    283:                        return (1);
                    284:                }
                    285:
                    286:                nparam->next = NULL;
1.33      tb        287:                if (cfg.key_first == NULL)
                    288:                        cfg.key_first = nparam;
1.19      inoguchi  289:                else
1.33      tb        290:                        cfg.key_param->next = nparam;
1.19      inoguchi  291:
1.33      tb        292:                cfg.key_param = nparam;
1.19      inoguchi  293:        }
                    294:
1.33      tb        295:        if (!sk_OPENSSL_STRING_push(cfg.key_param->param, arg))
1.19      inoguchi  296:                return (1);
                    297:
                    298:        return (0);
                    299: }
                    300:
                    301: static int
                    302: cms_opt_md(char *arg)
                    303: {
1.33      tb        304:        if ((cfg.sign_md = EVP_get_digestbyname(arg)) == NULL) {
1.19      inoguchi  305:                BIO_printf(bio_err, "Unknown digest %s\n", arg);
                    306:                return (1);
                    307:        }
                    308:        return (0);
                    309: }
                    310:
                    311: static int
                    312: cms_opt_print(void)
                    313: {
1.33      tb        314:        cfg.noout = 1;
                    315:        cfg.print = 1;
1.19      inoguchi  316:        return (0);
                    317: }
                    318:
                    319: static int
                    320: cms_opt_pwri_pass(char *arg)
                    321: {
1.33      tb        322:        cfg.pwri_pass = (unsigned char *)arg;
1.19      inoguchi  323:        return (0);
                    324: }
                    325:
                    326: static int
                    327: cms_opt_recip(char *arg)
                    328: {
1.33      tb        329:        if (cfg.operation == SMIME_ENCRYPT) {
                    330:                if (cfg.encerts == NULL) {
                    331:                        if ((cfg.encerts = sk_X509_new_null()) == NULL)
1.19      inoguchi  332:                                return (1);
                    333:                }
                    334:
1.33      tb        335:                cfg.cert = load_cert(bio_err, arg, FORMAT_PEM,
1.19      inoguchi  336:                    NULL, "recipient certificate file");
1.33      tb        337:                if (cfg.cert == NULL)
1.19      inoguchi  338:                        return (1);
                    339:
1.33      tb        340:                if (!sk_X509_push(cfg.encerts, cfg.cert))
1.19      inoguchi  341:                        return (1);
                    342:
1.33      tb        343:                cfg.cert = NULL;
1.19      inoguchi  344:        } else {
1.33      tb        345:                cfg.recipfile = arg;
1.19      inoguchi  346:        }
                    347:        return (0);
                    348: }
                    349:
                    350: static int
                    351: cms_opt_receipt_request_from(char *arg)
                    352: {
1.33      tb        353:        if (cfg.rr_from == NULL)
                    354:                cfg.rr_from = sk_OPENSSL_STRING_new_null();
                    355:        if (cfg.rr_from == NULL)
1.19      inoguchi  356:                return (1);
1.33      tb        357:        if (!sk_OPENSSL_STRING_push(cfg.rr_from, arg))
1.19      inoguchi  358:                return (1);
                    359:
                    360:        return (0);
                    361: }
                    362:
                    363: static int
                    364: cms_opt_receipt_request_to(char *arg)
                    365: {
1.33      tb        366:        if (cfg.rr_to == NULL)
                    367:                cfg.rr_to = sk_OPENSSL_STRING_new_null();
                    368:        if (cfg.rr_to == NULL)
1.19      inoguchi  369:                return (1);
1.33      tb        370:        if (!sk_OPENSSL_STRING_push(cfg.rr_to, arg))
1.19      inoguchi  371:                return (1);
                    372:
                    373:        return (0);
                    374: }
                    375:
                    376: static int
                    377: cms_opt_secretkey(char *arg)
                    378: {
                    379:        long ltmp;
                    380:
1.33      tb        381:        free(cfg.secret_key);
1.27      inoguchi  382:
1.33      tb        383:        if ((cfg.secret_key = string_to_hex(arg, &ltmp)) == NULL) {
1.19      inoguchi  384:                BIO_printf(bio_err, "Invalid key %s\n", arg);
                    385:                return (1);
                    386:        }
1.33      tb        387:        cfg.secret_keylen = (size_t)ltmp;
1.19      inoguchi  388:        return (0);
                    389: }
                    390:
                    391: static int
                    392: cms_opt_secretkeyid(char *arg)
                    393: {
                    394:        long ltmp;
1.27      inoguchi  395:
1.33      tb        396:        free(cfg.secret_keyid);
1.19      inoguchi  397:
1.33      tb        398:        if ((cfg.secret_keyid = string_to_hex(arg, &ltmp)) == NULL) {
1.19      inoguchi  399:                BIO_printf(bio_err, "Invalid id %s\n", arg);
                    400:                return (1);
                    401:        }
1.33      tb        402:        cfg.secret_keyidlen = (size_t)ltmp;
1.19      inoguchi  403:        return (0);
                    404: }
                    405:
                    406: static int
                    407: cms_opt_signer(char *arg)
                    408: {
1.33      tb        409:        if (cfg.signerfile == NULL) {
                    410:                cfg.signerfile = arg;
1.20      inoguchi  411:                return (0);
                    412:        }
                    413:
1.33      tb        414:        if (cfg.sksigners == NULL)
                    415:                cfg.sksigners = sk_OPENSSL_STRING_new_null();
                    416:        if (cfg.sksigners == NULL)
1.20      inoguchi  417:                return (1);
1.33      tb        418:        if (!sk_OPENSSL_STRING_push(cfg.sksigners, cfg.signerfile))
1.20      inoguchi  419:                return (1);
                    420:
1.33      tb        421:        if (cfg.keyfile == NULL)
                    422:                cfg.keyfile = cfg.signerfile;
1.19      inoguchi  423:
1.33      tb        424:        if (cfg.skkeys == NULL)
                    425:                cfg.skkeys = sk_OPENSSL_STRING_new_null();
                    426:        if (cfg.skkeys == NULL)
1.20      inoguchi  427:                return (1);
1.33      tb        428:        if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile))
1.20      inoguchi  429:                return (1);
1.19      inoguchi  430:
1.33      tb        431:        cfg.keyfile = NULL;
1.19      inoguchi  432:
1.33      tb        433:        cfg.signerfile = arg;
1.19      inoguchi  434:        return (0);
                    435: }
                    436:
                    437: static int
                    438: cms_opt_verify_param(int argc, char **argv, int *argsused)
                    439: {
                    440:        int oargc = argc;
                    441:        int badarg = 0;
                    442:
1.33      tb        443:        if (!args_verify(&argv, &argc, &badarg, bio_err, &cfg.vpm))
1.19      inoguchi  444:                return (1);
                    445:        if (badarg)
                    446:                return (1);
                    447:
                    448:        *argsused = oargc - argc;
                    449:
                    450:        return (0);
                    451: }
                    452:
                    453: static int
                    454: cms_opt_verify_receipt(char *arg)
                    455: {
1.33      tb        456:        cfg.operation = SMIME_VERIFY_RECEIPT;
                    457:        cfg.rctfile = arg;
1.19      inoguchi  458:        return (0);
                    459: }
                    460:
                    461: static const struct option cms_options[] = {
                    462: #ifndef OPENSSL_NO_AES
                    463:        {
                    464:                .name = "aes128",
                    465:                .desc = "Encrypt PEM output with CBC AES",
                    466:                .type = OPTION_ARGV_FUNC,
                    467:                .opt.argvfunc = cms_opt_cipher,
                    468:        },
                    469:        {
                    470:                .name = "aes192",
                    471:                .desc = "Encrypt PEM output with CBC AES",
                    472:                .type = OPTION_ARGV_FUNC,
                    473:                .opt.argvfunc = cms_opt_cipher,
                    474:        },
                    475:        {
                    476:                .name = "aes256",
                    477:                .desc = "Encrypt PEM output with CBC AES",
                    478:                .type = OPTION_ARGV_FUNC,
                    479:                .opt.argvfunc = cms_opt_cipher,
                    480:        },
                    481: #endif
                    482: #ifndef OPENSSL_NO_CAMELLIA
                    483:        {
                    484:                .name = "camellia128",
                    485:                .desc = "Encrypt PEM output with CBC Camellia",
                    486:                .type = OPTION_ARGV_FUNC,
                    487:                .opt.argvfunc = cms_opt_cipher,
                    488:        },
                    489:        {
                    490:                .name = "camellia192",
                    491:                .desc = "Encrypt PEM output with CBC Camellia",
                    492:                .type = OPTION_ARGV_FUNC,
                    493:                .opt.argvfunc = cms_opt_cipher,
                    494:        },
                    495:        {
                    496:                .name = "camellia256",
                    497:                .desc = "Encrypt PEM output with CBC Camellia",
                    498:                .type = OPTION_ARGV_FUNC,
                    499:                .opt.argvfunc = cms_opt_cipher,
                    500:        },
                    501: #endif
                    502: #ifndef OPENSSL_NO_DES
                    503:        {
                    504:                .name = "des",
                    505:                .desc = "Encrypt with DES",
                    506:                .type = OPTION_ARGV_FUNC,
                    507:                .opt.argvfunc = cms_opt_cipher,
                    508:        },
                    509:        {
                    510:                .name = "des3",
1.28      inoguchi  511:                .desc = "Encrypt with triple DES (default)",
1.19      inoguchi  512:                .type = OPTION_ARGV_FUNC,
                    513:                .opt.argvfunc = cms_opt_cipher,
                    514:        },
                    515: #endif
                    516: #ifndef OPENSSL_NO_RC2
                    517:        {
                    518:                .name = "rc2-40",
1.28      inoguchi  519:                .desc = "Encrypt with RC2-40",
1.19      inoguchi  520:                .type = OPTION_ARGV_FUNC,
                    521:                .opt.argvfunc = cms_opt_cipher,
                    522:        },
                    523:        {
                    524:                .name = "rc2-64",
                    525:                .desc = "Encrypt with RC2-64",
                    526:                .type = OPTION_ARGV_FUNC,
                    527:                .opt.argvfunc = cms_opt_cipher,
                    528:        },
                    529:        {
                    530:                .name = "rc2-128",
                    531:                .desc = "Encrypt with RC2-128",
                    532:                .type = OPTION_ARGV_FUNC,
                    533:                .opt.argvfunc = cms_opt_cipher,
                    534:        },
                    535: #endif
                    536:        {
                    537:                .name = "CAfile",
                    538:                .argname = "file",
                    539:                .desc = "Certificate Authority file",
                    540:                .type = OPTION_ARG,
1.33      tb        541:                .opt.arg = &cfg.CAfile,
1.19      inoguchi  542:        },
                    543:        {
                    544:                .name = "CApath",
                    545:                .argname = "path",
                    546:                .desc = "Certificate Authority path",
                    547:                .type = OPTION_ARG,
1.33      tb        548:                .opt.arg = &cfg.CApath,
1.19      inoguchi  549:        },
                    550:        {
                    551:                .name = "binary",
                    552:                .desc = "Do not translate message to text",
                    553:                .type = OPTION_VALUE_OR,
1.33      tb        554:                .opt.value = &cfg.flags,
1.19      inoguchi  555:                .value = CMS_BINARY,
                    556:        },
                    557:        {
                    558:                .name = "certfile",
                    559:                .argname = "file",
                    560:                .desc = "Other certificates file",
                    561:                .type = OPTION_ARG,
1.33      tb        562:                .opt.arg = &cfg.certfile,
1.19      inoguchi  563:        },
                    564:        {
                    565:                .name = "certsout",
                    566:                .argname = "file",
                    567:                .desc = "Certificate output file",
                    568:                .type = OPTION_ARG,
1.33      tb        569:                .opt.arg = &cfg.certsoutfile,
1.19      inoguchi  570:        },
                    571:        {
                    572:                .name = "cmsout",
                    573:                .desc = "Output CMS structure",
                    574:                .type = OPTION_VALUE,
1.33      tb        575:                .opt.value = &cfg.operation,
1.19      inoguchi  576:                .value = SMIME_CMSOUT,
                    577:        },
                    578:        {
                    579:                .name = "compress",
                    580:                .desc = "Create CMS CompressedData type",
                    581:                .type = OPTION_VALUE,
1.33      tb        582:                .opt.value = &cfg.operation,
1.19      inoguchi  583:                .value = SMIME_COMPRESS,
                    584:        },
                    585:        {
                    586:                .name = "content",
                    587:                .argname = "file",
                    588:                .desc = "Supply or override content for detached signature",
                    589:                .type = OPTION_ARG,
1.33      tb        590:                .opt.arg = &cfg.contfile,
1.19      inoguchi  591:        },
                    592:        {
                    593:                .name = "crlfeol",
                    594:                .desc = "Use CRLF as EOL termination instead of CR only",
                    595:                .type = OPTION_VALUE_OR,
1.33      tb        596:                .opt.value = &cfg.flags,
1.19      inoguchi  597:                .value = CMS_CRLFEOL,
                    598:        },
                    599:        {
                    600:                .name = "data_create",
                    601:                .desc = "Create CMS Data type",
                    602:                .type = OPTION_VALUE,
1.33      tb        603:                .opt.value = &cfg.operation,
1.19      inoguchi  604:                .value = SMIME_DATA_CREATE,
                    605:        },
                    606:        {
                    607:                .name = "data_out",
                    608:                .desc = "Output content from the input CMS Data type",
                    609:                .type = OPTION_VALUE,
1.33      tb        610:                .opt.value = &cfg.operation,
1.19      inoguchi  611:                .value = SMIME_DATAOUT,
                    612:        },
                    613:        {
                    614:                .name = "debug_decrypt",
                    615:                .desc = "Set the CMS_DEBUG_DECRYPT flag when decrypting",
                    616:                .type = OPTION_VALUE_OR,
1.33      tb        617:                .opt.value = &cfg.flags,
1.19      inoguchi  618:                .value = CMS_DEBUG_DECRYPT,
                    619:        },
                    620:        {
                    621:                .name = "decrypt",
                    622:                .desc = "Decrypt encrypted message",
                    623:                .type = OPTION_VALUE,
1.33      tb        624:                .opt.value = &cfg.operation,
1.19      inoguchi  625:                .value = SMIME_DECRYPT,
                    626:        },
                    627:        {
                    628:                .name = "digest_create",
                    629:                .desc = "Create CMS DigestedData type",
                    630:                .type = OPTION_VALUE,
1.33      tb        631:                .opt.value = &cfg.operation,
1.19      inoguchi  632:                .value = SMIME_DIGEST_CREATE,
                    633:        },
                    634:        {
                    635:                .name = "digest_verify",
                    636:                .desc = "Verify CMS DigestedData type and output the content",
                    637:                .type = OPTION_VALUE,
1.33      tb        638:                .opt.value = &cfg.operation,
1.19      inoguchi  639:                .value = SMIME_DIGEST_VERIFY,
                    640:        },
                    641:        {
                    642:                .name = "econtent_type",
                    643:                .argname = "type",
                    644:                .desc = "Set the encapsulated content type",
                    645:                .type = OPTION_ARG_FUNC,
                    646:                .opt.argfunc = cms_opt_econtent_type,
                    647:        },
                    648:        {
                    649:                .name = "encrypt",
                    650:                .desc = "Encrypt message",
                    651:                .type = OPTION_VALUE,
1.33      tb        652:                .opt.value = &cfg.operation,
1.19      inoguchi  653:                .value = SMIME_ENCRYPT,
                    654:        },
                    655:        {
                    656:                .name = "EncryptedData_decrypt",
                    657:                .desc = "Decrypt CMS EncryptedData",
                    658:                .type = OPTION_VALUE,
1.33      tb        659:                .opt.value = &cfg.operation,
1.19      inoguchi  660:                .value = SMIME_ENCRYPTED_DECRYPT,
                    661:        },
                    662:        {
                    663:                .name = "EncryptedData_encrypt",
                    664:                .desc = "Encrypt content using supplied symmetric key and algorithm",
                    665:                .type = OPTION_VALUE,
1.33      tb        666:                .opt.value = &cfg.operation,
1.19      inoguchi  667:                .value = SMIME_ENCRYPTED_ENCRYPT,
                    668:        },
                    669:        {
                    670:                .name = "from",
                    671:                .argname = "addr",
                    672:                .desc = "From address",
                    673:                .type = OPTION_ARG,
1.33      tb        674:                .opt.arg = &cfg.from,
1.19      inoguchi  675:        },
                    676:        {
                    677:                .name = "in",
                    678:                .argname = "file",
                    679:                .desc = "Input file",
                    680:                .type = OPTION_ARG,
1.33      tb        681:                .opt.arg = &cfg.infile,
1.19      inoguchi  682:        },
                    683:        {
                    684:                .name = "indef",
                    685:                .desc = "Same as -stream",
                    686:                .type = OPTION_VALUE_OR,
1.33      tb        687:                .opt.value = &cfg.flags,
1.19      inoguchi  688:                .value = CMS_STREAM,
                    689:        },
                    690:        {
                    691:                .name = "inform",
                    692:                .argname = "fmt",
                    693:                .desc = "Input format (DER, PEM or SMIME (default))",
                    694:                .type = OPTION_ARG_FORMAT,
1.33      tb        695:                .opt.value = &cfg.informat,
1.19      inoguchi  696:        },
                    697:        {
                    698:                .name = "inkey",
                    699:                .argname = "file",
                    700:                .desc = "Input key file",
                    701:                .type = OPTION_ARG_FUNC,
                    702:                .opt.argfunc = cms_opt_inkey,
                    703:        },
                    704:        {
                    705:                .name = "keyform",
                    706:                .argname = "fmt",
                    707:                .desc = "Input key format (DER or PEM (default))",
                    708:                .type = OPTION_ARG_FORMAT,
1.33      tb        709:                .opt.value = &cfg.keyform,
1.19      inoguchi  710:        },
                    711:        {
                    712:                .name = "keyid",
                    713:                .desc = "Use subject key identifier",
                    714:                .type = OPTION_VALUE_OR,
1.33      tb        715:                .opt.value = &cfg.flags,
1.19      inoguchi  716:                .value = CMS_USE_KEYID,
                    717:        },
                    718:        {
                    719:                .name = "keyopt",
                    720:                .argname = "nm:v",
                    721:                .desc = "Set public key parameters",
                    722:                .type = OPTION_ARG_FUNC,
                    723:                .opt.argfunc = cms_opt_keyopt,
                    724:        },
                    725:        {
                    726:                .name = "md",
                    727:                .argname = "digest",
                    728:                .desc = "Digest to use when signing or resigning",
                    729:                .type = OPTION_ARG_FUNC,
                    730:                .opt.argfunc = cms_opt_md,
                    731:        },
                    732:        {
                    733:                .name = "no_attr_verify",
                    734:                .desc = "Do not verify the signer's attribute of a signature",
                    735:                .type = OPTION_VALUE_OR,
1.33      tb        736:                .opt.value = &cfg.flags,
1.19      inoguchi  737:                .value = CMS_NO_ATTR_VERIFY,
                    738:        },
                    739:        {
                    740:                .name = "no_content_verify",
                    741:                .desc = "Do not verify the content of a signed message",
                    742:                .type = OPTION_VALUE_OR,
1.33      tb        743:                .opt.value = &cfg.flags,
1.19      inoguchi  744:                .value = CMS_NO_CONTENT_VERIFY,
                    745:        },
                    746:        {
                    747:                .name = "no_signer_cert_verify",
                    748:                .desc = "Do not verify the signer's certificate",
                    749:                .type = OPTION_VALUE_OR,
1.33      tb        750:                .opt.value = &cfg.flags,
1.19      inoguchi  751:                .value = CMS_NO_SIGNER_CERT_VERIFY,
                    752:        },
                    753:        {
                    754:                .name = "noattr",
                    755:                .desc = "Do not include any signed attributes",
                    756:                .type = OPTION_VALUE_OR,
1.33      tb        757:                .opt.value = &cfg.flags,
1.19      inoguchi  758:                .value = CMS_NOATTR,
                    759:        },
                    760:        {
                    761:                .name = "nocerts",
                    762:                .desc = "Do not include signer's certificate when signing",
                    763:                .type = OPTION_VALUE_OR,
1.33      tb        764:                .opt.value = &cfg.flags,
1.19      inoguchi  765:                .value = CMS_NOCERTS,
                    766:        },
                    767:        {
                    768:                .name = "nodetach",
                    769:                .desc = "Use opaque signing",
                    770:                .type = OPTION_VALUE_AND,
1.33      tb        771:                .opt.value = &cfg.flags,
1.19      inoguchi  772:                .value = ~CMS_DETACHED,
                    773:        },
                    774:        {
                    775:                .name = "noindef",
                    776:                .desc = "Disable CMS streaming",
                    777:                .type = OPTION_VALUE_AND,
1.33      tb        778:                .opt.value = &cfg.flags,
1.19      inoguchi  779:                .value = ~CMS_STREAM,
                    780:        },
                    781:        {
                    782:                .name = "nointern",
                    783:                .desc = "Do not search certificates in message for signer",
                    784:                .type = OPTION_VALUE_OR,
1.33      tb        785:                .opt.value = &cfg.flags,
1.19      inoguchi  786:                .value = CMS_NOINTERN,
                    787:        },
                    788:        {
                    789:                .name = "nooldmime",
                    790:                .desc = "Output old S/MIME content type",
                    791:                .type = OPTION_VALUE_OR,
1.33      tb        792:                .opt.value = &cfg.flags,
1.19      inoguchi  793:                .value = CMS_NOOLDMIMETYPE,
                    794:        },
                    795:        {
                    796:                .name = "noout",
                    797:                .desc = "Do not output the parsed CMS structure",
                    798:                .type = OPTION_FLAG,
1.33      tb        799:                .opt.flag = &cfg.noout,
1.19      inoguchi  800:        },
                    801:        {
                    802:                .name = "nosigs",
                    803:                .desc = "Do not verify message signature",
                    804:                .type = OPTION_VALUE_OR,
1.33      tb        805:                .opt.value = &cfg.flags,
1.19      inoguchi  806:                .value = CMS_NOSIGS,
                    807:        },
                    808:        {
                    809:                .name = "nosmimecap",
                    810:                .desc = "Omit the SMIMECapabilities attribute",
                    811:                .type = OPTION_VALUE_OR,
1.33      tb        812:                .opt.value = &cfg.flags,
1.19      inoguchi  813:                .value = CMS_NOSMIMECAP,
                    814:        },
                    815:        {
                    816:                .name = "noverify",
                    817:                .desc = "Do not verify signer's certificate",
                    818:                .type = OPTION_VALUE_OR,
1.33      tb        819:                .opt.value = &cfg.flags,
1.19      inoguchi  820:                .value = CMS_NO_SIGNER_CERT_VERIFY,
                    821:        },
                    822:        {
                    823:                .name = "out",
                    824:                .argname = "file",
                    825:                .desc = "Output file",
                    826:                .type = OPTION_ARG,
1.33      tb        827:                .opt.arg = &cfg.outfile,
1.19      inoguchi  828:        },
                    829:        {
                    830:                .name = "outform",
                    831:                .argname = "fmt",
                    832:                .desc = "Output format (DER, PEM or SMIME (default))",
                    833:                .type = OPTION_ARG_FORMAT,
1.33      tb        834:                .opt.value = &cfg.outformat,
1.19      inoguchi  835:        },
                    836:        {
                    837:                .name = "passin",
                    838:                .argname = "src",
                    839:                .desc = "Private key password source",
                    840:                .type = OPTION_ARG,
1.33      tb        841:                .opt.arg = &cfg.passargin,
1.19      inoguchi  842:        },
                    843:        {
                    844:                .name = "print",
                    845:                .desc = "Print out all fields of the CMS structure for the -cmsout",
                    846:                .type = OPTION_FUNC,
                    847:                .opt.func = cms_opt_print,
                    848:        },
                    849:        {
                    850:                .name = "pwri_password",
                    851:                .argname = "arg",
                    852:                .desc = "Specify PasswordRecipientInfo (PWRI) password to use",
                    853:                .type = OPTION_ARG_FUNC,
                    854:                .opt.argfunc = cms_opt_pwri_pass,
                    855:        },
                    856:        {
                    857:                .name = "rctform",
                    858:                .argname = "fmt",
                    859:                .desc = "Receipt file format (DER, PEM or SMIME (default))",
                    860:                .type = OPTION_ARG_FORMAT,
1.33      tb        861:                .opt.value = &cfg.rctformat,
1.19      inoguchi  862:        },
                    863:        {
                    864:                .name = "receipt_request_all",
                    865:                .desc = "Indicate requests should be provided by all recipients",
                    866:                .type = OPTION_VALUE,
1.33      tb        867:                .opt.value = &cfg.rr_allorfirst,
1.19      inoguchi  868:                .value = 0,
                    869:        },
                    870:        {
                    871:                .name = "receipt_request_first",
                    872:                .desc = "Indicate requests should be provided by first tier recipient",
                    873:                .type = OPTION_VALUE,
1.33      tb        874:                .opt.value = &cfg.rr_allorfirst,
1.19      inoguchi  875:                .value = 1,
                    876:        },
                    877:        {
                    878:                .name = "receipt_request_from",
                    879:                .argname = "addr",
                    880:                .desc = "Add explicit email address where receipts should be supplied",
                    881:                .type = OPTION_ARG_FUNC,
                    882:                .opt.argfunc = cms_opt_receipt_request_from,
                    883:        },
                    884:        {
                    885:                .name = "receipt_request_print",
                    886:                .desc = "Print out the contents of any signed receipt requests",
                    887:                .type = OPTION_FLAG,
1.33      tb        888:                .opt.flag = &cfg.rr_print,
1.19      inoguchi  889:        },
                    890:        {
                    891:                .name = "receipt_request_to",
                    892:                .argname = "addr",
                    893:                .desc = "Add explicit email address where receipts should be sent to",
                    894:                .type = OPTION_ARG_FUNC,
                    895:                .opt.argfunc = cms_opt_receipt_request_to,
                    896:        },
                    897:        {
                    898:                .name = "recip",
                    899:                .argname = "file",
                    900:                .desc = "Recipient certificate file for decryption",
                    901:                .type = OPTION_ARG_FUNC,
                    902:                .opt.argfunc = cms_opt_recip,
                    903:        },
                    904:        {
                    905:                .name = "resign",
                    906:                .desc = "Resign a signed message",
                    907:                .type = OPTION_VALUE,
1.33      tb        908:                .opt.value = &cfg.operation,
1.19      inoguchi  909:                .value = SMIME_RESIGN,
                    910:        },
                    911:        {
                    912:                .name = "secretkey",
                    913:                .argname = "key",
                    914:                .desc = "Specify symmetric key to use",
                    915:                .type = OPTION_ARG_FUNC,
                    916:                .opt.argfunc = cms_opt_secretkey,
                    917:        },
                    918:        {
                    919:                .name = "secretkeyid",
                    920:                .argname = "id",
                    921:                .desc = "The key identifier for the supplied symmetric key",
                    922:                .type = OPTION_ARG_FUNC,
                    923:                .opt.argfunc = cms_opt_secretkeyid,
                    924:        },
                    925:        {
                    926:                .name = "sign",
                    927:                .desc = "Sign message",
                    928:                .type = OPTION_VALUE,
1.33      tb        929:                .opt.value = &cfg.operation,
1.19      inoguchi  930:                .value = SMIME_SIGN,
                    931:        },
                    932:        {
                    933:                .name = "sign_receipt",
                    934:                .desc = "Generate a signed receipt for the message",
                    935:                .type = OPTION_VALUE,
1.33      tb        936:                .opt.value = &cfg.operation,
1.19      inoguchi  937:                .value = SMIME_SIGN_RECEIPT,
                    938:        },
                    939:        {
                    940:                .name = "signer",
                    941:                .argname = "file",
                    942:                .desc = "Signer certificate file",
                    943:                .type = OPTION_ARG_FUNC,
                    944:                .opt.argfunc = cms_opt_signer,
                    945:        },
                    946:        {
                    947:                .name = "stream",
                    948:                .desc = "Enable CMS streaming",
                    949:                .type = OPTION_VALUE_OR,
1.33      tb        950:                .opt.value = &cfg.flags,
1.19      inoguchi  951:                .value = CMS_STREAM,
                    952:        },
                    953:        {
                    954:                .name = "subject",
                    955:                .argname = "s",
                    956:                .desc = "Subject",
                    957:                .type = OPTION_ARG,
1.33      tb        958:                .opt.arg = &cfg.subject,
1.19      inoguchi  959:        },
                    960:        {
                    961:                .name = "text",
                    962:                .desc = "Include or delete text MIME headers",
                    963:                .type = OPTION_VALUE_OR,
1.33      tb        964:                .opt.value = &cfg.flags,
1.19      inoguchi  965:                .value = CMS_TEXT,
                    966:        },
                    967:        {
                    968:                .name = "to",
                    969:                .argname = "addr",
                    970:                .desc = "To address",
                    971:                .type = OPTION_ARG,
1.33      tb        972:                .opt.arg = &cfg.to,
1.19      inoguchi  973:        },
                    974:        {
                    975:                .name = "uncompress",
                    976:                .desc = "Uncompress CMS CompressedData type",
                    977:                .type = OPTION_VALUE,
1.33      tb        978:                .opt.value = &cfg.operation,
1.19      inoguchi  979:                .value = SMIME_UNCOMPRESS,
                    980:        },
                    981:        {
                    982:                .name = "verify",
                    983:                .desc = "Verify signed message",
                    984:                .type = OPTION_VALUE,
1.33      tb        985:                .opt.value = &cfg.operation,
1.19      inoguchi  986:                .value = SMIME_VERIFY,
                    987:        },
                    988:        {
                    989:                .name = "verify_receipt",
                    990:                .argname = "file",
                    991:                .desc = "Verify a signed receipt in file",
                    992:                .type = OPTION_ARG_FUNC,
                    993:                .opt.argfunc = cms_opt_verify_receipt,
                    994:        },
                    995:        {
                    996:                .name = "verify_retcode",
                    997:                .desc = "Set verification error code to exit code",
                    998:                .type = OPTION_FLAG,
1.33      tb        999:                .opt.flag = &cfg.verify_retcode,
1.19      inoguchi 1000:        },
                   1001:        {
                   1002:                .name = "check_ss_sig",
                   1003:                .type = OPTION_ARGV_FUNC,
                   1004:                .opt.argvfunc = cms_opt_verify_param,
                   1005:        },
                   1006:        {
                   1007:                .name = "crl_check",
                   1008:                .type = OPTION_ARGV_FUNC,
                   1009:                .opt.argvfunc = cms_opt_verify_param,
                   1010:        },
                   1011:        {
                   1012:                .name = "crl_check_all",
                   1013:                .type = OPTION_ARGV_FUNC,
                   1014:                .opt.argvfunc = cms_opt_verify_param,
                   1015:        },
                   1016:        {
                   1017:                .name = "extended_crl",
                   1018:                .type = OPTION_ARGV_FUNC,
                   1019:                .opt.argvfunc = cms_opt_verify_param,
                   1020:        },
                   1021:        {
                   1022:                .name = "ignore_critical",
                   1023:                .type = OPTION_ARGV_FUNC,
                   1024:                .opt.argvfunc = cms_opt_verify_param,
                   1025:        },
                   1026:        {
                   1027:                .name = "issuer_checks",
                   1028:                .type = OPTION_ARGV_FUNC,
                   1029:                .opt.argvfunc = cms_opt_verify_param,
                   1030:        },
                   1031:        {
                   1032:                .name = "policy",
                   1033:                .type = OPTION_ARGV_FUNC,
                   1034:                .opt.argvfunc = cms_opt_verify_param,
                   1035:        },
                   1036:        {
                   1037:                .name = "policy_check",
                   1038:                .type = OPTION_ARGV_FUNC,
                   1039:                .opt.argvfunc = cms_opt_verify_param,
                   1040:        },
                   1041:        {
                   1042:                .name = "purpose",
                   1043:                .type = OPTION_ARGV_FUNC,
                   1044:                .opt.argvfunc = cms_opt_verify_param,
                   1045:        },
                   1046:        {
                   1047:                .name = "x509_strict",
                   1048:                .type = OPTION_ARGV_FUNC,
                   1049:                .opt.argvfunc = cms_opt_verify_param,
                   1050:        },
                   1051:        {
                   1052:                .name = NULL,
                   1053:                .type = OPTION_ARGV_FUNC,
                   1054:                .opt.argvfunc = cms_opt_cipher,
                   1055:        },
                   1056:        { NULL },
                   1057: };
                   1058:
                   1059: static const struct option verify_shared_options[] = {
                   1060:        {
                   1061:                .name = "check_ss_sig",
                   1062:                .desc = "Check the root CA self-signed certificate signature",
                   1063:        },
                   1064:        {
                   1065:                .name = "crl_check",
                   1066:                .desc = "Enable CRL checking for the leaf certificate",
                   1067:        },
                   1068:        {
                   1069:                .name = "crl_check_all",
                   1070:                .desc = "Enable CRL checking for the entire certificate chain",
                   1071:        },
                   1072:        {
                   1073:                .name = "extended_crl",
                   1074:                .desc = "Enable extended CRL support",
                   1075:        },
                   1076:        {
                   1077:                .name = "ignore_critical",
                   1078:                .desc = "Disable critical extension checking",
                   1079:        },
                   1080:        {
                   1081:                .name = "issuer_checks",
                   1082:                .desc = "Enable debugging of certificate issuer checks",
                   1083:        },
                   1084:        {
                   1085:                .name = "policy",
                   1086:                .argname = "name",
                   1087:                .desc = "Add given policy to the acceptable set",
                   1088:        },
                   1089:        {
                   1090:                .name = "policy_check",
                   1091:                .desc = "Enable certificate policy checking",
                   1092:        },
                   1093:        {
                   1094:                .name = "purpose",
                   1095:                .argname = "name",
                   1096:                .desc = "Verify for the given purpose",
                   1097:        },
                   1098:        {
                   1099:                .name = "x509_strict",
                   1100:                .desc = "Use strict X.509 rules (disables workarounds)",
                   1101:        },
                   1102:        { NULL },
                   1103: };
                   1104:
                   1105: static void
                   1106: cms_usage(void)
                   1107: {
                   1108:        int i;
                   1109:
                   1110:        fprintf(stderr, "usage: cms "
                   1111:            "[-aes128 | -aes192 | -aes256 | -camellia128 |\n"
                   1112:            "    -camellia192 | -camellia256 | -des | -des3 |\n"
                   1113:            "    -rc2-40 | -rc2-64 | -rc2-128] [-CAfile file]\n"
                   1114:            "    [-CApath directory] [-binary] [-certfile file]\n"
                   1115:            "    [-certsout file] [-cmsout] [-compress] [-content file]\n"
                   1116:            "    [-crlfeol] [-data_create] [-data_out] [-debug_decrypt]\n"
                   1117:            "    [-decrypt] [-digest_create] [-digest_verify]\n"
                   1118:            "    [-econtent_type type] [-encrypt] [-EncryptedData_decrypt]\n"
                   1119:            "    [-EncryptedData_encrypt] [-from addr] [-in file]\n"
                   1120:            "    [-inform der | pem | smime] [-inkey file]\n"
                   1121:            "    [-keyform der | pem] [-keyid] [-keyopt nm:v] [-md digest]\n"
                   1122:            "    [-no_attr_verify] [-no_content_verify]\n"
                   1123:            "    [-no_signer_cert_verify] [-noattr] [-nocerts] [-nodetach]\n"
                   1124:            "    [-nointern] [-nooldmime] [-noout] [-nosigs] [-nosmimecap]\n"
                   1125:            "    [-noverify] [-out file] [-outform der | pem | smime]\n"
                   1126:            "    [-passin src] [-print] [-pwri_password arg]\n"
                   1127:            "    [-rctform der | pem | smime]\n"
                   1128:            "    [-receipt_request_all | -receipt_request_first]\n"
                   1129:            "    [-receipt_request_from addr] [-receipt_request_print]\n"
                   1130:            "    [-receipt_request_to addr] [-recip file] [-resign]\n"
                   1131:            "    [-secretkey key] [-secretkeyid id] [-sign] [-sign_receipt]\n"
                   1132:            "    [-signer file] [-stream | -indef | -noindef] [-subject s]\n"
                   1133:            "    [-text] [-to addr] [-uncompress] [-verify]\n"
                   1134:            "    [-verify_receipt file] [-verify_retcode] [cert.pem ...]\n\n");
                   1135:
                   1136:        options_usage(cms_options);
                   1137:
                   1138:        fprintf(stderr, "\nVerification options:\n\n");
                   1139:        options_usage(verify_shared_options);
                   1140:
                   1141:        fprintf(stderr, "\nValid purposes:\n\n");
                   1142:        for (i = 0; i < X509_PURPOSE_get_count(); i++) {
                   1143:                X509_PURPOSE *ptmp = X509_PURPOSE_get0(i);
                   1144:                fprintf(stderr, "  %-18s%s\n", X509_PURPOSE_get0_sname(ptmp),
                   1145:                    X509_PURPOSE_get0_name(ptmp));
                   1146:        }
                   1147: }
                   1148:
1.1       jsing    1149: int
                   1150: cms_main(int argc, char **argv)
                   1151: {
                   1152:        int ret = 0;
                   1153:        char **args;
1.19      inoguchi 1154:        int argsused = 0;
1.1       jsing    1155:        const char *inmode = "r", *outmode = "w";
                   1156:        CMS_ContentInfo *cms = NULL, *rcms = NULL;
                   1157:        X509_STORE *store = NULL;
1.19      inoguchi 1158:        X509 *recip = NULL, *signer = NULL;
1.1       jsing    1159:        EVP_PKEY *key = NULL;
1.19      inoguchi 1160:        STACK_OF(X509) *other = NULL;
1.1       jsing    1161:        BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
                   1162:        int badarg = 0;
                   1163:        CMS_ReceiptRequest *rr = NULL;
1.19      inoguchi 1164:        char *passin = NULL;
                   1165:        unsigned char *pwri_tmp = NULL;
1.4       doug     1166:
1.31      joshua   1167:        if (pledge("stdio rpath wpath cpath tty", NULL) == -1) {
                   1168:                perror("pledge");
                   1169:                exit(1);
1.4       doug     1170:        }
1.1       jsing    1171:
1.33      tb       1172:        memset(&cfg, 0, sizeof(cfg));
                   1173:        cfg.flags = CMS_DETACHED;
                   1174:        cfg.rr_allorfirst = -1;
                   1175:        cfg.informat = FORMAT_SMIME;
                   1176:        cfg.outformat = FORMAT_SMIME;
                   1177:        cfg.rctformat = FORMAT_SMIME;
                   1178:        cfg.keyform = FORMAT_PEM;
1.19      inoguchi 1179:        if (options_parse(argc, argv, cms_options, NULL, &argsused) != 0) {
                   1180:                goto argerr;
                   1181:        }
                   1182:        args = argv + argsused;
1.1       jsing    1183:        ret = 1;
                   1184:
1.33      tb       1185:        if (((cfg.rr_allorfirst != -1) || cfg.rr_from != NULL) &&
                   1186:            cfg.rr_to == NULL) {
1.1       jsing    1187:                BIO_puts(bio_err, "No Signed Receipts Recipients\n");
                   1188:                goto argerr;
                   1189:        }
1.33      tb       1190:        if (!(cfg.operation & SMIME_SIGNERS) &&
                   1191:            (cfg.rr_to != NULL || cfg.rr_from != NULL)) {
1.1       jsing    1192:                BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
                   1193:                goto argerr;
                   1194:        }
1.33      tb       1195:        if (!(cfg.operation & SMIME_SIGNERS) &&
                   1196:            (cfg.skkeys != NULL || cfg.sksigners != NULL)) {
1.1       jsing    1197:                BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
                   1198:                goto argerr;
                   1199:        }
1.33      tb       1200:        if (cfg.operation & SMIME_SIGNERS) {
                   1201:                if (cfg.keyfile != NULL &&
                   1202:                    cfg.signerfile == NULL) {
1.1       jsing    1203:                        BIO_puts(bio_err, "Illegal -inkey without -signer\n");
                   1204:                        goto argerr;
                   1205:                }
                   1206:                /* Check to see if any final signer needs to be appended */
1.33      tb       1207:                if (cfg.signerfile != NULL) {
                   1208:                        if (cfg.sksigners == NULL &&
                   1209:                            (cfg.sksigners =
1.24      inoguchi 1210:                            sk_OPENSSL_STRING_new_null()) == NULL)
1.16      inoguchi 1211:                                goto end;
1.33      tb       1212:                        if (!sk_OPENSSL_STRING_push(cfg.sksigners,
                   1213:                            cfg.signerfile))
1.15      inoguchi 1214:                                goto end;
1.33      tb       1215:                        if (cfg.skkeys == NULL &&
                   1216:                            (cfg.skkeys =
1.24      inoguchi 1217:                            sk_OPENSSL_STRING_new_null()) == NULL)
1.16      inoguchi 1218:                                goto end;
1.33      tb       1219:                        if (cfg.keyfile == NULL)
                   1220:                                cfg.keyfile = cfg.signerfile;
                   1221:                        if (!sk_OPENSSL_STRING_push(cfg.skkeys,
                   1222:                            cfg.keyfile))
1.15      inoguchi 1223:                                goto end;
1.1       jsing    1224:                }
1.33      tb       1225:                if (cfg.sksigners == NULL) {
1.1       jsing    1226:                        BIO_printf(bio_err,
                   1227:                            "No signer certificate specified\n");
                   1228:                        badarg = 1;
                   1229:                }
1.33      tb       1230:                cfg.signerfile = NULL;
                   1231:                cfg.keyfile = NULL;
                   1232:        } else if (cfg.operation == SMIME_DECRYPT) {
                   1233:                if (cfg.recipfile == NULL &&
                   1234:                    cfg.keyfile == NULL &&
                   1235:                    cfg.secret_key == NULL &&
                   1236:                    cfg.pwri_pass == NULL) {
1.1       jsing    1237:                        BIO_printf(bio_err,
                   1238:                            "No recipient certificate or key specified\n");
                   1239:                        badarg = 1;
                   1240:                }
1.33      tb       1241:        } else if (cfg.operation == SMIME_ENCRYPT) {
                   1242:                if (*args == NULL && cfg.secret_key == NULL &&
                   1243:                    cfg.pwri_pass == NULL &&
                   1244:                    cfg.encerts == NULL) {
1.1       jsing    1245:                        BIO_printf(bio_err,
                   1246:                            "No recipient(s) certificate(s) specified\n");
                   1247:                        badarg = 1;
                   1248:                }
1.33      tb       1249:        } else if (!cfg.operation) {
1.1       jsing    1250:                badarg = 1;
1.24      inoguchi 1251:        }
1.1       jsing    1252:
                   1253:        if (badarg) {
1.13      jsing    1254:  argerr:
1.19      inoguchi 1255:                cms_usage();
1.1       jsing    1256:                goto end;
                   1257:        }
                   1258:
1.33      tb       1259:        if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) {
1.1       jsing    1260:                BIO_printf(bio_err, "Error getting password\n");
                   1261:                goto end;
                   1262:        }
                   1263:        ret = 2;
                   1264:
1.33      tb       1265:        if (!(cfg.operation & SMIME_SIGNERS))
                   1266:                cfg.flags &= ~CMS_DETACHED;
1.1       jsing    1267:
1.33      tb       1268:        if (cfg.operation & SMIME_OP) {
                   1269:                if (cfg.outformat == FORMAT_ASN1)
1.1       jsing    1270:                        outmode = "wb";
                   1271:        } else {
1.33      tb       1272:                if (cfg.flags & CMS_BINARY)
1.1       jsing    1273:                        outmode = "wb";
                   1274:        }
                   1275:
1.33      tb       1276:        if (cfg.operation & SMIME_IP) {
                   1277:                if (cfg.informat == FORMAT_ASN1)
1.1       jsing    1278:                        inmode = "rb";
                   1279:        } else {
1.33      tb       1280:                if (cfg.flags & CMS_BINARY)
1.1       jsing    1281:                        inmode = "rb";
                   1282:        }
                   1283:
1.33      tb       1284:        if (cfg.operation == SMIME_ENCRYPT) {
                   1285:                if (cfg.cipher == NULL) {
1.1       jsing    1286: #ifndef OPENSSL_NO_DES
1.33      tb       1287:                        cfg.cipher = EVP_des_ede3_cbc();
1.1       jsing    1288: #else
                   1289:                        BIO_printf(bio_err, "No cipher selected\n");
                   1290:                        goto end;
                   1291: #endif
                   1292:                }
1.33      tb       1293:                if (cfg.secret_key != NULL &&
                   1294:                    cfg.secret_keyid == NULL) {
1.1       jsing    1295:                        BIO_printf(bio_err, "No secret key id\n");
                   1296:                        goto end;
                   1297:                }
1.33      tb       1298:                if (*args != NULL && cfg.encerts == NULL)
                   1299:                        if ((cfg.encerts = sk_X509_new_null()) == NULL)
1.16      inoguchi 1300:                                goto end;
1.1       jsing    1301:                while (*args) {
1.33      tb       1302:                        if ((cfg.cert = load_cert(bio_err, *args,
1.24      inoguchi 1303:                            FORMAT_PEM, NULL,
                   1304:                            "recipient certificate file")) == NULL)
1.1       jsing    1305:                                goto end;
1.33      tb       1306:                        if (!sk_X509_push(cfg.encerts, cfg.cert))
1.15      inoguchi 1307:                                goto end;
1.33      tb       1308:                        cfg.cert = NULL;
1.1       jsing    1309:                        args++;
                   1310:                }
                   1311:        }
1.33      tb       1312:        if (cfg.certfile != NULL) {
                   1313:                if ((other = load_certs(bio_err, cfg.certfile,
1.24      inoguchi 1314:                    FORMAT_PEM, NULL, "certificate file")) == NULL) {
1.1       jsing    1315:                        ERR_print_errors(bio_err);
                   1316:                        goto end;
                   1317:                }
                   1318:        }
1.33      tb       1319:        if (cfg.recipfile != NULL &&
                   1320:            (cfg.operation == SMIME_DECRYPT)) {
                   1321:                if ((recip = load_cert(bio_err, cfg.recipfile,
1.24      inoguchi 1322:                    FORMAT_PEM, NULL, "recipient certificate file")) == NULL) {
1.1       jsing    1323:                        ERR_print_errors(bio_err);
                   1324:                        goto end;
                   1325:                }
                   1326:        }
1.33      tb       1327:        if (cfg.operation == SMIME_SIGN_RECEIPT) {
                   1328:                if ((signer = load_cert(bio_err, cfg.signerfile,
1.24      inoguchi 1329:                    FORMAT_PEM, NULL,
1.22      inoguchi 1330:                    "receipt signer certificate file")) == NULL) {
1.1       jsing    1331:                        ERR_print_errors(bio_err);
                   1332:                        goto end;
                   1333:                }
                   1334:        }
1.33      tb       1335:        if (cfg.operation == SMIME_DECRYPT) {
                   1336:                if (cfg.keyfile == NULL)
                   1337:                        cfg.keyfile = cfg.recipfile;
                   1338:        } else if ((cfg.operation == SMIME_SIGN) ||
                   1339:            (cfg.operation == SMIME_SIGN_RECEIPT)) {
                   1340:                if (cfg.keyfile == NULL)
                   1341:                        cfg.keyfile = cfg.signerfile;
1.24      inoguchi 1342:        } else {
1.33      tb       1343:                cfg.keyfile = NULL;
1.24      inoguchi 1344:        }
1.1       jsing    1345:
1.33      tb       1346:        if (cfg.keyfile != NULL) {
                   1347:                key = load_key(bio_err, cfg.keyfile, cfg.keyform,
1.24      inoguchi 1348:                    0, passin, "signing key file");
1.22      inoguchi 1349:                if (key == NULL)
1.1       jsing    1350:                        goto end;
                   1351:        }
1.33      tb       1352:        if (cfg.infile != NULL) {
                   1353:                if ((in = BIO_new_file(cfg.infile, inmode)) == NULL) {
1.1       jsing    1354:                        BIO_printf(bio_err,
1.33      tb       1355:                            "Can't open input file %s\n", cfg.infile);
1.1       jsing    1356:                        goto end;
                   1357:                }
1.24      inoguchi 1358:        } else {
1.23      inoguchi 1359:                if ((in = BIO_new_fp(stdin, BIO_NOCLOSE)) == NULL)
                   1360:                        goto end;
1.24      inoguchi 1361:        }
1.1       jsing    1362:
1.33      tb       1363:        if (cfg.operation & SMIME_IP) {
                   1364:                if (cfg.informat == FORMAT_SMIME)
1.1       jsing    1365:                        cms = SMIME_read_CMS(in, &indata);
1.33      tb       1366:                else if (cfg.informat == FORMAT_PEM)
1.1       jsing    1367:                        cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
1.33      tb       1368:                else if (cfg.informat == FORMAT_ASN1)
1.1       jsing    1369:                        cms = d2i_CMS_bio(in, NULL);
                   1370:                else {
                   1371:                        BIO_printf(bio_err, "Bad input format for CMS file\n");
                   1372:                        goto end;
                   1373:                }
                   1374:
1.22      inoguchi 1375:                if (cms == NULL) {
1.1       jsing    1376:                        BIO_printf(bio_err, "Error reading S/MIME message\n");
                   1377:                        goto end;
                   1378:                }
1.33      tb       1379:                if (cfg.contfile != NULL) {
1.1       jsing    1380:                        BIO_free(indata);
1.33      tb       1381:                        if ((indata = BIO_new_file(cfg.contfile,
1.24      inoguchi 1382:                            "rb")) == NULL) {
1.1       jsing    1383:                                BIO_printf(bio_err,
1.24      inoguchi 1384:                                    "Can't read content file %s\n",
1.33      tb       1385:                                    cfg.contfile);
1.1       jsing    1386:                                goto end;
                   1387:                        }
                   1388:                }
1.33      tb       1389:                if (cfg.certsoutfile != NULL) {
1.12      jsing    1390:                        STACK_OF(X509) *allcerts;
1.17      inoguchi 1391:                        if ((allcerts = CMS_get1_certs(cms)) == NULL)
                   1392:                                goto end;
1.33      tb       1393:                        if (!save_certs(cfg.certsoutfile, allcerts)) {
1.1       jsing    1394:                                BIO_printf(bio_err,
                   1395:                                    "Error writing certs to %s\n",
1.33      tb       1396:                                    cfg.certsoutfile);
1.29      inoguchi 1397:                                sk_X509_pop_free(allcerts, X509_free);
1.1       jsing    1398:                                ret = 5;
                   1399:                                goto end;
                   1400:                        }
                   1401:                        sk_X509_pop_free(allcerts, X509_free);
                   1402:                }
                   1403:        }
1.33      tb       1404:        if (cfg.rctfile != NULL) {
                   1405:                char *rctmode = (cfg.rctformat == FORMAT_ASN1) ?
1.24      inoguchi 1406:                    "rb" : "r";
1.33      tb       1407:                if ((rctin = BIO_new_file(cfg.rctfile, rctmode)) == NULL) {
1.1       jsing    1408:                        BIO_printf(bio_err,
1.33      tb       1409:                            "Can't open receipt file %s\n", cfg.rctfile);
1.1       jsing    1410:                        goto end;
                   1411:                }
1.33      tb       1412:                if (cfg.rctformat == FORMAT_SMIME)
1.1       jsing    1413:                        rcms = SMIME_read_CMS(rctin, NULL);
1.33      tb       1414:                else if (cfg.rctformat == FORMAT_PEM)
1.1       jsing    1415:                        rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
1.33      tb       1416:                else if (cfg.rctformat == FORMAT_ASN1)
1.1       jsing    1417:                        rcms = d2i_CMS_bio(rctin, NULL);
                   1418:                else {
                   1419:                        BIO_printf(bio_err, "Bad input format for receipt\n");
                   1420:                        goto end;
                   1421:                }
                   1422:
1.22      inoguchi 1423:                if (rcms == NULL) {
1.1       jsing    1424:                        BIO_printf(bio_err, "Error reading receipt\n");
                   1425:                        goto end;
                   1426:                }
                   1427:        }
1.33      tb       1428:        if (cfg.outfile != NULL) {
                   1429:                if ((out = BIO_new_file(cfg.outfile, outmode)) == NULL) {
1.1       jsing    1430:                        BIO_printf(bio_err,
1.33      tb       1431:                            "Can't open output file %s\n", cfg.outfile);
1.1       jsing    1432:                        goto end;
                   1433:                }
                   1434:        } else {
1.23      inoguchi 1435:                if ((out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
                   1436:                        goto end;
1.1       jsing    1437:        }
                   1438:
1.33      tb       1439:        if ((cfg.operation == SMIME_VERIFY) ||
                   1440:            (cfg.operation == SMIME_VERIFY_RECEIPT)) {
                   1441:                if ((store = setup_verify(bio_err, cfg.CAfile,
                   1442:                    cfg.CApath)) == NULL)
1.1       jsing    1443:                        goto end;
1.33      tb       1444:                if (cfg.vpm != NULL) {
                   1445:                        if (!X509_STORE_set1_param(store, cfg.vpm))
1.23      inoguchi 1446:                                goto end;
                   1447:                }
1.1       jsing    1448:        }
                   1449:        ret = 3;
                   1450:
1.33      tb       1451:        if (cfg.operation == SMIME_DATA_CREATE) {
                   1452:                cms = CMS_data_create(in, cfg.flags);
                   1453:        } else if (cfg.operation == SMIME_DIGEST_CREATE) {
                   1454:                cms = CMS_digest_create(in, cfg.sign_md,
                   1455:                    cfg.flags);
                   1456:        } else if (cfg.operation == SMIME_COMPRESS) {
                   1457:                cms = CMS_compress(in, -1, cfg.flags);
                   1458:        } else if (cfg.operation == SMIME_ENCRYPT) {
1.14      inoguchi 1459:                int i;
1.33      tb       1460:                cfg.flags |= CMS_PARTIAL;
                   1461:                cms = CMS_encrypt(NULL, in, cfg.cipher,
                   1462:                    cfg.flags);
1.14      inoguchi 1463:                if (cms == NULL)
1.1       jsing    1464:                        goto end;
1.33      tb       1465:                for (i = 0; i < sk_X509_num(cfg.encerts); i++) {
1.14      inoguchi 1466:                        CMS_RecipientInfo *ri;
1.15      inoguchi 1467:                        struct cms_key_param *kparam;
1.33      tb       1468:                        int tflags = cfg.flags;
1.23      inoguchi 1469:                        X509 *x;
1.32      tb       1470:
1.33      tb       1471:                        if ((x = sk_X509_value(cfg.encerts, i)) == NULL)
1.23      inoguchi 1472:                                goto end;
1.33      tb       1473:                        for (kparam = cfg.key_first; kparam != NULL;
1.24      inoguchi 1474:                            kparam = kparam->next) {
1.14      inoguchi 1475:                                if (kparam->idx == i) {
                   1476:                                        tflags |= CMS_KEY_PARAM;
                   1477:                                        break;
                   1478:                                }
                   1479:                        }
                   1480:                        ri = CMS_add1_recipient_cert(cms, x, tflags);
                   1481:                        if (ri == NULL)
                   1482:                                goto end;
                   1483:                        if (kparam != NULL) {
                   1484:                                EVP_PKEY_CTX *pctx;
1.24      inoguchi 1485:                                if ((pctx = CMS_RecipientInfo_get0_pkey_ctx(
                   1486:                                    ri)) == NULL)
1.17      inoguchi 1487:                                        goto end;
1.14      inoguchi 1488:                                if (!cms_set_pkey_param(pctx, kparam->param))
                   1489:                                        goto end;
                   1490:                        }
                   1491:                }
                   1492:
1.33      tb       1493:                if (cfg.secret_key != NULL) {
1.24      inoguchi 1494:                        if (CMS_add0_recipient_key(cms, NID_undef,
1.33      tb       1495:                            cfg.secret_key, cfg.secret_keylen,
                   1496:                            cfg.secret_keyid, cfg.secret_keyidlen,
1.22      inoguchi 1497:                            NULL, NULL, NULL) == NULL)
1.1       jsing    1498:                                goto end;
                   1499:                        /* NULL these because call absorbs them */
1.33      tb       1500:                        cfg.secret_key = NULL;
                   1501:                        cfg.secret_keyid = NULL;
1.1       jsing    1502:                }
1.33      tb       1503:                if (cfg.pwri_pass != NULL) {
                   1504:                        pwri_tmp = strdup(cfg.pwri_pass);
1.22      inoguchi 1505:                        if (pwri_tmp == NULL)
1.1       jsing    1506:                                goto end;
1.22      inoguchi 1507:                        if (CMS_add0_recipient_password(cms, -1, NID_undef,
                   1508:                            NID_undef, pwri_tmp, -1, NULL) == NULL)
1.1       jsing    1509:                                goto end;
                   1510:                        pwri_tmp = NULL;
                   1511:                }
1.33      tb       1512:                if (!(cfg.flags & CMS_STREAM)) {
                   1513:                        if (!CMS_final(cms, in, NULL, cfg.flags))
1.1       jsing    1514:                                goto end;
                   1515:                }
1.33      tb       1516:        } else if (cfg.operation == SMIME_ENCRYPTED_ENCRYPT) {
                   1517:                cms = CMS_EncryptedData_encrypt(in, cfg.cipher,
                   1518:                    cfg.secret_key, cfg.secret_keylen,
                   1519:                    cfg.flags);
1.1       jsing    1520:
1.33      tb       1521:        } else if (cfg.operation == SMIME_SIGN_RECEIPT) {
1.1       jsing    1522:                CMS_ContentInfo *srcms = NULL;
1.12      jsing    1523:                STACK_OF(CMS_SignerInfo) *sis;
1.1       jsing    1524:                CMS_SignerInfo *si;
                   1525:                sis = CMS_get0_SignerInfos(cms);
1.22      inoguchi 1526:                if (sis == NULL)
1.1       jsing    1527:                        goto end;
                   1528:                si = sk_CMS_SignerInfo_value(sis, 0);
1.23      inoguchi 1529:                if (si == NULL)
                   1530:                        goto end;
1.24      inoguchi 1531:                srcms = CMS_sign_receipt(si, signer, key, other,
1.33      tb       1532:                    cfg.flags);
1.22      inoguchi 1533:                if (srcms == NULL)
1.1       jsing    1534:                        goto end;
                   1535:                CMS_ContentInfo_free(cms);
                   1536:                cms = srcms;
1.33      tb       1537:        } else if (cfg.operation & SMIME_SIGNERS) {
1.1       jsing    1538:                int i;
                   1539:                /*
                   1540:                 * If detached data content we enable streaming if S/MIME
                   1541:                 * output format.
                   1542:                 */
1.33      tb       1543:                if (cfg.operation == SMIME_SIGN) {
1.1       jsing    1544:
1.33      tb       1545:                        if (cfg.flags & CMS_DETACHED) {
                   1546:                                if (cfg.outformat == FORMAT_SMIME)
                   1547:                                        cfg.flags |= CMS_STREAM;
1.1       jsing    1548:                        }
1.33      tb       1549:                        cfg.flags |= CMS_PARTIAL;
                   1550:                        cms = CMS_sign(NULL, NULL, other, in, cfg.flags);
1.22      inoguchi 1551:                        if (cms == NULL)
1.1       jsing    1552:                                goto end;
1.33      tb       1553:                        if (cfg.econtent_type != NULL)
1.24      inoguchi 1554:                                if (!CMS_set1_eContentType(cms,
1.33      tb       1555:                                    cfg.econtent_type))
1.17      inoguchi 1556:                                        goto end;
1.1       jsing    1557:
1.33      tb       1558:                        if (cfg.rr_to != NULL) {
                   1559:                                rr = make_receipt_request(cfg.rr_to,
                   1560:                                    cfg.rr_allorfirst,
                   1561:                                    cfg.rr_from);
1.22      inoguchi 1562:                                if (rr == NULL) {
1.1       jsing    1563:                                        BIO_puts(bio_err,
                   1564:                                            "Signed Receipt Request Creation Error\n");
                   1565:                                        goto end;
                   1566:                                }
                   1567:                        }
1.24      inoguchi 1568:                } else {
1.33      tb       1569:                        cfg.flags |= CMS_REUSE_DIGEST;
1.24      inoguchi 1570:                }
                   1571:
1.33      tb       1572:                for (i = 0; i < sk_OPENSSL_STRING_num(cfg.sksigners); i++) {
1.1       jsing    1573:                        CMS_SignerInfo *si;
1.15      inoguchi 1574:                        struct cms_key_param *kparam;
1.33      tb       1575:                        int tflags = cfg.flags;
1.14      inoguchi 1576:
1.33      tb       1577:                        cfg.signerfile = sk_OPENSSL_STRING_value(
                   1578:                            cfg.sksigners, i);
                   1579:                        cfg.keyfile = sk_OPENSSL_STRING_value(
                   1580:                            cfg.skkeys, i);
1.24      inoguchi 1581:
1.33      tb       1582:                        signer = load_cert(bio_err, cfg.signerfile,
1.24      inoguchi 1583:                            FORMAT_PEM, NULL, "signer certificate");
1.22      inoguchi 1584:                        if (signer == NULL)
1.1       jsing    1585:                                goto end;
1.33      tb       1586:                        key = load_key(bio_err, cfg.keyfile,
                   1587:                            cfg.keyform, 0, passin, "signing key file");
1.22      inoguchi 1588:                        if (key == NULL)
1.1       jsing    1589:                                goto end;
1.33      tb       1590:                        for (kparam = cfg.key_first; kparam != NULL;
1.24      inoguchi 1591:                            kparam = kparam->next) {
1.14      inoguchi 1592:                                if (kparam->idx == i) {
                   1593:                                        tflags |= CMS_KEY_PARAM;
                   1594:                                        break;
                   1595:                                }
                   1596:                        }
1.24      inoguchi 1597:                        si = CMS_add1_signer(cms, signer, key,
1.33      tb       1598:                            cfg.sign_md, tflags);
1.14      inoguchi 1599:                        if (si == NULL)
1.1       jsing    1600:                                goto end;
1.14      inoguchi 1601:                        if (kparam != NULL) {
                   1602:                                EVP_PKEY_CTX *pctx;
1.24      inoguchi 1603:                                if ((pctx = CMS_SignerInfo_get0_pkey_ctx(
                   1604:                                    si)) == NULL)
1.17      inoguchi 1605:                                        goto end;
1.14      inoguchi 1606:                                if (!cms_set_pkey_param(pctx, kparam->param))
                   1607:                                        goto end;
                   1608:                        }
1.22      inoguchi 1609:                        if (rr != NULL && !CMS_add1_ReceiptRequest(si, rr))
1.1       jsing    1610:                                goto end;
                   1611:                        X509_free(signer);
                   1612:                        signer = NULL;
                   1613:                        EVP_PKEY_free(key);
                   1614:                        key = NULL;
                   1615:                }
                   1616:                /* If not streaming or resigning finalize structure */
1.33      tb       1617:                if ((cfg.operation == SMIME_SIGN) &&
                   1618:                    !(cfg.flags & CMS_STREAM)) {
                   1619:                        if (!CMS_final(cms, in, NULL, cfg.flags))
1.1       jsing    1620:                                goto end;
                   1621:                }
                   1622:        }
1.22      inoguchi 1623:        if (cms == NULL) {
1.1       jsing    1624:                BIO_printf(bio_err, "Error creating CMS structure\n");
                   1625:                goto end;
                   1626:        }
                   1627:        ret = 4;
1.33      tb       1628:        if (cfg.operation == SMIME_DECRYPT) {
                   1629:                if (cfg.flags & CMS_DEBUG_DECRYPT)
1.24      inoguchi 1630:                        CMS_decrypt(cms, NULL, NULL, NULL, NULL,
1.33      tb       1631:                            cfg.flags);
1.19      inoguchi 1632:
1.33      tb       1633:                if (cfg.secret_key != NULL) {
                   1634:                        if (!CMS_decrypt_set1_key(cms, cfg.secret_key,
                   1635:                            cfg.secret_keylen, cfg.secret_keyid,
                   1636:                            cfg.secret_keyidlen)) {
1.1       jsing    1637:                                BIO_puts(bio_err,
                   1638:                                    "Error decrypting CMS using secret key\n");
                   1639:                                goto end;
                   1640:                        }
                   1641:                }
1.22      inoguchi 1642:                if (key != NULL) {
1.1       jsing    1643:                        if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
                   1644:                                BIO_puts(bio_err,
                   1645:                                    "Error decrypting CMS using private key\n");
                   1646:                                goto end;
                   1647:                        }
                   1648:                }
1.33      tb       1649:                if (cfg.pwri_pass != NULL) {
1.24      inoguchi 1650:                        if (!CMS_decrypt_set1_password(cms,
1.33      tb       1651:                            cfg.pwri_pass, -1)) {
1.1       jsing    1652:                                BIO_puts(bio_err,
                   1653:                                    "Error decrypting CMS using password\n");
                   1654:                                goto end;
                   1655:                        }
                   1656:                }
1.24      inoguchi 1657:                if (!CMS_decrypt(cms, NULL, NULL, indata, out,
1.33      tb       1658:                    cfg.flags)) {
1.1       jsing    1659:                        BIO_printf(bio_err, "Error decrypting CMS structure\n");
                   1660:                        goto end;
                   1661:                }
1.33      tb       1662:        } else if (cfg.operation == SMIME_DATAOUT) {
                   1663:                if (!CMS_data(cms, out, cfg.flags))
1.1       jsing    1664:                        goto end;
1.33      tb       1665:        } else if (cfg.operation == SMIME_UNCOMPRESS) {
                   1666:                if (!CMS_uncompress(cms, indata, out, cfg.flags))
1.1       jsing    1667:                        goto end;
1.33      tb       1668:        } else if (cfg.operation == SMIME_DIGEST_VERIFY) {
                   1669:                if (CMS_digest_verify(cms, indata, out, cfg.flags) > 0)
1.1       jsing    1670:                        BIO_printf(bio_err, "Verification successful\n");
                   1671:                else {
                   1672:                        BIO_printf(bio_err, "Verification failure\n");
                   1673:                        goto end;
                   1674:                }
1.33      tb       1675:        } else if (cfg.operation == SMIME_ENCRYPTED_DECRYPT) {
                   1676:                if (!CMS_EncryptedData_decrypt(cms, cfg.secret_key,
                   1677:                    cfg.secret_keylen, indata, out, cfg.flags))
1.1       jsing    1678:                        goto end;
1.33      tb       1679:        } else if (cfg.operation == SMIME_VERIFY) {
1.24      inoguchi 1680:                if (CMS_verify(cms, other, store, indata, out,
1.33      tb       1681:                    cfg.flags) > 0) {
1.1       jsing    1682:                        BIO_printf(bio_err, "Verification successful\n");
1.24      inoguchi 1683:                } else {
1.1       jsing    1684:                        BIO_printf(bio_err, "Verification failure\n");
1.33      tb       1685:                        if (cfg.verify_retcode)
1.1       jsing    1686:                                ret = verify_err + 32;
                   1687:                        goto end;
                   1688:                }
1.33      tb       1689:                if (cfg.signerfile != NULL) {
1.12      jsing    1690:                        STACK_OF(X509) *signers;
1.17      inoguchi 1691:                        if ((signers = CMS_get0_signers(cms)) == NULL)
                   1692:                                goto end;
1.33      tb       1693:                        if (!save_certs(cfg.signerfile, signers)) {
1.1       jsing    1694:                                BIO_printf(bio_err,
                   1695:                                    "Error writing signers to %s\n",
1.33      tb       1696:                                    cfg.signerfile);
1.29      inoguchi 1697:                                sk_X509_free(signers);
1.1       jsing    1698:                                ret = 5;
                   1699:                                goto end;
                   1700:                        }
                   1701:                        sk_X509_free(signers);
                   1702:                }
1.33      tb       1703:                if (cfg.rr_print)
1.1       jsing    1704:                        receipt_request_print(bio_err, cms);
                   1705:
1.33      tb       1706:        } else if (cfg.operation == SMIME_VERIFY_RECEIPT) {
1.24      inoguchi 1707:                if (CMS_verify_receipt(rcms, cms, other, store,
1.33      tb       1708:                    cfg.flags) > 0) {
1.1       jsing    1709:                        BIO_printf(bio_err, "Verification successful\n");
1.24      inoguchi 1710:                } else {
1.1       jsing    1711:                        BIO_printf(bio_err, "Verification failure\n");
                   1712:                        goto end;
                   1713:                }
                   1714:        } else {
1.33      tb       1715:                if (cfg.noout) {
                   1716:                        if (cfg.print &&
1.17      inoguchi 1717:                            !CMS_ContentInfo_print_ctx(out, cms, 0, NULL))
                   1718:                                goto end;
1.33      tb       1719:                } else if (cfg.outformat == FORMAT_SMIME) {
                   1720:                        if (cfg.to != NULL)
                   1721:                                BIO_printf(out, "To: %s\n", cfg.to);
                   1722:                        if (cfg.from != NULL)
                   1723:                                BIO_printf(out, "From: %s\n", cfg.from);
                   1724:                        if (cfg.subject != NULL)
1.24      inoguchi 1725:                                BIO_printf(out, "Subject: %s\n",
1.33      tb       1726:                                    cfg.subject);
                   1727:                        if (cfg.operation == SMIME_RESIGN)
1.24      inoguchi 1728:                                ret = SMIME_write_CMS(out, cms, indata,
1.33      tb       1729:                                    cfg.flags);
1.1       jsing    1730:                        else
1.24      inoguchi 1731:                                ret = SMIME_write_CMS(out, cms, in,
1.33      tb       1732:                                    cfg.flags);
                   1733:                } else if (cfg.outformat == FORMAT_PEM) {
1.24      inoguchi 1734:                        ret = PEM_write_bio_CMS_stream(out, cms, in,
1.33      tb       1735:                            cfg.flags);
                   1736:                } else if (cfg.outformat == FORMAT_ASN1) {
                   1737:                        ret = i2d_CMS_bio_stream(out, cms, in, cfg.flags);
1.24      inoguchi 1738:                } else {
1.1       jsing    1739:                        BIO_printf(bio_err, "Bad output format for CMS file\n");
                   1740:                        goto end;
                   1741:                }
                   1742:                if (ret <= 0) {
                   1743:                        ret = 6;
                   1744:                        goto end;
                   1745:                }
                   1746:        }
                   1747:        ret = 0;
                   1748:
1.13      jsing    1749:  end:
1.1       jsing    1750:        if (ret)
                   1751:                ERR_print_errors(bio_err);
1.11      jsing    1752:
1.33      tb       1753:        sk_X509_pop_free(cfg.encerts, X509_free);
1.1       jsing    1754:        sk_X509_pop_free(other, X509_free);
1.33      tb       1755:        X509_VERIFY_PARAM_free(cfg.vpm);
                   1756:        sk_OPENSSL_STRING_free(cfg.sksigners);
                   1757:        sk_OPENSSL_STRING_free(cfg.skkeys);
                   1758:        free(cfg.secret_key);
                   1759:        free(cfg.secret_keyid);
1.1       jsing    1760:        free(pwri_tmp);
1.33      tb       1761:        ASN1_OBJECT_free(cfg.econtent_type);
1.11      jsing    1762:        CMS_ReceiptRequest_free(rr);
1.33      tb       1763:        sk_OPENSSL_STRING_free(cfg.rr_to);
                   1764:        sk_OPENSSL_STRING_free(cfg.rr_from);
                   1765:        for (cfg.key_param = cfg.key_first; cfg.key_param;) {
1.15      inoguchi 1766:                struct cms_key_param *tparam;
1.33      tb       1767:                sk_OPENSSL_STRING_free(cfg.key_param->param);
                   1768:                tparam = cfg.key_param->next;
                   1769:                free(cfg.key_param);
                   1770:                cfg.key_param = tparam;
1.14      inoguchi 1771:        }
1.1       jsing    1772:        X509_STORE_free(store);
1.33      tb       1773:        X509_free(cfg.cert);
1.1       jsing    1774:        X509_free(recip);
                   1775:        X509_free(signer);
                   1776:        EVP_PKEY_free(key);
                   1777:        CMS_ContentInfo_free(cms);
                   1778:        CMS_ContentInfo_free(rcms);
                   1779:        BIO_free(rctin);
                   1780:        BIO_free(in);
                   1781:        BIO_free(indata);
                   1782:        BIO_free_all(out);
                   1783:        free(passin);
1.11      jsing    1784:
1.1       jsing    1785:        return (ret);
                   1786: }
                   1787:
                   1788: static int
1.12      jsing    1789: save_certs(char *signerfile, STACK_OF(X509) *signers)
1.1       jsing    1790: {
                   1791:        int i;
                   1792:        BIO *tmp;
                   1793:
1.22      inoguchi 1794:        if (signerfile == NULL)
1.1       jsing    1795:                return 1;
                   1796:        tmp = BIO_new_file(signerfile, "w");
1.22      inoguchi 1797:        if (tmp == NULL)
1.1       jsing    1798:                return 0;
                   1799:        for (i = 0; i < sk_X509_num(signers); i++)
                   1800:                PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
                   1801:        BIO_free(tmp);
                   1802:        return 1;
                   1803: }
                   1804:
                   1805: static void
1.12      jsing    1806: gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns)
1.1       jsing    1807: {
1.12      jsing    1808:        STACK_OF(GENERAL_NAME) *gens;
1.1       jsing    1809:        GENERAL_NAME *gen;
                   1810:        int i, j;
                   1811:
                   1812:        for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) {
                   1813:                gens = sk_GENERAL_NAMES_value(gns, i);
                   1814:                for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) {
                   1815:                        gen = sk_GENERAL_NAME_value(gens, j);
                   1816:                        BIO_puts(out, "    ");
                   1817:                        GENERAL_NAME_print(out, gen);
                   1818:                        BIO_puts(out, "\n");
                   1819:                }
                   1820:        }
                   1821:        return;
                   1822: }
                   1823:
                   1824: static void
1.12      jsing    1825: receipt_request_print(BIO *out, CMS_ContentInfo *cms)
1.1       jsing    1826: {
1.12      jsing    1827:        STACK_OF(CMS_SignerInfo) *sis;
1.1       jsing    1828:        CMS_SignerInfo *si;
                   1829:        CMS_ReceiptRequest *rr;
                   1830:        int allorfirst;
1.12      jsing    1831:        STACK_OF(GENERAL_NAMES) *rto, *rlist;
1.1       jsing    1832:        ASN1_STRING *scid;
                   1833:        int i, rv;
                   1834:
1.17      inoguchi 1835:        if ((sis = CMS_get0_SignerInfos(cms)) == NULL)
                   1836:                return;
1.1       jsing    1837:        for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) {
1.23      inoguchi 1838:                if ((si = sk_CMS_SignerInfo_value(sis, i)) == NULL)
                   1839:                        return;
1.1       jsing    1840:                rv = CMS_get1_ReceiptRequest(si, &rr);
                   1841:                BIO_printf(bio_err, "Signer %d:\n", i + 1);
1.24      inoguchi 1842:                if (rv == 0) {
1.1       jsing    1843:                        BIO_puts(bio_err, "  No Receipt Request\n");
1.24      inoguchi 1844:                } else if (rv < 0) {
1.1       jsing    1845:                        BIO_puts(bio_err, "  Receipt Request Parse Error\n");
                   1846:                        ERR_print_errors(bio_err);
                   1847:                } else {
                   1848:                        char *id;
                   1849:                        int idlen;
1.24      inoguchi 1850:
1.1       jsing    1851:                        CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
                   1852:                            &rlist, &rto);
                   1853:                        BIO_puts(out, "  Signed Content ID:\n");
                   1854:                        idlen = ASN1_STRING_length(scid);
                   1855:                        id = (char *) ASN1_STRING_data(scid);
                   1856:                        BIO_dump_indent(out, id, idlen, 4);
                   1857:                        BIO_puts(out, "  Receipts From");
1.22      inoguchi 1858:                        if (rlist != NULL) {
1.1       jsing    1859:                                BIO_puts(out, " List:\n");
                   1860:                                gnames_stack_print(out, rlist);
1.24      inoguchi 1861:                        } else if (allorfirst == 1) {
1.1       jsing    1862:                                BIO_puts(out, ": First Tier\n");
1.24      inoguchi 1863:                        } else if (allorfirst == 0) {
1.1       jsing    1864:                                BIO_puts(out, ": All\n");
1.24      inoguchi 1865:                        } else {
1.1       jsing    1866:                                BIO_printf(out, " Unknown (%d)\n", allorfirst);
1.24      inoguchi 1867:                        }
1.1       jsing    1868:                        BIO_puts(out, "  Receipts To:\n");
                   1869:                        gnames_stack_print(out, rto);
                   1870:                }
1.25      inoguchi 1871:                CMS_ReceiptRequest_free(rr);
1.1       jsing    1872:        }
                   1873: }
                   1874:
                   1875: static STACK_OF(GENERAL_NAMES) *
1.12      jsing    1876: make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
1.1       jsing    1877: {
                   1878:        int i;
1.12      jsing    1879:        STACK_OF(GENERAL_NAMES) *ret;
1.1       jsing    1880:        GENERAL_NAMES *gens = NULL;
                   1881:        GENERAL_NAME *gen = NULL;
1.22      inoguchi 1882:
1.16      inoguchi 1883:        if ((ret = sk_GENERAL_NAMES_new_null()) == NULL)
1.1       jsing    1884:                goto err;
                   1885:        for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) {
                   1886:                char *str = sk_OPENSSL_STRING_value(ns, i);
                   1887:                gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0);
1.22      inoguchi 1888:                if (gen == NULL)
1.1       jsing    1889:                        goto err;
                   1890:                gens = GENERAL_NAMES_new();
1.22      inoguchi 1891:                if (gens == NULL)
1.1       jsing    1892:                        goto err;
                   1893:                if (!sk_GENERAL_NAME_push(gens, gen))
                   1894:                        goto err;
                   1895:                gen = NULL;
                   1896:                if (!sk_GENERAL_NAMES_push(ret, gens))
                   1897:                        goto err;
                   1898:                gens = NULL;
                   1899:        }
                   1900:
                   1901:        return ret;
                   1902:
1.13      jsing    1903:  err:
1.11      jsing    1904:        sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free);
                   1905:        GENERAL_NAMES_free(gens);
                   1906:        GENERAL_NAME_free(gen);
                   1907:
1.1       jsing    1908:        return NULL;
                   1909: }
                   1910:
                   1911:
                   1912: static CMS_ReceiptRequest *
1.12      jsing    1913: make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
                   1914:     STACK_OF(OPENSSL_STRING) *rr_from)
1.1       jsing    1915: {
1.26      inoguchi 1916:        STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL;
1.1       jsing    1917:        CMS_ReceiptRequest *rr;
                   1918:
                   1919:        rct_to = make_names_stack(rr_to);
1.22      inoguchi 1920:        if (rct_to == NULL)
1.1       jsing    1921:                goto err;
1.22      inoguchi 1922:        if (rr_from != NULL) {
1.1       jsing    1923:                rct_from = make_names_stack(rr_from);
1.22      inoguchi 1924:                if (rct_from == NULL)
1.1       jsing    1925:                        goto err;
1.24      inoguchi 1926:        } else {
1.1       jsing    1927:                rct_from = NULL;
1.24      inoguchi 1928:        }
1.17      inoguchi 1929:
                   1930:        if ((rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
                   1931:            rct_to)) == NULL)
                   1932:                goto err;
                   1933:
1.1       jsing    1934:        return rr;
                   1935:
1.13      jsing    1936:  err:
1.26      inoguchi 1937:        sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);
                   1938:        sk_GENERAL_NAMES_pop_free(rct_from, GENERAL_NAMES_free);
1.1       jsing    1939:        return NULL;
1.14      inoguchi 1940: }
                   1941:
                   1942: static int
                   1943: cms_set_pkey_param(EVP_PKEY_CTX *pctx, STACK_OF(OPENSSL_STRING) *param)
                   1944: {
                   1945:        char *keyopt;
                   1946:        int i;
1.15      inoguchi 1947:
1.14      inoguchi 1948:        if (sk_OPENSSL_STRING_num(param) <= 0)
                   1949:                return 1;
                   1950:        for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) {
                   1951:                keyopt = sk_OPENSSL_STRING_value(param, i);
                   1952:                if (pkey_ctrl_string(pctx, keyopt) <= 0) {
                   1953:                        BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt);
                   1954:                        ERR_print_errors(bio_err);
                   1955:                        return 0;
                   1956:                }
                   1957:        }
                   1958:        return 1;
1.1       jsing    1959: }
                   1960:
                   1961: #endif