1 /* 2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <time.h> 14 #include "apps.h" 15 #include "progs.h" 16 #include <openssl/err.h> 17 #include <openssl/objects.h> 18 #include <openssl/evp.h> 19 #include <openssl/x509.h> 20 #include <openssl/pkcs7.h> 21 #include <openssl/pem.h> 22 23 typedef enum OPTION_choice { 24 OPT_COMMON, 25 OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT, 26 OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE, 27 OPT_PROV_ENUM 28 } OPTION_CHOICE; 29 30 const OPTIONS pkcs7_options[] = { 31 OPT_SECTION("General"), 32 {"help", OPT_HELP, '-', "Display this summary"}, 33 #ifndef OPENSSL_NO_ENGINE 34 {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 35 #endif 36 37 OPT_SECTION("Input"), 38 {"in", OPT_IN, '<', "Input file"}, 39 {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, 40 41 OPT_SECTION("Output"), 42 {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, 43 {"out", OPT_OUT, '>', "Output file"}, 44 {"noout", OPT_NOOUT, '-', "Don't output encoded data"}, 45 {"text", OPT_TEXT, '-', "Print full details of certificates"}, 46 {"print", OPT_PRINT, '-', "Print out all fields of the PKCS7 structure"}, 47 {"print_certs", OPT_PRINT_CERTS, '-', 48 "Print_certs print any certs or crl in the input"}, 49 50 OPT_PROV_OPTIONS, 51 {NULL} 52 }; 53 54 int pkcs7_main(int argc, char **argv) 55 { 56 ENGINE *e = NULL; 57 PKCS7 *p7 = NULL, *p7i; 58 BIO *in = NULL, *out = NULL; 59 int informat = FORMAT_PEM, outformat = FORMAT_PEM; 60 char *infile = NULL, *outfile = NULL, *prog; 61 int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1; 62 OPTION_CHOICE o; 63 OSSL_LIB_CTX *libctx = app_get0_libctx(); 64 65 prog = opt_init(argc, argv, pkcs7_options); 66 while ((o = opt_next()) != OPT_EOF) { 67 switch (o) { 68 case OPT_EOF: 69 case OPT_ERR: 70 opthelp: 71 BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 72 goto end; 73 case OPT_HELP: 74 opt_help(pkcs7_options); 75 ret = 0; 76 goto end; 77 case OPT_INFORM: 78 if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 79 goto opthelp; 80 break; 81 case OPT_OUTFORM: 82 if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) 83 goto opthelp; 84 break; 85 case OPT_IN: 86 infile = opt_arg(); 87 break; 88 case OPT_OUT: 89 outfile = opt_arg(); 90 break; 91 case OPT_NOOUT: 92 noout = 1; 93 break; 94 case OPT_TEXT: 95 text = 1; 96 break; 97 case OPT_PRINT: 98 p7_print = 1; 99 break; 100 case OPT_PRINT_CERTS: 101 print_certs = 1; 102 break; 103 case OPT_ENGINE: 104 e = setup_engine(opt_arg(), 0); 105 break; 106 case OPT_PROV_CASES: 107 if (!opt_provider(o)) 108 goto end; 109 break; 110 } 111 } 112 113 /* No extra arguments. */ 114 argc = opt_num_rest(); 115 if (argc != 0) 116 goto opthelp; 117 118 in = bio_open_default(infile, 'r', informat); 119 if (in == NULL) 120 goto end; 121 122 p7 = PKCS7_new_ex(libctx, app_get0_propq()); 123 if (p7 == NULL) { 124 BIO_printf(bio_err, "unable to allocate PKCS7 object\n"); 125 ERR_print_errors(bio_err); 126 goto end; 127 } 128 129 if (informat == FORMAT_ASN1) 130 p7i = d2i_PKCS7_bio(in, &p7); 131 else 132 p7i = PEM_read_bio_PKCS7(in, &p7, NULL, NULL); 133 if (p7i == NULL) { 134 BIO_printf(bio_err, "unable to load PKCS7 object\n"); 135 ERR_print_errors(bio_err); 136 goto end; 137 } 138 139 out = bio_open_default(outfile, 'w', outformat); 140 if (out == NULL) 141 goto end; 142 143 if (p7_print) 144 PKCS7_print_ctx(out, p7, 0, NULL); 145 146 if (print_certs) { 147 STACK_OF(X509) *certs = NULL; 148 STACK_OF(X509_CRL) *crls = NULL; 149 150 i = OBJ_obj2nid(p7->type); 151 switch (i) { 152 case NID_pkcs7_signed: 153 if (p7->d.sign != NULL) { 154 certs = p7->d.sign->cert; 155 crls = p7->d.sign->crl; 156 } 157 break; 158 case NID_pkcs7_signedAndEnveloped: 159 if (p7->d.signed_and_enveloped != NULL) { 160 certs = p7->d.signed_and_enveloped->cert; 161 crls = p7->d.signed_and_enveloped->crl; 162 } 163 break; 164 default: 165 break; 166 } 167 168 if (certs != NULL) { 169 X509 *x; 170 171 for (i = 0; i < sk_X509_num(certs); i++) { 172 x = sk_X509_value(certs, i); 173 if (text) 174 X509_print(out, x); 175 else 176 dump_cert_text(out, x); 177 178 if (!noout) 179 PEM_write_bio_X509(out, x); 180 BIO_puts(out, "\n"); 181 } 182 } 183 if (crls != NULL) { 184 X509_CRL *crl; 185 186 for (i = 0; i < sk_X509_CRL_num(crls); i++) { 187 crl = sk_X509_CRL_value(crls, i); 188 189 X509_CRL_print_ex(out, crl, get_nameopt()); 190 191 if (!noout) 192 PEM_write_bio_X509_CRL(out, crl); 193 BIO_puts(out, "\n"); 194 } 195 } 196 197 ret = 0; 198 goto end; 199 } 200 201 if (!noout) { 202 if (outformat == FORMAT_ASN1) 203 i = i2d_PKCS7_bio(out, p7); 204 else 205 i = PEM_write_bio_PKCS7(out, p7); 206 207 if (!i) { 208 BIO_printf(bio_err, "unable to write pkcs7 object\n"); 209 ERR_print_errors(bio_err); 210 goto end; 211 } 212 } 213 ret = 0; 214 end: 215 PKCS7_free(p7); 216 release_engine(e); 217 BIO_free(in); 218 BIO_free_all(out); 219 return ret; 220 } 221