xref: /aosp_15_r20/external/fsverity-utils/lib/sign_digest.c (revision b13c0e4024008a1f948ee8189745cb3371f4ac04)
1*b13c0e40SEric Biggers // SPDX-License-Identifier: MIT
2*b13c0e40SEric Biggers /*
3*b13c0e40SEric Biggers  * Implementation of libfsverity_sign_digest().
4*b13c0e40SEric Biggers  *
5*b13c0e40SEric Biggers  * Copyright 2018 Google LLC
6*b13c0e40SEric Biggers  * Copyright (C) 2020 Facebook
7*b13c0e40SEric Biggers  *
8*b13c0e40SEric Biggers  * Use of this source code is governed by an MIT-style
9*b13c0e40SEric Biggers  * license that can be found in the LICENSE file or at
10*b13c0e40SEric Biggers  * https://opensource.org/licenses/MIT.
11*b13c0e40SEric Biggers  */
12*b13c0e40SEric Biggers 
13*b13c0e40SEric Biggers #include "lib_private.h"
14*b13c0e40SEric Biggers 
15*b13c0e40SEric Biggers #include <limits.h>
16*b13c0e40SEric Biggers #include <openssl/bio.h>
17*b13c0e40SEric Biggers #include <openssl/err.h>
18*b13c0e40SEric Biggers #include <openssl/pem.h>
19*b13c0e40SEric Biggers #include <openssl/pkcs7.h>
20*b13c0e40SEric Biggers #include <string.h>
21*b13c0e40SEric Biggers 
22*b13c0e40SEric Biggers #ifndef OPENSSL_IS_BORINGSSL
23*b13c0e40SEric Biggers #include <openssl/engine.h>
24*b13c0e40SEric Biggers #endif
25*b13c0e40SEric Biggers 
print_openssl_err_cb(const char * str,size_t len,void * u)26*b13c0e40SEric Biggers static int print_openssl_err_cb(const char *str,
27*b13c0e40SEric Biggers 				size_t len __attribute__((unused)),
28*b13c0e40SEric Biggers 				void *u __attribute__((unused)))
29*b13c0e40SEric Biggers {
30*b13c0e40SEric Biggers 	libfsverity_error_msg("%s", str);
31*b13c0e40SEric Biggers 	return 1;
32*b13c0e40SEric Biggers }
33*b13c0e40SEric Biggers 
34*b13c0e40SEric Biggers static void __printf(1, 2) __cold
error_msg_openssl(const char * format,...)35*b13c0e40SEric Biggers error_msg_openssl(const char *format, ...)
36*b13c0e40SEric Biggers {
37*b13c0e40SEric Biggers 	int saved_errno = errno;
38*b13c0e40SEric Biggers 	va_list va;
39*b13c0e40SEric Biggers 
40*b13c0e40SEric Biggers 	va_start(va, format);
41*b13c0e40SEric Biggers 	libfsverity_do_error_msg(format, va);
42*b13c0e40SEric Biggers 	va_end(va);
43*b13c0e40SEric Biggers 
44*b13c0e40SEric Biggers 	if (ERR_peek_error() == 0)
45*b13c0e40SEric Biggers 		return;
46*b13c0e40SEric Biggers 
47*b13c0e40SEric Biggers 	libfsverity_error_msg("OpenSSL library errors:");
48*b13c0e40SEric Biggers 	ERR_print_errors_cb(print_openssl_err_cb, NULL);
49*b13c0e40SEric Biggers 	errno = saved_errno;
50*b13c0e40SEric Biggers }
51*b13c0e40SEric Biggers 
52*b13c0e40SEric Biggers /* Read a PEM PKCS#8 formatted private key */
read_private_key(const char * keyfile,EVP_PKEY ** pkey_ret)53*b13c0e40SEric Biggers static int read_private_key(const char *keyfile, EVP_PKEY **pkey_ret)
54*b13c0e40SEric Biggers {
55*b13c0e40SEric Biggers 	BIO *bio;
56*b13c0e40SEric Biggers 	EVP_PKEY *pkey;
57*b13c0e40SEric Biggers 	int err;
58*b13c0e40SEric Biggers 
59*b13c0e40SEric Biggers 	errno = 0;
60*b13c0e40SEric Biggers 	bio = BIO_new_file(keyfile, "r");
61*b13c0e40SEric Biggers 	if (!bio) {
62*b13c0e40SEric Biggers 		error_msg_openssl("can't open '%s' for reading", keyfile);
63*b13c0e40SEric Biggers 		return errno ? -errno : -EIO;
64*b13c0e40SEric Biggers 	}
65*b13c0e40SEric Biggers 
66*b13c0e40SEric Biggers 	pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
67*b13c0e40SEric Biggers 	if (!pkey) {
68*b13c0e40SEric Biggers 		error_msg_openssl("Failed to parse private key file '%s'.\n"
69*b13c0e40SEric Biggers 				  "       Note: it must be in PEM PKCS#8 format.",
70*b13c0e40SEric Biggers 				  keyfile);
71*b13c0e40SEric Biggers 		err = -EBADMSG;
72*b13c0e40SEric Biggers 		goto out;
73*b13c0e40SEric Biggers 	}
74*b13c0e40SEric Biggers 	*pkey_ret = pkey;
75*b13c0e40SEric Biggers 	err = 0;
76*b13c0e40SEric Biggers out:
77*b13c0e40SEric Biggers 	BIO_free(bio);
78*b13c0e40SEric Biggers 	return err;
79*b13c0e40SEric Biggers }
80*b13c0e40SEric Biggers 
81*b13c0e40SEric Biggers /* Read a PEM X.509 formatted certificate */
read_certificate(const char * certfile,X509 ** cert_ret)82*b13c0e40SEric Biggers static int read_certificate(const char *certfile, X509 **cert_ret)
83*b13c0e40SEric Biggers {
84*b13c0e40SEric Biggers 	BIO *bio;
85*b13c0e40SEric Biggers 	X509 *cert;
86*b13c0e40SEric Biggers 	int err;
87*b13c0e40SEric Biggers 
88*b13c0e40SEric Biggers 	if (!certfile) {
89*b13c0e40SEric Biggers 		libfsverity_error_msg("no certificate specified");
90*b13c0e40SEric Biggers 		return -EINVAL;
91*b13c0e40SEric Biggers 	}
92*b13c0e40SEric Biggers 
93*b13c0e40SEric Biggers 	errno = 0;
94*b13c0e40SEric Biggers 	bio = BIO_new_file(certfile, "r");
95*b13c0e40SEric Biggers 	if (!bio) {
96*b13c0e40SEric Biggers 		error_msg_openssl("can't open '%s' for reading", certfile);
97*b13c0e40SEric Biggers 		return errno ? -errno : -EIO;
98*b13c0e40SEric Biggers 	}
99*b13c0e40SEric Biggers 	cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
100*b13c0e40SEric Biggers 	if (!cert) {
101*b13c0e40SEric Biggers 		error_msg_openssl("Failed to parse X.509 certificate file '%s'.\n"
102*b13c0e40SEric Biggers 				  "       Note: it must be in PEM format.",
103*b13c0e40SEric Biggers 				  certfile);
104*b13c0e40SEric Biggers 		err = -EBADMSG;
105*b13c0e40SEric Biggers 		goto out;
106*b13c0e40SEric Biggers 	}
107*b13c0e40SEric Biggers 	*cert_ret = cert;
108*b13c0e40SEric Biggers 	err = 0;
109*b13c0e40SEric Biggers out:
110*b13c0e40SEric Biggers 	BIO_free(bio);
111*b13c0e40SEric Biggers 	return err;
112*b13c0e40SEric Biggers }
113*b13c0e40SEric Biggers 
114*b13c0e40SEric Biggers #ifdef OPENSSL_IS_BORINGSSL
115*b13c0e40SEric Biggers 
sign_pkcs7(const void * data_to_sign,size_t data_size,EVP_PKEY * pkey,X509 * cert,const EVP_MD * md,u8 ** sig_ret,size_t * sig_size_ret)116*b13c0e40SEric Biggers static int sign_pkcs7(const void *data_to_sign, size_t data_size,
117*b13c0e40SEric Biggers 		      EVP_PKEY *pkey, X509 *cert, const EVP_MD *md,
118*b13c0e40SEric Biggers 		      u8 **sig_ret, size_t *sig_size_ret)
119*b13c0e40SEric Biggers {
120*b13c0e40SEric Biggers 	BIGNUM *serial;
121*b13c0e40SEric Biggers 	CBB out, outer_seq, wrapped_seq, seq, digest_algos_set, digest_algo,
122*b13c0e40SEric Biggers 		null, content_info, issuer_and_serial, signer_infos,
123*b13c0e40SEric Biggers 		signer_info, sign_algo, signature;
124*b13c0e40SEric Biggers 	EVP_MD_CTX md_ctx;
125*b13c0e40SEric Biggers 	u8 *name_der = NULL, *sig = NULL, *pkcs7_data = NULL;
126*b13c0e40SEric Biggers 	size_t pkcs7_data_len, sig_len;
127*b13c0e40SEric Biggers 	int name_der_len, sig_nid;
128*b13c0e40SEric Biggers 	int err;
129*b13c0e40SEric Biggers 
130*b13c0e40SEric Biggers 	EVP_MD_CTX_init(&md_ctx);
131*b13c0e40SEric Biggers 	serial = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), NULL);
132*b13c0e40SEric Biggers 
133*b13c0e40SEric Biggers 	if (!CBB_init(&out, 1024)) {
134*b13c0e40SEric Biggers 		error_msg_openssl("out of memory");
135*b13c0e40SEric Biggers 		err = -ENOMEM;
136*b13c0e40SEric Biggers 		goto out;
137*b13c0e40SEric Biggers 	}
138*b13c0e40SEric Biggers 
139*b13c0e40SEric Biggers 	name_der_len = i2d_X509_NAME(X509_get_subject_name(cert), &name_der);
140*b13c0e40SEric Biggers 	if (name_der_len < 0) {
141*b13c0e40SEric Biggers 		error_msg_openssl("i2d_X509_NAME failed");
142*b13c0e40SEric Biggers 		err = -EINVAL;
143*b13c0e40SEric Biggers 		goto out;
144*b13c0e40SEric Biggers 	}
145*b13c0e40SEric Biggers 
146*b13c0e40SEric Biggers 	if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey)) {
147*b13c0e40SEric Biggers 		error_msg_openssl("EVP_DigestSignInit failed");
148*b13c0e40SEric Biggers 		err = -EINVAL;
149*b13c0e40SEric Biggers 		goto out;
150*b13c0e40SEric Biggers 	}
151*b13c0e40SEric Biggers 
152*b13c0e40SEric Biggers 	sig_len = EVP_PKEY_size(pkey);
153*b13c0e40SEric Biggers 	sig = libfsverity_zalloc(sig_len);
154*b13c0e40SEric Biggers 	if (!sig) {
155*b13c0e40SEric Biggers 		err = -ENOMEM;
156*b13c0e40SEric Biggers 		goto out;
157*b13c0e40SEric Biggers 	}
158*b13c0e40SEric Biggers 	if (!EVP_DigestSign(&md_ctx, sig, &sig_len, data_to_sign, data_size)) {
159*b13c0e40SEric Biggers 		error_msg_openssl("EVP_DigestSign failed");
160*b13c0e40SEric Biggers 		err = -EINVAL;
161*b13c0e40SEric Biggers 		goto out;
162*b13c0e40SEric Biggers 	}
163*b13c0e40SEric Biggers 
164*b13c0e40SEric Biggers 	sig_nid = EVP_PKEY_id(pkey);
165*b13c0e40SEric Biggers 	/* To mirror OpenSSL behaviour, always use |NID_rsaEncryption| with RSA
166*b13c0e40SEric Biggers 	 * rather than the combined hash+pkey NID. */
167*b13c0e40SEric Biggers 	if (sig_nid != NID_rsaEncryption) {
168*b13c0e40SEric Biggers 		OBJ_find_sigid_by_algs(&sig_nid, EVP_MD_type(md),
169*b13c0e40SEric Biggers 				       EVP_PKEY_id(pkey));
170*b13c0e40SEric Biggers 	}
171*b13c0e40SEric Biggers 
172*b13c0e40SEric Biggers 	// See https://tools.ietf.org/html/rfc2315#section-7
173*b13c0e40SEric Biggers 	if (!CBB_add_asn1(&out, &outer_seq, CBS_ASN1_SEQUENCE) ||
174*b13c0e40SEric Biggers 	    !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
175*b13c0e40SEric Biggers 	    !CBB_add_asn1(&outer_seq, &wrapped_seq, CBS_ASN1_CONTEXT_SPECIFIC |
176*b13c0e40SEric Biggers 			  CBS_ASN1_CONSTRUCTED | 0) ||
177*b13c0e40SEric Biggers 	    // See https://tools.ietf.org/html/rfc2315#section-9.1
178*b13c0e40SEric Biggers 	    !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
179*b13c0e40SEric Biggers 	    !CBB_add_asn1_uint64(&seq, 1 /* version */) ||
180*b13c0e40SEric Biggers 	    !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
181*b13c0e40SEric Biggers 	    !CBB_add_asn1(&digest_algos_set, &digest_algo, CBS_ASN1_SEQUENCE) ||
182*b13c0e40SEric Biggers 	    !OBJ_nid2cbb(&digest_algo, EVP_MD_type(md)) ||
183*b13c0e40SEric Biggers 	    !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
184*b13c0e40SEric Biggers 	    !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
185*b13c0e40SEric Biggers 	    !OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
186*b13c0e40SEric Biggers 	    !CBB_add_asn1(&seq, &signer_infos, CBS_ASN1_SET) ||
187*b13c0e40SEric Biggers 	    !CBB_add_asn1(&signer_infos, &signer_info, CBS_ASN1_SEQUENCE) ||
188*b13c0e40SEric Biggers 	    !CBB_add_asn1_uint64(&signer_info, 1 /* version */) ||
189*b13c0e40SEric Biggers 	    !CBB_add_asn1(&signer_info, &issuer_and_serial,
190*b13c0e40SEric Biggers 			  CBS_ASN1_SEQUENCE) ||
191*b13c0e40SEric Biggers 	    !CBB_add_bytes(&issuer_and_serial, name_der, name_der_len) ||
192*b13c0e40SEric Biggers 	    !BN_marshal_asn1(&issuer_and_serial, serial) ||
193*b13c0e40SEric Biggers 	    !CBB_add_asn1(&signer_info, &digest_algo, CBS_ASN1_SEQUENCE) ||
194*b13c0e40SEric Biggers 	    !OBJ_nid2cbb(&digest_algo, EVP_MD_type(md)) ||
195*b13c0e40SEric Biggers 	    !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
196*b13c0e40SEric Biggers 	    !CBB_add_asn1(&signer_info, &sign_algo, CBS_ASN1_SEQUENCE) ||
197*b13c0e40SEric Biggers 	    !OBJ_nid2cbb(&sign_algo, sig_nid) ||
198*b13c0e40SEric Biggers 	    !CBB_add_asn1(&sign_algo, &null, CBS_ASN1_NULL) ||
199*b13c0e40SEric Biggers 	    !CBB_add_asn1(&signer_info, &signature, CBS_ASN1_OCTETSTRING) ||
200*b13c0e40SEric Biggers 	    !CBB_add_bytes(&signature, sig, sig_len) ||
201*b13c0e40SEric Biggers 	    !CBB_finish(&out, &pkcs7_data, &pkcs7_data_len)) {
202*b13c0e40SEric Biggers 		error_msg_openssl("failed to construct PKCS#7 data");
203*b13c0e40SEric Biggers 		err = -EINVAL;
204*b13c0e40SEric Biggers 		goto out;
205*b13c0e40SEric Biggers 	}
206*b13c0e40SEric Biggers 
207*b13c0e40SEric Biggers 	*sig_ret = libfsverity_memdup(pkcs7_data, pkcs7_data_len);
208*b13c0e40SEric Biggers 	if (!*sig_ret) {
209*b13c0e40SEric Biggers 		err = -ENOMEM;
210*b13c0e40SEric Biggers 		goto out;
211*b13c0e40SEric Biggers 	}
212*b13c0e40SEric Biggers 	*sig_size_ret = pkcs7_data_len;
213*b13c0e40SEric Biggers 	err = 0;
214*b13c0e40SEric Biggers out:
215*b13c0e40SEric Biggers 	BN_free(serial);
216*b13c0e40SEric Biggers 	EVP_MD_CTX_cleanup(&md_ctx);
217*b13c0e40SEric Biggers 	CBB_cleanup(&out);
218*b13c0e40SEric Biggers 	free(sig);
219*b13c0e40SEric Biggers 	OPENSSL_free(name_der);
220*b13c0e40SEric Biggers 	OPENSSL_free(pkcs7_data);
221*b13c0e40SEric Biggers 	return err;
222*b13c0e40SEric Biggers }
223*b13c0e40SEric Biggers 
224*b13c0e40SEric Biggers static int
load_pkcs11_private_key(const struct libfsverity_signature_params * sig_params,EVP_PKEY ** pkey_ret)225*b13c0e40SEric Biggers load_pkcs11_private_key(const struct libfsverity_signature_params *sig_params
226*b13c0e40SEric Biggers 			__attribute__((unused)),
227*b13c0e40SEric Biggers 			EVP_PKEY **pkey_ret __attribute__((unused)))
228*b13c0e40SEric Biggers {
229*b13c0e40SEric Biggers 	libfsverity_error_msg("BoringSSL doesn't support PKCS#11 tokens");
230*b13c0e40SEric Biggers 	return -EINVAL;
231*b13c0e40SEric Biggers }
232*b13c0e40SEric Biggers 
233*b13c0e40SEric Biggers #else /* OPENSSL_IS_BORINGSSL */
234*b13c0e40SEric Biggers 
new_mem_buf(const void * buf,size_t size)235*b13c0e40SEric Biggers static BIO *new_mem_buf(const void *buf, size_t size)
236*b13c0e40SEric Biggers {
237*b13c0e40SEric Biggers 	BIO *bio;
238*b13c0e40SEric Biggers 
239*b13c0e40SEric Biggers 	if (WARN_ON(size > INT_MAX))
240*b13c0e40SEric Biggers 		return NULL;
241*b13c0e40SEric Biggers 
242*b13c0e40SEric Biggers 	/*
243*b13c0e40SEric Biggers 	 * Prior to OpenSSL 1.1.0, BIO_new_mem_buf() took a non-const pointer,
244*b13c0e40SEric Biggers 	 * despite still marking the resulting bio as read-only.  So cast away
245*b13c0e40SEric Biggers 	 * the const to avoid a compiler warning with older OpenSSL versions.
246*b13c0e40SEric Biggers 	 */
247*b13c0e40SEric Biggers 	bio = BIO_new_mem_buf((void *)buf, size);
248*b13c0e40SEric Biggers 	if (!bio)
249*b13c0e40SEric Biggers 		error_msg_openssl("out of memory");
250*b13c0e40SEric Biggers 	return bio;
251*b13c0e40SEric Biggers }
252*b13c0e40SEric Biggers 
sign_pkcs7(const void * data_to_sign,size_t data_size,EVP_PKEY * pkey,X509 * cert,const EVP_MD * md,u8 ** sig_ret,size_t * sig_size_ret)253*b13c0e40SEric Biggers static int sign_pkcs7(const void *data_to_sign, size_t data_size,
254*b13c0e40SEric Biggers 		      EVP_PKEY *pkey, X509 *cert, const EVP_MD *md,
255*b13c0e40SEric Biggers 		      u8 **sig_ret, size_t *sig_size_ret)
256*b13c0e40SEric Biggers {
257*b13c0e40SEric Biggers 	/*
258*b13c0e40SEric Biggers 	 * PKCS#7 signing flags:
259*b13c0e40SEric Biggers 	 *
260*b13c0e40SEric Biggers 	 * - PKCS7_BINARY	signing binary data, so skip MIME translation
261*b13c0e40SEric Biggers 	 *
262*b13c0e40SEric Biggers 	 * - PKCS7_DETACHED	omit the signed data (include signature only)
263*b13c0e40SEric Biggers 	 *
264*b13c0e40SEric Biggers 	 * - PKCS7_NOATTR	omit extra authenticated attributes, such as
265*b13c0e40SEric Biggers 	 *			SMIMECapabilities
266*b13c0e40SEric Biggers 	 *
267*b13c0e40SEric Biggers 	 * - PKCS7_NOCERTS	omit the signer's certificate
268*b13c0e40SEric Biggers 	 *
269*b13c0e40SEric Biggers 	 * - PKCS7_PARTIAL	PKCS7_sign() creates a handle only, then
270*b13c0e40SEric Biggers 	 *			PKCS7_sign_add_signer() can add a signer later.
271*b13c0e40SEric Biggers 	 *			This is necessary to change the message digest
272*b13c0e40SEric Biggers 	 *			algorithm from the default of SHA-1.  Requires
273*b13c0e40SEric Biggers 	 *			OpenSSL 1.0.0 or later.
274*b13c0e40SEric Biggers 	 */
275*b13c0e40SEric Biggers 	int pkcs7_flags = PKCS7_BINARY | PKCS7_DETACHED | PKCS7_NOATTR |
276*b13c0e40SEric Biggers 			  PKCS7_NOCERTS | PKCS7_PARTIAL;
277*b13c0e40SEric Biggers 	u8 *sig;
278*b13c0e40SEric Biggers 	u32 sig_size;
279*b13c0e40SEric Biggers 	BIO *bio = NULL;
280*b13c0e40SEric Biggers 	PKCS7 *p7 = NULL;
281*b13c0e40SEric Biggers 	int err;
282*b13c0e40SEric Biggers 
283*b13c0e40SEric Biggers 	bio = new_mem_buf(data_to_sign, data_size);
284*b13c0e40SEric Biggers 	if (!bio) {
285*b13c0e40SEric Biggers 		err = -ENOMEM;
286*b13c0e40SEric Biggers 		goto out;
287*b13c0e40SEric Biggers 	}
288*b13c0e40SEric Biggers 
289*b13c0e40SEric Biggers 	p7 = PKCS7_sign(NULL, NULL, NULL, bio, pkcs7_flags);
290*b13c0e40SEric Biggers 	if (!p7) {
291*b13c0e40SEric Biggers 		error_msg_openssl("failed to initialize PKCS#7 signature object");
292*b13c0e40SEric Biggers 		err = -EINVAL;
293*b13c0e40SEric Biggers 		goto out;
294*b13c0e40SEric Biggers 	}
295*b13c0e40SEric Biggers 
296*b13c0e40SEric Biggers 	if (!PKCS7_sign_add_signer(p7, cert, pkey, md, pkcs7_flags)) {
297*b13c0e40SEric Biggers 		error_msg_openssl("failed to add signer to PKCS#7 signature object");
298*b13c0e40SEric Biggers 		err = -EINVAL;
299*b13c0e40SEric Biggers 		goto out;
300*b13c0e40SEric Biggers 	}
301*b13c0e40SEric Biggers 
302*b13c0e40SEric Biggers 	if (PKCS7_final(p7, bio, pkcs7_flags) != 1) {
303*b13c0e40SEric Biggers 		error_msg_openssl("failed to finalize PKCS#7 signature");
304*b13c0e40SEric Biggers 		err = -EINVAL;
305*b13c0e40SEric Biggers 		goto out;
306*b13c0e40SEric Biggers 	}
307*b13c0e40SEric Biggers 
308*b13c0e40SEric Biggers 	BIO_free(bio);
309*b13c0e40SEric Biggers 	bio = BIO_new(BIO_s_mem());
310*b13c0e40SEric Biggers 	if (!bio) {
311*b13c0e40SEric Biggers 		error_msg_openssl("out of memory");
312*b13c0e40SEric Biggers 		err = -ENOMEM;
313*b13c0e40SEric Biggers 		goto out;
314*b13c0e40SEric Biggers 	}
315*b13c0e40SEric Biggers 
316*b13c0e40SEric Biggers 	if (i2d_PKCS7_bio(bio, p7) != 1) {
317*b13c0e40SEric Biggers 		error_msg_openssl("failed to DER-encode PKCS#7 signature object");
318*b13c0e40SEric Biggers 		err = -EINVAL;
319*b13c0e40SEric Biggers 		goto out;
320*b13c0e40SEric Biggers 	}
321*b13c0e40SEric Biggers 
322*b13c0e40SEric Biggers 	sig_size = BIO_get_mem_data(bio, &sig);
323*b13c0e40SEric Biggers 	*sig_ret = libfsverity_memdup(sig, sig_size);
324*b13c0e40SEric Biggers 	if (!*sig_ret) {
325*b13c0e40SEric Biggers 		err = -ENOMEM;
326*b13c0e40SEric Biggers 		goto out;
327*b13c0e40SEric Biggers 	}
328*b13c0e40SEric Biggers 	*sig_size_ret = sig_size;
329*b13c0e40SEric Biggers 	err = 0;
330*b13c0e40SEric Biggers out:
331*b13c0e40SEric Biggers 	PKCS7_free(p7);
332*b13c0e40SEric Biggers 	BIO_free(bio);
333*b13c0e40SEric Biggers 	return err;
334*b13c0e40SEric Biggers }
335*b13c0e40SEric Biggers 
336*b13c0e40SEric Biggers static int
load_pkcs11_private_key(const struct libfsverity_signature_params * sig_params,EVP_PKEY ** pkey_ret)337*b13c0e40SEric Biggers load_pkcs11_private_key(const struct libfsverity_signature_params *sig_params,
338*b13c0e40SEric Biggers 			EVP_PKEY **pkey_ret)
339*b13c0e40SEric Biggers {
340*b13c0e40SEric Biggers 	ENGINE *engine;
341*b13c0e40SEric Biggers 
342*b13c0e40SEric Biggers 	if (!sig_params->pkcs11_engine) {
343*b13c0e40SEric Biggers 		libfsverity_error_msg("no PKCS#11 engine specified");
344*b13c0e40SEric Biggers 		return -EINVAL;
345*b13c0e40SEric Biggers 	}
346*b13c0e40SEric Biggers 	if (!sig_params->pkcs11_module) {
347*b13c0e40SEric Biggers 		libfsverity_error_msg("no PKCS#11 module specified");
348*b13c0e40SEric Biggers 		return -EINVAL;
349*b13c0e40SEric Biggers 	}
350*b13c0e40SEric Biggers 	ENGINE_load_dynamic();
351*b13c0e40SEric Biggers 	engine = ENGINE_by_id("dynamic");
352*b13c0e40SEric Biggers 	if (!engine) {
353*b13c0e40SEric Biggers 		error_msg_openssl("failed to initialize OpenSSL PKCS#11 engine");
354*b13c0e40SEric Biggers 		return -EINVAL;
355*b13c0e40SEric Biggers 	}
356*b13c0e40SEric Biggers 	if (!ENGINE_ctrl_cmd_string(engine, "SO_PATH",
357*b13c0e40SEric Biggers 				    sig_params->pkcs11_engine, 0) ||
358*b13c0e40SEric Biggers 	    !ENGINE_ctrl_cmd_string(engine, "ID", "pkcs11", 0) ||
359*b13c0e40SEric Biggers 	    !ENGINE_ctrl_cmd_string(engine, "LIST_ADD", "1", 0) ||
360*b13c0e40SEric Biggers 	    !ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0) ||
361*b13c0e40SEric Biggers 	    !ENGINE_ctrl_cmd_string(engine, "MODULE_PATH",
362*b13c0e40SEric Biggers 				    sig_params->pkcs11_module, 0) ||
363*b13c0e40SEric Biggers 	    !ENGINE_init(engine)) {
364*b13c0e40SEric Biggers 		error_msg_openssl("failed to initialize OpenSSL PKCS#11 engine");
365*b13c0e40SEric Biggers 		ENGINE_free(engine);
366*b13c0e40SEric Biggers 		return -EINVAL;
367*b13c0e40SEric Biggers 	}
368*b13c0e40SEric Biggers 	*pkey_ret = ENGINE_load_private_key(engine, sig_params->pkcs11_keyid,
369*b13c0e40SEric Biggers 					    NULL, NULL);
370*b13c0e40SEric Biggers 	ENGINE_finish(engine);
371*b13c0e40SEric Biggers 	ENGINE_free(engine);
372*b13c0e40SEric Biggers 	if (!*pkey_ret) {
373*b13c0e40SEric Biggers 		error_msg_openssl("failed to load private key from PKCS#11 token");
374*b13c0e40SEric Biggers 		return -EINVAL;
375*b13c0e40SEric Biggers 	}
376*b13c0e40SEric Biggers 	return 0;
377*b13c0e40SEric Biggers }
378*b13c0e40SEric Biggers 
379*b13c0e40SEric Biggers #endif /* !OPENSSL_IS_BORINGSSL */
380*b13c0e40SEric Biggers 
381*b13c0e40SEric Biggers /* Get a private key, either from disk or from a PKCS#11 token. */
382*b13c0e40SEric Biggers static int
get_private_key(const struct libfsverity_signature_params * sig_params,EVP_PKEY ** pkey_ret)383*b13c0e40SEric Biggers get_private_key(const struct libfsverity_signature_params *sig_params,
384*b13c0e40SEric Biggers 		EVP_PKEY **pkey_ret)
385*b13c0e40SEric Biggers {
386*b13c0e40SEric Biggers 	if (sig_params->pkcs11_engine || sig_params->pkcs11_module ||
387*b13c0e40SEric Biggers 	    sig_params->pkcs11_keyid) {
388*b13c0e40SEric Biggers 		if (sig_params->keyfile) {
389*b13c0e40SEric Biggers 			libfsverity_error_msg("private key must be specified either by file or by PKCS#11 token, not both");
390*b13c0e40SEric Biggers 			return -EINVAL;
391*b13c0e40SEric Biggers 		}
392*b13c0e40SEric Biggers 		return load_pkcs11_private_key(sig_params, pkey_ret);
393*b13c0e40SEric Biggers 	}
394*b13c0e40SEric Biggers 	if (!sig_params->keyfile) {
395*b13c0e40SEric Biggers 		libfsverity_error_msg("no private key specified");
396*b13c0e40SEric Biggers 		return -EINVAL;
397*b13c0e40SEric Biggers 	}
398*b13c0e40SEric Biggers 	return read_private_key(sig_params->keyfile, pkey_ret);
399*b13c0e40SEric Biggers }
400*b13c0e40SEric Biggers 
401*b13c0e40SEric Biggers LIBEXPORT int
libfsverity_sign_digest(const struct libfsverity_digest * digest,const struct libfsverity_signature_params * sig_params,u8 ** sig_ret,size_t * sig_size_ret)402*b13c0e40SEric Biggers libfsverity_sign_digest(const struct libfsverity_digest *digest,
403*b13c0e40SEric Biggers 			const struct libfsverity_signature_params *sig_params,
404*b13c0e40SEric Biggers 			u8 **sig_ret, size_t *sig_size_ret)
405*b13c0e40SEric Biggers {
406*b13c0e40SEric Biggers 	const struct fsverity_hash_alg *hash_alg;
407*b13c0e40SEric Biggers 	X509 *cert = NULL;
408*b13c0e40SEric Biggers 	EVP_PKEY *pkey = NULL;
409*b13c0e40SEric Biggers 	const EVP_MD *md;
410*b13c0e40SEric Biggers 	struct fsverity_formatted_digest *d = NULL;
411*b13c0e40SEric Biggers 	int err;
412*b13c0e40SEric Biggers 
413*b13c0e40SEric Biggers 	if (!digest || !sig_params || !sig_ret || !sig_size_ret)  {
414*b13c0e40SEric Biggers 		libfsverity_error_msg("missing required parameters for sign_digest");
415*b13c0e40SEric Biggers 		return -EINVAL;
416*b13c0e40SEric Biggers 	}
417*b13c0e40SEric Biggers 
418*b13c0e40SEric Biggers 	if (!libfsverity_mem_is_zeroed(sig_params->reserved1,
419*b13c0e40SEric Biggers 				       sizeof(sig_params->reserved1)) ||
420*b13c0e40SEric Biggers 	    !libfsverity_mem_is_zeroed(sig_params->reserved2,
421*b13c0e40SEric Biggers 				       sizeof(sig_params->reserved2))) {
422*b13c0e40SEric Biggers 		libfsverity_error_msg("reserved bits set in signature_params");
423*b13c0e40SEric Biggers 		return -EINVAL;
424*b13c0e40SEric Biggers 	}
425*b13c0e40SEric Biggers 
426*b13c0e40SEric Biggers 	hash_alg = libfsverity_find_hash_alg_by_num(digest->digest_algorithm);
427*b13c0e40SEric Biggers 	if (!hash_alg || digest->digest_size != hash_alg->digest_size) {
428*b13c0e40SEric Biggers 		libfsverity_error_msg("malformed fsverity digest");
429*b13c0e40SEric Biggers 		return -EINVAL;
430*b13c0e40SEric Biggers 	}
431*b13c0e40SEric Biggers 
432*b13c0e40SEric Biggers 	err = read_certificate(sig_params->certfile, &cert);
433*b13c0e40SEric Biggers 	if (err)
434*b13c0e40SEric Biggers 		goto out;
435*b13c0e40SEric Biggers 
436*b13c0e40SEric Biggers 	err = get_private_key(sig_params, &pkey);
437*b13c0e40SEric Biggers 	if (err)
438*b13c0e40SEric Biggers 		goto out;
439*b13c0e40SEric Biggers 
440*b13c0e40SEric Biggers 	OpenSSL_add_all_digests();
441*b13c0e40SEric Biggers 	md = EVP_get_digestbyname(hash_alg->name);
442*b13c0e40SEric Biggers 	if (!md) {
443*b13c0e40SEric Biggers 		libfsverity_error_msg("'%s' algorithm not found in OpenSSL library",
444*b13c0e40SEric Biggers 				      hash_alg->name);
445*b13c0e40SEric Biggers 		err = -ENOPKG;
446*b13c0e40SEric Biggers 		goto out;
447*b13c0e40SEric Biggers 	}
448*b13c0e40SEric Biggers 
449*b13c0e40SEric Biggers 	d = libfsverity_zalloc(sizeof(*d) + digest->digest_size);
450*b13c0e40SEric Biggers 	if (!d) {
451*b13c0e40SEric Biggers 		err = -ENOMEM;
452*b13c0e40SEric Biggers 		goto out;
453*b13c0e40SEric Biggers 	}
454*b13c0e40SEric Biggers 	memcpy(d->magic, "FSVerity", 8);
455*b13c0e40SEric Biggers 	d->digest_algorithm = cpu_to_le16(digest->digest_algorithm);
456*b13c0e40SEric Biggers 	d->digest_size = cpu_to_le16(digest->digest_size);
457*b13c0e40SEric Biggers 	memcpy(d->digest, digest->digest, digest->digest_size);
458*b13c0e40SEric Biggers 
459*b13c0e40SEric Biggers 	err = sign_pkcs7(d, sizeof(*d) + digest->digest_size,
460*b13c0e40SEric Biggers 			 pkey, cert, md, sig_ret, sig_size_ret);
461*b13c0e40SEric Biggers  out:
462*b13c0e40SEric Biggers 	X509_free(cert);
463*b13c0e40SEric Biggers 	EVP_PKEY_free(pkey);
464*b13c0e40SEric Biggers 	free(d);
465*b13c0e40SEric Biggers 	return err;
466*b13c0e40SEric Biggers }
467