From: Dmitry Kasatkin <d.kasatkin@samsung.com>
To: David Howells <dhowells@redhat.com>, rusty@rustcorp.com.au
Cc: mmarek@suse.cz, keyrings@linux-nfs.org,
linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org, zohar@linux.vnet.ibm.com
Subject: Re: [PATCH 4/5] MODSIGN: Provide a utility to append a PKCS#7 signature to a module [ver #2]
Date: Fri, 05 Dec 2014 10:54:54 +0200 [thread overview]
Message-ID: <548172DE.9090007@samsung.com> (raw)
In-Reply-To: <20141126141753.3944.22213.stgit@warthog.procyon.org.uk>
Hi David,
sign-file.c produce lots of annoying noise.
scripts/sign-file.c:153:2: warning: format not a string literal and no
format arguments [-Wformat-security]
ERR(!bd, dest_name);
^
scripts/sign-file.c:179:3: warning: format not a string literal and no
format arguments [-Wformat-security]
ERR(!b, pkcs7_name);
^
scripts/sign-file.c:180:3: warning: format not a string literal and no
format arguments [-Wformat-security]
ERR(i2d_PKCS7_bio_stream(b, pkcs7, NULL, 0) < 0, pkcs7_name);
^
scripts/sign-file.c:185:2: warning: format not a string literal and no
format arguments [-Wformat-security]
ERR(BIO_reset(bm) < 0, module_name);
^
Would be great to fix it.
Thanks,
Dmitry
On 26/11/14 16:17, David Howells wrote:
> Provide a utility that:
>
> (1) Digests a module using the specified hash algorithm (typically sha256).
>
> [The digest can be dumped into a file by passing the '-d' flag]
>
> (2) Generates a PKCS#7 message that:
>
> (a) Has detached data (ie. the module content).
>
> (b) Is signed with the specified private key.
>
> (c) Refers to the specified X.509 certificate.
>
> (d) Has an empty X.509 certificate list.
>
> [The PKCS#7 message can be dumped into a file by passing the '-p' flag]
>
> (3) Generates a signed module by concatenating the old module, the PKCS#7
> message, a descriptor and a magic string. The descriptor contains the
> size of the PKCS#7 message and indicates the id_type as PKEY_ID_PKCS7.
>
> (4) Either writes the signed module to the specified destination or renames
> it over the source module.
>
> This allows module signing to reuse the PKCS#7 handling code that was added
> for PE file parsing for signed kexec.
>
> Note that the utility is written in C and must be linked against the OpenSSL
> crypto library.
>
> Note further that I have temporarily dropped support for handling externally
> created signatures until we can work out the best way to do those. Hopefully,
> whoever creates the signature can give me a PKCS#7 certificate.
>
> Signed-off-by: David Howells <dhowells@redhat.com>
> ---
>
> include/crypto/public_key.h | 1
> scripts/sign-file.c | 189 +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 190 insertions(+)
> create mode 100755 scripts/sign-file.c
>
> diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
> index b6f27a240856..fda097e079a4 100644
> --- a/include/crypto/public_key.h
> +++ b/include/crypto/public_key.h
> @@ -33,6 +33,7 @@ extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST];
> enum pkey_id_type {
> PKEY_ID_PGP, /* OpenPGP generated key ID */
> PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
> + PKEY_ID_PKCS7, /* Signature in PKCS#7 message */
> PKEY_ID_TYPE__LAST
> };
>
> diff --git a/scripts/sign-file.c b/scripts/sign-file.c
> new file mode 100755
> index 000000000000..3f9bedbd185f
> --- /dev/null
> +++ b/scripts/sign-file.c
> @@ -0,0 +1,189 @@
> +/* Sign a module file using the given key.
> + *
> + * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
> + * Written by David Howells (dhowells@redhat.com)
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public Licence
> + * as published by the Free Software Foundation; either version
> + * 2 of the Licence, or (at your option) any later version.
> + */
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <stdbool.h>
> +#include <string.h>
> +#include <getopt.h>
> +#include <err.h>
> +#include <arpa/inet.h>
> +#include <openssl/bio.h>
> +#include <openssl/evp.h>
> +#include <openssl/pem.h>
> +#include <openssl/pkcs7.h>
> +#include <openssl/err.h>
> +
> +struct module_signature {
> + uint8_t algo; /* Public-key crypto algorithm [0] */
> + uint8_t hash; /* Digest algorithm [0] */
> + uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7] */
> + uint8_t signer_len; /* Length of signer's name [0] */
> + uint8_t key_id_len; /* Length of key identifier [0] */
> + uint8_t __pad[3];
> + uint32_t sig_len; /* Length of signature data */
> +};
> +
> +#define PKEY_ID_PKCS7 2
> +
> +static char magic_number[] = "~Module signature appended~\n";
> +
> +static __attribute__((noreturn))
> +void format(void)
> +{
> + fprintf(stderr,
> + "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n");
> + exit(2);
> +}
> +
> +static void display_openssl_errors(int l)
> +{
> + const char *file;
> + char buf[120];
> + int e, line;
> +
> + if (ERR_peek_error() == 0)
> + return;
> + fprintf(stderr, "At main.c:%d:\n", l);
> +
> + while ((e = ERR_get_error_line(&file, &line))) {
> + ERR_error_string(e, buf);
> + fprintf(stderr, "- SSL %s: %s:%d\n", buf, file, line);
> + }
> +}
> +
> +
> +#define ERR(cond, ...) \
> + do { \
> + bool __cond = (cond); \
> + display_openssl_errors(__LINE__); \
> + if (__cond) { \
> + err(1, ## __VA_ARGS__); \
> + } \
> + } while(0)
> +
> +int main(int argc, char **argv)
> +{
> + struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 };
> + char *hash_algo = NULL;
> + char *private_key_name, *x509_name, *module_name, *dest_name;
> + bool save_pkcs7 = false, replace_orig;
> + unsigned char buf[4096];
> + unsigned long module_size, pkcs7_size;
> + const EVP_MD *digest_algo;
> + EVP_PKEY *private_key;
> + PKCS7 *pkcs7;
> + X509 *x509;
> + BIO *b, *bd, *bm;
> + int opt, n;
> +
> + do {
> + opt = getopt(argc, argv, "dp");
> + switch (opt) {
> + case 'p': save_pkcs7 = true; break;
> + case -1: break;
> + default: format();
> + }
> + } while (opt != -1);
> +
> + argc -= optind;
> + argv += optind;
> + if (argc < 4 || argc > 5)
> + format();
> +
> + hash_algo = argv[0];
> + private_key_name = argv[1];
> + x509_name = argv[2];
> + module_name = argv[3];
> + if (argc == 5) {
> + dest_name = argv[4];
> + replace_orig = false;
> + } else {
> + ERR(asprintf(&dest_name, "%s.~signed~", module_name) < 0,
> + "asprintf");
> + replace_orig = true;
> + }
> +
> + ERR_load_crypto_strings();
> + ERR_clear_error();
> +
> + /* Read the private key and the X.509 cert the PKCS#7 message
> + * will point to.
> + */
> + b = BIO_new_file(private_key_name, "rb");
> + ERR(!b, "%s", private_key_name);
> + private_key = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
> + BIO_free(b);
> +
> + b = BIO_new_file(x509_name, "rb");
> + ERR(!b, "%s", x509_name);
> + x509 = PEM_read_bio_X509(b, NULL, NULL, NULL);
> + BIO_free(b);
> +
> + /* Open the destination file now so that we can shovel the module data
> + * across as we read it.
> + */
> + bd = BIO_new_file(dest_name, "wb");
> + ERR(!bd, dest_name);
> +
> + /* Digest the module data. */
> + OpenSSL_add_all_digests();
> + display_openssl_errors(__LINE__);
> + digest_algo = EVP_get_digestbyname(hash_algo);
> + ERR(!digest_algo, "EVP_get_digestbyname");
> +
> + bm = BIO_new_file(module_name, "rb");
> + ERR(!bm, "%s", module_name);
> +
> + /* Load the PKCS#7 message from the digest buffer. */
> + pkcs7 = PKCS7_sign(NULL, NULL, NULL, NULL,
> + PKCS7_NOCERTS | PKCS7_PARTIAL | PKCS7_BINARY | PKCS7_DETACHED | PKCS7_STREAM);
> + ERR(!pkcs7, "PKCS7_sign");
> +
> + ERR(PKCS7_sign_add_signer(pkcs7, x509, private_key, digest_algo, PKCS7_NOCERTS | PKCS7_BINARY) < 0,
> + "PKCS7_sign_add_signer");
> + ERR(PKCS7_final(pkcs7, bm, PKCS7_NOCERTS | PKCS7_BINARY) < 0,
> + "PKCS7_final");
> +
> + if (save_pkcs7) {
> + char *pkcs7_name;
> +
> + ERR(asprintf(&pkcs7_name, "%s.pkcs7", module_name) < 0, "asprintf");
> + b = BIO_new_file(pkcs7_name, "wb");
> + ERR(!b, pkcs7_name);
> + ERR(i2d_PKCS7_bio_stream(b, pkcs7, NULL, 0) < 0, pkcs7_name);
> + BIO_free(b);
> + }
> +
> + /* Append the marker and the PKCS#7 message to the destination file */
> + ERR(BIO_reset(bm) < 0, module_name);
> + while ((n = BIO_read(bm, buf, sizeof(buf))),
> + n > 0) {
> + ERR(BIO_write(bd, buf, n) < 0, dest_name);
> + }
> + ERR(n < 0, module_name);
> + module_size = BIO_number_written(bd);
> +
> + ERR(i2d_PKCS7_bio_stream(bd, pkcs7, NULL, 0) < 0, dest_name);
> + pkcs7_size = BIO_number_written(bd) - module_size;
> + sig_info.sig_len = htonl(pkcs7_size);
> + ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, dest_name);
> + ERR(BIO_write(bd, magic_number, sizeof(magic_number) - 1) < 0, dest_name);
> +
> + ERR(BIO_free(bd) < 0, dest_name);
> +
> + /* Finally, if we're signing in place, replace the original. */
> + if (replace_orig)
> + ERR(rename(dest_name, module_name) < 0, dest_name);
> +
> + return 0;
> +}
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
next prev parent reply other threads:[~2014-12-05 8:56 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-26 14:17 [PATCH 0/5] MODSIGN: Use PKCS#7 for module signatures [ver #2] David Howells
2014-11-26 14:17 ` [PATCH 1/5] X.509: Extract both parts of the AuthorityKeyIdentifier " David Howells
2014-12-04 12:14 ` Dmitry Kasatkin
2014-12-04 12:51 ` David Howells
2014-11-26 14:17 ` [PATCH 2/5] X.509: Support X.509 lookup by Issuer+Serial form " David Howells
2014-11-26 14:17 ` [PATCH 3/5] PKCS#7: Allow detached data to be supplied for signature checking purposes " David Howells
2014-11-26 14:17 ` [PATCH 4/5] MODSIGN: Provide a utility to append a PKCS#7 signature to a module " David Howells
2014-12-05 8:54 ` Dmitry Kasatkin [this message]
2014-12-05 10:23 ` David Howells
2014-12-05 12:47 ` Dmitry Kasatkin
2014-12-05 12:49 ` Dmitry Kasatkin
2014-12-05 14:04 ` David Howells
2014-12-05 14:37 ` Dmitry Kasatkin
2014-12-11 16:41 ` David Howells
2014-11-26 14:18 ` [PATCH 5/5] MODSIGN: Use PKCS#7 messages as module signatures " David Howells
2014-12-04 18:56 ` [PATCH 0/5] MODSIGN: Use PKCS#7 for " Vivek Goyal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=548172DE.9090007@samsung.com \
--to=d.kasatkin@samsung.com \
--cc=dhowells@redhat.com \
--cc=keyrings@linux-nfs.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mmarek@suse.cz \
--cc=rusty@rustcorp.com.au \
--cc=zohar@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.