diff options
-rw-r--r-- | scripts/Makefile.modpost | 77 | ||||
-rw-r--r-- | scripts/sign-file | 115 |
2 files changed, 191 insertions, 1 deletions
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 08dce14f2dc..2a4d1a17652 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -14,7 +14,8 @@ # 3) create one <module>.mod.c file pr. module # 4) create one Module.symvers file with CRC for all exported symbols # 5) compile all <module>.mod.c files -# 6) final link of the module to a <module.ko> file +# 6) final link of the module to a <module.ko> (or <module.unsigned>) file +# 7) signs the modules to a <module.ko> file # Step 3 is used to place certain information in the module's ELF # section, including information such as: @@ -32,6 +33,8 @@ # Step 4 is solely used to allow module versioning in external modules, # where the CRC of each module is retrieved from the Module.symvers file. +# Step 7 is dependent on CONFIG_MODULE_SIG being enabled. + # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined # symbols in the final module linking stage # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. @@ -116,6 +119,7 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE targets += $(modules:.ko=.mod.o) # Step 6), final link of the modules +ifneq ($(CONFIG_MODULE_SIG),y) quiet_cmd_ld_ko_o = LD [M] $@ cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ @@ -125,7 +129,78 @@ $(modules): %.ko :%.o %.mod.o FORCE $(call if_changed,ld_ko_o) targets += $(modules) +else +quiet_cmd_ld_ko_unsigned_o = LD [M] $@ + cmd_ld_ko_unsigned_o = \ + $(LD) -r $(LDFLAGS) \ + $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ + -o $@ $(filter-out FORCE,$^) \ + $(if $(AFTER_LINK),; $(AFTER_LINK)) + +$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE + $(call if_changed,ld_ko_unsigned_o) + +targets += $(modules:.ko=.ko.unsigned) + +# Step 7), sign the modules +MODSECKEY = ./signing_key.priv +MODPUBKEY = ./signing_key.x509 + +ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) +ifeq ($(KBUILD_SRC),) + # no O= is being used + SCRIPTS_DIR := scripts +else + SCRIPTS_DIR := $(KBUILD_SRC)/scripts +endif +SIGN_MODULES := 1 +else +SIGN_MODULES := 0 +endif + +# only sign if it's an in-tree module +ifneq ($(KBUILD_EXTMOD),) +SIGN_MODULES := 0 +endif +# We strip the module as best we can - note that using both strip and eu-strip +# results in a smaller module than using either alone. +EU_STRIP = $(shell which eu-strip || echo true) + +quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@ + cmd_sign_ko_stripped_ko_unsigned = \ + cp $< $@ && \ + strip -x -g $@ && \ + $(EU_STRIP) $@ + +ifeq ($(SIGN_MODULES),1) + +quiet_cmd_genkeyid = GENKEYID $@ + cmd_genkeyid = \ + perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid + +%.signer %.keyid: % + $(call if_changed,genkeyid) + +KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid +quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@ + cmd_sign_ko_ko_stripped = \ + sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@ +else +KEYRING_DEP := +quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ + cmd_sign_ko_ko_unsigned = \ + cp $< $@ +endif + +$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE + $(call if_changed,sign_ko_ko_stripped) + +$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE + $(call if_changed,sign_ko_stripped_ko_unsigned) + +targets += $(modules) +endif # Add FORCE to the prequisites of a target to force it to be always rebuilt. # --------------------------------------------------------------------------- diff --git a/scripts/sign-file b/scripts/sign-file new file mode 100644 index 00000000000..e58e34e50ac --- /dev/null +++ b/scripts/sign-file @@ -0,0 +1,115 @@ +#!/bin/sh +# +# Sign a module file using the given key. +# +# Format: sign-file <key> <x509> <src-file> <dst-file> +# + +scripts=`dirname $0` + +CONFIG_MODULE_SIG_SHA512=y +if [ -r .config ] +then + . ./.config +fi + +key="$1" +x509="$2" +src="$3" +dst="$4" + +if [ ! -r "$key" ] +then + echo "Can't read private key" >&2 + exit 2 +fi + +if [ ! -r "$x509" ] +then + echo "Can't read X.509 certificate" >&2 + exit 2 +fi +if [ ! -r "$x509.signer" ] +then + echo "Can't read Signer name" >&2 + exit 2; +fi +if [ ! -r "$x509.keyid" ] +then + echo "Can't read Key identifier" >&2 + exit 2; +fi + +# +# Signature parameters +# +algo=1 # Public-key crypto algorithm: RSA +hash= # Digest algorithm +id_type=1 # Identifier type: X.509 + +# +# Digest the data +# +dgst= +if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] +then + prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" + dgst=-sha1 + hash=2 +elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] +then + prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" + dgst=-sha224 + hash=7 +elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] +then + prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" + dgst=-sha256 + hash=4 +elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] +then + prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" + dgst=-sha384 + hash=5 +elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] +then + prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" + dgst=-sha512 + hash=6 +else + echo "$0: Can't determine hash algorithm" >&2 + exit 2 +fi + +( +perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? +openssl dgst $dgst -binary $src || exit $? +) >$src.dig || exit $? + +# +# Generate the binary signature, which will be just the integer that comprises +# the signature with no metadata attached. +# +openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? +signerlen=`stat -c %s $x509.signer` +keyidlen=`stat -c %s $x509.keyid` +siglen=`stat -c %s $src.sig` + +# +# Build the signed binary +# +( + cat $src || exit $? + echo '~Module signature appended~' || exit $? + cat $x509.signer $x509.keyid || exit $? + + # Preface each signature integer with a 2-byte BE length + perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? + cat $src.sig || exit $? + + # Generate the information block + perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? +) >$dst~ || exit $? + +# Permit in-place signing +mv $dst~ $dst || exit $? |