[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.21

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