xref: /minix3/external/bsd/pkg_install/dist/lib/pkcs7.c (revision a824f5a1008ee67499d167f8c48e64aae26960ca)
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