blob: 20fecfa768a67755b6dc9e33a7082bb6b9555ffa [file] [log] [blame]
Eric Biggers431c67b2018-06-27 15:01:06 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Signature support for 'fsverity setup'
4 *
Eric Biggers8387ad32018-08-21 12:37:56 -07005 * Copyright (C) 2018 Google LLC
Eric Biggers431c67b2018-06-27 15:01:06 -07006 *
Eric Biggers8387ad32018-08-21 12:37:56 -07007 * Written by Eric Biggers.
Eric Biggers431c67b2018-06-27 15:01:06 -07008 */
9
10#include <fcntl.h>
Eric Biggersd0ae4522018-06-27 22:01:25 -070011#include <limits.h>
Eric Biggers431c67b2018-06-27 15:01:06 -070012#include <openssl/bio.h>
13#include <openssl/err.h>
14#include <openssl/pem.h>
15#include <openssl/pkcs7.h>
Eric Biggersd0ae4522018-06-27 22:01:25 -070016#include <stdlib.h>
Eric Biggers431c67b2018-06-27 15:01:06 -070017#include <string.h>
18
Eric Biggers25b59452018-07-27 10:47:02 -070019#include "fsverity_uapi.h"
Eric Biggers431c67b2018-06-27 15:01:06 -070020#include "fsveritysetup.h"
21#include "hash_algs.h"
22
Adam Langley8957d752018-08-06 16:11:22 -070023static void __printf(1, 2) __cold
24error_msg_openssl(const char *format, ...)
Eric Biggers431c67b2018-06-27 15:01:06 -070025{
Adam Langley8957d752018-08-06 16:11:22 -070026 va_list va;
27
28 va_start(va, format);
29 do_error_msg(format, va, 0);
30 va_end(va);
31
Eric Biggers431c67b2018-06-27 15:01:06 -070032 if (ERR_peek_error() == 0)
33 return;
34
35 fprintf(stderr, "OpenSSL library errors:\n");
Adam Langley06666002018-08-06 16:03:07 -070036 ERR_print_errors_fp(stderr);
Eric Biggers431c67b2018-06-27 15:01:06 -070037}
38
39/* Read a PEM PKCS#8 formatted private key */
40static EVP_PKEY *read_private_key(const char *keyfile)
41{
42 BIO *bio;
43 EVP_PKEY *pkey;
44
45 bio = BIO_new_file(keyfile, "r");
46 if (!bio) {
Adam Langley8957d752018-08-06 16:11:22 -070047 error_msg_openssl("can't open '%s' for reading", keyfile);
Eric Biggers431c67b2018-06-27 15:01:06 -070048 return NULL;
49 }
50
51 pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
52 if (!pkey) {
Adam Langley8957d752018-08-06 16:11:22 -070053 error_msg_openssl("Failed to parse private key file '%s'.\n"
54 " Note: it must be in PEM PKCS#8 format.",
55 keyfile);
Eric Biggers431c67b2018-06-27 15:01:06 -070056 }
57 BIO_free(bio);
58 return pkey;
59}
60
61/* Read a PEM X.509 formatted certificate */
62static X509 *read_certificate(const char *certfile)
63{
64 BIO *bio;
65 X509 *cert;
66
67 bio = BIO_new_file(certfile, "r");
68 if (!bio) {
Adam Langley8957d752018-08-06 16:11:22 -070069 error_msg_openssl("can't open '%s' for reading", certfile);
Eric Biggers431c67b2018-06-27 15:01:06 -070070 return NULL;
71 }
72 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
73 if (!cert) {
Adam Langley8957d752018-08-06 16:11:22 -070074 error_msg_openssl("Failed to parse X.509 certificate file '%s'.\n"
75 " Note: it must be in PEM format.",
76 certfile);
Eric Biggers431c67b2018-06-27 15:01:06 -070077 }
78 BIO_free(bio);
79 return cert;
80}
81
82/*
Eric Biggers25b59452018-07-27 10:47:02 -070083 * Check that the given data is a valid 'struct fsverity_digest_disk' that
84 * matches the given @expected_digest and @hash_alg.
Eric Biggers431c67b2018-06-27 15:01:06 -070085 *
Eric Biggers25b59452018-07-27 10:47:02 -070086 * Return: NULL if the digests match, else a string describing the difference.
Eric Biggers431c67b2018-06-27 15:01:06 -070087 */
88static const char *
Eric Biggers25b59452018-07-27 10:47:02 -070089compare_fsverity_digest(const void *data, size_t size,
90 const u8 *expected_digest,
91 const struct fsverity_hash_alg *hash_alg)
Eric Biggers431c67b2018-06-27 15:01:06 -070092{
Eric Biggers25b59452018-07-27 10:47:02 -070093 const struct fsverity_digest_disk *d = data;
Eric Biggers431c67b2018-06-27 15:01:06 -070094
Eric Biggers25b59452018-07-27 10:47:02 -070095 if (size != sizeof(*d) + hash_alg->digest_size)
Eric Biggers431c67b2018-06-27 15:01:06 -070096 return "unexpected length";
97
Eric Biggers25b59452018-07-27 10:47:02 -070098 if (le16_to_cpu(d->digest_algorithm) != hash_alg - fsverity_hash_algs)
Eric Biggers431c67b2018-06-27 15:01:06 -070099 return "unexpected hash algorithm";
100
Eric Biggers25b59452018-07-27 10:47:02 -0700101 if (le16_to_cpu(d->digest_size) != hash_alg->digest_size)
Eric Biggers431c67b2018-06-27 15:01:06 -0700102 return "wrong digest size for hash algorithm";
103
Eric Biggers25b59452018-07-27 10:47:02 -0700104 if (memcmp(expected_digest, d->digest, hash_alg->digest_size))
105 return "wrong digest";
Eric Biggers431c67b2018-06-27 15:01:06 -0700106
107 return NULL;
108}
109
Adam Langleybdebc452018-08-07 10:32:19 -0700110#ifdef OPENSSL_IS_BORINGSSL
111
112static bool sign_pkcs7(const void *data_to_sign, size_t data_size,
113 EVP_PKEY *pkey, X509 *cert, const EVP_MD *md,
114 void **sig_ret, int *sig_size_ret)
Eric Biggers431c67b2018-06-27 15:01:06 -0700115{
Adam Langleybdebc452018-08-07 10:32:19 -0700116 CBB out, outer_seq, wrapped_seq, seq, digest_algos_set, digest_algo,
117 null, content_info, issuer_and_serial, signed_data,
118 wrapped_signed_data, signer_infos, signer_info, sign_algo,
119 signature;
120 EVP_MD_CTX md_ctx;
121 u8 *name_der = NULL, *sig = NULL, *pkcs7_data = NULL;
122 size_t pkcs7_data_len, sig_len;
123 int name_der_len, sig_nid;
124 bool ok = false;
125
126 EVP_MD_CTX_init(&md_ctx);
127 BIGNUM *serial = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), NULL);
128
129 if (!CBB_init(&out, 1024)) {
130 error_msg("out of memory");
131 goto out;
132 }
133
134 name_der_len = i2d_X509_NAME(X509_get_subject_name(cert), &name_der);
135 if (name_der_len < 0) {
136 error_msg_openssl("i2d_X509_NAME failed");
137 goto out;
138 }
139
140 if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey)) {
141 error_msg_openssl("EVP_DigestSignInit failed");
142 goto out;
143 }
144
145 sig_len = EVP_PKEY_size(pkey);
146 sig = xmalloc(sig_len);
147 if (!EVP_DigestSign(&md_ctx, sig, &sig_len, data_to_sign, data_size)) {
148 error_msg_openssl("EVP_DigestSign failed");
149 goto out;
150 }
151
152 sig_nid = EVP_PKEY_id(pkey);
153 /* To mirror OpenSSL behaviour, always use |NID_rsaEncryption| with RSA
154 * rather than the combined hash+pkey NID. */
155 if (sig_nid != NID_rsaEncryption) {
156 OBJ_find_sigid_by_algs(&sig_nid, EVP_MD_type(md),
157 EVP_PKEY_id(pkey));
158 }
159
160 // See https://tools.ietf.org/html/rfc2315#section-7
161 if (!CBB_add_asn1(&out, &outer_seq, CBS_ASN1_SEQUENCE) ||
162 !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
163 !CBB_add_asn1(&outer_seq, &wrapped_seq, CBS_ASN1_CONTEXT_SPECIFIC |
164 CBS_ASN1_CONSTRUCTED | 0) ||
165 // See https://tools.ietf.org/html/rfc2315#section-9.1
166 !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
167 !CBB_add_asn1_uint64(&seq, 1 /* version */) ||
168 !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
169 !CBB_add_asn1(&digest_algos_set, &digest_algo, CBS_ASN1_SEQUENCE) ||
170 !OBJ_nid2cbb(&digest_algo, EVP_MD_type(md)) ||
171 !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
172 !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
173 !OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
174 !CBB_add_asn1(
175 &content_info, &signed_data,
176 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
177 !CBB_add_asn1(&signed_data, &wrapped_signed_data,
178 CBS_ASN1_OCTETSTRING) ||
179 !CBB_add_bytes(&wrapped_signed_data, (const u8 *)data_to_sign,
180 data_size) ||
181 !CBB_add_asn1(&seq, &signer_infos, CBS_ASN1_SET) ||
182 !CBB_add_asn1(&signer_infos, &signer_info, CBS_ASN1_SEQUENCE) ||
183 !CBB_add_asn1_uint64(&signer_info, 1 /* version */) ||
184 !CBB_add_asn1(&signer_info, &issuer_and_serial,
185 CBS_ASN1_SEQUENCE) ||
186 !CBB_add_bytes(&issuer_and_serial, name_der, name_der_len) ||
187 !BN_marshal_asn1(&issuer_and_serial, serial) ||
188 !CBB_add_asn1(&signer_info, &digest_algo, CBS_ASN1_SEQUENCE) ||
189 !OBJ_nid2cbb(&digest_algo, EVP_MD_type(md)) ||
190 !CBB_add_asn1(&digest_algo, &null, CBS_ASN1_NULL) ||
191 !CBB_add_asn1(&signer_info, &sign_algo, CBS_ASN1_SEQUENCE) ||
192 !OBJ_nid2cbb(&sign_algo, sig_nid) ||
193 !CBB_add_asn1(&sign_algo, &null, CBS_ASN1_NULL) ||
194 !CBB_add_asn1(&signer_info, &signature, CBS_ASN1_OCTETSTRING) ||
195 !CBB_add_bytes(&signature, sig, sig_len) ||
196 !CBB_finish(&out, &pkcs7_data, &pkcs7_data_len)) {
197 error_msg_openssl("failed to construct PKCS#7 data");
198 goto out;
199 }
200
201 *sig_ret = xmemdup(pkcs7_data, pkcs7_data_len);
202 *sig_size_ret = pkcs7_data_len;
203 ok = true;
204out:
205 BN_free(serial);
206 EVP_MD_CTX_cleanup(&md_ctx);
207 CBB_cleanup(&out);
208 free(sig);
209 OPENSSL_free(name_der);
210 OPENSSL_free(pkcs7_data);
211 return ok;
212}
213
214static const char *
215compare_fsverity_digest_pkcs7(const void *sig, size_t sig_len,
216 const u8 *expected_measurement,
217 const struct fsverity_hash_alg *hash_alg)
218{
219 CBS in, content_info, content_type, wrapped_signed_data, signed_data,
220 content, wrapped_data, data;
221 u64 version;
222
223 CBS_init(&in, sig, sig_len);
224 if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) ||
225 !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT) ||
226 (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) ||
227 !CBS_get_asn1(
228 &content_info, &wrapped_signed_data,
229 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
230 !CBS_get_asn1(&wrapped_signed_data, &signed_data,
231 CBS_ASN1_SEQUENCE) ||
232 !CBS_get_asn1_uint64(&signed_data, &version) ||
233 (version < 1) ||
234 !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) ||
235 !CBS_get_asn1(&signed_data, &content, CBS_ASN1_SEQUENCE) ||
236 !CBS_get_asn1(&content, &content_type, CBS_ASN1_OBJECT) ||
237 (OBJ_cbs2nid(&content_type) != NID_pkcs7_data) ||
238 !CBS_get_asn1(&content, &wrapped_data, CBS_ASN1_CONTEXT_SPECIFIC |
239 CBS_ASN1_CONSTRUCTED | 0) ||
240 !CBS_get_asn1(&wrapped_data, &data, CBS_ASN1_OCTETSTRING)) {
241 return "invalid PKCS#7 data";
242 }
243
244 return compare_fsverity_digest(CBS_data(&data), CBS_len(&data),
245 expected_measurement, hash_alg);
246}
247
248#else /* OPENSSL_IS_BORINGSSL */
249
250static BIO *new_mem_buf(const void *buf, size_t size)
251{
252 BIO *bio;
253
254 ASSERT(size <= INT_MAX);
255 /*
256 * Prior to OpenSSL 1.1.0, BIO_new_mem_buf() took a non-const pointer,
257 * despite still marking the resulting bio as read-only. So cast away
258 * the const to avoid a compiler warning with older OpenSSL versions.
259 */
260 bio = BIO_new_mem_buf((void *)buf, size);
261 if (!bio)
262 error_msg_openssl("out of memory");
263 return bio;
264}
265
266static bool sign_pkcs7(const void *data_to_sign, size_t data_size,
267 EVP_PKEY *pkey, X509 *cert, const EVP_MD *md,
268 void **sig_ret, int *sig_size_ret)
269{
Eric Biggers431c67b2018-06-27 15:01:06 -0700270 /*
271 * PKCS#7 signing flags:
272 *
273 * - PKCS7_BINARY signing binary data, so skip MIME translation
274 *
275 * - PKCS7_NOATTR omit extra authenticated attributes, such as
276 * SMIMECapabilities
277 *
278 * - PKCS7_NOCERTS omit the signer's certificate
279 *
280 * - PKCS7_PARTIAL PKCS7_sign() creates a handle only, then
281 * PKCS7_sign_add_signer() can add a signer later.
282 * This is necessary to change the message digest
283 * algorithm from the default of SHA-1. Requires
284 * OpenSSL 1.0.0 or later.
285 */
286 int pkcs7_flags = PKCS7_BINARY | PKCS7_NOATTR | PKCS7_NOCERTS |
287 PKCS7_PARTIAL;
288 void *sig;
289 int sig_size;
Adam Langleybdebc452018-08-07 10:32:19 -0700290 BIO *bio = NULL;
291 PKCS7 *p7 = NULL;
Eric Biggers431c67b2018-06-27 15:01:06 -0700292 bool ok = false;
293
Eric Biggersd0ae4522018-06-27 22:01:25 -0700294 bio = new_mem_buf(data_to_sign, data_size);
295 if (!bio)
Eric Biggers431c67b2018-06-27 15:01:06 -0700296 goto out;
Eric Biggers431c67b2018-06-27 15:01:06 -0700297
298 p7 = PKCS7_sign(NULL, NULL, NULL, bio, pkcs7_flags);
299 if (!p7) {
Adam Langley8957d752018-08-06 16:11:22 -0700300 error_msg_openssl("failed to initialize PKCS#7 signature object");
Eric Biggers431c67b2018-06-27 15:01:06 -0700301 goto out;
302 }
303
304 if (!PKCS7_sign_add_signer(p7, cert, pkey, md, pkcs7_flags)) {
Adam Langley8957d752018-08-06 16:11:22 -0700305 error_msg_openssl("failed to add signer to PKCS#7 signature object");
Eric Biggers431c67b2018-06-27 15:01:06 -0700306 goto out;
307 }
308
309 if (PKCS7_final(p7, bio, pkcs7_flags) != 1) {
Adam Langley8957d752018-08-06 16:11:22 -0700310 error_msg_openssl("failed to finalize PKCS#7 signature");
Eric Biggers431c67b2018-06-27 15:01:06 -0700311 goto out;
312 }
313
314 BIO_free(bio);
315 bio = BIO_new(BIO_s_mem());
316 if (!bio) {
Adam Langley8957d752018-08-06 16:11:22 -0700317 error_msg_openssl("out of memory");
Eric Biggers431c67b2018-06-27 15:01:06 -0700318 goto out;
319 }
320
321 if (i2d_PKCS7_bio(bio, p7) != 1) {
Adam Langley8957d752018-08-06 16:11:22 -0700322 error_msg_openssl("failed to DER-encode PKCS#7 signature object");
Eric Biggers431c67b2018-06-27 15:01:06 -0700323 goto out;
324 }
325
326 sig_size = BIO_get_mem_data(bio, &sig);
327 *sig_ret = xmemdup(sig, sig_size);
328 *sig_size_ret = sig_size;
329 ok = true;
330out:
Eric Biggers431c67b2018-06-27 15:01:06 -0700331 PKCS7_free(p7);
332 BIO_free(bio);
333 return ok;
334}
335
Adam Langleybdebc452018-08-07 10:32:19 -0700336static const char *
337compare_fsverity_digest_pkcs7(const void *sig, size_t sig_len,
338 const u8 *expected_measurement,
339 const struct fsverity_hash_alg *hash_alg)
340{
341 BIO *bio = NULL;
342 PKCS7 *p7 = NULL;
343 const char *reason = NULL;
344
345 bio = new_mem_buf(sig, sig_len);
346 if (!bio)
347 return "out of memory";
348
349 p7 = d2i_PKCS7_bio(bio, NULL);
350 if (!p7) {
351 reason = "failed to decode PKCS#7 signature";
352 goto out;
353 }
354
355 if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed ||
356 OBJ_obj2nid(p7->d.sign->contents->type) != NID_pkcs7_data) {
357 reason = "unexpected PKCS#7 content type";
358 } else {
359 const ASN1_OCTET_STRING *o = p7->d.sign->contents->d.data;
360
361 reason = compare_fsverity_digest(o->data, o->length,
362 expected_measurement,
363 hash_alg);
364 }
365out:
366 BIO_free(bio);
367 PKCS7_free(p7);
368 return reason;
369}
370
371#endif /* !OPENSSL_IS_BORINGSSL */
372
373/*
374 * Sign the specified @data_to_sign of length @data_size bytes using the private
375 * key in @keyfile, the certificate in @certfile, and the hash algorithm
376 * @hash_alg. Returns the DER-formatted PKCS#7 signature, with the signed data
377 * included (not detached), in @sig_ret and @sig_size_ret.
378 */
379static bool sign_data(const void *data_to_sign, size_t data_size,
380 const char *keyfile, const char *certfile,
381 const struct fsverity_hash_alg *hash_alg,
382 void **sig_ret, int *sig_size_ret)
383{
384 EVP_PKEY *pkey = NULL;
385 X509 *cert = NULL;
386 const EVP_MD *md;
387 bool ok = false;
388
389 pkey = read_private_key(keyfile);
390 if (!pkey)
391 goto out;
392
393 cert = read_certificate(certfile);
394 if (!cert)
395 goto out;
396
397 OpenSSL_add_all_digests();
398 ASSERT(hash_alg->cryptographic);
399 md = EVP_get_digestbyname(hash_alg->name);
400 if (!md) {
401 fprintf(stderr,
402 "Warning: '%s' algorithm not found in OpenSSL library.\n"
403 " Falling back to SHA-256 signature.\n",
404 hash_alg->name);
405 md = EVP_sha256();
406 }
407
408 ok = sign_pkcs7(data_to_sign, data_size, pkey, cert, md,
409 sig_ret, sig_size_ret);
410out:
411 EVP_PKEY_free(pkey);
412 X509_free(cert);
413 return ok;
414}
415
Eric Biggers431c67b2018-06-27 15:01:06 -0700416/*
417 * Read a file measurement signature in PKCS#7 DER format from @signature_file,
418 * validate that the signed data matches the expected measurement, then return
419 * the PKCS#7 DER message in @sig_ret and @sig_size_ret.
420 */
421static bool read_signature(const char *signature_file,
422 const u8 *expected_measurement,
423 const struct fsverity_hash_alg *hash_alg,
424 void **sig_ret, int *sig_size_ret)
425{
426 struct filedes file = { .fd = -1 };
427 u64 filesize;
428 void *sig = NULL;
Eric Biggers431c67b2018-06-27 15:01:06 -0700429 bool ok = false;
430 const char *reason;
431
432 if (!open_file(&file, signature_file, O_RDONLY, 0))
433 goto out;
434 if (!get_file_size(&file, &filesize))
435 goto out;
436 if (filesize <= 0) {
437 error_msg("signature file '%s' is empty", signature_file);
438 goto out;
439 }
440 if (filesize > 1000000) {
441 error_msg("signature file '%s' is too large", signature_file);
442 goto out;
443 }
444 sig = xmalloc(filesize);
445 if (!full_read(&file, sig, filesize))
446 goto out;
447
Adam Langleybdebc452018-08-07 10:32:19 -0700448 reason = compare_fsverity_digest_pkcs7(sig, filesize,
449 expected_measurement, hash_alg);
Eric Biggers431c67b2018-06-27 15:01:06 -0700450 if (reason) {
451 error_msg("signed file measurement from '%s' is invalid (%s)",
452 signature_file, reason);
453 goto out;
454 }
455
456 printf("Using existing signed file measurement from '%s'\n",
457 signature_file);
458 *sig_ret = sig;
459 *sig_size_ret = filesize;
460 sig = NULL;
461 ok = true;
462out:
463 filedes_close(&file);
464 free(sig);
Eric Biggers431c67b2018-06-27 15:01:06 -0700465 return ok;
466}
467
468static bool write_signature(const char *signature_file,
469 const void *sig, int sig_size)
470{
471 struct filedes file;
472 bool ok;
473
474 if (!open_file(&file, signature_file, O_WRONLY|O_CREAT|O_TRUNC, 0644))
475 return false;
476 ok = full_write(&file, sig, sig_size);
477 ok &= filedes_close(&file);
478 if (ok)
479 printf("Wrote signed file measurement to '%s'\n",
480 signature_file);
481 return ok;
482}
483
484/*
Eric Biggers25b59452018-07-27 10:47:02 -0700485 * Append the signed file measurement to the output file as a PKCS7_SIGNATURE
486 * extension item.
Eric Biggers431c67b2018-06-27 15:01:06 -0700487 *
488 * Return: exit status code (0 on success, nonzero on failure)
489 */
490int append_signed_measurement(struct filedes *out,
491 const struct fsveritysetup_params *params,
492 const u8 *measurement)
493{
Eric Biggers25b59452018-07-27 10:47:02 -0700494 struct fsverity_digest_disk *data_to_sign = NULL;
Eric Biggers431c67b2018-06-27 15:01:06 -0700495 void *sig = NULL;
496 void *extbuf = NULL;
497 void *tmp;
498 int sig_size;
499 int status;
500
501 if (params->signing_key_file) {
502 size_t data_size = sizeof(*data_to_sign) +
503 params->hash_alg->digest_size;
504
505 /* Sign the file measurement using the given key */
506
507 data_to_sign = xzalloc(data_size);
508 data_to_sign->digest_algorithm =
509 cpu_to_le16(params->hash_alg - fsverity_hash_algs);
510 data_to_sign->digest_size =
511 cpu_to_le16(params->hash_alg->digest_size);
512 memcpy(data_to_sign->digest, measurement,
513 params->hash_alg->digest_size);
514
Eric Biggers25b59452018-07-27 10:47:02 -0700515 ASSERT(compare_fsverity_digest(data_to_sign, data_size,
516 measurement, params->hash_alg) == NULL);
Eric Biggers431c67b2018-06-27 15:01:06 -0700517
518 if (!sign_data(data_to_sign, data_size,
519 params->signing_key_file,
520 params->signing_cert_file ?:
521 params->signing_key_file,
522 params->hash_alg,
523 &sig, &sig_size))
524 goto out_err;
525
526 if (params->signature_file &&
527 !write_signature(params->signature_file, sig, sig_size))
528 goto out_err;
529 } else {
Eric Biggers431c67b2018-06-27 15:01:06 -0700530 /* Using a signature that was already created */
531 if (!read_signature(params->signature_file, measurement,
532 params->hash_alg, &sig, &sig_size))
533 goto out_err;
534 }
535
Eric Biggers431c67b2018-06-27 15:01:06 -0700536 tmp = extbuf = xzalloc(FSVERITY_EXTLEN(sig_size));
537 fsverity_append_extension(&tmp, FS_VERITY_EXT_PKCS7_SIGNATURE,
538 sig, sig_size);
539 ASSERT(tmp == extbuf + FSVERITY_EXTLEN(sig_size));
540 if (!full_write(out, extbuf, FSVERITY_EXTLEN(sig_size)))
541 goto out_err;
542 status = 0;
543out:
544 free(data_to_sign);
545 free(sig);
546 free(extbuf);
547 return status;
548
549out_err:
550 status = 1;
551 goto out;
552}