2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
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
12 #include <sys/types.h>
15 #include <openssl/err.h>
16 #include <openssl/evp.h>
17 #include <openssl/x509.h>
18 #include <openssl/pkcs7.h>
19 #include <openssl/pem.h>
20 #include <openssl/objects.h>
22 static int add_certs_from_file(STACK_OF(X509
) *stack
, char *certfile
);
24 typedef enum OPTION_choice
{
26 OPT_INFORM
, OPT_OUTFORM
, OPT_IN
, OPT_OUT
, OPT_NOCRL
, OPT_CERTFILE
,
30 const OPTIONS crl2pkcs7_options
[] = {
31 OPT_SECTION("General"),
32 {"help", OPT_HELP
, '-', "Display this summary"},
35 {"in", OPT_IN
, '<', "Input file"},
36 {"inform", OPT_INFORM
, 'F', "Input format - DER or PEM"},
37 {"nocrl", OPT_NOCRL
, '-', "No crl to load, just certs from '-certfile'"},
38 {"certfile", OPT_CERTFILE
, '<',
39 "File of chain of certs to a trusted CA; can be repeated"},
41 OPT_SECTION("Output"),
42 {"out", OPT_OUT
, '>', "Output file"},
43 {"outform", OPT_OUTFORM
, 'F', "Output format - DER or PEM"},
49 int crl2pkcs7_main(int argc
, char **argv
)
51 BIO
*in
= NULL
, *out
= NULL
;
53 PKCS7_SIGNED
*p7s
= NULL
;
54 STACK_OF(OPENSSL_STRING
) *certflst
= NULL
;
55 STACK_OF(X509
) *cert_stack
= NULL
;
56 STACK_OF(X509_CRL
) *crl_stack
= NULL
;
58 char *infile
= NULL
, *outfile
= NULL
, *prog
, *certfile
;
59 int i
= 0, informat
= FORMAT_PEM
, outformat
= FORMAT_PEM
, ret
= 1, nocrl
=
63 prog
= opt_init(argc
, argv
, crl2pkcs7_options
);
64 while ((o
= opt_next()) != OPT_EOF
) {
69 BIO_printf(bio_err
, "%s: Use -help for summary.\n", prog
);
72 opt_help(crl2pkcs7_options
);
76 if (!opt_format(opt_arg(), OPT_FMT_PEMDER
, &informat
))
80 if (!opt_format(opt_arg(), OPT_FMT_PEMDER
, &outformat
))
93 if ((certflst
== NULL
)
94 && (certflst
= sk_OPENSSL_STRING_new_null()) == NULL
)
96 if (!sk_OPENSSL_STRING_push(certflst
, opt_arg()))
100 if (!opt_provider(o
))
106 /* No remaining args. */
107 argc
= opt_num_rest();
112 in
= bio_open_default(infile
, 'r', informat
);
116 if (informat
== FORMAT_ASN1
)
117 crl
= d2i_X509_CRL_bio(in
, NULL
);
118 else if (informat
== FORMAT_PEM
)
119 crl
= PEM_read_bio_X509_CRL(in
, NULL
, NULL
, NULL
);
121 BIO_printf(bio_err
, "unable to load CRL\n");
122 ERR_print_errors(bio_err
);
127 if ((p7
= PKCS7_new()) == NULL
)
129 if ((p7s
= PKCS7_SIGNED_new()) == NULL
)
131 p7
->type
= OBJ_nid2obj(NID_pkcs7_signed
);
133 p7s
->contents
->type
= OBJ_nid2obj(NID_pkcs7_data
);
135 if (!ASN1_INTEGER_set(p7s
->version
, 1))
139 if ((crl_stack
= sk_X509_CRL_new_null()) == NULL
)
141 p7s
->crl
= crl_stack
;
142 sk_X509_CRL_push(crl_stack
, crl
);
143 crl
= NULL
; /* now part of p7 for OPENSSL_freeing */
146 if (certflst
!= NULL
) {
147 if ((cert_stack
= sk_X509_new_null()) == NULL
)
149 p7s
->cert
= cert_stack
;
151 for (i
= 0; i
< sk_OPENSSL_STRING_num(certflst
); i
++) {
152 certfile
= sk_OPENSSL_STRING_value(certflst
, i
);
153 if (add_certs_from_file(cert_stack
, certfile
) < 0) {
154 BIO_printf(bio_err
, "error loading certificates\n");
155 ERR_print_errors(bio_err
);
161 out
= bio_open_default(outfile
, 'w', outformat
);
165 if (outformat
== FORMAT_ASN1
)
166 i
= i2d_PKCS7_bio(out
, p7
);
167 else if (outformat
== FORMAT_PEM
)
168 i
= PEM_write_bio_PKCS7(out
, p7
);
170 BIO_printf(bio_err
, "unable to write pkcs7 object\n");
171 ERR_print_errors(bio_err
);
176 sk_OPENSSL_STRING_free(certflst
);
186 *----------------------------------------------------------------------
187 * int add_certs_from_file
189 * Read a list of certificates to be checked from a file.
192 * number of certs added if successful, -1 if not.
193 *----------------------------------------------------------------------
195 static int add_certs_from_file(STACK_OF(X509
) *stack
, char *certfile
)
200 STACK_OF(X509_INFO
) *sk
= NULL
;
203 in
= BIO_new_file(certfile
, "r");
205 BIO_printf(bio_err
, "error opening the file, %s\n", certfile
);
209 /* This loads from a file, a stack of x509/crl/pkey sets */
210 sk
= PEM_X509_INFO_read_bio(in
, NULL
, NULL
, NULL
);
212 BIO_printf(bio_err
, "error reading the file, %s\n", certfile
);
216 /* scan over it and pull out the CRL's */
217 while (sk_X509_INFO_num(sk
)) {
218 xi
= sk_X509_INFO_shift(sk
);
219 if (xi
->x509
!= NULL
) {
220 sk_X509_push(stack
, xi
->x509
);
229 /* never need to OPENSSL_free x */
231 sk_X509_INFO_free(sk
);