diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-17 21:33:45 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-17 21:33:45 +0300 |
commit | bb7aeae3d680c2c777f54274b0270ced0599f33d (patch) | |
tree | 4801a103c2b157b5019cf38a19dc67d54bf38453 /scripts/sign-file.c | |
parent | 70477371dc350746d10431d74f0f213a8d59924c (diff) | |
parent | 88a1b564a20e371e6be41b39b85673e9c1959491 (diff) | |
download | linux-bb7aeae3d680c2c777f54274b0270ced0599f33d.tar.xz |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security layer updates from James Morris:
"There are a bunch of fixes to the TPM, IMA, and Keys code, with minor
fixes scattered across the subsystem.
IMA now requires signed policy, and that policy is also now measured
and appraised"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (67 commits)
X.509: Make algo identifiers text instead of enum
akcipher: Move the RSA DER encoding check to the crypto layer
crypto: Add hash param to pkcs1pad
sign-file: fix build with CMS support disabled
MAINTAINERS: update tpmdd urls
MODSIGN: linux/string.h should be #included to get memcpy()
certs: Fix misaligned data in extra certificate list
X.509: Handle midnight alternative notation in GeneralizedTime
X.509: Support leap seconds
Handle ISO 8601 leap seconds and encodings of midnight in mktime64()
X.509: Fix leap year handling again
PKCS#7: fix unitialized boolean 'want'
firmware: change kernel read fail to dev_dbg()
KEYS: Use the symbol value for list size, updated by scripts/insert-sys-cert
KEYS: Reserve an extra certificate symbol for inserting without recompiling
modsign: hide openssl output in silent builds
tpm_tis: fix build warning with tpm_tis_resume
ima: require signed IMA policy
ima: measure and appraise the IMA policy itself
ima: load policy using path
...
Diffstat (limited to 'scripts/sign-file.c')
-rwxr-xr-x | scripts/sign-file.c | 238 |
1 files changed, 147 insertions, 91 deletions
diff --git a/scripts/sign-file.c b/scripts/sign-file.c index 250a7a645033..d912d5a56a5e 100755 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -2,9 +2,11 @@ * * Copyright © 2014-2015 Red Hat, Inc. All Rights Reserved. * Copyright © 2015 Intel Corporation. + * Copyright © 2016 Hewlett Packard Enterprise Development LP * * Authors: David Howells <dhowells@redhat.com> * David Woodhouse <dwmw2@infradead.org> + * Juerg Haefliger <juerg.haefliger@hpe.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -39,7 +41,7 @@ * signing with anything other than SHA1 - so we're stuck with that if such is * the case. */ -#if OPENSSL_VERSION_NUMBER < 0x10000000L +#if OPENSSL_VERSION_NUMBER < 0x10000000L || defined(OPENSSL_NO_CMS) #define USE_PKCS7 #endif #ifndef USE_PKCS7 @@ -67,6 +69,8 @@ void format(void) { fprintf(stderr, "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n"); + fprintf(stderr, + " scripts/sign-file -s <raw sig> <hash algo> <x509> <module> [<dest>]\n"); exit(2); } @@ -126,26 +130,84 @@ static int pem_pw_cb(char *buf, int len, int w, void *v) return pwlen; } +static EVP_PKEY *read_private_key(const char *private_key_name) +{ + EVP_PKEY *private_key; + + if (!strncmp(private_key_name, "pkcs11:", 7)) { + ENGINE *e; + + ENGINE_load_builtin_engines(); + drain_openssl_errors(); + e = ENGINE_by_id("pkcs11"); + ERR(!e, "Load PKCS#11 ENGINE"); + if (ENGINE_init(e)) + drain_openssl_errors(); + else + ERR(1, "ENGINE_init"); + if (key_pass) + ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), + "Set PKCS#11 PIN"); + private_key = ENGINE_load_private_key(e, private_key_name, + NULL, NULL); + ERR(!private_key, "%s", private_key_name); + } else { + BIO *b; + + b = BIO_new_file(private_key_name, "rb"); + ERR(!b, "%s", private_key_name); + private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, + NULL); + ERR(!private_key, "%s", private_key_name); + BIO_free(b); + } + + return private_key; +} + +static X509 *read_x509(const char *x509_name) +{ + X509 *x509; + BIO *b; + + b = BIO_new_file(x509_name, "rb"); + ERR(!b, "%s", x509_name); + x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */ + if (!x509) { + ERR(BIO_reset(b) != 1, "%s", x509_name); + x509 = PEM_read_bio_X509(b, NULL, NULL, + NULL); /* PEM encoded X.509 */ + if (x509) + drain_openssl_errors(); + } + BIO_free(b); + ERR(!x509, "%s", x509_name); + + return x509; +} + 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; + char *private_key_name = NULL, *raw_sig_name = NULL; + char *x509_name, *module_name, *dest_name; bool save_sig = false, replace_orig; bool sign_only = false; + bool raw_sig = false; unsigned char buf[4096]; unsigned long module_size, sig_size; unsigned int use_signed_attrs; const EVP_MD *digest_algo; EVP_PKEY *private_key; #ifndef USE_PKCS7 - CMS_ContentInfo *cms; + CMS_ContentInfo *cms = NULL; unsigned int use_keyid = 0; #else - PKCS7 *pkcs7; + PKCS7 *pkcs7 = NULL; #endif X509 *x509; - BIO *b, *bd = NULL, *bm; + BIO *bd, *bm; int opt, n; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -160,8 +222,9 @@ int main(int argc, char **argv) #endif do { - opt = getopt(argc, argv, "dpk"); + opt = getopt(argc, argv, "sdpk"); switch (opt) { + case 's': raw_sig = true; break; case 'p': save_sig = true; break; case 'd': sign_only = true; save_sig = true; break; #ifndef USE_PKCS7 @@ -177,8 +240,13 @@ int main(int argc, char **argv) if (argc < 4 || argc > 5) format(); - hash_algo = argv[0]; - private_key_name = argv[1]; + if (raw_sig) { + raw_sig_name = argv[0]; + hash_algo = argv[1]; + } else { + hash_algo = argv[0]; + private_key_name = argv[1]; + } x509_name = argv[2]; module_name = argv[3]; if (argc == 5) { @@ -198,101 +266,74 @@ int main(int argc, char **argv) } #endif - /* Read the private key and the X.509 cert the PKCS#7 message - * will point to. - */ - if (!strncmp(private_key_name, "pkcs11:", 7)) { - ENGINE *e; - - ENGINE_load_builtin_engines(); - drain_openssl_errors(); - e = ENGINE_by_id("pkcs11"); - ERR(!e, "Load PKCS#11 ENGINE"); - if (ENGINE_init(e)) - drain_openssl_errors(); - else - ERR(1, "ENGINE_init"); - if (key_pass) - ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN"); - private_key = ENGINE_load_private_key(e, private_key_name, NULL, - NULL); - ERR(!private_key, "%s", private_key_name); - } else { - b = BIO_new_file(private_key_name, "rb"); - ERR(!b, "%s", private_key_name); - private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, NULL); - ERR(!private_key, "%s", private_key_name); - BIO_free(b); - } - - b = BIO_new_file(x509_name, "rb"); - ERR(!b, "%s", x509_name); - x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */ - if (!x509) { - ERR(BIO_reset(b) != 1, "%s", x509_name); - x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); /* PEM encoded X.509 */ - if (x509) - drain_openssl_errors(); - } - BIO_free(b); - ERR(!x509, "%s", x509_name); - - /* Open the destination file now so that we can shovel the module data - * across as we read it. - */ - if (!sign_only) { - bd = BIO_new_file(dest_name, "wb"); - ERR(!bd, "%s", 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"); - + /* Open the module file */ bm = BIO_new_file(module_name, "rb"); ERR(!bm, "%s", module_name); + if (!raw_sig) { + /* Read the private key and the X.509 cert the PKCS#7 message + * will point to. + */ + private_key = read_private_key(private_key_name); + x509 = read_x509(x509_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"); + #ifndef USE_PKCS7 - /* Load the signature message from the digest buffer. */ - cms = CMS_sign(NULL, NULL, NULL, NULL, - CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | CMS_STREAM); - ERR(!cms, "CMS_sign"); - - ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, - CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP | - use_keyid | use_signed_attrs), - "CMS_add1_signer"); - ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0, - "CMS_final"); + /* Load the signature message from the digest buffer. */ + cms = CMS_sign(NULL, NULL, NULL, NULL, + CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | + CMS_DETACHED | CMS_STREAM); + ERR(!cms, "CMS_sign"); + + ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, + CMS_NOCERTS | CMS_BINARY | + CMS_NOSMIMECAP | use_keyid | + use_signed_attrs), + "CMS_add1_signer"); + ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0, + "CMS_final"); #else - pkcs7 = PKCS7_sign(x509, private_key, NULL, bm, - PKCS7_NOCERTS | PKCS7_BINARY | - PKCS7_DETACHED | use_signed_attrs); - ERR(!pkcs7, "PKCS7_sign"); + pkcs7 = PKCS7_sign(x509, private_key, NULL, bm, + PKCS7_NOCERTS | PKCS7_BINARY | + PKCS7_DETACHED | use_signed_attrs); + ERR(!pkcs7, "PKCS7_sign"); #endif - if (save_sig) { - char *sig_file_name; + if (save_sig) { + char *sig_file_name; + BIO *b; - ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0, - "asprintf"); - b = BIO_new_file(sig_file_name, "wb"); - ERR(!b, "%s", sig_file_name); + ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0, + "asprintf"); + b = BIO_new_file(sig_file_name, "wb"); + ERR(!b, "%s", sig_file_name); #ifndef USE_PKCS7 - ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, - "%s", sig_file_name); + ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, + "%s", sig_file_name); #else - ERR(i2d_PKCS7_bio(b, pkcs7) < 0, - "%s", sig_file_name); + ERR(i2d_PKCS7_bio(b, pkcs7) < 0, + "%s", sig_file_name); #endif - BIO_free(b); + BIO_free(b); + } + + if (sign_only) { + BIO_free(bm); + return 0; + } } - if (sign_only) - return 0; + /* 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, "%s", dest_name); /* Append the marker and the PKCS#7 message to the destination file */ ERR(BIO_reset(bm) < 0, "%s", module_name); @@ -300,14 +341,29 @@ int main(int argc, char **argv) n > 0) { ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); } + BIO_free(bm); ERR(n < 0, "%s", module_name); module_size = BIO_number_written(bd); + if (!raw_sig) { #ifndef USE_PKCS7 - ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name); + ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name); #else - ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name); + ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name); #endif + } else { + BIO *b; + + /* Read the raw signature file and write the data to the + * destination file + */ + b = BIO_new_file(raw_sig_name, "rb"); + ERR(!b, "%s", raw_sig_name); + while ((n = BIO_read(b, buf, sizeof(buf))), n > 0) + ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); + BIO_free(b); + } + sig_size = BIO_number_written(bd) - module_size; sig_info.sig_len = htonl(sig_size); ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name); |