1*a824f5a1SJean-Baptiste Boric /* $NetBSD: pkcs7.c,v 1.1.1.4 2009/08/06 16:55:27 joerg Exp $ */
2*a824f5a1SJean-Baptiste Boric #if HAVE_CONFIG_H
3*a824f5a1SJean-Baptiste Boric #include "config.h"
4*a824f5a1SJean-Baptiste Boric #endif
5*a824f5a1SJean-Baptiste Boric #include <nbcompat.h>
6*a824f5a1SJean-Baptiste Boric #if HAVE_SYS_CDEFS_H
7*a824f5a1SJean-Baptiste Boric #include <sys/cdefs.h>
8*a824f5a1SJean-Baptiste Boric #endif
9*a824f5a1SJean-Baptiste Boric
10*a824f5a1SJean-Baptiste Boric __RCSID("$NetBSD: pkcs7.c,v 1.1.1.4 2009/08/06 16:55:27 joerg Exp $");
11*a824f5a1SJean-Baptiste Boric
12*a824f5a1SJean-Baptiste Boric /*-
13*a824f5a1SJean-Baptiste Boric * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc.
14*a824f5a1SJean-Baptiste Boric * All rights reserved.
15*a824f5a1SJean-Baptiste Boric *
16*a824f5a1SJean-Baptiste Boric * This code is derived from software contributed to The NetBSD Foundation
17*a824f5a1SJean-Baptiste Boric * by Love H�rnquist �strand <lha@it.su.se>
18*a824f5a1SJean-Baptiste Boric *
19*a824f5a1SJean-Baptiste Boric * Redistribution and use in source and binary forms, with or without
20*a824f5a1SJean-Baptiste Boric * modification, are permitted provided that the following conditions
21*a824f5a1SJean-Baptiste Boric * are met:
22*a824f5a1SJean-Baptiste Boric * 1. Redistributions of source code must retain the above copyright
23*a824f5a1SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer.
24*a824f5a1SJean-Baptiste Boric * 2. Redistributions in binary form must reproduce the above copyright
25*a824f5a1SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer in the
26*a824f5a1SJean-Baptiste Boric * documentation and/or other materials provided with the distribution.
27*a824f5a1SJean-Baptiste Boric *
28*a824f5a1SJean-Baptiste Boric * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29*a824f5a1SJean-Baptiste Boric * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30*a824f5a1SJean-Baptiste Boric * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31*a824f5a1SJean-Baptiste Boric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32*a824f5a1SJean-Baptiste Boric * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33*a824f5a1SJean-Baptiste Boric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34*a824f5a1SJean-Baptiste Boric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35*a824f5a1SJean-Baptiste Boric * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36*a824f5a1SJean-Baptiste Boric * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37*a824f5a1SJean-Baptiste Boric * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38*a824f5a1SJean-Baptiste Boric * POSSIBILITY OF SUCH DAMAGE.
39*a824f5a1SJean-Baptiste Boric */
40*a824f5a1SJean-Baptiste Boric
41*a824f5a1SJean-Baptiste Boric #if HAVE_ERR_H
42*a824f5a1SJean-Baptiste Boric #include <err.h>
43*a824f5a1SJean-Baptiste Boric #endif
44*a824f5a1SJean-Baptiste Boric
45*a824f5a1SJean-Baptiste Boric #include <openssl/pkcs7.h>
46*a824f5a1SJean-Baptiste Boric #include <openssl/evp.h>
47*a824f5a1SJean-Baptiste Boric #include <openssl/x509.h>
48*a824f5a1SJean-Baptiste Boric #include <openssl/x509v3.h>
49*a824f5a1SJean-Baptiste Boric #include <openssl/pem.h>
50*a824f5a1SJean-Baptiste Boric #include <openssl/err.h>
51*a824f5a1SJean-Baptiste Boric
52*a824f5a1SJean-Baptiste Boric #include "lib.h"
53*a824f5a1SJean-Baptiste Boric
54*a824f5a1SJean-Baptiste Boric #ifndef NS_ANY_CA
55*a824f5a1SJean-Baptiste Boric #define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
56*a824f5a1SJean-Baptiste Boric #endif
57*a824f5a1SJean-Baptiste Boric
58*a824f5a1SJean-Baptiste Boric static const unsigned int pkg_key_usage = XKU_CODE_SIGN | XKU_SMIME;
59*a824f5a1SJean-Baptiste Boric
60*a824f5a1SJean-Baptiste Boric static int
check_ca(X509 * cert)61*a824f5a1SJean-Baptiste Boric check_ca(X509 *cert)
62*a824f5a1SJean-Baptiste Boric {
63*a824f5a1SJean-Baptiste Boric if ((cert->ex_flags & EXFLAG_KUSAGE) != 0 &&
64*a824f5a1SJean-Baptiste Boric (cert->ex_kusage & KU_KEY_CERT_SIGN) != KU_KEY_CERT_SIGN)
65*a824f5a1SJean-Baptiste Boric return 0;
66*a824f5a1SJean-Baptiste Boric if ((cert->ex_flags & EXFLAG_BCONS) != 0)
67*a824f5a1SJean-Baptiste Boric return (cert->ex_flags & EXFLAG_CA) == EXFLAG_CA;
68*a824f5a1SJean-Baptiste Boric if ((cert->ex_flags & (EXFLAG_V1|EXFLAG_SS)) == (EXFLAG_V1|EXFLAG_SS))
69*a824f5a1SJean-Baptiste Boric return 1;
70*a824f5a1SJean-Baptiste Boric if ((cert->ex_flags & EXFLAG_KUSAGE) != 0)
71*a824f5a1SJean-Baptiste Boric return 1;
72*a824f5a1SJean-Baptiste Boric if ((cert->ex_flags & EXFLAG_NSCERT) != 0 &&
73*a824f5a1SJean-Baptiste Boric (cert->ex_nscert & NS_ANY_CA) != 0)
74*a824f5a1SJean-Baptiste Boric return 1;
75*a824f5a1SJean-Baptiste Boric return 0;
76*a824f5a1SJean-Baptiste Boric }
77*a824f5a1SJean-Baptiste Boric
STACK_OF(X509)78*a824f5a1SJean-Baptiste Boric static STACK_OF(X509) *
79*a824f5a1SJean-Baptiste Boric file_to_certs(const char *file)
80*a824f5a1SJean-Baptiste Boric {
81*a824f5a1SJean-Baptiste Boric unsigned long ret;
82*a824f5a1SJean-Baptiste Boric STACK_OF(X509) *certs;
83*a824f5a1SJean-Baptiste Boric FILE *f;
84*a824f5a1SJean-Baptiste Boric
85*a824f5a1SJean-Baptiste Boric if ((f = fopen(file, "r")) == NULL) {
86*a824f5a1SJean-Baptiste Boric warn("open failed %s", file);
87*a824f5a1SJean-Baptiste Boric return NULL;
88*a824f5a1SJean-Baptiste Boric }
89*a824f5a1SJean-Baptiste Boric
90*a824f5a1SJean-Baptiste Boric certs = sk_X509_new_null();
91*a824f5a1SJean-Baptiste Boric for (;;) {
92*a824f5a1SJean-Baptiste Boric X509 *cert;
93*a824f5a1SJean-Baptiste Boric
94*a824f5a1SJean-Baptiste Boric cert = PEM_read_X509(f, NULL, NULL, NULL);
95*a824f5a1SJean-Baptiste Boric if (cert == NULL) {
96*a824f5a1SJean-Baptiste Boric ret = ERR_GET_REASON(ERR_peek_error());
97*a824f5a1SJean-Baptiste Boric if (ret == PEM_R_NO_START_LINE) {
98*a824f5a1SJean-Baptiste Boric /* End of file reached. no error */
99*a824f5a1SJean-Baptiste Boric ERR_clear_error();
100*a824f5a1SJean-Baptiste Boric break;
101*a824f5a1SJean-Baptiste Boric }
102*a824f5a1SJean-Baptiste Boric sk_X509_free(certs);
103*a824f5a1SJean-Baptiste Boric warnx("Can't read certificate in file: %s", file);
104*a824f5a1SJean-Baptiste Boric fclose(f);
105*a824f5a1SJean-Baptiste Boric return NULL;
106*a824f5a1SJean-Baptiste Boric }
107*a824f5a1SJean-Baptiste Boric sk_X509_insert(certs, cert, sk_X509_num(certs));
108*a824f5a1SJean-Baptiste Boric }
109*a824f5a1SJean-Baptiste Boric
110*a824f5a1SJean-Baptiste Boric fclose(f);
111*a824f5a1SJean-Baptiste Boric
112*a824f5a1SJean-Baptiste Boric if (sk_X509_num(certs) == 0) {
113*a824f5a1SJean-Baptiste Boric sk_X509_free(certs);
114*a824f5a1SJean-Baptiste Boric certs = NULL;
115*a824f5a1SJean-Baptiste Boric warnx("No certificate found in file %s", file);
116*a824f5a1SJean-Baptiste Boric }
117*a824f5a1SJean-Baptiste Boric
118*a824f5a1SJean-Baptiste Boric return certs;
119*a824f5a1SJean-Baptiste Boric }
120*a824f5a1SJean-Baptiste Boric
121*a824f5a1SJean-Baptiste Boric int
easy_pkcs7_verify(const char * content,size_t len,const char * signature,size_t signature_len,const char * anchor,int is_pkg)122*a824f5a1SJean-Baptiste Boric easy_pkcs7_verify(const char *content, size_t len,
123*a824f5a1SJean-Baptiste Boric const char *signature, size_t signature_len,
124*a824f5a1SJean-Baptiste Boric const char *anchor, int is_pkg)
125*a824f5a1SJean-Baptiste Boric {
126*a824f5a1SJean-Baptiste Boric STACK_OF(X509) *cert_chain, *signers;
127*a824f5a1SJean-Baptiste Boric X509_STORE *store;
128*a824f5a1SJean-Baptiste Boric BIO *sig, *in;
129*a824f5a1SJean-Baptiste Boric PKCS7 *p7;
130*a824f5a1SJean-Baptiste Boric int i, status;
131*a824f5a1SJean-Baptiste Boric X509_NAME *name;
132*a824f5a1SJean-Baptiste Boric char *subject;
133*a824f5a1SJean-Baptiste Boric
134*a824f5a1SJean-Baptiste Boric OpenSSL_add_all_algorithms();
135*a824f5a1SJean-Baptiste Boric ERR_load_crypto_strings();
136*a824f5a1SJean-Baptiste Boric
137*a824f5a1SJean-Baptiste Boric status = -1;
138*a824f5a1SJean-Baptiste Boric
139*a824f5a1SJean-Baptiste Boric if (cert_chain_file)
140*a824f5a1SJean-Baptiste Boric cert_chain = file_to_certs(cert_chain_file);
141*a824f5a1SJean-Baptiste Boric else
142*a824f5a1SJean-Baptiste Boric cert_chain = NULL;
143*a824f5a1SJean-Baptiste Boric
144*a824f5a1SJean-Baptiste Boric store = X509_STORE_new();
145*a824f5a1SJean-Baptiste Boric if (store == NULL) {
146*a824f5a1SJean-Baptiste Boric sk_X509_free(cert_chain);
147*a824f5a1SJean-Baptiste Boric warnx("Failed to create certificate store");
148*a824f5a1SJean-Baptiste Boric return -1;
149*a824f5a1SJean-Baptiste Boric }
150*a824f5a1SJean-Baptiste Boric
151*a824f5a1SJean-Baptiste Boric X509_STORE_load_locations(store, anchor, NULL);
152*a824f5a1SJean-Baptiste Boric
153*a824f5a1SJean-Baptiste Boric in = BIO_new_mem_buf(__UNCONST(content), len);
154*a824f5a1SJean-Baptiste Boric sig = BIO_new_mem_buf(__UNCONST(signature), signature_len);
155*a824f5a1SJean-Baptiste Boric signers = NULL;
156*a824f5a1SJean-Baptiste Boric
157*a824f5a1SJean-Baptiste Boric p7 = PEM_read_bio_PKCS7(sig, NULL, NULL, NULL);
158*a824f5a1SJean-Baptiste Boric if (p7 == NULL) {
159*a824f5a1SJean-Baptiste Boric warnx("Failed to parse the signature");
160*a824f5a1SJean-Baptiste Boric goto cleanup;
161*a824f5a1SJean-Baptiste Boric }
162*a824f5a1SJean-Baptiste Boric
163*a824f5a1SJean-Baptiste Boric if (PKCS7_verify(p7, cert_chain, store, in, NULL, 0) != 1) {
164*a824f5a1SJean-Baptiste Boric warnx("Failed to verify signature");
165*a824f5a1SJean-Baptiste Boric goto cleanup;
166*a824f5a1SJean-Baptiste Boric }
167*a824f5a1SJean-Baptiste Boric
168*a824f5a1SJean-Baptiste Boric signers = PKCS7_get0_signers(p7, NULL, 0);
169*a824f5a1SJean-Baptiste Boric if (signers == NULL) {
170*a824f5a1SJean-Baptiste Boric warnx("Failed to get signers");
171*a824f5a1SJean-Baptiste Boric goto cleanup;
172*a824f5a1SJean-Baptiste Boric }
173*a824f5a1SJean-Baptiste Boric
174*a824f5a1SJean-Baptiste Boric if (sk_X509_num(signers) == 0) {
175*a824f5a1SJean-Baptiste Boric warnx("No signers found");
176*a824f5a1SJean-Baptiste Boric goto cleanup;
177*a824f5a1SJean-Baptiste Boric }
178*a824f5a1SJean-Baptiste Boric
179*a824f5a1SJean-Baptiste Boric for (i = 0; i < sk_X509_num(signers); i++) {
180*a824f5a1SJean-Baptiste Boric /* Compute ex_xkusage */
181*a824f5a1SJean-Baptiste Boric X509_check_purpose(sk_X509_value(signers, i), -1, -1);
182*a824f5a1SJean-Baptiste Boric
183*a824f5a1SJean-Baptiste Boric if (check_ca(sk_X509_value(signers, i))) {
184*a824f5a1SJean-Baptiste Boric warnx("CA keys are not valid for signatures");
185*a824f5a1SJean-Baptiste Boric goto cleanup;
186*a824f5a1SJean-Baptiste Boric }
187*a824f5a1SJean-Baptiste Boric if (is_pkg) {
188*a824f5a1SJean-Baptiste Boric if (sk_X509_value(signers, i)->ex_xkusage != pkg_key_usage) {
189*a824f5a1SJean-Baptiste Boric warnx("Certificate must have CODE SIGNING "
190*a824f5a1SJean-Baptiste Boric "and EMAIL PROTECTION property");
191*a824f5a1SJean-Baptiste Boric goto cleanup;
192*a824f5a1SJean-Baptiste Boric }
193*a824f5a1SJean-Baptiste Boric } else {
194*a824f5a1SJean-Baptiste Boric if (sk_X509_value(signers, i)->ex_xkusage != 0) {
195*a824f5a1SJean-Baptiste Boric warnx("Certificate must not have any property");
196*a824f5a1SJean-Baptiste Boric goto cleanup;
197*a824f5a1SJean-Baptiste Boric }
198*a824f5a1SJean-Baptiste Boric }
199*a824f5a1SJean-Baptiste Boric }
200*a824f5a1SJean-Baptiste Boric
201*a824f5a1SJean-Baptiste Boric printf("Sigature ok, signed by:\n");
202*a824f5a1SJean-Baptiste Boric
203*a824f5a1SJean-Baptiste Boric for (i = 0; i < sk_X509_num(signers); i++) {
204*a824f5a1SJean-Baptiste Boric name = X509_get_subject_name(sk_X509_value(signers, i));
205*a824f5a1SJean-Baptiste Boric subject = X509_NAME_oneline(name, NULL, 0);
206*a824f5a1SJean-Baptiste Boric
207*a824f5a1SJean-Baptiste Boric printf("\t%s\n", subject);
208*a824f5a1SJean-Baptiste Boric
209*a824f5a1SJean-Baptiste Boric OPENSSL_free(subject);
210*a824f5a1SJean-Baptiste Boric }
211*a824f5a1SJean-Baptiste Boric
212*a824f5a1SJean-Baptiste Boric status = 0;
213*a824f5a1SJean-Baptiste Boric
214*a824f5a1SJean-Baptiste Boric cleanup:
215*a824f5a1SJean-Baptiste Boric sk_X509_free(cert_chain);
216*a824f5a1SJean-Baptiste Boric sk_X509_free(signers);
217*a824f5a1SJean-Baptiste Boric X509_STORE_free(store);
218*a824f5a1SJean-Baptiste Boric
219*a824f5a1SJean-Baptiste Boric PKCS7_free(p7);
220*a824f5a1SJean-Baptiste Boric BIO_free(in);
221*a824f5a1SJean-Baptiste Boric BIO_free(sig);
222*a824f5a1SJean-Baptiste Boric
223*a824f5a1SJean-Baptiste Boric return status;
224*a824f5a1SJean-Baptiste Boric }
225*a824f5a1SJean-Baptiste Boric
226*a824f5a1SJean-Baptiste Boric static int
ssl_pass_cb(char * buf,int size,int rwflag,void * u)227*a824f5a1SJean-Baptiste Boric ssl_pass_cb(char *buf, int size, int rwflag, void *u)
228*a824f5a1SJean-Baptiste Boric {
229*a824f5a1SJean-Baptiste Boric
230*a824f5a1SJean-Baptiste Boric if (EVP_read_pw_string(buf, size, "Passphrase :", 0)) {
231*a824f5a1SJean-Baptiste Boric #if OPENSSL_VERSION >= 0x0090608fL
232*a824f5a1SJean-Baptiste Boric OPENSSL_cleanse(buf, size);
233*a824f5a1SJean-Baptiste Boric #else
234*a824f5a1SJean-Baptiste Boric memset(buf, 0, size);
235*a824f5a1SJean-Baptiste Boric #endif
236*a824f5a1SJean-Baptiste Boric return 0;
237*a824f5a1SJean-Baptiste Boric }
238*a824f5a1SJean-Baptiste Boric return strlen(buf);
239*a824f5a1SJean-Baptiste Boric }
240*a824f5a1SJean-Baptiste Boric
241*a824f5a1SJean-Baptiste Boric int
easy_pkcs7_sign(const char * content,size_t len,char ** signature,size_t * signature_len,const char * key_file,const char * cert_file)242*a824f5a1SJean-Baptiste Boric easy_pkcs7_sign(const char *content, size_t len,
243*a824f5a1SJean-Baptiste Boric char **signature, size_t *signature_len,
244*a824f5a1SJean-Baptiste Boric const char *key_file, const char *cert_file)
245*a824f5a1SJean-Baptiste Boric {
246*a824f5a1SJean-Baptiste Boric FILE *f;
247*a824f5a1SJean-Baptiste Boric X509 *certificate;
248*a824f5a1SJean-Baptiste Boric STACK_OF(X509) *c, *cert_chain;
249*a824f5a1SJean-Baptiste Boric EVP_PKEY *private_key;
250*a824f5a1SJean-Baptiste Boric char *tmp_sig;
251*a824f5a1SJean-Baptiste Boric BIO *out, *in;
252*a824f5a1SJean-Baptiste Boric PKCS7 *p7;
253*a824f5a1SJean-Baptiste Boric int status;
254*a824f5a1SJean-Baptiste Boric
255*a824f5a1SJean-Baptiste Boric OpenSSL_add_all_algorithms();
256*a824f5a1SJean-Baptiste Boric ERR_load_crypto_strings();
257*a824f5a1SJean-Baptiste Boric
258*a824f5a1SJean-Baptiste Boric status = -1;
259*a824f5a1SJean-Baptiste Boric private_key = NULL;
260*a824f5a1SJean-Baptiste Boric cert_chain = NULL;
261*a824f5a1SJean-Baptiste Boric in = NULL;
262*a824f5a1SJean-Baptiste Boric
263*a824f5a1SJean-Baptiste Boric c = file_to_certs(cert_file);
264*a824f5a1SJean-Baptiste Boric
265*a824f5a1SJean-Baptiste Boric if (sk_X509_num(c) != 1) {
266*a824f5a1SJean-Baptiste Boric warnx("More then one certificate in the certificate file");
267*a824f5a1SJean-Baptiste Boric goto cleanup;
268*a824f5a1SJean-Baptiste Boric }
269*a824f5a1SJean-Baptiste Boric certificate = sk_X509_value(c, 0);
270*a824f5a1SJean-Baptiste Boric
271*a824f5a1SJean-Baptiste Boric /* Compute ex_kusage */
272*a824f5a1SJean-Baptiste Boric X509_check_purpose(certificate, -1, 0);
273*a824f5a1SJean-Baptiste Boric
274*a824f5a1SJean-Baptiste Boric if (check_ca(certificate)) {
275*a824f5a1SJean-Baptiste Boric warnx("CA keys are not valid for signatures");
276*a824f5a1SJean-Baptiste Boric goto cleanup;
277*a824f5a1SJean-Baptiste Boric }
278*a824f5a1SJean-Baptiste Boric
279*a824f5a1SJean-Baptiste Boric if (certificate->ex_xkusage != pkg_key_usage) {
280*a824f5a1SJean-Baptiste Boric warnx("Certificate must have CODE SIGNING "
281*a824f5a1SJean-Baptiste Boric "and EMAIL PROTECTION property");
282*a824f5a1SJean-Baptiste Boric goto cleanup;
283*a824f5a1SJean-Baptiste Boric }
284*a824f5a1SJean-Baptiste Boric
285*a824f5a1SJean-Baptiste Boric if (cert_chain_file)
286*a824f5a1SJean-Baptiste Boric cert_chain = file_to_certs(cert_chain_file);
287*a824f5a1SJean-Baptiste Boric
288*a824f5a1SJean-Baptiste Boric if ((f = fopen(key_file, "r")) == NULL) {
289*a824f5a1SJean-Baptiste Boric warn("Failed to open private key file %s", key_file);
290*a824f5a1SJean-Baptiste Boric goto cleanup;
291*a824f5a1SJean-Baptiste Boric }
292*a824f5a1SJean-Baptiste Boric private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, NULL);
293*a824f5a1SJean-Baptiste Boric fclose(f);
294*a824f5a1SJean-Baptiste Boric if (private_key == NULL) {
295*a824f5a1SJean-Baptiste Boric warnx("Can't read private key: %s", key_file);
296*a824f5a1SJean-Baptiste Boric goto cleanup;
297*a824f5a1SJean-Baptiste Boric }
298*a824f5a1SJean-Baptiste Boric
299*a824f5a1SJean-Baptiste Boric if (X509_check_private_key(certificate, private_key) != 1) {
300*a824f5a1SJean-Baptiste Boric warnx("The private key %s doesn't match the certificate %s",
301*a824f5a1SJean-Baptiste Boric key_file, cert_file);
302*a824f5a1SJean-Baptiste Boric goto cleanup;
303*a824f5a1SJean-Baptiste Boric }
304*a824f5a1SJean-Baptiste Boric
305*a824f5a1SJean-Baptiste Boric in = BIO_new_mem_buf(__UNCONST(content), len);
306*a824f5a1SJean-Baptiste Boric
307*a824f5a1SJean-Baptiste Boric p7 = PKCS7_sign(certificate, private_key, cert_chain, in,
308*a824f5a1SJean-Baptiste Boric PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
309*a824f5a1SJean-Baptiste Boric if (p7 == NULL) {
310*a824f5a1SJean-Baptiste Boric warnx("Failed to create signature structure");
311*a824f5a1SJean-Baptiste Boric goto cleanup;
312*a824f5a1SJean-Baptiste Boric }
313*a824f5a1SJean-Baptiste Boric
314*a824f5a1SJean-Baptiste Boric out = BIO_new(BIO_s_mem());
315*a824f5a1SJean-Baptiste Boric PEM_write_bio_PKCS7(out, p7);
316*a824f5a1SJean-Baptiste Boric *signature_len = BIO_get_mem_data(out, &tmp_sig);
317*a824f5a1SJean-Baptiste Boric *signature = xmalloc(*signature_len);
318*a824f5a1SJean-Baptiste Boric memcpy(*signature, tmp_sig, *signature_len);
319*a824f5a1SJean-Baptiste Boric BIO_free_all(out);
320*a824f5a1SJean-Baptiste Boric
321*a824f5a1SJean-Baptiste Boric PKCS7_free(p7);
322*a824f5a1SJean-Baptiste Boric
323*a824f5a1SJean-Baptiste Boric status = 0;
324*a824f5a1SJean-Baptiste Boric
325*a824f5a1SJean-Baptiste Boric cleanup:
326*a824f5a1SJean-Baptiste Boric sk_X509_free(c);
327*a824f5a1SJean-Baptiste Boric sk_X509_free(cert_chain);
328*a824f5a1SJean-Baptiste Boric EVP_PKEY_free(private_key);
329*a824f5a1SJean-Baptiste Boric BIO_free(in);
330*a824f5a1SJean-Baptiste Boric
331*a824f5a1SJean-Baptiste Boric return status;
332*a824f5a1SJean-Baptiste Boric }
333