Use GOST for signing kernel modules

This commit is contained in:
Mikhail Novosyolov 2019-12-07 21:57:55 +03:00
parent efe34d83a7
commit 12362ac8e3
3 changed files with 132 additions and 48 deletions

View file

@ -1,16 +1,16 @@
sources: sources:
linux-5.3.tar.xz: 988855d1fee4eb12495a5b3602e2f3471623ec3e linux-5.3.tar.xz: 988855d1fee4eb12495a5b3602e2f3471623ec3e
patch-5.3.15.xz: fe9a01fb17002a8e826b61a256eaaba772569990 patch-5.3.15.xz: fe9a01fb17002a8e826b61a256eaaba772569990
public1.pem: 566af3655617863906dbe38e741d2eabf12ab5fd public_rsa_1.pem: 566af3655617863906dbe38e741d2eabf12ab5fd
public2.pem: 7a12031abe1c60c5126e78c1b26197c076aa0574 public_rsa_2.pem: 7a12031abe1c60c5126e78c1b26197c076aa0574
public3.pem: 0b817d48a087945355999c745af58bcefe02bc91 public_rsa_3.pem: 0b817d48a087945355999c745af58bcefe02bc91
public4.pem: 5c1a192addb793614e75a0badcc087497a5c0566 public_rsa_4.pem: 5c1a192addb793614e75a0badcc087497a5c0566
public5.pem: b28c90b4d9719c9aebcb4a5da038085d4b66a629 public_rsa_5.pem: b28c90b4d9719c9aebcb4a5da038085d4b66a629
public6.pem: e8cad69248492e9d0f70b5365f981315bad315d0 public_rsa_6.pem: e8cad69248492e9d0f70b5365f981315bad315d0
public7.pem: 8afc073668f0f9dc9290cc42007385b6579ee4cc public_rsa_7.pem: 8afc073668f0f9dc9290cc42007385b6579ee4cc
public8.pem: 55a07fd289922fbaa9fe9632483155159ec45725 public_rsa_8.pem: 55a07fd289922fbaa9fe9632483155159ec45725
public9.pem: 4365ccc0ee5fb7c1676c4ae9dd9e9094ac5a288e public_rsa_9.pem: 4365ccc0ee5fb7c1676c4ae9dd9e9094ac5a288e
public10.pem: 67396ec42b7fb2ebbd22b8520ad198954817928d public_rsa_10.pem: 67396ec42b7fb2ebbd22b8520ad198954817928d
public11.pem: a48b4006707b3d9c7bb2e0a919ddd703b7be273f public_rsa_11.pem: a48b4006707b3d9c7bb2e0a919ddd703b7be273f
public12.pem: 21f68e7b06ed8dbe7a5aff82d668fbe9aa42c205 public_rsa_12.pem: 21f68e7b06ed8dbe7a5aff82d668fbe9aa42c205

View file

@ -87,7 +87,8 @@
# "rnd" is "random" and means that a key pair is generated at build time # "rnd" is "random" and means that a key pair is generated at build time
# and is not saved anywhere. # and is not saved anywhere.
%define certs_dir_rnd certs %define certs_dir_rnd certs
%define certs_signing_key_rnd %{certs_dir_rnd}/signing_key.pem %define certs_signing_key_priv_rnd %{certs_dir_rnd}/signing_key_priv.key
%define certs_signing_der %{certs_dir_rnd}/signing_key.x509
%define certs_key_config_rnd %{certs_dir_rnd}/x509.genkey %define certs_key_config_rnd %{certs_dir_rnd}/x509.genkey
%define certs_public_keys %{certs_dir_rnd}/public.pem %define certs_public_keys %{certs_dir_rnd}/public.pem
%define certs_verify_tmp %{certs_dir_rnd}/verify.tmp %define certs_verify_tmp %{certs_dir_rnd}/verify.tmp
@ -177,8 +178,8 @@ Source53: cpupower.path
Source80: kernel.rpmlintrc Source80: kernel.rpmlintrc
# Additional keys that can be used to sign kernel modules # Additional keys that can be used to sign kernel modules
# Source201..212: public1..12.pem # Source201..212: public_rsa_1..12.pem
%{expand:%(for i in `seq 1 12`; do echo "Source$((200+${i})): public${i}.pem"; done)} %{expand:%(for i in `seq 1 12`; do echo "Source$((200+${i})): public_rsa_${i}.pem"; done)}
#################################################################### ####################################################################
@ -207,6 +208,8 @@ Patch105: perf-silence-format-warnings-gcc8.patch
# AUFS from http://aufs.sourceforge.net/ # AUFS from http://aufs.sourceforge.net/
Patch109: fs-aufs.patch Patch109: fs-aufs.patch
Patch200: modsig-streebog.diff
#################################################################### ####################################################################
Autoreqprov: no Autoreqprov: no
@ -253,10 +256,9 @@ BuildRequires: pkgconfig(libcrypto)
%if %{enhanced_security} %if %{enhanced_security}
# (To generate keys) # (To generate keys)
# LibreSSL has GOST support without making additional configuration that # LibreSSL has GOST support without editing openssl.cnf
# OpenSSL requires and which is not possible to be done inside a spec file # or dlopen()-ing external library
# because editing /etc/pki/tls/openssl.cnf is not possible. BuildRequires: libressl libressl-devel
BuildRequires: libressl
# To verify signatures (find, xargs, hexdump) # To verify signatures (find, xargs, hexdump)
BuildRequires: findutils util-linux BuildRequires: findutils util-linux
%endif %endif
@ -791,15 +793,13 @@ echo CONFIG_MODULE_SIG_FORCE=y >> .config
%else %else
echo CONFIG_MODULE_SIG_FORCE=n >> .config echo CONFIG_MODULE_SIG_FORCE=n >> .config
%endif %endif
# If %%build_debig is true, automatic signatures will be stripped, # If %%build_debig is true, signatures will be stripped
# then modules will be resigned, otherwise automatic signatures # We sign modules manually in a tricky way bellow
# will not be stripped and modules will not be resigned. echo CONFIG_MODULE_SIG_ALL=n >> .config
# Without this option being on, keys do not get into vmlinuz. # Use STREEBOG-512 algo (GOST R 34.11-12)
echo CONFIG_MODULE_SIG_ALL=y >> .config echo CONFIG_MODULE_SIG_STREEBOG512=y >> .config
# Use SHA-512 algo
echo CONFIG_MODULE_SIG_SHA512=y >> .config
# Set path to the key that will be generated later by openssl/libressl # Set path to the key that will be generated later by openssl/libressl
echo CONFIG_MODULE_SIG_KEY=\"%{certs_signing_key_rnd}\" >> .config echo CONFIG_MODULE_SIG_KEY=\"%{certs_signing_key_priv_rnd}\" >> .config
# Set path to one PEM file with all keys that the kernel must trust # Set path to one PEM file with all keys that the kernel must trust
sed -i '/CONFIG_SYSTEM_TRUSTED_KEYS/d' .config sed -i '/CONFIG_SYSTEM_TRUSTED_KEYS/d' .config
echo CONFIG_SYSTEM_TRUSTED_KEYS=\"%{certs_public_keys}\" >> .config echo CONFIG_SYSTEM_TRUSTED_KEYS=\"%{certs_public_keys}\" >> .config
@ -908,10 +908,8 @@ email="$(_get_email)"
cat <<EOF > "%{certs_key_config_rnd}" cat <<EOF > "%{certs_key_config_rnd}"
[ req ] [ req ]
prompt = no prompt = no
default_bits = 4096
default_md = sha512
string_mask = utf8only string_mask = utf8only
default_keyfile = %{certs_signing_key_rnd} default_keyfile = %{certs_signing_key_priv_rnd}
distinguished_name = req_distinguished_name distinguished_name = req_distinguished_name
x509_extensions = myexts x509_extensions = myexts
[ req_distinguished_name ] [ req_distinguished_name ]
@ -926,23 +924,40 @@ authorityKeyIdentifier=keyid
EOF EOF
cat "%{certs_key_config_rnd}" cat "%{certs_key_config_rnd}"
libressl req -new -nodes -utf8 -batch -x509 \ libressl req -new -nodes -utf8 -batch \
-newkey gost2001 \
-pkeyopt dgst:streebog512 -pkeyopt paramset:A \
-streebog512 \
-days 109500 \ -days 109500 \
-config "%{certs_key_config_rnd}" \ -x509 -config "%{certs_key_config_rnd}" \
-outform PEM \ -outform PEM \
-out "%{certs_signing_key_rnd}" \ -out "%{certs_signing_key_priv_rnd}" \
-keyout "%{certs_signing_key_rnd}" -keyout "%{certs_signing_key_priv_rnd}"
# Verify
libressl x509 -in "%{certs_signing_key_priv_rnd}" -text -noout \
| grep -E 'Signature Algorithm:.*GOST R 34.10-2012'
libressl x509 -in "%{certs_signing_key_priv_rnd}" -text -noout \
| grep -E 'Digest Algorithm:.*GOST R 34-11-2012'
libressl x509 -in "%{certs_signing_key_priv_rnd}" -text -noout \
| grep -E 'Public Key Algorithm:.*GOST R 34.10-2012'
# Strip public part from the generated PEM # Strip public part from the generated PEM
sed -n \ sed -n \
'/^-----BEGIN CERTIFICATE-----$/,/^-----END CERTIFICATE-----$/p;/^-----END CERTIFICATE-----$/q' \ '/^-----BEGIN CERTIFICATE-----$/,/^-----END CERTIFICATE-----$/p;/^-----END CERTIFICATE-----$/q' \
"%{certs_signing_key_rnd}" > "%{certs_public_keys}" "%{certs_signing_key_priv_rnd}" > "%{certs_public_keys}"
# link sign-file and extract-cert with LibreSSL instead of OpenSSL
libressl_cflags="$(pkg-config --cflags --libs libressl-libcrypto)"
if [ $? != 0 ] ; then exit $? ; fi
sed -i %{src_dir}/scripts/Makefile \
-e "s,-lcrypto,${libressl_cflags},g"
%if %{with additional_keys} %if %{with additional_keys}
# Add additional public keys to the list of trusted keys for kernel modules # Add additional public keys to the list of trusted keys for kernel modules
# Build kernel --without additional_keys if you do not want to trust them # Build kernel --without additional_keys if you do not want to trust them
cat %{expand:%(for i in `seq 1 12`; do echo "%%SOURCE$((200+${i}))" | tr "\n" " "; done)} \ ##cat %{expand:%(for i in `seq 1 12`; do echo "%%SOURCE$((200+${i}))" | tr "\n" " "; done)} \
>> "%{certs_public_keys}" ## >> "%{certs_public_keys}"
%endif #endif additional_keys %endif #endif additional_keys
cat %{certs_public_keys} cat %{certs_public_keys}
%endif #endif enhanced_security %endif #endif enhanced_security
@ -957,7 +972,7 @@ LC_ALL=C sed -ri "s/^EXTRAVERSION.*/EXTRAVERSION = -%{flavour}-%{buildrpmrel}/"
# build the kernel # build the kernel
echo "Building kernel %{kver_full}" echo "Building kernel %{kver_full}"
%kmake -s all %kmake V=1 -s all
# Start installing stuff # Start installing stuff
install -d %{temp_boot} install -d %{temp_boot}
@ -1083,16 +1098,30 @@ rm -f %{temp_modules}/debug_module_list
# endif build_debug # endif build_debug
%endif %endif
%if %{enhanced_security} && %{build_debug} %if %{enhanced_security}
# Sign modules (after stripping) # scripts/sign-file.c fails to sign modules:
# scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>] # "CMS routines:func(4095):not supported for this key type"
find %{temp_modules}/%{kver_full}/kernel -name '*.ko' | sort -u | \ # So make a dettached signature via libressl and attach it
%kxargs -I '{}' \ # as a raw signature via sign-file.
%{src_dir}/scripts/sign-file \ # TODO: fix scripts/sign-file.c
sha512 \ _libressl_sign(){
%{certs_signing_key_rnd} \ if [ ! -f "$1" ]; then
%{certs_signing_key_rnd} \ echo "No file $1"
'{}' return 0
fi
f="$1"
libressl dgst -streebog512 \
-sign "%{certs_signing_key_priv_rnd}" "$f" \
> "${f}.sig"
%{src_dir}/scripts/sign-file -s "${f}.sig" streebog512 \
"%{certs_signing_key_priv_rnd}" "$f"
rm "${f}.sig"
unset f
}
export -f _libressl_sign
find %{temp_modules}/%{kver_full}/kernel -name '*.ko' -print0 | sort -u | \
xargs --null -P "$(nproc)" -I {} "$SHELL" -e -x -c 'if ! _libressl_sign "{}"; \
then echo Failed _libressl_sign on "{}" && exit 1; fi'
%endif %endif
# Create the list of files for the kernel. # Create the list of files for the kernel.

55
modsig-streebog.diff Normal file
View file

@ -0,0 +1,55 @@
diff --git a/certs/Makefile b/certs/Makefile
index f4c25b67aad9..39fb3a53bfe3 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -60,6 +60,7 @@ $(obj)/signing_key.pem: $(obj)/x509.genkey
@$(kecho) "### needs to be run as root, and uses a hardware random"
@$(kecho) "### number generator if one is available."
@$(kecho) "###"
+# TODO: fix for LibreSSL/OpenSSL + GOST (Streebog)
$(Q)openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \
-batch -x509 -config $(obj)/x509.genkey \
-outform PEM -out $(obj)/signing_key.pem \
diff --git a/init/Kconfig b/init/Kconfig
index bd7d650d4a99..eef670c9571b 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2070,6 +2070,14 @@ config MODULE_SIG_SHA512
bool "Sign modules with SHA-512"
select CRYPTO_SHA512
+config MODULE_SIG_STREEBOG256
+ bool "Sign modules with STREEBOG-256"
+ select CRYPTO_STREEBOG
+
+config MODULE_SIG_STREEBOG512
+ bool "Sign modules with STREEBOG-512"
+ select CRYPTO_STREEBOG
+
endchoice
config MODULE_SIG_HASH
@@ -2080,6 +2088,8 @@ config MODULE_SIG_HASH
default "sha256" if MODULE_SIG_SHA256
default "sha384" if MODULE_SIG_SHA384
default "sha512" if MODULE_SIG_SHA512
+ default "streebog256" if MODULE_SIG_STREEBOG256
+ default "streebog512" if MODULE_SIG_STREEBOG512
config MODULE_COMPRESS
bool "Compress modules on installation"
diff --git a/scripts/sign-file.c b/scripts/sign-file.c
index fbd34b8e8f57..010c5f02ff5e 100644
--- a/scripts/sign-file.c
+++ b/scripts/sign-file.c
@@ -41,9 +41,7 @@
* signing with anything other than SHA1 - so we're stuck with that if such is
* the case.
*/
-#if defined(LIBRESSL_VERSION_NUMBER) || \
- OPENSSL_VERSION_NUMBER < 0x10000000L || \
- defined(OPENSSL_NO_CMS)
+#if defined(OPENSSL_NO_CMS) || OPENSSL_VERSION_NUMBER < 0x10000000L
#define USE_PKCS7
#endif
#ifndef USE_PKCS7