2012-10-19 05:23:15 +04:00
#!/bin/bash
2012-09-26 13:11:06 +04:00
#
# Sign a module file using the given key.
#
2012-10-19 05:23:15 +04:00
# Format: sign-file <key> <x509> <keyid-script> <module>
2012-09-26 13:11:06 +04:00
#
scripts=`dirname $0`
CONFIG_MODULE_SIG_SHA512=y
if [ -r .config ]
then
. ./.config
fi
key="$1"
x509="$2"
2012-10-19 05:23:15 +04:00
keyid_script="$3"
mod="$4"
2012-09-26 13:11:06 +04:00
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
#
# 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 $?
2012-10-19 05:23:15 +04:00
openssl dgst $dgst -binary $mod || exit $?
) >$mod.dig || exit $?
2012-09-26 13:11:06 +04:00
#
# Generate the binary signature, which will be just the integer that comprises
# the signature with no metadata attached.
#
2012-10-19 05:23:15 +04:00
openssl rsautl -sign -inkey $key -keyform PEM -in $mod.dig -out $mod.sig || exit $?
kbuild: Fix module signature generation
Rusty had clearly not actually tested his module signing changes that I
(trustingly) applied as commit e2a666d52b48 ("kbuild: sign the modules
at install time"). That commit had multiple bugs:
- using "${#VARIABLE}" to get the number of characters in a shell
variable may look clever, but it's locale-dependent: it returns the
number of *characters*, not bytes. And we do need bytes.
So don't use "${#..}" expansion, do the stupid "wc -c" thing instead
(where "c" stands for "bytes", not "characters", despite the letter.
- Rusty had confused "siglen" and "signerlen", and his conversion
didn't set "signerlen" at all, and incorrectly set "siglen" to the
size of the signer, not the size of the signature.
End result: the modified sign-file script did create something that
superficially *looked* like a signature, but didn't actually work at
all, and would fail the signature check. Oops.
Tssk, tssk, Rusty.
But Rusty was definitely right that this whole thing should be rewritten
in perl by somebody who has the perl-fu to do so. That is not me,
though - I'm just doing an emergency fix for the shell script.
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-10-19 23:43:19 +04:00
siglen=`stat -c %s $mod.sig`
2012-10-19 05:23:15 +04:00
SIGNER="`perl $keyid_script $x509 signer-name`"
KEYID="`perl $keyid_script $x509 keyid`"
kbuild: Fix module signature generation
Rusty had clearly not actually tested his module signing changes that I
(trustingly) applied as commit e2a666d52b48 ("kbuild: sign the modules
at install time"). That commit had multiple bugs:
- using "${#VARIABLE}" to get the number of characters in a shell
variable may look clever, but it's locale-dependent: it returns the
number of *characters*, not bytes. And we do need bytes.
So don't use "${#..}" expansion, do the stupid "wc -c" thing instead
(where "c" stands for "bytes", not "characters", despite the letter.
- Rusty had confused "siglen" and "signerlen", and his conversion
didn't set "signerlen" at all, and incorrectly set "siglen" to the
size of the signer, not the size of the signature.
End result: the modified sign-file script did create something that
superficially *looked* like a signature, but didn't actually work at
all, and would fail the signature check. Oops.
Tssk, tssk, Rusty.
But Rusty was definitely right that this whole thing should be rewritten
in perl by somebody who has the perl-fu to do so. That is not me,
though - I'm just doing an emergency fix for the shell script.
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2012-10-19 23:43:19 +04:00
keyidlen=$(echo -n "$KEYID" | wc -c)
signerlen=$(echo -n "$SIGNER" | wc -c)
2012-09-26 13:11:06 +04:00
#
# Build the signed binary
#
(
2012-10-19 05:23:15 +04:00
cat $mod || exit $?
2012-09-26 13:11:06 +04:00
echo '~Module signature appended~' || exit $?
2012-10-19 05:23:15 +04:00
echo -n "$SIGNER" || exit $?
echo -n "$KEYID" || exit $?
2012-09-26 13:11:06 +04:00
# Preface each signature integer with a 2-byte BE length
perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $?
2012-10-19 05:23:15 +04:00
cat $mod.sig || exit $?
2012-09-26 13:11:06 +04:00
# Generate the information block
perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $?
2012-10-19 05:23:15 +04:00
) >$mod~ || exit $?
2012-09-26 13:11:06 +04:00
2012-10-19 05:23:15 +04:00
mv $mod~ $mod || exit $?