aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/configs/colibri_pxa270_defconfig1
-rw-r--r--arch/arm/configs/iop13xx_defconfig1
-rw-r--r--arch/arm/configs/iop32x_defconfig1
-rw-r--r--arch/arm/configs/trizeps4_defconfig1
-rw-r--r--arch/microblaze/configs/mmu_defconfig1
-rw-r--r--arch/microblaze/configs/nommu_defconfig1
-rw-r--r--arch/mips/configs/bigsur_defconfig1
-rw-r--r--arch/mips/configs/ip22_defconfig1
-rw-r--r--arch/mips/configs/ip27_defconfig1
-rw-r--r--arch/mips/configs/ip32_defconfig1
-rw-r--r--arch/mips/configs/jazz_defconfig1
-rw-r--r--arch/mips/configs/lemote2f_defconfig1
-rw-r--r--arch/mips/configs/rm200_defconfig1
-rw-r--r--arch/mips/configs/sb1250_swarm_defconfig1
-rw-r--r--arch/parisc/configs/712_defconfig1
-rw-r--r--arch/parisc/configs/a500_defconfig1
-rw-r--r--arch/parisc/configs/default_defconfig1
-rw-r--r--arch/parisc/configs/generic-32bit_defconfig1
-rw-r--r--arch/powerpc/configs/c2k_defconfig1
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig1
-rw-r--r--arch/score/configs/spct6600_defconfig1
-rw-r--r--arch/tile/configs/tilegx_defconfig1
-rw-r--r--arch/tile/configs/tilepro_defconfig1
-rw-r--r--arch/x86/configs/i386_defconfig1
-rw-r--r--arch/x86/configs/x86_64_defconfig1
-rw-r--r--certs/Kconfig16
-rw-r--r--certs/Makefile33
-rw-r--r--certs/system_certificates.S13
-rw-r--r--certs/system_keyring.c4
-rw-r--r--crypto/asymmetric_keys/Kconfig7
-rw-r--r--crypto/asymmetric_keys/Makefile8
-rw-r--r--crypto/asymmetric_keys/mscode_parser.c14
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.c32
-rw-r--r--crypto/asymmetric_keys/pkcs7_trust.c2
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c10
-rw-r--r--crypto/asymmetric_keys/public_key.c154
-rw-r--r--crypto/asymmetric_keys/public_key.h36
-rw-r--r--crypto/asymmetric_keys/rsa.c278
-rw-r--r--crypto/asymmetric_keys/verify_pefile.c4
-rw-r--r--crypto/asymmetric_keys/verify_pefile.h2
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c75
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c34
-rw-r--r--crypto/asymmetric_keys/x509_rsakey.asn14
-rw-r--r--crypto/rsa-pkcs1pad.c182
-rw-r--r--include/crypto/public_key.h76
-rw-r--r--include/linux/key.h1
-rw-r--r--init/Kconfig2
-rw-r--r--kernel/module_signing.c7
-rw-r--r--kernel/time/time.c9
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Makefile1
-rwxr-xr-xscripts/extract-sys-certs.pl29
-rw-r--r--scripts/insert-sys-cert.c410
-rwxr-xr-xscripts/sign-file.c238
-rw-r--r--security/integrity/Kconfig2
-rw-r--r--security/integrity/digsig_asymmetric.c16
-rw-r--r--security/integrity/integrity.h2
-rw-r--r--security/keys/big_key.c15
-rw-r--r--security/keys/key.c2
59 files changed, 999 insertions, 745 deletions
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 18c311ae1113..0b9211b2b73b 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -166,7 +166,6 @@ CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_SHA1=m
diff --git a/arch/arm/configs/iop13xx_defconfig b/arch/arm/configs/iop13xx_defconfig
index 4fa94a1f115b..652b7bd9e544 100644
--- a/arch/arm/configs/iop13xx_defconfig
+++ b/arch/arm/configs/iop13xx_defconfig
@@ -95,7 +95,6 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_NLS=y
CONFIG_DEBUG_USER=y
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_LRW=y
CONFIG_CRYPTO_PCBC=m
diff --git a/arch/arm/configs/iop32x_defconfig b/arch/arm/configs/iop32x_defconfig
index c3058da631da..aa3af0a6b8f7 100644
--- a/arch/arm/configs/iop32x_defconfig
+++ b/arch/arm/configs/iop32x_defconfig
@@ -108,7 +108,6 @@ CONFIG_DEBUG_USER=y
CONFIG_DEBUG_LL=y
CONFIG_DEBUG_LL_UART_8250=y
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_LRW=y
CONFIG_CRYPTO_PCBC=m
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 4bc870028035..0ada29d568ec 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -214,7 +214,6 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_USER=y
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_SHA256=m
diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig
index e2f6543b91e7..dc5dd5b69fde 100644
--- a/arch/microblaze/configs/mmu_defconfig
+++ b/arch/microblaze/configs/mmu_defconfig
@@ -87,5 +87,4 @@ CONFIG_KGDB_KDB=y
CONFIG_EARLY_PRINTK=y
CONFIG_KEYS=y
CONFIG_ENCRYPTED_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/microblaze/configs/nommu_defconfig b/arch/microblaze/configs/nommu_defconfig
index a29ebd4a9fcb..4cdaf565e638 100644
--- a/arch/microblaze/configs/nommu_defconfig
+++ b/arch/microblaze/configs/nommu_defconfig
@@ -92,7 +92,6 @@ CONFIG_DEBUG_INFO=y
CONFIG_EARLY_PRINTK=y
CONFIG_KEYS=y
CONFIG_ENCRYPTED_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index b3e7a1b61220..e070dac071c8 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -247,7 +247,6 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_LIST=y
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_NETWORK_XFRM=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 57ed466e00db..6ba9ce9fcdd5 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -358,7 +358,6 @@ CONFIG_DLM=m
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_CRYPTD=m
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 48e16d98b2cc..77e9f505f5e4 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -346,7 +346,6 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_DLM=m
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITYFS=y
CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_NULL=m
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index fe48220157a9..f9af98f63cff 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -181,7 +181,6 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_ECB=y
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index 4f37a5985459..a5e85e1ee5de 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -362,7 +362,6 @@ CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
CONFIG_DLM=m
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_LRW=m
diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig
index 004cf52d1b7d..d1f198b072a0 100644
--- a/arch/mips/configs/lemote2f_defconfig
+++ b/arch/mips/configs/lemote2f_defconfig
@@ -412,7 +412,6 @@ CONFIG_DEBUG_FS=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_CRYPTD=m
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index db029f4ff759..82db4e3e4cf1 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -453,7 +453,6 @@ CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
CONFIG_DLM=m
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_LRW=m
diff --git a/arch/mips/configs/sb1250_swarm_defconfig b/arch/mips/configs/sb1250_swarm_defconfig
index 51bab13ef6f8..7fca09fedb59 100644
--- a/arch/mips/configs/sb1250_swarm_defconfig
+++ b/arch/mips/configs/sb1250_swarm_defconfig
@@ -87,7 +87,6 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_DLM=m
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m
diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig
index 9387cc2693f6..db8f56bf3883 100644
--- a/arch/parisc/configs/712_defconfig
+++ b/arch/parisc/configs/712_defconfig
@@ -183,7 +183,6 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MUTEXES=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_DEBUG_RODATA=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_HMAC=y
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index 0490199d7b15..1a4f776b49b8 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -193,7 +193,6 @@ CONFIG_HEADERS_CHECK=y
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_HMAC=y
diff --git a/arch/parisc/configs/default_defconfig b/arch/parisc/configs/default_defconfig
index 4d8127e8428a..310b6657e4ac 100644
--- a/arch/parisc/configs/default_defconfig
+++ b/arch/parisc/configs/default_defconfig
@@ -211,7 +211,6 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MUTEXES=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_MD4=m
diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig
index 0ffb08ff5125..5b04d703a924 100644
--- a/arch/parisc/configs/generic-32bit_defconfig
+++ b/arch/parisc/configs/generic-32bit_defconfig
@@ -301,7 +301,6 @@ CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_LATENCYTOP=y
CONFIG_LKDTM=m
CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_HMAC=y
diff --git a/arch/powerpc/configs/c2k_defconfig b/arch/powerpc/configs/c2k_defconfig
index 91862292cd55..340685caa7b8 100644
--- a/arch/powerpc/configs/c2k_defconfig
+++ b/arch/powerpc/configs/c2k_defconfig
@@ -387,7 +387,6 @@ CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_BOOTX_TEXT=y
CONFIG_PPC_EARLY_DEBUG=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index e5d2c3dc07f1..99ccbebabfd3 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -1175,7 +1175,6 @@ CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_XMON=y
CONFIG_BOOTX_TEXT=y
CONFIG_PPC_EARLY_DEBUG=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_NETWORK_XFRM=y
diff --git a/arch/score/configs/spct6600_defconfig b/arch/score/configs/spct6600_defconfig
index df1edbf507a2..b2d8802f43b4 100644
--- a/arch/score/configs/spct6600_defconfig
+++ b/arch/score/configs/spct6600_defconfig
@@ -70,7 +70,6 @@ CONFIG_NFSD=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_CRYPTO_NULL=y
diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig
index 37dc9364c4a1..c1387b7f447d 100644
--- a/arch/tile/configs/tilegx_defconfig
+++ b/arch/tile/configs/tilegx_defconfig
@@ -374,7 +374,6 @@ CONFIG_DEBUG_CREDENTIALS=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60
CONFIG_ASYNC_RAID6_TEST=m
CONFIG_KGDB=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y
diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig
index 76a2781dec2c..6d9ce8af1107 100644
--- a/arch/tile/configs/tilepro_defconfig
+++ b/arch/tile/configs/tilepro_defconfig
@@ -486,7 +486,6 @@ CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_CREDENTIALS=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60
CONFIG_ASYNC_RAID6_TEST=m
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index 028be48c8839..a212b68a4909 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -303,7 +303,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_DEBUG_BOOT_PARAMS=y
CONFIG_OPTIMIZE_INLINING=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index cb5b3ab5beec..4f404a64681b 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -300,7 +300,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_DEBUG_BOOT_PARAMS=y
CONFIG_OPTIMIZE_INLINING=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
diff --git a/certs/Kconfig b/certs/Kconfig
index b030b9c7ed34..f0f8a4433685 100644
--- a/certs/Kconfig
+++ b/certs/Kconfig
@@ -39,4 +39,20 @@ config SYSTEM_TRUSTED_KEYS
form of DER-encoded *.x509 files in the top-level build directory,
those are no longer used. You will need to set this option instead.
+config SYSTEM_EXTRA_CERTIFICATE
+ bool "Reserve area for inserting a certificate without recompiling"
+ depends on SYSTEM_TRUSTED_KEYRING
+ help
+ If set, space for an extra certificate will be reserved in the kernel
+ image. This allows introducing a trusted certificate to the default
+ system keyring without recompiling the kernel.
+
+config SYSTEM_EXTRA_CERTIFICATE_SIZE
+ int "Number of bytes to reserve for the extra certificate"
+ depends on SYSTEM_EXTRA_CERTIFICATE
+ default 4096
+ help
+ This is the number of bytes reserved in the kernel image for a
+ certificate to be inserted.
+
endmenu
diff --git a/certs/Makefile b/certs/Makefile
index 28ac694dd11a..2773c4afa24c 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -36,29 +36,34 @@ ifndef CONFIG_MODULE_SIG_HASH
$(error Could not determine digest type to use from kernel config)
endif
+redirect_openssl = 2>&1
+quiet_redirect_openssl = 2>&1
+silent_redirect_openssl = 2>/dev/null
+
# We do it this way rather than having a boolean option for enabling an
# external private key, because 'make randconfig' might enable such a
# boolean option and we unfortunately can't make it depend on !RANDCONFIG.
ifeq ($(CONFIG_MODULE_SIG_KEY),"certs/signing_key.pem")
$(obj)/signing_key.pem: $(obj)/x509.genkey
- @echo "###"
- @echo "### Now generating an X.509 key pair to be used for signing modules."
- @echo "###"
- @echo "### If this takes a long time, you might wish to run rngd in the"
- @echo "### background to keep the supply of entropy topped up. It"
- @echo "### needs to be run as root, and uses a hardware random"
- @echo "### number generator if one is available."
- @echo "###"
- openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \
+ @$(kecho) "###"
+ @$(kecho) "### Now generating an X.509 key pair to be used for signing modules."
+ @$(kecho) "###"
+ @$(kecho) "### If this takes a long time, you might wish to run rngd in the"
+ @$(kecho) "### background to keep the supply of entropy topped up. It"
+ @$(kecho) "### needs to be run as root, and uses a hardware random"
+ @$(kecho) "### number generator if one is available."
+ @$(kecho) "###"
+ $(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 \
- -keyout $(obj)/signing_key.pem 2>&1
- @echo "###"
- @echo "### Key pair generated."
- @echo "###"
+ -keyout $(obj)/signing_key.pem \
+ $($(quiet)redirect_openssl)
+ @$(kecho) "###"
+ @$(kecho) "### Key pair generated."
+ @$(kecho) "###"
$(obj)/x509.genkey:
- @echo Generating X.509 key generation config
+ @$(kecho) Generating X.509 key generation config
@echo >$@ "[ req ]"
@echo >>$@ "default_bits = 4096"
@echo >>$@ "distinguished_name = req_distinguished_name"
diff --git a/certs/system_certificates.S b/certs/system_certificates.S
index 9216e8c81764..c9ceb71a43fe 100644
--- a/certs/system_certificates.S
+++ b/certs/system_certificates.S
@@ -13,6 +13,19 @@ __cert_list_start:
.incbin "certs/x509_certificate_list"
__cert_list_end:
+#ifdef CONFIG_SYSTEM_EXTRA_CERTIFICATE
+ .globl VMLINUX_SYMBOL(system_extra_cert)
+ .size system_extra_cert, CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE
+VMLINUX_SYMBOL(system_extra_cert):
+ .fill CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE, 1, 0
+
+ .align 4
+ .globl VMLINUX_SYMBOL(system_extra_cert_used)
+VMLINUX_SYMBOL(system_extra_cert_used):
+ .int 0
+
+#endif /* CONFIG_SYSTEM_EXTRA_CERTIFICATE */
+
.align 8
.globl VMLINUX_SYMBOL(system_certificate_list_size)
VMLINUX_SYMBOL(system_certificate_list_size):
diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index 2570598b784d..f4180326c2e1 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -84,12 +84,12 @@ static __init int load_system_certificate_list(void)
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ),
KEY_ALLOC_NOT_IN_QUOTA |
- KEY_ALLOC_TRUSTED);
+ KEY_ALLOC_TRUSTED |
+ KEY_ALLOC_BUILT_IN);
if (IS_ERR(key)) {
pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
PTR_ERR(key));
} else {
- set_bit(KEY_FLAG_BUILTIN, &key_ref_to_ptr(key)->flags);
pr_notice("Loaded X.509 cert '%s'\n",
key_ref_to_ptr(key)->description);
key_ref_put(key);
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 4870f28403f5..91a7e047a765 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -12,7 +12,6 @@ if ASYMMETRIC_KEY_TYPE
config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
tristate "Asymmetric public-key crypto algorithm subtype"
select MPILIB
- select PUBLIC_KEY_ALGO_RSA
select CRYPTO_HASH_INFO
help
This option provides support for asymmetric public key type handling.
@@ -20,12 +19,6 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
appropriate hash algorithms (such as SHA-1) must be available.
ENOPKG will be reported if the requisite algorithm is unavailable.
-config PUBLIC_KEY_ALGO_RSA
- tristate "RSA public-key algorithm"
- select MPILIB
- help
- This option enables support for the RSA algorithm (PKCS#1, RFC3447).
-
config X509_CERTIFICATE_PARSER
tristate "X.509 certificate parser"
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index cd1406f9b14a..f90486256f01 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := asymmetric_type.o signature.o
obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
-obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
#
# X.509 Certificate handling
@@ -16,21 +15,18 @@ obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
x509_key_parser-y := \
x509-asn1.o \
x509_akid-asn1.o \
- x509_rsakey-asn1.o \
x509_cert_parser.o \
x509_public_key.o
$(obj)/x509_cert_parser.o: \
$(obj)/x509-asn1.h \
- $(obj)/x509_akid-asn1.h \
- $(obj)/x509_rsakey-asn1.h
+ $(obj)/x509_akid-asn1.h
+
$(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h
$(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h
-$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h
clean-files += x509-asn1.c x509-asn1.h
clean-files += x509_akid-asn1.c x509_akid-asn1.h
-clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h
#
# PKCS#7 message handling
diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c
index adcef59eec0b..3242cbfaeaa2 100644
--- a/crypto/asymmetric_keys/mscode_parser.c
+++ b/crypto/asymmetric_keys/mscode_parser.c
@@ -86,25 +86,25 @@ int mscode_note_digest_algo(void *context, size_t hdrlen,
oid = look_up_OID(value, vlen);
switch (oid) {
case OID_md4:
- ctx->digest_algo = HASH_ALGO_MD4;
+ ctx->digest_algo = "md4";
break;
case OID_md5:
- ctx->digest_algo = HASH_ALGO_MD5;
+ ctx->digest_algo = "md5";
break;
case OID_sha1:
- ctx->digest_algo = HASH_ALGO_SHA1;
+ ctx->digest_algo = "sha1";
break;
case OID_sha256:
- ctx->digest_algo = HASH_ALGO_SHA256;
+ ctx->digest_algo = "sha256";
break;
case OID_sha384:
- ctx->digest_algo = HASH_ALGO_SHA384;
+ ctx->digest_algo = "sha384";
break;
case OID_sha512:
- ctx->digest_algo = HASH_ALGO_SHA512;
+ ctx->digest_algo = "sha512";
break;
case OID_sha224:
- ctx->digest_algo = HASH_ALGO_SHA224;
+ ctx->digest_algo = "sha224";
break;
case OID__NR:
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 8f3056cd0399..40de03f49ff8 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -15,7 +15,7 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/oid_registry.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
#include "pkcs7_parser.h"
#include "pkcs7-asn1.h"
@@ -44,7 +44,7 @@ struct pkcs7_parse_context {
static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
{
if (sinfo) {
- mpi_free(sinfo->sig.mpi[0]);
+ kfree(sinfo->sig.s);
kfree(sinfo->sig.digest);
kfree(sinfo->signing_cert_id);
kfree(sinfo);
@@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(pkcs7_free_message);
static int pkcs7_check_authattrs(struct pkcs7_message *msg)
{
struct pkcs7_signed_info *sinfo;
- bool want;
+ bool want = false;
sinfo = msg->signed_infos;
if (sinfo->authattrs) {
@@ -218,25 +218,25 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
switch (ctx->last_oid) {
case OID_md4:
- ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4;
+ ctx->sinfo->sig.hash_algo = "md4";
break;
case OID_md5:
- ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5;
+ ctx->sinfo->sig.hash_algo = "md5";
break;
case OID_sha1:
- ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1;
+ ctx->sinfo->sig.hash_algo = "sha1";
break;
case OID_sha256:
- ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256;
+ ctx->sinfo->sig.hash_algo = "sha256";
break;
case OID_sha384:
- ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA384;
+ ctx->sinfo->sig.hash_algo = "sha384";
break;
case OID_sha512:
- ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA512;
+ ctx->sinfo->sig.hash_algo = "sha512";
break;
case OID_sha224:
- ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA224;
+ ctx->sinfo->sig.hash_algo = "sha224";
default:
printk("Unsupported digest algo: %u\n", ctx->last_oid);
return -ENOPKG;
@@ -255,7 +255,7 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
switch (ctx->last_oid) {
case OID_rsaEncryption:
- ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA;
+ ctx->sinfo->sig.pkey_algo = "rsa";
break;
default:
printk("Unsupported pkey algo: %u\n", ctx->last_oid);
@@ -614,16 +614,12 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct pkcs7_parse_context *ctx = context;
- MPI mpi;
- BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA);
-
- mpi = mpi_read_raw_data(value, vlen);
- if (!mpi)
+ ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL);
+ if (!ctx->sinfo->sig.s)
return -ENOMEM;
- ctx->sinfo->sig.mpi[0] = mpi;
- ctx->sinfo->sig.nr_mpi = 1;
+ ctx->sinfo->sig.s_size = vlen;
return 0;
}
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
index 90d6d47965b0..3bbdcc79a3d3 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -17,7 +17,7 @@
#include <linux/asn1.h>
#include <linux/key.h>
#include <keys/asymmetric-type.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
#include "pkcs7_parser.h"
/**
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 325575caf6b4..50be2a15e531 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -16,7 +16,7 @@
#include <linux/err.h>
#include <linux/asn1.h>
#include <crypto/hash.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
#include "pkcs7_parser.h"
/*
@@ -31,17 +31,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
void *digest;
int ret;
- kenter(",%u,%u", sinfo->index, sinfo->sig.pkey_hash_algo);
+ kenter(",%u,%s", sinfo->index, sinfo->sig.hash_algo);
- if (sinfo->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
- !hash_algo_name[sinfo->sig.pkey_hash_algo])
+ if (!sinfo->sig.hash_algo)
return -ENOPKG;
/* Allocate the hashing algorithm we're going to need and find out how
* big the hash operational data will be.
*/
- tfm = crypto_alloc_shash(hash_algo_name[sinfo->sig.pkey_hash_algo],
- 0, 0);
+ tfm = crypto_alloc_shash(sinfo->sig.hash_algo, 0, 0);
if (IS_ERR(tfm))
return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 6db4c01c6503..0f8b264b3961 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -17,32 +17,13 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
+#include <linux/scatterlist.h>
#include <keys/asymmetric-subtype.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
+#include <crypto/akcipher.h>
MODULE_LICENSE("GPL");
-const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
- [PKEY_ALGO_DSA] = "DSA",
- [PKEY_ALGO_RSA] = "RSA",
-};
-EXPORT_SYMBOL_GPL(pkey_algo_name);
-
-const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = {
-#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
- defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
- [PKEY_ALGO_RSA] = &RSA_public_key_algorithm,
-#endif
-};
-EXPORT_SYMBOL_GPL(pkey_algo);
-
-const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
- [PKEY_ID_PGP] = "PGP",
- [PKEY_ID_X509] = "X509",
- [PKEY_ID_PKCS7] = "PKCS#7",
-};
-EXPORT_SYMBOL_GPL(pkey_id_type_name);
-
/*
* Provide a part of a description of the key for /proc/keys.
*/
@@ -52,8 +33,7 @@ static void public_key_describe(const struct key *asymmetric_key,
struct public_key *key = asymmetric_key->payload.data[asym_crypto];
if (key)
- seq_printf(m, "%s.%s",
- pkey_id_type_name[key->id_type], key->algo->name);
+ seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
}
/*
@@ -62,50 +42,116 @@ static void public_key_describe(const struct key *asymmetric_key,
void public_key_destroy(void *payload)
{
struct public_key *key = payload;
- int i;
- if (key) {
- for (i = 0; i < ARRAY_SIZE(key->mpi); i++)
- mpi_free(key->mpi[i]);
- kfree(key);
- }
+ if (key)
+ kfree(key->key);
+ kfree(key);
}
EXPORT_SYMBOL_GPL(public_key_destroy);
+struct public_key_completion {
+ struct completion completion;
+ int err;
+};
+
+static void public_key_verify_done(struct crypto_async_request *req, int err)
+{
+ struct public_key_completion *compl = req->data;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ compl->err = err;
+ complete(&compl->completion);
+}
+
/*
* Verify a signature using a public key.
*/
-int public_key_verify_signature(const struct public_key *pk,
+int public_key_verify_signature(const struct public_key *pkey,
const struct public_key_signature *sig)
{
- const struct public_key_algorithm *algo;
-
- BUG_ON(!pk);
- BUG_ON(!pk->mpi[0]);
- BUG_ON(!pk->mpi[1]);
+ struct public_key_completion compl;
+ struct crypto_akcipher *tfm;
+ struct akcipher_request *req;
+ struct scatterlist sig_sg, digest_sg;
+ const char *alg_name;
+ char alg_name_buf[CRYPTO_MAX_ALG_NAME];
+ void *output;
+ unsigned int outlen;
+ int ret = -ENOMEM;
+
+ pr_devel("==>%s()\n", __func__);
+
+ BUG_ON(!pkey);
BUG_ON(!sig);
BUG_ON(!sig->digest);
- BUG_ON(!sig->mpi[0]);
-
- algo = pk->algo;
- if (!algo) {
- if (pk->pkey_algo >= PKEY_ALGO__LAST)
- return -ENOPKG;
- algo = pkey_algo[pk->pkey_algo];
- if (!algo)
- return -ENOPKG;
+ BUG_ON(!sig->s);
+
+ alg_name = sig->pkey_algo;
+ if (strcmp(sig->pkey_algo, "rsa") == 0) {
+ /* The data wangled by the RSA algorithm is typically padded
+ * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
+ * sec 8.2].
+ */
+ if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME,
+ "pkcs1pad(rsa,%s)", sig->hash_algo
+ ) >= CRYPTO_MAX_ALG_NAME)
+ return -EINVAL;
+ alg_name = alg_name_buf;
}
- if (!algo->verify_signature)
- return -ENOTSUPP;
-
- if (sig->nr_mpi != algo->n_sig_mpi) {
- pr_debug("Signature has %u MPI not %u\n",
- sig->nr_mpi, algo->n_sig_mpi);
- return -EINVAL;
+ tfm = crypto_alloc_akcipher(alg_name, 0, 0);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+
+ req = akcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req)
+ goto error_free_tfm;
+
+ ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
+ if (ret)
+ goto error_free_req;
+
+ outlen = crypto_akcipher_maxsize(tfm);
+ output = kmalloc(outlen, GFP_KERNEL);
+ if (!output)
+ goto error_free_req;
+
+ sg_init_one(&sig_sg, sig->s, sig->s_size);
+ sg_init_one(&digest_sg, output, outlen);
+ akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size,
+ outlen);
+ init_completion(&compl.completion);
+ akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ public_key_verify_done, &compl);
+
+ /* Perform the verification calculation. This doesn't actually do the
+ * verification, but rather calculates the hash expected by the
+ * signature and returns that to us.
+ */
+ ret = crypto_akcipher_verify(req);
+ if (ret == -EINPROGRESS) {
+ wait_for_completion(&compl.completion);
+ ret = compl.err;
}
-
- return algo->verify_signature(pk, sig);
+ if (ret < 0)
+ goto out_free_output;
+
+ /* Do the actual verification step. */
+ if (req->dst_len != sig->digest_size ||
+ memcmp(sig->digest, output, sig->digest_size) != 0)
+ ret = -EKEYREJECTED;
+
+out_free_output:
+ kfree(output);
+error_free_req:
+ akcipher_request_free(req);
+error_free_tfm:
+ crypto_free_akcipher(tfm);
+ pr_devel("<==%s() = %d\n", __func__, ret);
+ return ret;
}
EXPORT_SYMBOL_GPL(public_key_verify_signature);
diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h
deleted file mode 100644
index 5c37a22a0637..000000000000
--- a/crypto/asymmetric_keys/public_key.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Public key algorithm internals
- *
- * See Documentation/crypto/asymmetric-keys.txt
- *
- * Copyright (C) 2012 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.
- */
-
-#include <crypto/public_key.h>
-
-extern struct asymmetric_key_subtype public_key_subtype;
-
-/*
- * Public key algorithm definition.
- */
-struct public_key_algorithm {
- const char *name;
- u8 n_pub_mpi; /* Number of MPIs in public key */
- u8 n_sec_mpi; /* Number of MPIs in secret key */
- u8 n_sig_mpi; /* Number of MPIs in a signature */
- int (*verify_signature)(const struct public_key *key,
- const struct public_key_signature *sig);
-};
-
-extern const struct public_key_algorithm RSA_public_key_algorithm;
-
-/*
- * public_key.c
- */
-extern int public_key_verify_signature(const struct public_key *pk,
- const struct public_key_signature *sig);
diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
deleted file mode 100644
index 508b57b77474..000000000000
--- a/crypto/asymmetric_keys/rsa.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* RSA asymmetric public-key algorithm [RFC3447]
- *
- * Copyright (C) 2012 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 pr_fmt(fmt) "RSA: "fmt
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <crypto/algapi.h>
-#include "public_key.h"
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("RSA Public Key Algorithm");
-
-#define kenter(FMT, ...) \
- pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
-#define kleave(FMT, ...) \
- pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
-
-/*
- * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
- */
-static const u8 RSA_digest_info_MD5[] = {
- 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
- 0x05, 0x00, 0x04, 0x10
-};
-
-static const u8 RSA_digest_info_SHA1[] = {
- 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
- 0x2B, 0x0E, 0x03, 0x02, 0x1A,
- 0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 RSA_digest_info_RIPE_MD_160[] = {
- 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
- 0x2B, 0x24, 0x03, 0x02, 0x01,
- 0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 RSA_digest_info_SHA224[] = {
- 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
- 0x05, 0x00, 0x04, 0x1C
-};
-
-static const u8 RSA_digest_info_SHA256[] = {
- 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
- 0x05, 0x00, 0x04, 0x20
-};
-
-static const u8 RSA_digest_info_SHA384[] = {
- 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
- 0x05, 0x00, 0x04, 0x30
-};
-
-static const u8 RSA_digest_info_SHA512[] = {
- 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
- 0x05, 0x00, 0x04, 0x40
-};
-
-static const struct {
- const u8 *data;
- size_t size;
-} RSA_ASN1_templates[PKEY_HASH__LAST] = {
-#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
- [HASH_ALGO_MD5] = _(MD5),
- [HASH_ALGO_SHA1] = _(SHA1),
- [HASH_ALGO_RIPE_MD_160] = _(RIPE_MD_160),
- [HASH_ALGO_SHA256] = _(SHA256),
- [HASH_ALGO_SHA384] = _(SHA384),
- [HASH_ALGO_SHA512] = _(SHA512),
- [HASH_ALGO_SHA224] = _(SHA224),
-#undef _
-};
-
-/*
- * RSAVP1() function [RFC3447 sec 5.2.2]
- */
-static int RSAVP1(const struct public_key *key, MPI s, MPI *_m)
-{
- MPI m;
- int ret;
-
- /* (1) Validate 0 <= s < n */
- if (mpi_cmp_ui(s, 0) < 0) {
- kleave(" = -EBADMSG [s < 0]");
- return -EBADMSG;
- }
- if (mpi_cmp(s, key->rsa.n) >= 0) {
- kleave(" = -EBADMSG [s >= n]");
- return -EBADMSG;
- }
-
- m = mpi_alloc(0);
- if (!m)
- return -ENOMEM;
-
- /* (2) m = s^e mod n */
- ret = mpi_powm(m, s, key->rsa.e, key->rsa.n);
- if (ret < 0) {
- mpi_free(m);
- return ret;
- }
-
- *_m = m;
- return 0;
-}
-
-/*
- * Integer to Octet String conversion [RFC3447 sec 4.1]
- */
-static int RSA_I2OSP(MPI x, size_t xLen, u8 **pX)
-{
- unsigned X_size, x_size;
- int X_sign;
- u8 *X;
-
- /* Make sure the string is the right length. The number should begin
- * with { 0x00, 0x01, ... } so we have to account for 15 leading zero
- * bits not being reported by MPI.
- */
- x_size = mpi_get_nbits(x);
- pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8);
- if (x_size != xLen * 8 - 15)
- return -ERANGE;
-
- X = mpi_get_buffer(x, &X_size, &X_sign);
- if (!X)
- return -ENOMEM;
- if (X_sign < 0) {
- kfree(X);
- return -EBADMSG;
- }
- if (X_size != xLen - 1) {
- kfree(X);
- return -EBADMSG;
- }
-
- *pX = X;
- return 0;
-}
-
-/*
- * Perform the RSA signature verification.
- * @H: Value of hash of data and metadata
- * @EM: The computed signature value
- * @k: The size of EM (EM[0] is an invalid location but should hold 0x00)
- * @hash_size: The size of H
- * @asn1_template: The DigestInfo ASN.1 template
- * @asn1_size: Size of asm1_template[]
- */
-static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
- const u8 *asn1_template, size_t asn1_size)
-{
- unsigned PS_end, T_offset, i;
-
- kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size);
-
- if (k < 2 + 1 + asn1_size + hash_size)
- return -EBADMSG;
-
- /* Decode the EMSA-PKCS1-v1_5 */
- if (EM[1] != 0x01) {
- kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]);
- return -EBADMSG;
- }
-
- T_offset = k - (asn1_size + hash_size);
- PS_end = T_offset - 1;
- if (EM[PS_end] != 0x00) {
- kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]);
- return -EBADMSG;
- }
-
- for (i = 2; i < PS_end; i++) {
- if (EM[i] != 0xff) {
- kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]);
- return -EBADMSG;
- }
- }
-
- if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) {
- kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
- return -EBADMSG;
- }
-
- if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) {
- kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
- return -EKEYREJECTED;
- }
-
- kleave(" = 0");
- return 0;
-}
-
-/*
- * Perform the verification step [RFC3447 sec 8.2.2].
- */
-static int RSA_verify_signature(const struct public_key *key,
- const struct public_key_signature *sig)
-{
- size_t tsize;
- int ret;
-
- /* Variables as per RFC3447 sec 8.2.2 */
- const u8 *H = sig->digest;
- u8 *EM = NULL;
- MPI m = NULL;
- size_t k;
-
- kenter("");
-
- if (!RSA_ASN1_templates[sig->pkey_hash_algo].data)
- return -ENOTSUPP;
-
- /* (1) Check the signature size against the public key modulus size */
- k = mpi_get_nbits(key->rsa.n);
- tsize = mpi_get_nbits(sig->rsa.s);
-
- /* According to RFC 4880 sec 3.2, length of MPI is computed starting
- * from most significant bit. So the RFC 3447 sec 8.2.2 size check
- * must be relaxed to conform with shorter signatures - so we fail here
- * only if signature length is longer than modulus size.
- */
- pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize);
- if (k < tsize) {
- ret = -EBADMSG;
- goto error;
- }
-
- /* Round up and convert to octets */
- k = (k + 7) / 8;
-
- /* (2b) Apply the RSAVP1 verification primitive to the public key */
- ret = RSAVP1(key, sig->rsa.s, &m);
- if (ret < 0)
- goto error;
-
- /* (2c) Convert the message representative (m) to an encoded message
- * (EM) of length k octets.
- *
- * NOTE! The leading zero byte is suppressed by MPI, so we pass a
- * pointer to the _preceding_ byte to RSA_verify()!
- */
- ret = RSA_I2OSP(m, k, &EM);
- if (ret < 0)
- goto error;
-
- ret = RSA_verify(H, EM - 1, k, sig->digest_size,
- RSA_ASN1_templates[sig->pkey_hash_algo].data,
- RSA_ASN1_templates[sig->pkey_hash_algo].size);
-
-error:
- kfree(EM);
- mpi_free(m);
- kleave(" = %d", ret);
- return ret;
-}
-
-const struct public_key_algorithm RSA_public_key_algorithm = {
- .name = "RSA",
- .n_pub_mpi = 2,
- .n_sec_mpi = 3,
- .n_sig_mpi = 1,
- .verify_signature = RSA_verify_signature,
-};
-EXPORT_SYMBOL_GPL(RSA_public_key_algorithm);
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c
index 897b734dabf9..7e8c2338ae25 100644
--- a/crypto/asymmetric_keys/verify_pefile.c
+++ b/crypto/asymmetric_keys/verify_pefile.c
@@ -328,12 +328,12 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
void *digest;
int ret;
- kenter(",%u", ctx->digest_algo);
+ kenter(",%s", ctx->digest_algo);
/* Allocate the hashing algorithm we're going to need and find out how
* big the hash operational data will be.
*/
- tfm = crypto_alloc_shash(hash_algo_name[ctx->digest_algo], 0, 0);
+ tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0);
if (IS_ERR(tfm))
return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
diff --git a/crypto/asymmetric_keys/verify_pefile.h b/crypto/asymmetric_keys/verify_pefile.h
index 55d5f7ebc45a..a133eb81a492 100644
--- a/crypto/asymmetric_keys/verify_pefile.h
+++ b/crypto/asymmetric_keys/verify_pefile.h
@@ -28,7 +28,7 @@ struct pefile_context {
/* PKCS#7 MS Individual Code Signing content */
const void *digest; /* Digest */
unsigned digest_len; /* Digest length */
- enum hash_algo digest_algo; /* Digest algorithm */
+ const char *digest_algo; /* Digest algorithm */
};
#define kenter(FMT, ...) \
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 021d39c0ba75..4a29bac70060 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -15,11 +15,10 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/oid_registry.h>
-#include "public_key.h"
+#include <crypto/public_key.h>
#include "x509_parser.h"
#include "x509-asn1.h"
#include "x509_akid-asn1.h"
-#include "x509_rsakey-asn1.h"
struct x509_parse_context {
struct x509_certificate *cert; /* Certificate being constructed */
@@ -56,7 +55,7 @@ void x509_free_certificate(struct x509_certificate *cert)
kfree(cert->akid_id);
kfree(cert->akid_skid);
kfree(cert->sig.digest);
- mpi_free(cert->sig.rsa.s);
+ kfree(cert->sig.s);
kfree(cert);
}
}
@@ -103,12 +102,12 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
}
}
- /* Decode the public key */
- ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx,
- ctx->key, ctx->key_size);
- if (ret < 0)
+ cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL);
+ if (!cert->pub->key)
goto error_decode;
+ cert->pub->keylen = ctx->key_size;
+
/* Generate cert issuer + serial number key ID */
kid = asymmetric_key_generate_id(cert->raw_serial,
cert->raw_serial_size,
@@ -124,6 +123,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
return cert;
error_decode:
+ kfree(cert->pub->key);
kfree(ctx);
error_no_ctx:
x509_free_certificate(cert);
@@ -188,33 +188,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
return -ENOPKG; /* Unsupported combination */
case OID_md4WithRSAEncryption:
- ctx->cert->sig.pkey_hash_algo = HASH_ALGO_MD5;
- ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+ ctx->cert->sig.hash_algo = "md4";
+ ctx->cert->sig.pkey_algo = "rsa";
break;
case OID_sha1WithRSAEncryption:
- ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA1;
- ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+ ctx->cert->sig.hash_algo = "sha1";
+ ctx->cert->sig.pkey_algo = "rsa";
break;
case OID_sha256WithRSAEncryption:
- ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA256;
- ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+ ctx->cert->sig.hash_algo = "sha256";
+ ctx->cert->sig.pkey_algo = "rsa";
break;
case OID_sha384WithRSAEncryption:
- ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA384;
- ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+ ctx->cert->sig.hash_algo = "sha384";
+ ctx->cert->sig.pkey_algo = "rsa";
break;
case OID_sha512WithRSAEncryption:
- ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA512;
- ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+ ctx->cert->sig.hash_algo = "sha512";
+ ctx->cert->sig.pkey_algo = "rsa";
break;
case OID_sha224WithRSAEncryption:
- ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA224;
- ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
+ ctx->cert->sig.hash_algo = "sha224";
+ ctx->cert->sig.pkey_algo = "rsa";
break;
}
@@ -396,7 +396,7 @@ int x509_extract_key_data(void *context, size_t hdrlen,
if (ctx->last_oid != OID_rsaEncryption)
return -ENOPKG;
- ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA;
+ ctx->cert->pub->pkey_algo = "rsa";
/* Discard the BIT STRING metadata */
ctx->key = value + 1;
@@ -404,29 +404,6 @@ int x509_extract_key_data(void *context, size_t hdrlen,
return 0;
}
-/*
- * Extract a RSA public key value
- */
-int rsa_extract_mpi(void *context, size_t hdrlen,
- unsigned char tag,
- const void *value, size_t vlen)
-{
- struct x509_parse_context *ctx = context;
- MPI mpi;
-
- if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) {
- pr_err("Too many public key MPIs in certificate\n");
- return -EBADMSG;
- }
-
- mpi = mpi_read_raw_data(value, vlen);
- if (!mpi)
- return -ENOMEM;
-
- ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi;
- return 0;
-}
-
/* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */
#define SEQ_TAG_KEYID (ASN1_CONT << 6)
@@ -494,7 +471,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
unsigned char tag,
const unsigned char *value, size_t vlen)
{
- static const unsigned char month_lengths[] = { 31, 29, 31, 30, 31, 30,
+ static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };
const unsigned char *p = value;
unsigned year, mon, day, hour, min, sec, mon_len;
@@ -540,17 +517,17 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
if (year % 4 == 0) {
mon_len = 29;
if (year % 100 == 0) {
- year /= 100;
- if (year % 4 != 0)
- mon_len = 28;
+ mon_len = 28;
+ if (year % 400 == 0)
+ mon_len = 29;
}
}
}
if (day < 1 || day > mon_len ||
- hour > 23 ||
+ hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */
min > 59 ||
- sec > 59)
+ sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */
goto invalid_time;
*_t = mktime64(year, mon, day, hour, min, sec);
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 9e9e5a6a9ed6..733c046aacc6 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -13,15 +13,11 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/mpi.h>
-#include <linux/asn1_decoder.h>
#include <keys/asymmetric-subtype.h>
#include <keys/asymmetric-parser.h>
#include <keys/system_keyring.h>
#include <crypto/hash.h>
#include "asymmetric_keys.h"
-#include "public_key.h"
#include "x509_parser.h"
static bool use_builtin_keys;
@@ -167,18 +163,20 @@ int x509_get_sig_params(struct x509_certificate *cert)
if (cert->unsupported_crypto)
return -ENOPKG;
- if (cert->sig.rsa.s)
+ if (cert->sig.s)
return 0;
- cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size);
- if (!cert->sig.rsa.s)
+ cert->sig.s = kmemdup(cert->raw_sig, cert->raw_sig_size,
+ GFP_KERNEL);
+ if (!cert->sig.s)
return -ENOMEM;
- cert->sig.nr_mpi = 1;
+
+ cert->sig.s_size = cert->raw_sig_size;
/* Allocate the hashing algorithm we're going to need and find out how
* big the hash operational data will be.
*/
- tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0);
+ tfm = crypto_alloc_shash(cert->sig.hash_algo, 0, 0);
if (IS_ERR(tfm)) {
if (PTR_ERR(tfm) == -ENOENT) {
cert->unsupported_crypto = true;
@@ -293,24 +291,20 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
pr_devel("Cert Issuer: %s\n", cert->issuer);
pr_devel("Cert Subject: %s\n", cert->subject);
- if (cert->pub->pkey_algo >= PKEY_ALGO__LAST ||
- cert->sig.pkey_algo >= PKEY_ALGO__LAST ||
- cert->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
- !pkey_algo[cert->pub->pkey_algo] ||
- !pkey_algo[cert->sig.pkey_algo] ||
- !hash_algo_name[cert->sig.pkey_hash_algo]) {
+ if (!cert->pub->pkey_algo ||
+ !cert->sig.pkey_algo ||
+ !cert->sig.hash_algo) {
ret = -ENOPKG;
goto error_free_cert;
}
- pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]);
+ pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
pr_devel("Cert Signature: %s + %s\n",
- pkey_algo_name[cert->sig.pkey_algo],
- hash_algo_name[cert->sig.pkey_hash_algo]);
+ cert->sig.pkey_algo,
+ cert->sig.hash_algo);
- cert->pub->algo = pkey_algo[cert->pub->pkey_algo];
- cert->pub->id_type = PKEY_ID_X509;
+ cert->pub->id_type = "X509";
/* Check the signature on the key if it appears to be self-signed */
if ((!cert->akid_skid && !cert->akid_id) ||
diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1
deleted file mode 100644
index 4ec7cc6532c1..000000000000
--- a/crypto/asymmetric_keys/x509_rsakey.asn1
+++ /dev/null
@@ -1,4 +0,0 @@
-RSAPublicKey ::= SEQUENCE {
- modulus INTEGER ({ rsa_extract_mpi }), -- n
- publicExponent INTEGER ({ rsa_extract_mpi }) -- e
- }
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 50f5c97e1087..1cea67d43e1d 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -18,12 +18,89 @@
#include <linux/module.h>
#include <linux/random.h>
+/*
+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
+ */
+static const u8 rsa_digest_info_md5[] = {
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
+ 0x05, 0x00, 0x04, 0x10
+};
+
+static const u8 rsa_digest_info_sha1[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+ 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 rsa_digest_info_rmd160[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+ 0x2b, 0x24, 0x03, 0x02, 0x01,
+ 0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 rsa_digest_info_sha224[] = {
+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+ 0x05, 0x00, 0x04, 0x1c
+};
+
+static const u8 rsa_digest_info_sha256[] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+ 0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 rsa_digest_info_sha384[] = {
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+ 0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 rsa_digest_info_sha512[] = {
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+ 0x05, 0x00, 0x04, 0x40
+};
+
+static const struct rsa_asn1_template {
+ const char *name;
+ const u8 *data;
+ size_t size;
+} rsa_asn1_templates[] = {
+#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
+ _(md5),
+ _(sha1),
+ _(rmd160),
+ _(sha256),
+ _(sha384),
+ _(sha512),
+ _(sha224),
+ { NULL }
+#undef _
+};
+
+static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
+{
+ const struct rsa_asn1_template *p;
+
+ for (p = rsa_asn1_templates; p->name; p++)
+ if (strcmp(name, p->name) == 0)
+ return p;
+ return NULL;
+}
+
struct pkcs1pad_ctx {
struct crypto_akcipher *child;
-
+ const char *hash_name;
unsigned int key_size;
};
+struct pkcs1pad_inst_ctx {
+ struct crypto_akcipher_spawn spawn;
+ const char *hash_name;
+};
+
struct pkcs1pad_request {
struct akcipher_request child_req;
@@ -339,13 +416,22 @@ static int pkcs1pad_sign(struct akcipher_request *req)
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
+ const struct rsa_asn1_template *digest_info = NULL;
int err;
- unsigned int ps_end;
+ unsigned int ps_end, digest_size = 0;
if (!ctx->key_size)
return -EINVAL;
- if (req->src_len > ctx->key_size - 11)
+ if (ctx->hash_name) {
+ digest_info = rsa_lookup_asn1(ctx->hash_name);
+ if (!digest_info)
+ return -EINVAL;
+
+ digest_size = digest_info->size;
+ }
+
+ if (req->src_len + digest_size > ctx->key_size - 11)
return -EOVERFLOW;
if (req->dst_len < ctx->key_size) {
@@ -371,11 +457,16 @@ static int pkcs1pad_sign(struct akcipher_request *req)
if (!req_ctx->in_buf)
return -ENOMEM;
- ps_end = ctx->key_size - req->src_len - 2;
+ ps_end = ctx->key_size - digest_size - req->src_len - 2;
req_ctx->in_buf[0] = 0x01;
memset(req_ctx->in_buf + 1, 0xff, ps_end - 1);
req_ctx->in_buf[ps_end] = 0x00;
+ if (digest_info) {
+ memcpy(req_ctx->in_buf + ps_end + 1, digest_info->data,
+ digest_info->size);
+ }
+
pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
ctx->key_size - 1 - req->src_len, req->src);
@@ -408,6 +499,7 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
+ const struct rsa_asn1_template *digest_info;
unsigned int pos;
if (err == -EOVERFLOW)
@@ -422,20 +514,33 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
goto done;
}
- if (req_ctx->out_buf[0] != 0x01) {
- err = -EINVAL;
+ err = -EBADMSG;
+ if (req_ctx->out_buf[0] != 0x01)
goto done;
- }
+
for (pos = 1; pos < req_ctx->child_req.dst_len; pos++)
if (req_ctx->out_buf[pos] != 0xff)
break;
+
if (pos < 9 || pos == req_ctx->child_req.dst_len ||
- req_ctx->out_buf[pos] != 0x00) {
- err = -EINVAL;
+ req_ctx->out_buf[pos] != 0x00)
goto done;
- }
pos++;
+ if (ctx->hash_name) {
+ digest_info = rsa_lookup_asn1(ctx->hash_name);
+ if (!digest_info)
+ goto done;
+
+ if (memcmp(req_ctx->out_buf + pos, digest_info->data,
+ digest_info->size))
+ goto done;
+
+ pos += digest_info->size;
+ }
+
+ err = 0;
+
if (req->dst_len < req_ctx->child_req.dst_len - pos)
err = -EOVERFLOW;
req->dst_len = req_ctx->child_req.dst_len - pos;
@@ -444,7 +549,6 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
sg_copy_from_buffer(req->dst,
sg_nents_for_len(req->dst, req->dst_len),
req_ctx->out_buf + pos, req->dst_len);
-
done:
kzfree(req_ctx->out_buf);
@@ -481,7 +585,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
int err;
- if (!ctx->key_size || req->src_len != ctx->key_size)
+ if (!ctx->key_size || req->src_len < ctx->key_size)
return -EINVAL;
if (ctx->key_size > PAGE_SIZE)
@@ -518,6 +622,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
{
struct akcipher_instance *inst = akcipher_alg_instance(tfm);
+ struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct crypto_akcipher *child_tfm;
@@ -526,7 +631,7 @@ static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
return PTR_ERR(child_tfm);
ctx->child = child_tfm;
-
+ ctx->hash_name = ictx->hash_name;
return 0;
}
@@ -539,10 +644,11 @@ static void pkcs1pad_exit_tfm(struct crypto_akcipher *tfm)
static void pkcs1pad_free(struct akcipher_instance *inst)
{
- struct crypto_akcipher_spawn *spawn = akcipher_instance_ctx(inst);
+ struct pkcs1pad_inst_ctx *ctx = akcipher_instance_ctx(inst);
+ struct crypto_akcipher_spawn *spawn = &ctx->spawn;
crypto_drop_akcipher(spawn);
-
+ kfree(ctx->hash_name);
kfree(inst);
}
@@ -550,9 +656,11 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
{
struct crypto_attr_type *algt;
struct akcipher_instance *inst;
+ struct pkcs1pad_inst_ctx *ctx;
struct crypto_akcipher_spawn *spawn;
struct akcipher_alg *rsa_alg;
const char *rsa_alg_name;
+ const char *hash_name;
int err;
algt = crypto_get_attr_type(tb);
@@ -566,11 +674,18 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
if (IS_ERR(rsa_alg_name))
return PTR_ERR(rsa_alg_name);
- inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+ hash_name = crypto_attr_alg_name(tb[2]);
+ if (IS_ERR(hash_name))
+ hash_name = NULL;
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
if (!inst)
return -ENOMEM;
- spawn = akcipher_instance_ctx(inst);
+ ctx = akcipher_instance_ctx(inst);
+ spawn = &ctx->spawn;
+ ctx->hash_name = hash_name ? kstrdup(hash_name, GFP_KERNEL) : NULL;
+
crypto_set_spawn(&spawn->base, akcipher_crypto_instance(inst));
err = crypto_grab_akcipher(spawn, rsa_alg_name, 0,
crypto_requires_sync(algt->type, algt->mask));
@@ -580,15 +695,28 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
rsa_alg = crypto_spawn_akcipher_alg(spawn);
err = -ENAMETOOLONG;
- if (snprintf(inst->alg.base.cra_name,
- CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
- rsa_alg->base.cra_name) >=
- CRYPTO_MAX_ALG_NAME ||
- snprintf(inst->alg.base.cra_driver_name,
- CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
- rsa_alg->base.cra_driver_name) >=
- CRYPTO_MAX_ALG_NAME)
+
+ if (!hash_name) {
+ if (snprintf(inst->alg.base.cra_name,
+ CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
+ rsa_alg->base.cra_name) >=
+ CRYPTO_MAX_ALG_NAME ||
+ snprintf(inst->alg.base.cra_driver_name,
+ CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
+ rsa_alg->base.cra_driver_name) >=
+ CRYPTO_MAX_ALG_NAME)
goto out_drop_alg;
+ } else {
+ if (snprintf(inst->alg.base.cra_name,
+ CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
+ rsa_alg->base.cra_name, hash_name) >=
+ CRYPTO_MAX_ALG_NAME ||
+ snprintf(inst->alg.base.cra_driver_name,
+ CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
+ rsa_alg->base.cra_driver_name, hash_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto out_free_hash;
+ }
inst->alg.base.cra_flags = rsa_alg->base.cra_flags & CRYPTO_ALG_ASYNC;
inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
@@ -610,10 +738,12 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
err = akcipher_register_instance(tmpl, inst);
if (err)
- goto out_drop_alg;
+ goto out_free_hash;
return 0;
+out_free_hash:
+ kfree(ctx->hash_name);
out_drop_alg:
crypto_drop_akcipher(spawn);
out_free_inst:
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index cc2516df0efa..aa730ea7faf8 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -14,30 +14,6 @@
#ifndef _LINUX_PUBLIC_KEY_H
#define _LINUX_PUBLIC_KEY_H
-#include <linux/mpi.h>
-#include <crypto/hash_info.h>
-
-enum pkey_algo {
- PKEY_ALGO_DSA,
- PKEY_ALGO_RSA,
- PKEY_ALGO__LAST
-};
-
-extern const char *const pkey_algo_name[PKEY_ALGO__LAST];
-extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST];
-
-/* asymmetric key implementation supports only up to SHA224 */
-#define PKEY_HASH__LAST (HASH_ALGO_SHA224 + 1)
-
-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
-};
-
-extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST];
-
/*
* The use to which an asymmetric key is being put.
*/
@@ -59,31 +35,10 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
* part.
*/
struct public_key {
- const struct public_key_algorithm *algo;
- u8 capabilities;
-#define PKEY_CAN_ENCRYPT 0x01
-#define PKEY_CAN_DECRYPT 0x02
-#define PKEY_CAN_SIGN 0x04
-#define PKEY_CAN_VERIFY 0x08
- enum pkey_algo pkey_algo : 8;
- enum pkey_id_type id_type : 8;
- union {
- MPI mpi[5];
- struct {
- MPI p; /* DSA prime */
- MPI q; /* DSA group order */
- MPI g; /* DSA group generator */
- MPI y; /* DSA public-key value = g^x mod p */
- MPI x; /* DSA secret exponent (if present) */
- } dsa;
- struct {
- MPI n; /* RSA public modulus */
- MPI e; /* RSA public encryption exponent */
- MPI d; /* RSA secret encryption exponent (if present) */
- MPI p; /* RSA secret prime (if present) */
- MPI q; /* RSA secret prime (if present) */
- } rsa;
- };
+ void *key;
+ u32 keylen;
+ const char *id_type;
+ const char *pkey_algo;
};
extern void public_key_destroy(void *payload);
@@ -92,23 +47,15 @@ extern void public_key_destroy(void *payload);
* Public key cryptography signature data
*/
struct public_key_signature {
+ u8 *s; /* Signature */
+ u32 s_size; /* Number of bytes in signature */
u8 *digest;
- u8 digest_size; /* Number of bytes in digest */
- u8 nr_mpi; /* Occupancy of mpi[] */
- enum pkey_algo pkey_algo : 8;
- enum hash_algo pkey_hash_algo : 8;
- union {
- MPI mpi[2];
- struct {
- MPI s; /* m^d mod n */
- } rsa;
- struct {
- MPI r;
- MPI s;
- } dsa;
- };
+ u8 digest_size; /* Number of bytes in digest */
+ const char *pkey_algo;
+ const char *hash_algo;
};
+extern struct asymmetric_key_subtype public_key_subtype;
struct key;
extern int verify_signature(const struct key *key,
const struct public_key_signature *sig);
@@ -119,4 +66,7 @@ extern struct key *x509_request_asymmetric_key(struct key *keyring,
const struct asymmetric_key_id *skid,
bool partial);
+int public_key_verify_signature(const struct public_key *pkey,
+ const struct public_key_signature *sig);
+
#endif /* _LINUX_PUBLIC_KEY_H */
diff --git a/include/linux/key.h b/include/linux/key.h
index 7321ab8ef949..5f5b1129dc92 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -219,6 +219,7 @@ extern struct key *key_alloc(struct key_type *type,
#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */
#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */
+#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */
extern void key_revoke(struct key *key);
extern void key_invalidate(struct key *key);
diff --git a/init/Kconfig b/init/Kconfig
index 22320804fbaf..af4de4f1b02c 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1757,9 +1757,9 @@ config SYSTEM_DATA_VERIFICATION
select SYSTEM_TRUSTED_KEYRING
select KEYS
select CRYPTO
+ select CRYPTO_RSA
select ASYMMETRIC_KEY_TYPE
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
- select PUBLIC_KEY_ALGO_RSA
select ASN1
select OID_REGISTRY
select X509_CERTIFICATE_PARSER
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index 6528a79d998d..64b9dead4a07 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -11,10 +11,17 @@
#include <linux/kernel.h>
#include <linux/errno.h>
+#include <linux/string.h>
#include <keys/system_keyring.h>
#include <crypto/public_key.h>
#include "module-internal.h"
+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 */
+};
+
/*
* Module signature information block.
*
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 86751c68e08d..be115b020d27 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -322,6 +322,13 @@ EXPORT_SYMBOL(timespec_trunc);
* -year/100+year/400 terms, and add 10.]
*
* This algorithm was first published by Gauss (I think).
+ *
+ * A leap second can be indicated by calling this function with sec as
+ * 60 (allowable under ISO 8601). The leap second is treated the same
+ * as the following second since they don't exist in UNIX time.
+ *
+ * An encoding of midnight at the end of the day as 24:00:00 - ie. midnight
+ * tomorrow - (allowable under ISO 8601) is supported.
*/
time64_t mktime64(const unsigned int year0, const unsigned int mon0,
const unsigned int day, const unsigned int hour,
@@ -338,7 +345,7 @@ time64_t mktime64(const unsigned int year0, const unsigned int mon0,
return ((((time64_t)
(year/4 - year/100 + year/400 + 367*mon/12 + day) +
year*365 - 719499
- )*24 + hour /* now have hours */
+ )*24 + hour /* now have hours - midnight tomorrow handled here */
)*60 + min /* now have minutes */
)*60 + sec; /* finally seconds */
}
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 1f78169d4254..e063daa3ec4a 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -13,3 +13,4 @@ sortextable
asn1_compiler
extract-cert
sign-file
+insert-sys-cert
diff --git a/scripts/Makefile b/scripts/Makefile
index fd0d53d4a234..822ab4a6a4aa 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -19,6 +19,7 @@ hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
hostprogs-$(CONFIG_ASN1) += asn1_compiler
hostprogs-$(CONFIG_MODULE_SIG) += sign-file
hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
+hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
diff --git a/scripts/extract-sys-certs.pl b/scripts/extract-sys-certs.pl
index d476e7d1fd88..8227ca10a494 100755
--- a/scripts/extract-sys-certs.pl
+++ b/scripts/extract-sys-certs.pl
@@ -91,13 +91,15 @@ print "Have $nr_symbols symbols\n";
die "Can't find system certificate list"
unless (exists($symbols{"__cert_list_start"}) &&
- exists($symbols{"__cert_list_end"}));
+ exists($symbols{"system_certificate_list_size"}));
my $start = Math::BigInt->new($symbols{"__cert_list_start"});
-my $end = Math::BigInt->new($symbols{"__cert_list_end"});
-my $size = $end - $start;
+my $end;
+my $size;
+my $size_sym = Math::BigInt->new($symbols{"system_certificate_list_size"});
-printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start;
+open FD, "<$vmlinux" || die $vmlinux;
+binmode(FD);
my $s = undef;
foreach my $sec (@sections) {
@@ -110,11 +112,24 @@ foreach my $sec (@sections) {
next unless ($start >= $s_vma);
next if ($start >= $s_vend);
- die "Cert object partially overflows section $s_name\n"
- if ($end > $s_vend);
+ die "Certificate list size was not found on the same section\n"
+ if ($size_sym < $s_vma || $size_sym > $s_vend);
die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n"
if ($s);
+
+ my $size_off = $size_sym -$s_vma + $s_foff;
+ my $packed;
+ die $vmlinux if (!defined(sysseek(FD, $size_off, SEEK_SET)));
+ sysread(FD, $packed, 8);
+ $size = unpack 'L!', $packed;
+ $end = $start + $size;
+
+ printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start;
+
+ die "Cert object partially overflows section $s_name\n"
+ if ($end > $s_vend);
+
$s = $sec;
}
@@ -127,8 +142,6 @@ my $foff = $start - $s->{vma} + $s->{foff};
printf "Certificate list at file offset 0x%x\n", $foff;
-open FD, "<$vmlinux" || die $vmlinux;
-binmode(FD);
die $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET)));
my $buf = "";
my $len = sysread(FD, $buf, $size);
diff --git a/scripts/insert-sys-cert.c b/scripts/insert-sys-cert.c
new file mode 100644
index 000000000000..8902836c2342
--- /dev/null
+++ b/scripts/insert-sys-cert.c
@@ -0,0 +1,410 @@
+/* Write the contents of the <certfile> into kernel symbol system_extra_cert
+ *
+ * Copyright (C) IBM Corporation, 2015
+ *
+ * Author: Mehmet Kayaalp <mkayaalp@linux.vnet.ibm.com>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * Usage: insert-sys-cert [-s <System.map> -b <vmlinux> -c <certfile>
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <elf.h>
+
+#define CERT_SYM "system_extra_cert"
+#define USED_SYM "system_extra_cert_used"
+#define LSIZE_SYM "system_certificate_list_size"
+
+#define info(format, args...) fprintf(stderr, "INFO: " format, ## args)
+#define warn(format, args...) fprintf(stdout, "WARNING: " format, ## args)
+#define err(format, args...) fprintf(stderr, "ERROR: " format, ## args)
+
+#if UINTPTR_MAX == 0xffffffff
+#define CURRENT_ELFCLASS ELFCLASS32
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#else
+#define CURRENT_ELFCLASS ELFCLASS64
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#endif
+
+static unsigned char endianness(void)
+{
+ uint16_t two_byte = 0x00FF;
+ uint8_t low_address = *((uint8_t *)&two_byte);
+
+ if (low_address == 0)
+ return ELFDATA2MSB;
+ else
+ return ELFDATA2LSB;
+}
+
+struct sym {
+ char *name;
+ unsigned long address;
+ unsigned long offset;
+ void *content;
+ int size;
+};
+
+static unsigned long get_offset_from_address(Elf_Ehdr *hdr, unsigned long addr)
+{
+ Elf_Shdr *x;
+ unsigned int i, num_sections;
+
+ x = (void *)hdr + hdr->e_shoff;
+ if (hdr->e_shnum == SHN_UNDEF)
+ num_sections = x[0].sh_size;
+ else
+ num_sections = hdr->e_shnum;
+
+ for (i = 1; i < num_sections; i++) {
+ unsigned long start = x[i].sh_addr;
+ unsigned long end = start + x[i].sh_size;
+ unsigned long offset = x[i].sh_offset;
+
+ if (addr >= start && addr <= end)
+ return addr - start + offset;
+ }
+ return 0;
+}
+
+
+#define LINE_SIZE 100
+
+static void get_symbol_from_map(Elf_Ehdr *hdr, FILE *f, char *name,
+ struct sym *s)
+{
+ char l[LINE_SIZE];
+ char *w, *p, *n;
+
+ s->size = 0;
+ s->address = 0;
+ s->offset = 0;
+ if (fseek(f, 0, SEEK_SET) != 0) {
+ perror("File seek failed");
+ exit(EXIT_FAILURE);
+ }
+ while (fgets(l, LINE_SIZE, f)) {
+ p = strchr(l, '\n');
+ if (!p) {
+ err("Missing line ending.\n");
+ return;
+ }
+ n = strstr(l, name);
+ if (n)
+ break;
+ }
+ if (!n) {
+ err("Unable to find symbol: %s\n", name);
+ return;
+ }
+ w = strchr(l, ' ');
+ if (!w)
+ return;
+
+ *w = '\0';
+ s->address = strtoul(l, NULL, 16);
+ if (s->address == 0)
+ return;
+ s->offset = get_offset_from_address(hdr, s->address);
+ s->name = name;
+ s->content = (void *)hdr + s->offset;
+}
+
+static Elf_Sym *find_elf_symbol(Elf_Ehdr *hdr, Elf_Shdr *symtab, char *name)
+{
+ Elf_Sym *sym, *symtab_start;
+ char *strtab, *symname;
+ unsigned int link;
+ Elf_Shdr *x;
+ int i, n;
+
+ x = (void *)hdr + hdr->e_shoff;
+ link = symtab->sh_link;
+ symtab_start = (void *)hdr + symtab->sh_offset;
+ n = symtab->sh_size / symtab->sh_entsize;
+ strtab = (void *)hdr + x[link].sh_offset;
+
+ for (i = 0; i < n; i++) {
+ sym = &symtab_start[i];
+ symname = strtab + sym->st_name;
+ if (strcmp(symname, name) == 0)
+ return sym;
+ }
+ err("Unable to find symbol: %s\n", name);
+ return NULL;
+}
+
+static void get_symbol_from_table(Elf_Ehdr *hdr, Elf_Shdr *symtab,
+ char *name, struct sym *s)
+{
+ Elf_Shdr *sec;
+ int secndx;
+ Elf_Sym *elf_sym;
+ Elf_Shdr *x;
+
+ x = (void *)hdr + hdr->e_shoff;
+ s->size = 0;
+ s->address = 0;
+ s->offset = 0;
+ elf_sym = find_elf_symbol(hdr, symtab, name);
+ if (!elf_sym)
+ return;
+ secndx = elf_sym->st_shndx;
+ if (!secndx)
+ return;
+ sec = &x[secndx];
+ s->size = elf_sym->st_size;
+ s->address = elf_sym->st_value;
+ s->offset = s->address - sec->sh_addr
+ + sec->sh_offset;
+ s->name = name;
+ s->content = (void *)hdr + s->offset;
+}
+
+static Elf_Shdr *get_symbol_table(Elf_Ehdr *hdr)
+{
+ Elf_Shdr *x;
+ unsigned int i, num_sections;
+
+ x = (void *)hdr + hdr->e_shoff;
+ if (hdr->e_shnum == SHN_UNDEF)
+ num_sections = x[0].sh_size;
+ else
+ num_sections = hdr->e_shnum;
+
+ for (i = 1; i < num_sections; i++)
+ if (x[i].sh_type == SHT_SYMTAB)
+ return &x[i];
+ return NULL;
+}
+
+static void *map_file(char *file_name, int *size)
+{
+ struct stat st;
+ void *map;
+ int fd;
+
+ fd = open(file_name, O_RDWR);
+ if (fd < 0) {
+ perror(file_name);
+ return NULL;
+ }
+ if (fstat(fd, &st)) {
+ perror("Could not determine file size");
+ close(fd);
+ return NULL;
+ }
+ *size = st.st_size;
+ map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (map == MAP_FAILED) {
+ perror("Mapping to memory failed");
+ close(fd);
+ return NULL;
+ }
+ close(fd);
+ return map;
+}
+
+static char *read_file(char *file_name, int *size)
+{
+ struct stat st;
+ char *buf;
+ int fd;
+
+ fd = open(file_name, O_RDONLY);
+ if (fd < 0) {
+ perror(file_name);
+ return NULL;
+ }
+ if (fstat(fd, &st)) {
+ perror("Could not determine file size");
+ close(fd);
+ return NULL;
+ }
+ *size = st.st_size;
+ buf = malloc(*size);
+ if (!buf) {
+ perror("Allocating memory failed");
+ close(fd);
+ return NULL;
+ }
+ if (read(fd, buf, *size) != *size) {
+ perror("File read failed");
+ close(fd);
+ return NULL;
+ }
+ close(fd);
+ return buf;
+}
+
+static void print_sym(Elf_Ehdr *hdr, struct sym *s)
+{
+ info("sym: %s\n", s->name);
+ info("addr: 0x%lx\n", s->address);
+ info("size: %d\n", s->size);
+ info("offset: 0x%lx\n", (unsigned long)s->offset);
+}
+
+static void print_usage(char *e)
+{
+ printf("Usage %s [-s <System.map>] -b <vmlinux> -c <certfile>\n", e);
+}
+
+int main(int argc, char **argv)
+{
+ char *system_map_file = NULL;
+ char *vmlinux_file = NULL;
+ char *cert_file = NULL;
+ int vmlinux_size;
+ int cert_size;
+ Elf_Ehdr *hdr;
+ char *cert;
+ FILE *system_map;
+ unsigned long *lsize;
+ int *used;
+ int opt;
+ Elf_Shdr *symtab = NULL;
+ struct sym cert_sym, lsize_sym, used_sym;
+
+ while ((opt = getopt(argc, argv, "b:c:s:")) != -1) {
+ switch (opt) {
+ case 's':
+ system_map_file = optarg;
+ break;
+ case 'b':
+ vmlinux_file = optarg;
+ break;
+ case 'c':
+ cert_file = optarg;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!vmlinux_file || !cert_file) {
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ cert = read_file(cert_file, &cert_size);
+ if (!cert)
+ exit(EXIT_FAILURE);
+
+ hdr = map_file(vmlinux_file, &vmlinux_size);
+ if (!hdr)
+ exit(EXIT_FAILURE);
+
+ if (vmlinux_size < sizeof(*hdr)) {
+ err("Invalid ELF file.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if ((hdr->e_ident[EI_MAG0] != ELFMAG0) ||
+ (hdr->e_ident[EI_MAG1] != ELFMAG1) ||
+ (hdr->e_ident[EI_MAG2] != ELFMAG2) ||
+ (hdr->e_ident[EI_MAG3] != ELFMAG3)) {
+ err("Invalid ELF magic.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (hdr->e_ident[EI_CLASS] != CURRENT_ELFCLASS) {
+ err("ELF class mismatch.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (hdr->e_ident[EI_DATA] != endianness()) {
+ err("ELF endian mismatch.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (hdr->e_shoff > vmlinux_size) {
+ err("Could not find section header.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ symtab = get_symbol_table(hdr);
+ if (!symtab) {
+ warn("Could not find the symbol table.\n");
+ if (!system_map_file) {
+ err("Please provide a System.map file.\n");
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ system_map = fopen(system_map_file, "r");
+ if (!system_map) {
+ perror(system_map_file);
+ exit(EXIT_FAILURE);
+ }
+ get_symbol_from_map(hdr, system_map, CERT_SYM, &cert_sym);
+ get_symbol_from_map(hdr, system_map, USED_SYM, &used_sym);
+ get_symbol_from_map(hdr, system_map, LSIZE_SYM, &lsize_sym);
+ cert_sym.size = used_sym.address - cert_sym.address;
+ } else {
+ info("Symbol table found.\n");
+ if (system_map_file)
+ warn("System.map is ignored.\n");
+ get_symbol_from_table(hdr, symtab, CERT_SYM, &cert_sym);
+ get_symbol_from_table(hdr, symtab, USED_SYM, &used_sym);
+ get_symbol_from_table(hdr, symtab, LSIZE_SYM, &lsize_sym);
+ }
+
+ if (!cert_sym.offset || !lsize_sym.offset || !used_sym.offset)
+ exit(EXIT_FAILURE);
+
+ print_sym(hdr, &cert_sym);
+ print_sym(hdr, &used_sym);
+ print_sym(hdr, &lsize_sym);
+
+ lsize = (unsigned long *)lsize_sym.content;
+ used = (int *)used_sym.content;
+
+ if (cert_sym.size < cert_size) {
+ err("Certificate is larger than the reserved area!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* If the existing cert is the same, don't overwrite */
+ if (cert_size == *used &&
+ strncmp(cert_sym.content, cert, cert_size) == 0) {
+ warn("Certificate was already inserted.\n");
+ exit(EXIT_SUCCESS);
+ }
+
+ if (*used > 0)
+ warn("Replacing previously inserted certificate.\n");
+
+ memcpy(cert_sym.content, cert, cert_size);
+ if (cert_size < cert_sym.size)
+ memset(cert_sym.content + cert_size,
+ 0, cert_sym.size - cert_size);
+
+ *lsize = *lsize + cert_size - *used;
+ *used = cert_size;
+ info("Inserted the contents of %s into %lx.\n", cert_file,
+ cert_sym.address);
+ info("Used %d bytes out of %d bytes reserved.\n", *used,
+ cert_sym.size);
+ exit(EXIT_SUCCESS);
+}
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);
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 21d756832b75..979be65d22c4 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -36,6 +36,7 @@ config INTEGRITY_ASYMMETRIC_KEYS
select ASYMMETRIC_KEY_TYPE
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select PUBLIC_KEY_ALGO_RSA
+ select CRYPTO_RSA
select X509_CERTIFICATE_PARSER
help
This option enables digital signature verification using
@@ -45,7 +46,6 @@ config INTEGRITY_TRUSTED_KEYRING
bool "Require all keys on the integrity keyrings be signed"
depends on SYSTEM_TRUSTED_KEYRING
depends on INTEGRITY_ASYMMETRIC_KEYS
- select KEYS_DEBUG_PROC_KEYS
default y
help
This option requires that all keys added to the .ima and
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
index 5ade2a7517a6..80052ed8d467 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -16,6 +16,7 @@
#include <linux/ratelimit.h>
#include <linux/key-type.h>
#include <crypto/public_key.h>
+#include <crypto/hash_info.h>
#include <keys/asymmetric-type.h>
#include <keys/system_keyring.h>
@@ -94,7 +95,7 @@ int asymmetric_verify(struct key *keyring, const char *sig,
if (siglen != __be16_to_cpu(hdr->sig_size))
return -EBADMSG;
- if (hdr->hash_algo >= PKEY_HASH__LAST)
+ if (hdr->hash_algo >= HASH_ALGO__LAST)
return -ENOPKG;
key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
@@ -103,16 +104,13 @@ int asymmetric_verify(struct key *keyring, const char *sig,
memset(&pks, 0, sizeof(pks));
- pks.pkey_hash_algo = hdr->hash_algo;
+ pks.pkey_algo = "rsa";
+ pks.hash_algo = hash_algo_name[hdr->hash_algo];
pks.digest = (u8 *)data;
pks.digest_size = datalen;
- pks.nr_mpi = 1;
- pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);
-
- if (pks.rsa.s)
- ret = verify_signature(key, &pks);
-
- mpi_free(pks.rsa.s);
+ pks.s = hdr->sig;
+ pks.s_size = siglen;
+ ret = verify_signature(key, &pks);
key_put(key);
pr_debug("%s() = %d\n", __func__, ret);
return ret;
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index c7a111cc7d89..e08935cf343f 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -90,7 +90,7 @@ struct ima_digest_data {
struct signature_v2_hdr {
uint8_t type; /* xattr type */
uint8_t version; /* signature format version */
- uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */
+ uint8_t hash_algo; /* Digest algorithm [enum hash_algo] */
uint32_t keyid; /* IMA key identifier - not X509/PGP specific */
uint16_t sig_size; /* signature size */
uint8_t sig[0]; /* signature payload */
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index 907c1522ee46..c721e398893a 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -9,7 +9,6 @@
* 2 of the Licence, or (at your option) any later version.
*/
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/file.h>
@@ -18,8 +17,6 @@
#include <keys/user-type.h>
#include <keys/big_key-type.h>
-MODULE_LICENSE("GPL");
-
/*
* Layout of key payload words.
*/
@@ -212,18 +209,8 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
return ret;
}
-/*
- * Module stuff
- */
static int __init big_key_init(void)
{
return register_key_type(&key_type_big_key);
}
-
-static void __exit big_key_cleanup(void)
-{
- unregister_key_type(&key_type_big_key);
-}
-
-module_init(big_key_init);
-module_exit(big_key_cleanup);
+device_initcall(big_key_init);
diff --git a/security/keys/key.c b/security/keys/key.c
index 09ef276c4bdc..b28755131687 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -296,6 +296,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->flags |= 1 << KEY_FLAG_IN_QUOTA;
if (flags & KEY_ALLOC_TRUSTED)
key->flags |= 1 << KEY_FLAG_TRUSTED;
+ if (flags & KEY_ALLOC_BUILT_IN)
+ key->flags |= 1 << KEY_FLAG_BUILTIN;
#ifdef KEY_DEBUGGING
key->magic = KEY_DEBUG_MAGIC;