]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 17 Mar 2016 18:33:45 +0000 (11:33 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 17 Mar 2016 18:33:45 +0000 (11:33 -0700)
Pull security layer updates from James Morris:
 "There are a bunch of fixes to the TPM, IMA, and Keys code, with minor
  fixes scattered across the subsystem.

  IMA now requires signed policy, and that policy is also now measured
  and appraised"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (67 commits)
  X.509: Make algo identifiers text instead of enum
  akcipher: Move the RSA DER encoding check to the crypto layer
  crypto: Add hash param to pkcs1pad
  sign-file: fix build with CMS support disabled
  MAINTAINERS: update tpmdd urls
  MODSIGN: linux/string.h should be #included to get memcpy()
  certs: Fix misaligned data in extra certificate list
  X.509: Handle midnight alternative notation in GeneralizedTime
  X.509: Support leap seconds
  Handle ISO 8601 leap seconds and encodings of midnight in mktime64()
  X.509: Fix leap year handling again
  PKCS#7: fix unitialized boolean 'want'
  firmware: change kernel read fail to dev_dbg()
  KEYS: Use the symbol value for list size, updated by scripts/insert-sys-cert
  KEYS: Reserve an extra certificate symbol for inserting without recompiling
  modsign: hide openssl output in silent builds
  tpm_tis: fix build warning with tpm_tis_resume
  ima: require signed IMA policy
  ima: measure and appraise the IMA policy itself
  ima: load policy using path
  ...

91 files changed:
Documentation/ABI/testing/ima_policy
MAINTAINERS
arch/arm/configs/colibri_pxa270_defconfig
arch/arm/configs/iop13xx_defconfig
arch/arm/configs/iop32x_defconfig
arch/arm/configs/trizeps4_defconfig
arch/microblaze/configs/mmu_defconfig
arch/microblaze/configs/nommu_defconfig
arch/mips/configs/bigsur_defconfig
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip27_defconfig
arch/mips/configs/ip32_defconfig
arch/mips/configs/jazz_defconfig
arch/mips/configs/lemote2f_defconfig
arch/mips/configs/rm200_defconfig
arch/mips/configs/sb1250_swarm_defconfig
arch/parisc/configs/712_defconfig
arch/parisc/configs/a500_defconfig
arch/parisc/configs/default_defconfig
arch/parisc/configs/generic-32bit_defconfig
arch/powerpc/configs/c2k_defconfig
arch/powerpc/configs/ppc6xx_defconfig
arch/score/configs/spct6600_defconfig
arch/tile/configs/tilegx_defconfig
arch/tile/configs/tilepro_defconfig
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig
certs/Kconfig
certs/Makefile
certs/system_certificates.S
certs/system_keyring.c
crypto/asymmetric_keys/Kconfig
crypto/asymmetric_keys/Makefile
crypto/asymmetric_keys/mscode_parser.c
crypto/asymmetric_keys/pkcs7_parser.c
crypto/asymmetric_keys/pkcs7_trust.c
crypto/asymmetric_keys/pkcs7_verify.c
crypto/asymmetric_keys/public_key.c
crypto/asymmetric_keys/public_key.h [deleted file]
crypto/asymmetric_keys/rsa.c [deleted file]
crypto/asymmetric_keys/verify_pefile.c
crypto/asymmetric_keys/verify_pefile.h
crypto/asymmetric_keys/x509_cert_parser.c
crypto/asymmetric_keys/x509_public_key.c
crypto/asymmetric_keys/x509_rsakey.asn1 [deleted file]
crypto/rsa-pkcs1pad.c
drivers/base/firmware_class.c
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_crb.c
drivers/char/tpm/tpm_eventlog.c
drivers/char/tpm/tpm_tis.c
fs/exec.c
include/crypto/public_key.h
include/keys/trusted-type.h
include/linux/fs.h
include/linux/ima.h
include/linux/key.h
include/linux/lsm_hooks.h
include/linux/security.h
init/Kconfig
kernel/kexec_file.c
kernel/module.c
kernel/module_signing.c
kernel/time/time.c
scripts/.gitignore
scripts/Makefile
scripts/extract-sys-certs.pl
scripts/insert-sys-cert.c [new file with mode: 0644]
scripts/sign-file.c
security/integrity/Kconfig
security/integrity/digsig_asymmetric.c
security/integrity/iint.c
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_appraise.c
security/integrity/ima/ima_crypto.c
security/integrity/ima/ima_fs.c
security/integrity/ima/ima_init.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/integrity/ima/ima_template.c
security/integrity/ima/ima_template_lib.c
security/integrity/integrity.h
security/keys/big_key.c
security/keys/key.c
security/keys/trusted.c
security/security.c
security/selinux/Makefile
security/smack/smack_lsm.c

index 0a378a88217a48a00b012435cba2ba2bdccd3fa6..bb0f9a135e21be07c5ef009d449fdb8656fb05d2 100644 (file)
@@ -27,6 +27,7 @@ Description:
 
                base:   func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
                                [FIRMWARE_CHECK]
+                               [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
                        mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
                               [[^]MAY_EXEC]
                        fsmagic:= hex value
index 99bd725affc60e1c5882e409890fbe94f061bc67..5e6f388f3c3e813947bf2befb65ee98d34e5b4c4 100644 (file)
@@ -11126,8 +11126,8 @@ M:      Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
 R:     Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
 W:     http://tpmdd.sourceforge.net
 L:     tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
-Q:     git git://github.com/PeterHuewe/linux-tpmdd.git
-T:     git https://github.com/PeterHuewe/linux-tpmdd
+Q:     https://patchwork.kernel.org/project/tpmdd-devel/list/
+T:     git git://git.infradead.org/users/jjs/linux-tpmdd.git
 S:     Maintained
 F:     drivers/char/tpm/
 
index 18c311ae111306879ceb719869e1bfad59ffa83d..0b9211b2b73bb0a41a95d757500b8e3bc0a7cfbf 100644 (file)
@@ -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
index 4fa94a1f115be35423f779df6a5ae61f8f06e5da..652b7bd9e544531501a42a76d297aa5e267e97df 100644 (file)
@@ -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
index c3058da631da7624e4705b235275c200fc05b082..aa3af0a6b8f7a70e5adc08bd83be3c8677a25b2e 100644 (file)
@@ -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
index 4bc870028035da9641c5a26f09c85b46785a1a97..0ada29d568ec413119ee998d0b7f898fe50b58d0 100644 (file)
@@ -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
index e2f6543b91e766916ee511e0194b47b4834c4e4d..dc5dd5b69fde95ad131acac0e3d515b8da49ed5f 100644 (file)
@@ -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
index a29ebd4a9fcb477e4ebe50529bf4bfec0763fdf4..4cdaf565e638e280d02e34f33c4b067d2b34e556 100644 (file)
@@ -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
index b3e7a1b61220bdff725a28661e39ab75e0744f72..e070dac071c89955658e876de197b98fbb479d8a 100644 (file)
@@ -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
index 57ed466e00dbbd8ba783f58c3bb5604951fc5927..6ba9ce9fcdd54ca8671f65d35cb2cff31dd7af39 100644 (file)
@@ -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
index 48e16d98b2ccac50279514b6a211571de81b3d84..77e9f505f5e4380aab069cb2119afe56b642df3f 100644 (file)
@@ -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
index fe48220157a90bbab1aa99f8ff2a5dfbc8509db0..f9af98f63cff480382345c006c9830c3a9e097d3 100644 (file)
@@ -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
index 4f37a598545995db32c26b0ad025ed10ac328eb1..a5e85e1ee5de43b246250d5f63e50b386b135e56 100644 (file)
@@ -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
index 004cf52d1b7d81911e5e911a0dcee274be23b869..d1f198b072a0f17520491bacecc901fe88d11a06 100644 (file)
@@ -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
index db029f4ff759159cf6abc278837e1c04aef31d9e..82db4e3e4cf1947869989ae090a33de8413ea85c 100644 (file)
@@ -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
index 51bab13ef6f8d3e849dfc84faba549a793d6b6f9..7fca09fedb591cd1fbe40cb95ee25c737f468d9a 100644 (file)
@@ -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
index 9387cc2693f6a33a70459fcb46da058db395e2c4..db8f56bf388392d71f99046ac6ccb1862b0e412d 100644 (file)
@@ -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
index 0490199d7b15b00e476435193f168c894da80538..1a4f776b49b8915dca8cf9d1dbd09e6116b96204 100644 (file)
@@ -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
index 4d8127e8428af7bb3d128b008d2c3dc293f8a447..310b6657e4ac9b38380eaecab1eccf12aeaad0d6 100644 (file)
@@ -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
index 0ffb08ff51252ac97d565176b8392cd413c14a07..5b04d703a924aa527d9ae23e621e7411f2862402 100644 (file)
@@ -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
index 91862292cd55867d7e0fe1a1333763a3574304ff..340685caa7b83cdb8e89b548eae8bff8e3fce26a 100644 (file)
@@ -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
index e5d2c3dc07f1dbc16e4a7c3f1fa31c2948fa4610..99ccbebabfd336f7866e94e76fbc26c916d0ec30 100644 (file)
@@ -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
index df1edbf507a2df28b5c78f08a5d0c8159e39e7ba..b2d8802f43b4c3bd923156521f6197bc34e3740f 100644 (file)
@@ -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
index 37dc9364c4a12485b513429af8288e65a725db37..c1387b7f447da9e70c0cee1e5cedc564010b26ad 100644 (file)
@@ -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
index 76a2781dec2c879bf1dde6d861bd22155094ca0b..6d9ce8af11074eef6a283ad08c5247f000fba206 100644 (file)
@@ -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
index e25a1630320cc47b3112b8082eaba3cb66cc0cee..265901a84f3f51f60c54fd3a3bab50234ac331e5 100644 (file)
@@ -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
index cb5b3ab5beeccad020901b488891e6728b0816ad..4f404a64681b879b3e1365af9bb4488562d654dd 100644 (file)
@@ -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
index b030b9c7ed34ad05f62faf8f253cfb0efd1c01b4..f0f8a4433685aaa0c42ac776c590e9840e1ba52d 100644 (file)
@@ -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
index 28ac694dd11aacedd12857f6cb716b028acda3d2..2773c4afa24c0af0d8bfd73ab05a01606c292a7d 100644 (file)
@@ -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"
index 9216e8c817649eefd3a6d9c2a64a1b4da2b38ffe..c9ceb71a43fef10925090939e9ce3de8367e8e86 100644 (file)
@@ -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):
index 2570598b784de05e9030d3e08aca1c199b2a8fc6..f4180326c2e158129ed7527224c3ab33cacb5503 100644 (file)
@@ -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);
index 4870f28403f54543c06d0b5c5f1b0168e13caa36..91a7e047a765ebfe24e969e15f3e85114dd7445b 100644 (file)
@@ -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
index cd1406f9b14ab2b45615aed6574cade8c539161c..f90486256f01aeabeffe2c5715bce9fe79691f8c 100644 (file)
@@ -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
index adcef59eec0b6a58eb8c0ee0ebf7c48a91472c57..3242cbfaeaa277cacb167ac950782b16e2762b6d 100644 (file)
@@ -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:
index 8f3056cd03991ddf820c3d8442d35daf3db7ee84..40de03f49ff8d612df32e57a07987d65210eccdf 100644 (file)
@@ -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;
 }
 
index 90d6d47965b0826d40e795bc68f563aa2f033856..3bbdcc79a3d345549a51e816754559f2a650ccd9 100644 (file)
@@ -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"
 
 /**
index 325575caf6b452ba89ef84985c13d504e956f86e..50be2a15e5318432e2366cb96d92be7356a02197 100644 (file)
@@ -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);
 
index 6db4c01c6503ff267e0d7ecbe4dbf09496743c15..0f8b264b3961af4db7c448669624e4333dbe3ed5 100644 (file)
 #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 (file)
index 5c37a22..0000000
+++ /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 (file)
index 508b57b..0000000
+++ /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);
index 897b734dabf9ba7ebc7d356707927c789b9175c9..7e8c2338ae256631ae3a219f3a7686295f96f3cb 100644 (file)
@@ -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);
 
index 55d5f7ebc45a1e9bad0321e99750e736e64b298c..a133eb81a49256b60529011ea189edd8f3d9c169 100644 (file)
@@ -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, ...)                                       \
index 021d39c0ba75a8ce3c8c6cb4ea2c41cddd954ad7..4a29bac7006053f04eec3268d92899efafe85649 100644 (file)
 #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);
index 9e9e5a6a9ed63a156ddf5a58b726cadc00ef1e3a..733c046aacc6e18e5e3b0b56ae97e0fa010fe7db 100644 (file)
 #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 (file)
index 4ec7cc6..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-RSAPublicKey ::= SEQUENCE {
-       modulus                 INTEGER ({ rsa_extract_mpi }),  -- n
-       publicExponent          INTEGER ({ rsa_extract_mpi })   -- e
-       }
index 50f5c97e10873cb727654ee68e10be536f75bed8..1cea67d43e1db25c55db64b2f805f035428faa29 100644 (file)
 #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:
index b9250e564ebf008f36bd38de5c3df0e2c1efc5c9..f3f7215ad378d6a971fa643fe3a656ee064fe5fa 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sched.h>
 #include <linux/file.h>
 #include <linux/list.h>
+#include <linux/fs.h>
 #include <linux/async.h>
 #include <linux/pm.h>
 #include <linux/suspend.h>
@@ -291,40 +292,19 @@ static const char * const fw_path[] = {
 module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
 MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
 
-static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
+static void fw_finish_direct_load(struct device *device,
+                                 struct firmware_buf *buf)
 {
-       int size;
-       char *buf;
-       int rc;
-
-       if (!S_ISREG(file_inode(file)->i_mode))
-               return -EINVAL;
-       size = i_size_read(file_inode(file));
-       if (size <= 0)
-               return -EINVAL;
-       buf = vmalloc(size);
-       if (!buf)
-               return -ENOMEM;
-       rc = kernel_read(file, 0, buf, size);
-       if (rc != size) {
-               if (rc > 0)
-                       rc = -EIO;
-               goto fail;
-       }
-       rc = security_kernel_fw_from_file(file, buf, size);
-       if (rc)
-               goto fail;
-       fw_buf->data = buf;
-       fw_buf->size = size;
-       return 0;
-fail:
-       vfree(buf);
-       return rc;
+       mutex_lock(&fw_lock);
+       set_bit(FW_STATUS_DONE, &buf->status);
+       complete_all(&buf->completion);
+       mutex_unlock(&fw_lock);
 }
 
 static int fw_get_filesystem_firmware(struct device *device,
                                       struct firmware_buf *buf)
 {
+       loff_t size;
        int i, len;
        int rc = -ENOENT;
        char *path;
@@ -334,8 +314,6 @@ static int fw_get_filesystem_firmware(struct device *device,
                return -ENOMEM;
 
        for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
-               struct file *file;
-
                /* skip the unset customized path */
                if (!fw_path[i][0])
                        continue;
@@ -347,28 +325,25 @@ static int fw_get_filesystem_firmware(struct device *device,
                        break;
                }
 
-               file = filp_open(path, O_RDONLY, 0);
-               if (IS_ERR(file))
+               buf->size = 0;
+               rc = kernel_read_file_from_path(path, &buf->data, &size,
+                                               INT_MAX, READING_FIRMWARE);
+               if (rc) {
+                       if (rc == -ENOENT)
+                               dev_dbg(device, "loading %s failed with error %d\n",
+                                        path, rc);
+                       else
+                               dev_warn(device, "loading %s failed with error %d\n",
+                                        path, rc);
                        continue;
-               rc = fw_read_file_contents(file, buf);
-               fput(file);
-               if (rc)
-                       dev_warn(device, "firmware, attempted to load %s, but failed with error %d\n",
-                               path, rc);
-               else
-                       break;
+               }
+               dev_dbg(device, "direct-loading %s\n", buf->fw_id);
+               buf->size = size;
+               fw_finish_direct_load(device, buf);
+               break;
        }
        __putname(path);
 
-       if (!rc) {
-               dev_dbg(device, "firmware: direct-loading firmware %s\n",
-                       buf->fw_id);
-               mutex_lock(&fw_lock);
-               set_bit(FW_STATUS_DONE, &buf->status);
-               complete_all(&buf->completion);
-               mutex_unlock(&fw_lock);
-       }
-
        return rc;
 }
 
@@ -685,8 +660,9 @@ static ssize_t firmware_loading_store(struct device *dev,
                                dev_err(dev, "%s: map pages failed\n",
                                        __func__);
                        else
-                               rc = security_kernel_fw_from_file(NULL,
-                                               fw_buf->data, fw_buf->size);
+                               rc = security_kernel_post_read_file(NULL,
+                                               fw_buf->data, fw_buf->size,
+                                               READING_FIRMWARE);
 
                        /*
                         * Same logic as fw_load_abort, only the DONE bit
@@ -1051,7 +1027,7 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
        }
 
        if (fw_get_builtin_firmware(firmware, name)) {
-               dev_dbg(device, "firmware: using built-in firmware %s\n", name);
+               dev_dbg(device, "using built-in %s\n", name);
                return 0; /* assigned */
        }
 
index 45cc39aabeeeb8fde7967971516a4efad50d2caa..274dd0123237861eccfd1dc6ab76a5f9adcbdda6 100644 (file)
@@ -88,6 +88,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
                                 const struct tpm_class_ops *ops)
 {
        struct tpm_chip *chip;
+       int rc;
 
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
@@ -136,11 +137,17 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
        chip->cdev.owner = chip->pdev->driver->owner;
        chip->cdev.kobj.parent = &chip->dev.kobj;
 
+       rc = devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev);
+       if (rc) {
+               put_device(&chip->dev);
+               return ERR_PTR(rc);
+       }
+
        return chip;
 }
 EXPORT_SYMBOL_GPL(tpmm_chip_alloc);
 
-static int tpm_dev_add_device(struct tpm_chip *chip)
+static int tpm_add_char_device(struct tpm_chip *chip)
 {
        int rc;
 
@@ -151,7 +158,6 @@ static int tpm_dev_add_device(struct tpm_chip *chip)
                        chip->devname, MAJOR(chip->dev.devt),
                        MINOR(chip->dev.devt), rc);
 
-               device_unregister(&chip->dev);
                return rc;
        }
 
@@ -162,16 +168,17 @@ static int tpm_dev_add_device(struct tpm_chip *chip)
                        chip->devname, MAJOR(chip->dev.devt),
                        MINOR(chip->dev.devt), rc);
 
+               cdev_del(&chip->cdev);
                return rc;
        }
 
        return rc;
 }
 
-static void tpm_dev_del_device(struct tpm_chip *chip)
+static void tpm_del_char_device(struct tpm_chip *chip)
 {
        cdev_del(&chip->cdev);
-       device_unregister(&chip->dev);
+       device_del(&chip->dev);
 }
 
 static int tpm1_chip_register(struct tpm_chip *chip)
@@ -222,7 +229,7 @@ int tpm_chip_register(struct tpm_chip *chip)
 
        tpm_add_ppi(chip);
 
-       rc = tpm_dev_add_device(chip);
+       rc = tpm_add_char_device(chip);
        if (rc)
                goto out_err;
 
@@ -274,6 +281,6 @@ void tpm_chip_unregister(struct tpm_chip *chip)
                sysfs_remove_link(&chip->pdev->kobj, "ppi");
 
        tpm1_chip_unregister(chip);
-       tpm_dev_del_device(chip);
+       tpm_del_char_device(chip);
 }
 EXPORT_SYMBOL_GPL(tpm_chip_unregister);
index 542a80cbfd9cf054278dff185166161ec429db96..28b477e8da6ac0ef7e1168c48f36322ad4ff8479 100644 (file)
@@ -128,13 +128,6 @@ enum tpm2_startup_types {
        TPM2_SU_STATE   = 0x0001,
 };
 
-enum tpm2_start_method {
-       TPM2_START_ACPI = 2,
-       TPM2_START_FIFO = 6,
-       TPM2_START_CRB = 7,
-       TPM2_START_CRB_WITH_ACPI = 8,
-};
-
 struct tpm_chip;
 
 struct tpm_vendor_specific {
index 45a634016f9556f1770928c0cf42972017fc494b..b28e4da3d2cfff2f5a73b49be30b5f359557b553 100644 (file)
 #include <keys/trusted-type.h>
 
 enum tpm2_object_attributes {
-       TPM2_ATTR_USER_WITH_AUTH        = BIT(6),
+       TPM2_OA_USER_WITH_AUTH          = BIT(6),
+};
+
+enum tpm2_session_attributes {
+       TPM2_SA_CONTINUE_SESSION        = BIT(0),
 };
 
 struct tpm2_startup_in {
@@ -478,22 +482,18 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
        tpm_buf_append_u8(&buf, payload->migratable);
 
        /* public */
-       if (options->policydigest)
-               tpm_buf_append_u16(&buf, 14 + options->digest_len);
-       else
-               tpm_buf_append_u16(&buf, 14);
-
+       tpm_buf_append_u16(&buf, 14 + options->policydigest_len);
        tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
        tpm_buf_append_u16(&buf, hash);
 
        /* policy */
-       if (options->policydigest) {
+       if (options->policydigest_len) {
                tpm_buf_append_u32(&buf, 0);
-               tpm_buf_append_u16(&buf, options->digest_len);
+               tpm_buf_append_u16(&buf, options->policydigest_len);
                tpm_buf_append(&buf, options->policydigest,
-                              options->digest_len);
+                              options->policydigest_len);
        } else {
-               tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
+               tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH);
                tpm_buf_append_u16(&buf, 0);
        }
 
@@ -631,7 +631,7 @@ static int tpm2_unseal(struct tpm_chip *chip,
                             options->policyhandle ?
                             options->policyhandle : TPM2_RS_PW,
                             NULL /* nonce */, 0,
-                            0 /* session_attributes */,
+                            TPM2_SA_CONTINUE_SESSION,
                             options->blobauth /* hmac */,
                             TPM_DIGEST_SIZE);
 
index 8342cf51ffdc0e2b8e2bd93e0a468ed2982ea781..a12b3194034442ad4c5f87d9c6c6999d954edff5 100644 (file)
@@ -34,14 +34,6 @@ enum crb_defaults {
        CRB_ACPI_START_INDEX = 1,
 };
 
-struct acpi_tpm2 {
-       struct acpi_table_header hdr;
-       u16 platform_class;
-       u16 reserved;
-       u64 control_area_pa;
-       u32 start_method;
-} __packed;
-
 enum crb_ca_request {
        CRB_CA_REQ_GO_IDLE      = BIT(0),
        CRB_CA_REQ_CMD_READY    = BIT(1),
@@ -85,6 +77,8 @@ enum crb_flags {
 
 struct crb_priv {
        unsigned int flags;
+       struct resource res;
+       void __iomem *iobase;
        struct crb_control_area __iomem *cca;
        u8 __iomem *cmd;
        u8 __iomem *rsp;
@@ -97,7 +91,7 @@ static u8 crb_status(struct tpm_chip *chip)
        struct crb_priv *priv = chip->vendor.priv;
        u8 sts = 0;
 
-       if ((le32_to_cpu(ioread32(&priv->cca->start)) & CRB_START_INVOKE) !=
+       if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) !=
            CRB_START_INVOKE)
                sts |= CRB_STS_COMPLETE;
 
@@ -113,7 +107,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)
        if (count < 6)
                return -EIO;
 
-       if (le32_to_cpu(ioread32(&priv->cca->sts)) & CRB_CA_STS_ERROR)
+       if (ioread32(&priv->cca->sts) & CRB_CA_STS_ERROR)
                return -EIO;
 
        memcpy_fromio(buf, priv->rsp, 6);
@@ -149,11 +143,11 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
        struct crb_priv *priv = chip->vendor.priv;
        int rc = 0;
 
-       if (len > le32_to_cpu(ioread32(&priv->cca->cmd_size))) {
+       if (len > ioread32(&priv->cca->cmd_size)) {
                dev_err(&chip->dev,
                        "invalid command count value %x %zx\n",
                        (unsigned int) len,
-                       (size_t) le32_to_cpu(ioread32(&priv->cca->cmd_size)));
+                       (size_t) ioread32(&priv->cca->cmd_size));
                return -E2BIG;
        }
 
@@ -189,7 +183,7 @@ static void crb_cancel(struct tpm_chip *chip)
 static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
 {
        struct crb_priv *priv = chip->vendor.priv;
-       u32 cancel = le32_to_cpu(ioread32(&priv->cca->cancel));
+       u32 cancel = ioread32(&priv->cca->cancel);
 
        return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
 }
@@ -204,97 +198,145 @@ static const struct tpm_class_ops tpm_crb = {
        .req_complete_val = CRB_STS_COMPLETE,
 };
 
-static int crb_acpi_add(struct acpi_device *device)
+static int crb_init(struct acpi_device *device, struct crb_priv *priv)
 {
        struct tpm_chip *chip;
-       struct acpi_tpm2 *buf;
+       int rc;
+
+       chip = tpmm_chip_alloc(&device->dev, &tpm_crb);
+       if (IS_ERR(chip))
+               return PTR_ERR(chip);
+
+       chip->vendor.priv = priv;
+       chip->acpi_dev_handle = device->handle;
+       chip->flags = TPM_CHIP_FLAG_TPM2;
+
+       rc = tpm_get_timeouts(chip);
+       if (rc)
+               return rc;
+
+       rc = tpm2_do_selftest(chip);
+       if (rc)
+               return rc;
+
+       return tpm_chip_register(chip);
+}
+
+static int crb_check_resource(struct acpi_resource *ares, void *data)
+{
+       struct crb_priv *priv = data;
+       struct resource res;
+
+       if (acpi_dev_resource_memory(ares, &res)) {
+               priv->res = res;
+               priv->res.name = NULL;
+       }
+
+       return 1;
+}
+
+static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv,
+                                u64 start, u32 size)
+{
+       struct resource new_res = {
+               .start  = start,
+               .end    = start + size - 1,
+               .flags  = IORESOURCE_MEM,
+       };
+
+       /* Detect a 64 bit address on a 32 bit system */
+       if (start != new_res.start)
+               return ERR_PTR(-EINVAL);
+
+       if (!resource_contains(&priv->res, &new_res))
+               return devm_ioremap_resource(dev, &new_res);
+
+       return priv->iobase + (new_res.start - priv->res.start);
+}
+
+static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
+                     struct acpi_table_tpm2 *buf)
+{
+       struct list_head resources;
+       struct device *dev = &device->dev;
+       u64 pa;
+       int ret;
+
+       INIT_LIST_HEAD(&resources);
+       ret = acpi_dev_get_resources(device, &resources, crb_check_resource,
+                                    priv);
+       if (ret < 0)
+               return ret;
+       acpi_dev_free_resource_list(&resources);
+
+       if (resource_type(&priv->res) != IORESOURCE_MEM) {
+               dev_err(dev,
+                       FW_BUG "TPM2 ACPI table does not define a memory resource\n");
+               return -EINVAL;
+       }
+
+       priv->iobase = devm_ioremap_resource(dev, &priv->res);
+       if (IS_ERR(priv->iobase))
+               return PTR_ERR(priv->iobase);
+
+       priv->cca = crb_map_res(dev, priv, buf->control_address, 0x1000);
+       if (IS_ERR(priv->cca))
+               return PTR_ERR(priv->cca);
+
+       pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) |
+             (u64) ioread32(&priv->cca->cmd_pa_low);
+       priv->cmd = crb_map_res(dev, priv, pa, ioread32(&priv->cca->cmd_size));
+       if (IS_ERR(priv->cmd))
+               return PTR_ERR(priv->cmd);
+
+       memcpy_fromio(&pa, &priv->cca->rsp_pa, 8);
+       pa = le64_to_cpu(pa);
+       priv->rsp = crb_map_res(dev, priv, pa, ioread32(&priv->cca->rsp_size));
+       return PTR_ERR_OR_ZERO(priv->rsp);
+}
+
+static int crb_acpi_add(struct acpi_device *device)
+{
+       struct acpi_table_tpm2 *buf;
        struct crb_priv *priv;
        struct device *dev = &device->dev;
        acpi_status status;
        u32 sm;
-       u64 pa;
        int rc;
 
        status = acpi_get_table(ACPI_SIG_TPM2, 1,
                                (struct acpi_table_header **) &buf);
-       if (ACPI_FAILURE(status)) {
-               dev_err(dev, "failed to get TPM2 ACPI table\n");
-               return -ENODEV;
+       if (ACPI_FAILURE(status) || buf->header.length < sizeof(*buf)) {
+               dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n");
+               return -EINVAL;
        }
 
        /* Should the FIFO driver handle this? */
-       if (buf->start_method == TPM2_START_FIFO)
+       sm = buf->start_method;
+       if (sm == ACPI_TPM2_MEMORY_MAPPED)
                return -ENODEV;
 
-       chip = tpmm_chip_alloc(dev, &tpm_crb);
-       if (IS_ERR(chip))
-               return PTR_ERR(chip);
-
-       chip->flags = TPM_CHIP_FLAG_TPM2;
-
-       if (buf->hdr.length < sizeof(struct acpi_tpm2)) {
-               dev_err(dev, "TPM2 ACPI table has wrong size");
-               return -EINVAL;
-       }
-
-       priv = (struct crb_priv *) devm_kzalloc(dev, sizeof(struct crb_priv),
-                                               GFP_KERNEL);
-       if (!priv) {
-               dev_err(dev, "failed to devm_kzalloc for private data\n");
+       priv = devm_kzalloc(dev, sizeof(struct crb_priv), GFP_KERNEL);
+       if (!priv)
                return -ENOMEM;
-       }
-
-       sm = le32_to_cpu(buf->start_method);
 
        /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs
         * report only ACPI start but in practice seems to require both
         * ACPI start and CRB start.
         */
-       if (sm == TPM2_START_CRB || sm == TPM2_START_FIFO ||
+       if (sm == ACPI_TPM2_COMMAND_BUFFER || sm == ACPI_TPM2_MEMORY_MAPPED ||
            !strcmp(acpi_device_hid(device), "MSFT0101"))
                priv->flags |= CRB_FL_CRB_START;
 
-       if (sm == TPM2_START_ACPI || sm == TPM2_START_CRB_WITH_ACPI)
+       if (sm == ACPI_TPM2_START_METHOD ||
+           sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)
                priv->flags |= CRB_FL_ACPI_START;
 
-       priv->cca = (struct crb_control_area __iomem *)
-               devm_ioremap_nocache(dev, buf->control_area_pa, 0x1000);
-       if (!priv->cca) {
-               dev_err(dev, "ioremap of the control area failed\n");
-               return -ENOMEM;
-       }
-
-       pa = ((u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_high)) << 32) |
-               (u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_low));
-       priv->cmd = devm_ioremap_nocache(dev, pa,
-                                        ioread32(&priv->cca->cmd_size));
-       if (!priv->cmd) {
-               dev_err(dev, "ioremap of the command buffer failed\n");
-               return -ENOMEM;
-       }
-
-       memcpy_fromio(&pa, &priv->cca->rsp_pa, 8);
-       pa = le64_to_cpu(pa);
-       priv->rsp = devm_ioremap_nocache(dev, pa,
-                                        ioread32(&priv->cca->rsp_size));
-       if (!priv->rsp) {
-               dev_err(dev, "ioremap of the response buffer failed\n");
-               return -ENOMEM;
-       }
-
-       chip->vendor.priv = priv;
-
-       rc = tpm_get_timeouts(chip);
+       rc = crb_map_io(device, priv, buf);
        if (rc)
                return rc;
 
-       chip->acpi_dev_handle = device->handle;
-
-       rc = tpm2_do_selftest(chip);
-       if (rc)
-               return rc;
-
-       return tpm_chip_register(chip);
+       return crb_init(device, priv);
 }
 
 static int crb_acpi_remove(struct acpi_device *device)
@@ -302,11 +344,11 @@ static int crb_acpi_remove(struct acpi_device *device)
        struct device *dev = &device->dev;
        struct tpm_chip *chip = dev_get_drvdata(dev);
 
-       tpm_chip_unregister(chip);
-
        if (chip->flags & TPM_CHIP_FLAG_TPM2)
                tpm2_shutdown(chip, TPM2_SU_CLEAR);
 
+       tpm_chip_unregister(chip);
+
        return 0;
 }
 
index bd72fb04225e43f8ae21acba1cc5ddb351701c5d..4e6940acf639b00333baed9660567d81e4b75bf0 100644 (file)
@@ -232,7 +232,7 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
 {
        struct tcpa_event *event = v;
        struct tcpa_event temp_event;
-       char *tempPtr;
+       char *temp_ptr;
        int i;
 
        memcpy(&temp_event, event, sizeof(struct tcpa_event));
@@ -242,10 +242,16 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
        temp_event.event_type = do_endian_conversion(event->event_type);
        temp_event.event_size = do_endian_conversion(event->event_size);
 
-       tempPtr = (char *)&temp_event;
+       temp_ptr = (char *) &temp_event;
 
-       for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++)
-               seq_putc(m, tempPtr[i]);
+       for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
+               seq_putc(m, temp_ptr[i]);
+
+       temp_ptr = (char *) v;
+
+       for (i = (sizeof(struct tcpa_event) - 1);
+            i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
+               seq_putc(m, temp_ptr[i]);
 
        return 0;
 
index 8a3509cb10dad824ef3911f0b622a28e1ccaed6e..a507006728e0976cf608e70a7f800c71401b9ccf 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/wait.h>
 #include <linux/acpi.h>
 #include <linux/freezer.h>
-#include <acpi/actbl2.h>
 #include "tpm.h"
 
 enum tis_access {
@@ -60,22 +59,18 @@ enum tis_int_flags {
 };
 
 enum tis_defaults {
-       TIS_MEM_BASE = 0xFED40000,
        TIS_MEM_LEN = 0x5000,
        TIS_SHORT_TIMEOUT = 750,        /* ms */
        TIS_LONG_TIMEOUT = 2000,        /* 2 sec */
 };
 
 struct tpm_info {
-       unsigned long start;
-       unsigned long len;
-       unsigned int irq;
-};
-
-static struct tpm_info tis_default_info = {
-       .start = TIS_MEM_BASE,
-       .len = TIS_MEM_LEN,
-       .irq = 0,
+       struct resource res;
+       /* irq > 0 means: use irq $irq;
+        * irq = 0 means: autoprobe for an irq;
+        * irq = -1 means: no irq support
+        */
+       int irq;
 };
 
 /* Some timeout values are needed before it is known whether the chip is
@@ -118,39 +113,11 @@ static inline int is_itpm(struct acpi_device *dev)
 {
        return has_hid(dev, "INTC0102");
 }
-
-static inline int is_fifo(struct acpi_device *dev)
-{
-       struct acpi_table_tpm2 *tbl;
-       acpi_status st;
-
-       /* TPM 1.2 FIFO */
-       if (!has_hid(dev, "MSFT0101"))
-               return 1;
-
-       st = acpi_get_table(ACPI_SIG_TPM2, 1,
-                           (struct acpi_table_header **) &tbl);
-       if (ACPI_FAILURE(st)) {
-               dev_err(&dev->dev, "failed to get TPM2 ACPI table\n");
-               return 0;
-       }
-
-       if (le32_to_cpu(tbl->start_method) != TPM2_START_FIFO)
-               return 0;
-
-       /* TPM 2.0 FIFO */
-       return 1;
-}
 #else
 static inline int is_itpm(struct acpi_device *dev)
 {
        return 0;
 }
-
-static inline int is_fifo(struct acpi_device *dev)
-{
-       return 1;
-}
 #endif
 
 /* Before we attempt to access the TPM we must see that the valid bit is set.
@@ -716,9 +683,9 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
        chip->acpi_dev_handle = acpi_dev_handle;
 #endif
 
-       chip->vendor.iobase = devm_ioremap(dev, tpm_info->start, tpm_info->len);
-       if (!chip->vendor.iobase)
-               return -EIO;
+       chip->vendor.iobase = devm_ioremap_resource(dev, &tpm_info->res);
+       if (IS_ERR(chip->vendor.iobase))
+               return PTR_ERR(chip->vendor.iobase);
 
        /* Maximum timeouts */
        chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX;
@@ -807,7 +774,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
        /* INTERRUPT Setup */
        init_waitqueue_head(&chip->vendor.read_queue);
        init_waitqueue_head(&chip->vendor.int_queue);
-       if (interrupts) {
+       if (interrupts && tpm_info->irq != -1) {
                if (tpm_info->irq) {
                        tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
                                                 tpm_info->irq);
@@ -893,29 +860,29 @@ static int tpm_tis_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
 
-#ifdef CONFIG_PNP
 static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
-                                     const struct pnp_device_id *pnp_id)
+                           const struct pnp_device_id *pnp_id)
 {
-       struct tpm_info tpm_info = tis_default_info;
+       struct tpm_info tpm_info = {};
        acpi_handle acpi_dev_handle = NULL;
+       struct resource *res;
 
-       tpm_info.start = pnp_mem_start(pnp_dev, 0);
-       tpm_info.len = pnp_mem_len(pnp_dev, 0);
+       res = pnp_get_resource(pnp_dev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+       tpm_info.res = *res;
 
        if (pnp_irq_valid(pnp_dev, 0))
                tpm_info.irq = pnp_irq(pnp_dev, 0);
        else
-               interrupts = false;
+               tpm_info.irq = -1;
 
-#ifdef CONFIG_ACPI
        if (pnp_acpi_device(pnp_dev)) {
                if (is_itpm(pnp_acpi_device(pnp_dev)))
                        itpm = true;
 
-               acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle;
+               acpi_dev_handle = ACPI_HANDLE(&pnp_dev->dev);
        }
-#endif
 
        return tpm_tis_init(&pnp_dev->dev, &tpm_info, acpi_dev_handle);
 }
@@ -956,7 +923,6 @@ static struct pnp_driver tis_pnp_driver = {
 module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
                    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
 MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
-#endif
 
 #ifdef CONFIG_ACPI
 static int tpm_check_resource(struct acpi_resource *ares, void *data)
@@ -964,11 +930,11 @@ static int tpm_check_resource(struct acpi_resource *ares, void *data)
        struct tpm_info *tpm_info = (struct tpm_info *) data;
        struct resource res;
 
-       if (acpi_dev_resource_interrupt(ares, 0, &res)) {
+       if (acpi_dev_resource_interrupt(ares, 0, &res))
                tpm_info->irq = res.start;
-       else if (acpi_dev_resource_memory(ares, &res)) {
-               tpm_info->start = res.start;
-               tpm_info->len = resource_size(&res);
+       else if (acpi_dev_resource_memory(ares, &res)) {
+               tpm_info->res = res;
+               tpm_info->res.name = NULL;
        }
 
        return 1;
@@ -976,14 +942,25 @@ static int tpm_check_resource(struct acpi_resource *ares, void *data)
 
 static int tpm_tis_acpi_init(struct acpi_device *acpi_dev)
 {
+       struct acpi_table_tpm2 *tbl;
+       acpi_status st;
        struct list_head resources;
-       struct tpm_info tpm_info = tis_default_info;
+       struct tpm_info tpm_info = {};
        int ret;
 
-       if (!is_fifo(acpi_dev))
+       st = acpi_get_table(ACPI_SIG_TPM2, 1,
+                           (struct acpi_table_header **) &tbl);
+       if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) {
+               dev_err(&acpi_dev->dev,
+                       FW_BUG "failed to get TPM2 ACPI table\n");
+               return -EINVAL;
+       }
+
+       if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED)
                return -ENODEV;
 
        INIT_LIST_HEAD(&resources);
+       tpm_info.irq = -1;
        ret = acpi_dev_get_resources(acpi_dev, &resources, tpm_check_resource,
                                     &tpm_info);
        if (ret < 0)
@@ -991,8 +968,11 @@ static int tpm_tis_acpi_init(struct acpi_device *acpi_dev)
 
        acpi_dev_free_resource_list(&resources);
 
-       if (!tpm_info.irq)
-               interrupts = false;
+       if (resource_type(&tpm_info.res) != IORESOURCE_MEM) {
+               dev_err(&acpi_dev->dev,
+                       FW_BUG "TPM2 ACPI table does not define a memory resource\n");
+               return -EINVAL;
+       }
 
        if (is_itpm(acpi_dev))
                itpm = true;
@@ -1031,80 +1011,135 @@ static struct acpi_driver tis_acpi_driver = {
 };
 #endif
 
+static struct platform_device *force_pdev;
+
+static int tpm_tis_plat_probe(struct platform_device *pdev)
+{
+       struct tpm_info tpm_info = {};
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "no memory resource defined\n");
+               return -ENODEV;
+       }
+       tpm_info.res = *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res) {
+               tpm_info.irq = res->start;
+       } else {
+               if (pdev == force_pdev)
+                       tpm_info.irq = -1;
+               else
+                       /* When forcing auto probe the IRQ */
+                       tpm_info.irq = 0;
+       }
+
+       return tpm_tis_init(&pdev->dev, &tpm_info, NULL);
+}
+
+static int tpm_tis_plat_remove(struct platform_device *pdev)
+{
+       struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
+
+       tpm_chip_unregister(chip);
+       tpm_tis_remove(chip);
+
+       return 0;
+}
+
 static struct platform_driver tis_drv = {
+       .probe = tpm_tis_plat_probe,
+       .remove = tpm_tis_plat_remove,
        .driver = {
                .name           = "tpm_tis",
                .pm             = &tpm_tis_pm,
        },
 };
 
-static struct platform_device *pdev;
-
 static bool force;
+#ifdef CONFIG_X86
 module_param(force, bool, 0444);
 MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
+#endif
+
+static int tpm_tis_force_device(void)
+{
+       struct platform_device *pdev;
+       static const struct resource x86_resources[] = {
+               {
+                       .start = 0xFED40000,
+                       .end = 0xFED40000 + TIS_MEM_LEN - 1,
+                       .flags = IORESOURCE_MEM,
+               },
+       };
+
+       if (!force)
+               return 0;
+
+       /* The driver core will match the name tpm_tis of the device to
+        * the tpm_tis platform driver and complete the setup via
+        * tpm_tis_plat_probe
+        */
+       pdev = platform_device_register_simple("tpm_tis", -1, x86_resources,
+                                              ARRAY_SIZE(x86_resources));
+       if (IS_ERR(pdev))
+               return PTR_ERR(pdev);
+       force_pdev = pdev;
+
+       return 0;
+}
+
 static int __init init_tis(void)
 {
        int rc;
-#ifdef CONFIG_PNP
-       if (!force) {
-               rc = pnp_register_driver(&tis_pnp_driver);
-               if (rc)
-                       return rc;
-       }
-#endif
+
+       rc = tpm_tis_force_device();
+       if (rc)
+               goto err_force;
+
+       rc = platform_driver_register(&tis_drv);
+       if (rc)
+               goto err_platform;
+
 #ifdef CONFIG_ACPI
-       if (!force) {
-               rc = acpi_bus_register_driver(&tis_acpi_driver);
-               if (rc) {
-#ifdef CONFIG_PNP
-                       pnp_unregister_driver(&tis_pnp_driver);
-#endif
-                       return rc;
-               }
-       }
+       rc = acpi_bus_register_driver(&tis_acpi_driver);
+       if (rc)
+               goto err_acpi;
 #endif
-       if (!force)
-               return 0;
 
-       rc = platform_driver_register(&tis_drv);
-       if (rc < 0)
-               return rc;
-       pdev = platform_device_register_simple("tpm_tis", -1, NULL, 0);
-       if (IS_ERR(pdev)) {
-               rc = PTR_ERR(pdev);
-               goto err_dev;
+       if (IS_ENABLED(CONFIG_PNP)) {
+               rc = pnp_register_driver(&tis_pnp_driver);
+               if (rc)
+                       goto err_pnp;
        }
-       rc = tpm_tis_init(&pdev->dev, &tis_default_info, NULL);
-       if (rc)
-               goto err_init;
+
        return 0;
-err_init:
-       platform_device_unregister(pdev);
-err_dev:
-       platform_driver_unregister(&tis_drv);
+
+err_pnp:
+#ifdef CONFIG_ACPI
+       acpi_bus_unregister_driver(&tis_acpi_driver);
+err_acpi:
+#endif
+       platform_device_unregister(force_pdev);
+err_platform:
+       if (force_pdev)
+               platform_device_unregister(force_pdev);
+err_force:
        return rc;
 }
 
 static void __exit cleanup_tis(void)
 {
-       struct tpm_chip *chip;
-#if defined(CONFIG_PNP) || defined(CONFIG_ACPI)
-       if (!force) {
+       pnp_unregister_driver(&tis_pnp_driver);
 #ifdef CONFIG_ACPI
-               acpi_bus_unregister_driver(&tis_acpi_driver);
-#endif
-#ifdef CONFIG_PNP
-               pnp_unregister_driver(&tis_pnp_driver);
+       acpi_bus_unregister_driver(&tis_acpi_driver);
 #endif
-               return;
-       }
-#endif
-       chip = dev_get_drvdata(&pdev->dev);
-       tpm_chip_unregister(chip);
-       tpm_tis_remove(chip);
-       platform_device_unregister(pdev);
        platform_driver_unregister(&tis_drv);
+
+       if (force_pdev)
+               platform_device_unregister(force_pdev);
 }
 
 module_init(init_tis);
index dcd4ac7d3f1e77b45fde8a84585150a4862b84d9..9bdf0edf570dcc189edb608ccf2f2fba49634e1c 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -56,6 +56,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/oom.h>
 #include <linux/compat.h>
+#include <linux/vmalloc.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -831,6 +832,97 @@ int kernel_read(struct file *file, loff_t offset,
 
 EXPORT_SYMBOL(kernel_read);
 
+int kernel_read_file(struct file *file, void **buf, loff_t *size,
+                    loff_t max_size, enum kernel_read_file_id id)
+{
+       loff_t i_size, pos;
+       ssize_t bytes = 0;
+       int ret;
+
+       if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
+               return -EINVAL;
+
+       ret = security_kernel_read_file(file, id);
+       if (ret)
+               return ret;
+
+       i_size = i_size_read(file_inode(file));
+       if (max_size > 0 && i_size > max_size)
+               return -EFBIG;
+       if (i_size <= 0)
+               return -EINVAL;
+
+       *buf = vmalloc(i_size);
+       if (!*buf)
+               return -ENOMEM;
+
+       pos = 0;
+       while (pos < i_size) {
+               bytes = kernel_read(file, pos, (char *)(*buf) + pos,
+                                   i_size - pos);
+               if (bytes < 0) {
+                       ret = bytes;
+                       goto out;
+               }
+
+               if (bytes == 0)
+                       break;
+               pos += bytes;
+       }
+
+       if (pos != i_size) {
+               ret = -EIO;
+               goto out;
+       }
+
+       ret = security_kernel_post_read_file(file, *buf, i_size, id);
+       if (!ret)
+               *size = pos;
+
+out:
+       if (ret < 0) {
+               vfree(*buf);
+               *buf = NULL;
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(kernel_read_file);
+
+int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
+                              loff_t max_size, enum kernel_read_file_id id)
+{
+       struct file *file;
+       int ret;
+
+       if (!path || !*path)
+               return -EINVAL;
+
+       file = filp_open(path, O_RDONLY, 0);
+       if (IS_ERR(file))
+               return PTR_ERR(file);
+
+       ret = kernel_read_file(file, buf, size, max_size, id);
+       fput(file);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
+
+int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
+                            enum kernel_read_file_id id)
+{
+       struct fd f = fdget(fd);
+       int ret = -EBADF;
+
+       if (!f.file)
+               goto out;
+
+       ret = kernel_read_file(f.file, buf, size, max_size, id);
+out:
+       fdput(f);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
+
 ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
 {
        ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);
index cc2516df0efac72d43ddde2a055fa88c38f2ece5..aa730ea7faf87d5f9b83dedeb8ed576bb5281e65 100644 (file)
 #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 */
index 42cf2d991bf4b496a4b13fdbfc0a6da753621820..4ea7e55f20b0de3c3cdf3912224a86d4d5160eb2 100644 (file)
@@ -38,7 +38,7 @@ struct trusted_key_options {
        unsigned char pcrinfo[MAX_PCRINFO_SIZE];
        int pcrlock;
        uint32_t hash;
-       uint32_t digest_len;
+       uint32_t policydigest_len;
        unsigned char policydigest[MAX_DIGEST_SIZE];
        uint32_t policyhandle;
 };
index ae681002100a1fb8401e934a99f40dedf039cd7d..e514f76db04f9f08a8275f8b810004a991760df6 100644 (file)
@@ -2576,7 +2576,22 @@ static inline void i_readcount_inc(struct inode *inode)
 #endif
 extern int do_pipe_flags(int *, int);
 
+enum kernel_read_file_id {
+       READING_FIRMWARE = 1,
+       READING_MODULE,
+       READING_KEXEC_IMAGE,
+       READING_KEXEC_INITRAMFS,
+       READING_POLICY,
+       READING_MAX_ID
+};
+
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);
+extern int kernel_read_file(struct file *, void **, loff_t *, loff_t,
+                           enum kernel_read_file_id);
+extern int kernel_read_file_from_path(char *, void **, loff_t *, loff_t,
+                                     enum kernel_read_file_id);
+extern int kernel_read_file_from_fd(int, void **, loff_t *, loff_t,
+                                   enum kernel_read_file_id);
 extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
index 120ccc53fcb7f85d80a3f1f0f94c2241e864fbb2..e6516cbbe9bfebc26e76278c2d4f574ced311dfe 100644 (file)
@@ -18,8 +18,9 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_file_check(struct file *file, int mask, int opened);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
-extern int ima_module_check(struct file *file);
-extern int ima_fw_from_file(struct file *file, char *buf, size_t size);
+extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
+extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
+                             enum kernel_read_file_id id);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -42,12 +43,13 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
        return 0;
 }
 
-static inline int ima_module_check(struct file *file)
+static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
 {
        return 0;
 }
 
-static inline int ima_fw_from_file(struct file *file, char *buf, size_t size)
+static inline int ima_post_read_file(struct file *file, void *buf, loff_t size,
+                                    enum kernel_read_file_id id)
 {
        return 0;
 }
index 7321ab8ef949c8fb73da592e75c3dacddf723b6f..5f5b1129dc92705edd5c1658571cffb6548453b7 100644 (file)
@@ -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);
index 71969de4058c9922e7a174173fca4dec5394be4f..cdee11cbcdf1487a7cd99d0f58a3c348e4b118d0 100644 (file)
  *     @inode points to the inode to use as a reference.
  *     The current task must be the one that nominated @inode.
  *     Return 0 if successful.
- * @kernel_fw_from_file:
- *     Load firmware from userspace (not called for built-in firmware).
- *     @file contains the file structure pointing to the file containing
- *     the firmware to load. This argument will be NULL if the firmware
- *     was loaded via the uevent-triggered blob-based interface exposed
- *     by CONFIG_FW_LOADER_USER_HELPER.
- *     @buf pointer to buffer containing firmware contents.
- *     @size length of the firmware contents.
- *     Return 0 if permission is granted.
  * @kernel_module_request:
  *     Ability to trigger the kernel to automatically upcall to userspace for
  *     userspace to load a kernel module with the given name.
  *     @kmod_name name of the module requested by the kernel
  *     Return 0 if successful.
- * @kernel_module_from_file:
- *     Load a kernel module from userspace.
- *     @file contains the file structure pointing to the file containing
- *     the kernel module to load. If the module is being loaded from a blob,
- *     this argument will be NULL.
+ * @kernel_read_file:
+ *     Read a file specified by userspace.
+ *     @file contains the file structure pointing to the file being read
+ *     by the kernel.
+ *     @id kernel read file identifier
+ *     Return 0 if permission is granted.
+ * @kernel_post_read_file:
+ *     Read a file specified by userspace.
+ *     @file contains the file structure pointing to the file being read
+ *     by the kernel.
+ *     @buf pointer to buffer containing the file contents.
+ *     @size length of the file contents.
+ *     @id kernel read file identifier
  *     Return 0 if permission is granted.
  * @task_fix_setuid:
  *     Update the module's state after setting one or more of the user
@@ -1454,9 +1453,11 @@ union security_list_options {
        void (*cred_transfer)(struct cred *new, const struct cred *old);
        int (*kernel_act_as)(struct cred *new, u32 secid);
        int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
-       int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
        int (*kernel_module_request)(char *kmod_name);
        int (*kernel_module_from_file)(struct file *file);
+       int (*kernel_read_file)(struct file *file, enum kernel_read_file_id id);
+       int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size,
+                                    enum kernel_read_file_id id);
        int (*task_fix_setuid)(struct cred *new, const struct cred *old,
                                int flags);
        int (*task_setpgid)(struct task_struct *p, pid_t pgid);
@@ -1715,9 +1716,9 @@ struct security_hook_heads {
        struct list_head cred_transfer;
        struct list_head kernel_act_as;
        struct list_head kernel_create_files_as;
-       struct list_head kernel_fw_from_file;
+       struct list_head kernel_read_file;
+       struct list_head kernel_post_read_file;
        struct list_head kernel_module_request;
-       struct list_head kernel_module_from_file;
        struct list_head task_fix_setuid;
        struct list_head task_setpgid;
        struct list_head task_getpgid;
index 4824a4ccaf1c37942d7fafc64b2a430062c962a1..157f0cb1e4d2f9a6116b81d517093ec914b853a7 100644 (file)
 
 #include <linux/key.h>
 #include <linux/capability.h>
+#include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/fs.h>
 
 struct linux_binprm;
 struct cred;
@@ -298,9 +300,11 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp);
 void security_transfer_creds(struct cred *new, const struct cred *old);
 int security_kernel_act_as(struct cred *new, u32 secid);
 int security_kernel_create_files_as(struct cred *new, struct inode *inode);
-int security_kernel_fw_from_file(struct file *file, char *buf, size_t size);
 int security_kernel_module_request(char *kmod_name);
 int security_kernel_module_from_file(struct file *file);
+int security_kernel_read_file(struct file *file, enum kernel_read_file_id id);
+int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
+                                  enum kernel_read_file_id id);
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
                             int flags);
 int security_task_setpgid(struct task_struct *p, pid_t pgid);
@@ -850,18 +854,20 @@ static inline int security_kernel_create_files_as(struct cred *cred,
        return 0;
 }
 
-static inline int security_kernel_fw_from_file(struct file *file,
-                                              char *buf, size_t size)
+static inline int security_kernel_module_request(char *kmod_name)
 {
        return 0;
 }
 
-static inline int security_kernel_module_request(char *kmod_name)
+static inline int security_kernel_read_file(struct file *file,
+                                           enum kernel_read_file_id id)
 {
        return 0;
 }
 
-static inline int security_kernel_module_from_file(struct file *file)
+static inline int security_kernel_post_read_file(struct file *file,
+                                                char *buf, loff_t size,
+                                                enum kernel_read_file_id id)
 {
        return 0;
 }
index fd664b3ab99ef79432643ab3e954943e759f81ca..2d70c8c4b1d8fdcff16997b7b145cc32d8a5d7f9 100644 (file)
@@ -1779,9 +1779,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
index 56b18eb1f0013c9bc7e041a3dd2a8ecaeb580b95..c72d2ff5896e9f37e21c789d45d7b2cc058be9f0 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/kexec.h>
 #include <linux/mutex.h>
 #include <linux/list.h>
+#include <linux/fs.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
 #include <linux/syscalls.h>
@@ -33,65 +34,6 @@ size_t __weak kexec_purgatory_size = 0;
 
 static int kexec_calculate_store_digests(struct kimage *image);
 
-static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len)
-{
-       struct fd f = fdget(fd);
-       int ret;
-       struct kstat stat;
-       loff_t pos;
-       ssize_t bytes = 0;
-
-       if (!f.file)
-               return -EBADF;
-
-       ret = vfs_getattr(&f.file->f_path, &stat);
-       if (ret)
-               goto out;
-
-       if (stat.size > INT_MAX) {
-               ret = -EFBIG;
-               goto out;
-       }
-
-       /* Don't hand 0 to vmalloc, it whines. */
-       if (stat.size == 0) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       *buf = vmalloc(stat.size);
-       if (!*buf) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       pos = 0;
-       while (pos < stat.size) {
-               bytes = kernel_read(f.file, pos, (char *)(*buf) + pos,
-                                   stat.size - pos);
-               if (bytes < 0) {
-                       vfree(*buf);
-                       ret = bytes;
-                       goto out;
-               }
-
-               if (bytes == 0)
-                       break;
-               pos += bytes;
-       }
-
-       if (pos != stat.size) {
-               ret = -EBADF;
-               vfree(*buf);
-               goto out;
-       }
-
-       *buf_len = pos;
-out:
-       fdput(f);
-       return ret;
-}
-
 /* Architectures can provide this probe function */
 int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
                                         unsigned long buf_len)
@@ -182,16 +124,17 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
 {
        int ret = 0;
        void *ldata;
+       loff_t size;
 
-       ret = copy_file_from_fd(kernel_fd, &image->kernel_buf,
-                               &image->kernel_buf_len);
+       ret = kernel_read_file_from_fd(kernel_fd, &image->kernel_buf,
+                                      &size, INT_MAX, READING_KEXEC_IMAGE);
        if (ret)
                return ret;
+       image->kernel_buf_len = size;
 
        /* Call arch image probe handlers */
        ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
                                            image->kernel_buf_len);
-
        if (ret)
                goto out;
 
@@ -206,10 +149,12 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
 #endif
        /* It is possible that there no initramfs is being loaded */
        if (!(flags & KEXEC_FILE_NO_INITRAMFS)) {
-               ret = copy_file_from_fd(initrd_fd, &image->initrd_buf,
-                                       &image->initrd_buf_len);
+               ret = kernel_read_file_from_fd(initrd_fd, &image->initrd_buf,
+                                              &size, INT_MAX,
+                                              READING_KEXEC_INITRAMFS);
                if (ret)
                        goto out;
+               image->initrd_buf_len = size;
        }
 
        if (cmdline_len) {
index 794ebe8e878d55cf9a0b94a1ae7a994ac4dec80b..87cfeb25cf65516236fbc911b1ccedd6d5f09e3d 100644 (file)
@@ -2675,7 +2675,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
        if (info->len < sizeof(*(info->hdr)))
                return -ENOEXEC;
 
-       err = security_kernel_module_from_file(NULL);
+       err = security_kernel_read_file(NULL, READING_MODULE);
        if (err)
                return err;
 
@@ -2693,63 +2693,6 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
        return 0;
 }
 
-/* Sets info->hdr and info->len. */
-static int copy_module_from_fd(int fd, struct load_info *info)
-{
-       struct fd f = fdget(fd);
-       int err;
-       struct kstat stat;
-       loff_t pos;
-       ssize_t bytes = 0;
-
-       if (!f.file)
-               return -ENOEXEC;
-
-       err = security_kernel_module_from_file(f.file);
-       if (err)
-               goto out;
-
-       err = vfs_getattr(&f.file->f_path, &stat);
-       if (err)
-               goto out;
-
-       if (stat.size > INT_MAX) {
-               err = -EFBIG;
-               goto out;
-       }
-
-       /* Don't hand 0 to vmalloc, it whines. */
-       if (stat.size == 0) {
-               err = -EINVAL;
-               goto out;
-       }
-
-       info->hdr = vmalloc(stat.size);
-       if (!info->hdr) {
-               err = -ENOMEM;
-               goto out;
-       }
-
-       pos = 0;
-       while (pos < stat.size) {
-               bytes = kernel_read(f.file, pos, (char *)(info->hdr) + pos,
-                                   stat.size - pos);
-               if (bytes < 0) {
-                       vfree(info->hdr);
-                       err = bytes;
-                       goto out;
-               }
-               if (bytes == 0)
-                       break;
-               pos += bytes;
-       }
-       info->len = pos;
-
-out:
-       fdput(f);
-       return err;
-}
-
 static void free_copy(struct load_info *info)
 {
        vfree(info->hdr);
@@ -3611,8 +3554,10 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
 
 SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
 {
-       int err;
        struct load_info info = { };
+       loff_t size;
+       void *hdr;
+       int err;
 
        err = may_init_module();
        if (err)
@@ -3624,9 +3569,12 @@ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
                      |MODULE_INIT_IGNORE_VERMAGIC))
                return -EINVAL;
 
-       err = copy_module_from_fd(fd, &info);
+       err = kernel_read_file_from_fd(fd, &hdr, &size, INT_MAX,
+                                      READING_MODULE);
        if (err)
                return err;
+       info.hdr = hdr;
+       info.len = size;
 
        return load_module(&info, uargs, flags);
 }
index 6528a79d998d08120e9e80524164e5c759d911f3..64b9dead4a0763f2ad9e853a6221b31a0fa6f938 100644 (file)
 
 #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.
  *
index 86751c68e08d8cb1e3309d17f254fa0eb982589a..be115b020d2772ae6794320cf79499723137411d 100644 (file)
@@ -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 */
 }
index 1f78169d425493356b560459ec5ef2da1b93c903..e063daa3ec4a3d8b22556b1cbc9f6facfee75550 100644 (file)
@@ -13,3 +13,4 @@ sortextable
 asn1_compiler
 extract-cert
 sign-file
+insert-sys-cert
index fd0d53d4a2346f762aa52f86c7b66abd78ae7470..822ab4a6a4aa34b513f6c55f1dd2ab27ef69fe43 100644 (file)
@@ -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
index d476e7d1fd88a4328a31a18bb62bcfcb66310062..8227ca10a4942b688aacd3ef64e3f8ad7ec9b33e 100755 (executable)
@@ -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 (file)
index 0000000..8902836
--- /dev/null
@@ -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);
+}
index 250a7a6450331ae0805aaf3100da46af66dd4827..d912d5a56a5ebf05f3e1f2fb0f93cfd028907167 100755 (executable)
@@ -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);
index 21d756832b754322f71722f6b0857294e1a5ffd2..979be65d22c4260aad2f7c2a9b3fc0b4247656a2 100644 (file)
@@ -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
index 5ade2a7517a6341305ba4aafbb18469cd1ed8db8..80052ed8d4673c8abfb0c219bba47562003dde74 100644 (file)
@@ -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;
index 8f1ab37f28971daacd3ad62800d4e426ab34202a..345b75997e4c2fdd6308dd76ab4e322388a4ae82 100644 (file)
@@ -77,7 +77,7 @@ static void iint_free(struct integrity_iint_cache *iint)
        iint->ima_file_status = INTEGRITY_UNKNOWN;
        iint->ima_mmap_status = INTEGRITY_UNKNOWN;
        iint->ima_bprm_status = INTEGRITY_UNKNOWN;
-       iint->ima_module_status = INTEGRITY_UNKNOWN;
+       iint->ima_read_status = INTEGRITY_UNKNOWN;
        iint->evm_status = INTEGRITY_UNKNOWN;
        kmem_cache_free(iint_cache, iint);
 }
@@ -157,7 +157,7 @@ static void init_once(void *foo)
        iint->ima_file_status = INTEGRITY_UNKNOWN;
        iint->ima_mmap_status = INTEGRITY_UNKNOWN;
        iint->ima_bprm_status = INTEGRITY_UNKNOWN;
-       iint->ima_module_status = INTEGRITY_UNKNOWN;
+       iint->ima_read_status = INTEGRITY_UNKNOWN;
        iint->evm_status = INTEGRITY_UNKNOWN;
 }
 
index 585af61ed3992e5c046bbfe5b9f7487626060858..5d0f61163d982d7e533cadfa8da6d5e1026a96bb 100644 (file)
 
 #include <linux/types.h>
 #include <linux/crypto.h>
+#include <linux/fs.h>
 #include <linux/security.h>
 #include <linux/hash.h>
 #include <linux/tpm.h>
 #include <linux/audit.h>
+#include <crypto/hash_info.h>
 
 #include "../integrity.h"
 
@@ -106,6 +108,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
                           const char *op, struct inode *inode,
                           const unsigned char *filename);
 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+                        struct ima_digest_data *hash);
 int ima_calc_field_array_hash(struct ima_field_data *field_data,
                              struct ima_template_desc *desc, int num_fields,
                              struct ima_digest_data *hash);
@@ -136,13 +140,25 @@ static inline unsigned long ima_hash_key(u8 *digest)
        return hash_long(*digest, IMA_HASH_BITS);
 }
 
+enum ima_hooks {
+       FILE_CHECK = 1,
+       MMAP_CHECK,
+       BPRM_CHECK,
+       POST_SETATTR,
+       MODULE_CHECK,
+       FIRMWARE_CHECK,
+       KEXEC_KERNEL_CHECK,
+       KEXEC_INITRAMFS_CHECK,
+       POLICY_CHECK,
+       MAX_CHECK
+};
+
 /* LIM API function definitions */
-int ima_get_action(struct inode *inode, int mask, int function);
-int ima_must_measure(struct inode *inode, int mask, int function);
+int ima_get_action(struct inode *inode, int mask, enum ima_hooks func);
+int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-                           struct file *file,
-                           struct evm_ima_xattr_data **xattr_value,
-                           int *xattr_len);
+                           struct file *file, void *buf, loff_t size,
+                           enum hash_algo algo);
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
                           const unsigned char *filename,
                           struct evm_ima_xattr_data *xattr_value,
@@ -157,8 +173,6 @@ void ima_free_template_entry(struct ima_template_entry *entry);
 const char *ima_d_path(struct path *path, char **pathbuf);
 
 /* IMA policy related functions */
-enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR };
-
 int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
                     int flags);
 void ima_init_policy(void);
@@ -178,23 +192,25 @@ int ima_policy_show(struct seq_file *m, void *v);
 #define IMA_APPRAISE_LOG       0x04
 #define IMA_APPRAISE_MODULES   0x08
 #define IMA_APPRAISE_FIRMWARE  0x10
+#define IMA_APPRAISE_POLICY    0x20
 
 #ifdef CONFIG_IMA_APPRAISE
-int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
+int ima_appraise_measurement(enum ima_hooks func,
+                            struct integrity_iint_cache *iint,
                             struct file *file, const unsigned char *filename,
                             struct evm_ima_xattr_data *xattr_value,
                             int xattr_len, int opened);
 int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
-                                          int func);
-void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
-                      struct ima_digest_data *hash);
+                                          enum ima_hooks func);
+enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+                                int xattr_len);
 int ima_read_xattr(struct dentry *dentry,
                   struct evm_ima_xattr_data **xattr_value);
 
 #else
-static inline int ima_appraise_measurement(int func,
+static inline int ima_appraise_measurement(enum ima_hooks func,
                                           struct integrity_iint_cache *iint,
                                           struct file *file,
                                           const unsigned char *filename,
@@ -216,15 +232,16 @@ static inline void ima_update_xattr(struct integrity_iint_cache *iint,
 }
 
 static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache
-                                                        *iint, int func)
+                                                        *iint,
+                                                        enum ima_hooks func)
 {
        return INTEGRITY_UNKNOWN;
 }
 
-static inline void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
-                                    int xattr_len,
-                                    struct ima_digest_data *hash)
+static inline enum hash_algo
+ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len)
 {
+       return ima_hash_algo;
 }
 
 static inline int ima_read_xattr(struct dentry *dentry,
index 1d950fbb2aecbb21c62b28233dba7a707a116a6b..370e42dfc5c58bd78d88faa0116edb13d264fd72 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/fs.h>
 #include <linux/xattr.h>
 #include <linux/evm.h>
-#include <crypto/hash_info.h>
+
 #include "ima.h"
 
 /*
@@ -156,7 +156,7 @@ err_out:
  * ima_get_action - appraise & measure decision based on policy.
  * @inode: pointer to inode to measure
  * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
- * @function: calling function (FILE_CHECK, BPRM_CHECK, MMAP_CHECK, MODULE_CHECK)
+ * @func: caller identifier
  *
  * The policy is defined in terms of keypairs:
  *             subj=, obj=, type=, func=, mask=, fsmagic=
@@ -168,13 +168,13 @@ err_out:
  * Returns IMA_MEASURE, IMA_APPRAISE mask.
  *
  */
-int ima_get_action(struct inode *inode, int mask, int function)
+int ima_get_action(struct inode *inode, int mask, enum ima_hooks func)
 {
        int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
 
        flags &= ima_policy_flag;
 
-       return ima_match_policy(inode, function, mask, flags);
+       return ima_match_policy(inode, func, mask, flags);
 }
 
 /*
@@ -188,9 +188,8 @@ int ima_get_action(struct inode *inode, int mask, int function)
  * Return 0 on success, error code otherwise
  */
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-                           struct file *file,
-                           struct evm_ima_xattr_data **xattr_value,
-                           int *xattr_len)
+                           struct file *file, void *buf, loff_t size,
+                           enum hash_algo algo)
 {
        const char *audit_cause = "failed";
        struct inode *inode = file_inode(file);
@@ -201,9 +200,6 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
                char digest[IMA_MAX_DIGEST_SIZE];
        } hash;
 
-       if (xattr_value)
-               *xattr_len = ima_read_xattr(file->f_path.dentry, xattr_value);
-
        if (!(iint->flags & IMA_COLLECTED)) {
                u64 i_version = file_inode(file)->i_version;
 
@@ -213,13 +209,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
                        goto out;
                }
 
-               /* use default hash algorithm */
-               hash.hdr.algo = ima_hash_algo;
-
-               if (xattr_value)
-                       ima_get_hash_algo(*xattr_value, *xattr_len, &hash.hdr);
+               hash.hdr.algo = algo;
 
-               result = ima_calc_file_hash(file, &hash.hdr);
+               result = (!buf) ?  ima_calc_file_hash(file, &hash.hdr) :
+                       ima_calc_buffer_hash(buf, size, &hash.hdr);
                if (!result) {
                        int length = sizeof(hash.hdr) + hash.hdr.length;
                        void *tmpbuf = krealloc(iint->ima_hash, length,
index 1873b5536f804c28cbb9452b5b1a8cc2f180828a..6b4694aedae8cebf80cff4963949d8d6460cdd32 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/magic.h>
 #include <linux/ima.h>
 #include <linux/evm.h>
-#include <crypto/hash_info.h>
 
 #include "ima.h"
 
@@ -68,25 +67,25 @@ static int ima_fix_xattr(struct dentry *dentry,
 
 /* Return specific func appraised cached result */
 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
-                                          int func)
+                                          enum ima_hooks func)
 {
        switch (func) {
        case MMAP_CHECK:
                return iint->ima_mmap_status;
        case BPRM_CHECK:
                return iint->ima_bprm_status;
-       case MODULE_CHECK:
-               return iint->ima_module_status;
-       case FIRMWARE_CHECK:
-               return iint->ima_firmware_status;
        case FILE_CHECK:
-       default:
+       case POST_SETATTR:
                return iint->ima_file_status;
+       case MODULE_CHECK ... MAX_CHECK - 1:
+       default:
+               return iint->ima_read_status;
        }
 }
 
 static void ima_set_cache_status(struct integrity_iint_cache *iint,
-                                int func, enum integrity_status status)
+                                enum ima_hooks func,
+                                enum integrity_status status)
 {
        switch (func) {
        case MMAP_CHECK:
@@ -95,20 +94,19 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint,
        case BPRM_CHECK:
                iint->ima_bprm_status = status;
                break;
-       case MODULE_CHECK:
-               iint->ima_module_status = status;
-               break;
-       case FIRMWARE_CHECK:
-               iint->ima_firmware_status = status;
-               break;
        case FILE_CHECK:
-       default:
+       case POST_SETATTR:
                iint->ima_file_status = status;
                break;
+       case MODULE_CHECK ... MAX_CHECK - 1:
+       default:
+               iint->ima_read_status = status;
+               break;
        }
 }
 
-static void ima_cache_flags(struct integrity_iint_cache *iint, int func)
+static void ima_cache_flags(struct integrity_iint_cache *iint,
+                            enum ima_hooks func)
 {
        switch (func) {
        case MMAP_CHECK:
@@ -117,49 +115,51 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func)
        case BPRM_CHECK:
                iint->flags |= (IMA_BPRM_APPRAISED | IMA_APPRAISED);
                break;
-       case MODULE_CHECK:
-               iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED);
-               break;
-       case FIRMWARE_CHECK:
-               iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED);
-               break;
        case FILE_CHECK:
-       default:
+       case POST_SETATTR:
                iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED);
                break;
+       case MODULE_CHECK ... MAX_CHECK - 1:
+       default:
+               iint->flags |= (IMA_READ_APPRAISED | IMA_APPRAISED);
+               break;
        }
 }
 
-void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
-                      struct ima_digest_data *hash)
+enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+                                int xattr_len)
 {
        struct signature_v2_hdr *sig;
 
        if (!xattr_value || xattr_len < 2)
-               return;
+               /* return default hash algo */
+               return ima_hash_algo;
 
        switch (xattr_value->type) {
        case EVM_IMA_XATTR_DIGSIG:
                sig = (typeof(sig))xattr_value;
                if (sig->version != 2 || xattr_len <= sizeof(*sig))
-                       return;
-               hash->algo = sig->hash_algo;
+                       return ima_hash_algo;
+               return sig->hash_algo;
                break;
        case IMA_XATTR_DIGEST_NG:
-               hash->algo = xattr_value->digest[0];
+               return xattr_value->digest[0];
                break;
        case IMA_XATTR_DIGEST:
                /* this is for backward compatibility */
                if (xattr_len == 21) {
                        unsigned int zero = 0;
                        if (!memcmp(&xattr_value->digest[16], &zero, 4))
-                               hash->algo = HASH_ALGO_MD5;
+                               return HASH_ALGO_MD5;
                        else
-                               hash->algo = HASH_ALGO_SHA1;
+                               return HASH_ALGO_SHA1;
                } else if (xattr_len == 17)
-                       hash->algo = HASH_ALGO_MD5;
+                       return HASH_ALGO_MD5;
                break;
        }
+
+       /* return default hash algo */
+       return ima_hash_algo;
 }
 
 int ima_read_xattr(struct dentry *dentry,
@@ -182,7 +182,8 @@ int ima_read_xattr(struct dentry *dentry,
  *
  * Return 0 on success, error code otherwise
  */
-int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
+int ima_appraise_measurement(enum ima_hooks func,
+                            struct integrity_iint_cache *iint,
                             struct file *file, const unsigned char *filename,
                             struct evm_ima_xattr_data *xattr_value,
                             int xattr_len, int opened)
@@ -296,7 +297,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
        if (iint->flags & IMA_DIGSIG)
                return;
 
-       rc = ima_collect_measurement(iint, file, NULL, NULL);
+       rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo);
        if (rc < 0)
                return;
 
index 6eb62936c6723c02ca0b565ebe955aab2eb74c17..38f2ed830dd6fb23c216b014e39405318705d8ee 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <crypto/hash.h>
-#include <crypto/hash_info.h>
+
 #include "ima.h"
 
 struct ahash_completion {
@@ -519,6 +519,124 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
        return rc;
 }
 
+static int calc_buffer_ahash_atfm(const void *buf, loff_t len,
+                                 struct ima_digest_data *hash,
+                                 struct crypto_ahash *tfm)
+{
+       struct ahash_request *req;
+       struct scatterlist sg;
+       struct ahash_completion res;
+       int rc, ahash_rc = 0;
+
+       hash->length = crypto_ahash_digestsize(tfm);
+
+       req = ahash_request_alloc(tfm, GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       init_completion(&res.completion);
+       ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+                                  CRYPTO_TFM_REQ_MAY_SLEEP,
+                                  ahash_complete, &res);
+
+       rc = ahash_wait(crypto_ahash_init(req), &res);
+       if (rc)
+               goto out;
+
+       sg_init_one(&sg, buf, len);
+       ahash_request_set_crypt(req, &sg, NULL, len);
+
+       ahash_rc = crypto_ahash_update(req);
+
+       /* wait for the update request to complete */
+       rc = ahash_wait(ahash_rc, &res);
+       if (!rc) {
+               ahash_request_set_crypt(req, NULL, hash->digest, 0);
+               rc = ahash_wait(crypto_ahash_final(req), &res);
+       }
+out:
+       ahash_request_free(req);
+       return rc;
+}
+
+static int calc_buffer_ahash(const void *buf, loff_t len,
+                            struct ima_digest_data *hash)
+{
+       struct crypto_ahash *tfm;
+       int rc;
+
+       tfm = ima_alloc_atfm(hash->algo);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+
+       rc = calc_buffer_ahash_atfm(buf, len, hash, tfm);
+
+       ima_free_atfm(tfm);
+
+       return rc;
+}
+
+static int calc_buffer_shash_tfm(const void *buf, loff_t size,
+                               struct ima_digest_data *hash,
+                               struct crypto_shash *tfm)
+{
+       SHASH_DESC_ON_STACK(shash, tfm);
+       unsigned int len;
+       int rc;
+
+       shash->tfm = tfm;
+       shash->flags = 0;
+
+       hash->length = crypto_shash_digestsize(tfm);
+
+       rc = crypto_shash_init(shash);
+       if (rc != 0)
+               return rc;
+
+       while (size) {
+               len = size < PAGE_SIZE ? size : PAGE_SIZE;
+               rc = crypto_shash_update(shash, buf, len);
+               if (rc)
+                       break;
+               buf += len;
+               size -= len;
+       }
+
+       if (!rc)
+               rc = crypto_shash_final(shash, hash->digest);
+       return rc;
+}
+
+static int calc_buffer_shash(const void *buf, loff_t len,
+                            struct ima_digest_data *hash)
+{
+       struct crypto_shash *tfm;
+       int rc;
+
+       tfm = ima_alloc_tfm(hash->algo);
+       if (IS_ERR(tfm))
+               return PTR_ERR(tfm);
+
+       rc = calc_buffer_shash_tfm(buf, len, hash, tfm);
+
+       ima_free_tfm(tfm);
+       return rc;
+}
+
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+                        struct ima_digest_data *hash)
+{
+       int rc;
+
+       if (ima_ahash_minsize && len >= ima_ahash_minsize) {
+               rc = calc_buffer_ahash(buf, len, hash);
+               if (!rc)
+                       return 0;
+       }
+
+       return calc_buffer_shash(buf, len, hash);
+}
+
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
        if (!ima_used_chip)
index f355231997b462d1d6acee7664cabe9c51fdc91e..60d011aaec389dc26e77091e86455cd550892c64 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
 #include <linux/parser.h>
+#include <linux/vmalloc.h>
 
 #include "ima.h"
 
@@ -258,6 +259,43 @@ static const struct file_operations ima_ascii_measurements_ops = {
        .release = seq_release,
 };
 
+static ssize_t ima_read_policy(char *path)
+{
+       void *data;
+       char *datap;
+       loff_t size;
+       int rc, pathlen = strlen(path);
+
+       char *p;
+
+       /* remove \n */
+       datap = path;
+       strsep(&datap, "\n");
+
+       rc = kernel_read_file_from_path(path, &data, &size, 0, READING_POLICY);
+       if (rc < 0) {
+               pr_err("Unable to open file: %s (%d)", path, rc);
+               return rc;
+       }
+
+       datap = data;
+       while (size > 0 && (p = strsep(&datap, "\n"))) {
+               pr_debug("rule: %s\n", p);
+               rc = ima_parse_add_rule(p);
+               if (rc < 0)
+                       break;
+               size -= rc;
+       }
+
+       vfree(data);
+       if (rc < 0)
+               return rc;
+       else if (size)
+               return -EINVAL;
+       else
+               return pathlen;
+}
+
 static ssize_t ima_write_policy(struct file *file, const char __user *buf,
                                size_t datalen, loff_t *ppos)
 {
@@ -286,9 +324,20 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
        result = mutex_lock_interruptible(&ima_write_mutex);
        if (result < 0)
                goto out_free;
-       result = ima_parse_add_rule(data);
-       mutex_unlock(&ima_write_mutex);
 
+       if (data[0] == '/') {
+               result = ima_read_policy(data);
+       } else if (ima_appraise & IMA_APPRAISE_POLICY) {
+               pr_err("IMA: signed policy file (specified as an absolute pathname) required\n");
+               integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
+                                   "policy_update", "signed policy required",
+                                   1, 0);
+               if (ima_appraise & IMA_APPRAISE_ENFORCE)
+                       result = -EACCES;
+       } else {
+               result = ima_parse_add_rule(data);
+       }
+       mutex_unlock(&ima_write_mutex);
 out_free:
        kfree(data);
 out:
index bd79f254d204b3503b3a7a64cec88ae3d37a1e9f..5d679a6856162d738db8d258a06e171724565806 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
 #include <linux/err.h>
-#include <crypto/hash_info.h>
+
 #include "ima.h"
 
 /* name for boot aggregate entry */
index 9d96551d0196cb3e7136ace6e747f9504c07fc7a..391f41751021ff43a765ab5fe02cf19aa6e056bf 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/slab.h>
 #include <linux/xattr.h>
 #include <linux/ima.h>
-#include <crypto/hash_info.h>
 
 #include "ima.h"
 
@@ -154,8 +153,8 @@ void ima_file_free(struct file *file)
        ima_check_last_writer(iint, inode, file);
 }
 
-static int process_measurement(struct file *file, int mask, int function,
-                              int opened)
+static int process_measurement(struct file *file, char *buf, loff_t size,
+                              int mask, enum ima_hooks func, int opened)
 {
        struct inode *inode = file_inode(file);
        struct integrity_iint_cache *iint = NULL;
@@ -163,9 +162,10 @@ static int process_measurement(struct file *file, int mask, int function,
        char *pathbuf = NULL;
        const char *pathname = NULL;
        int rc = -ENOMEM, action, must_appraise;
-       struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL;
+       struct evm_ima_xattr_data *xattr_value = NULL;
        int xattr_len = 0;
        bool violation_check;
+       enum hash_algo hash_algo;
 
        if (!ima_policy_flag || !S_ISREG(inode->i_mode))
                return 0;
@@ -174,8 +174,8 @@ static int process_measurement(struct file *file, int mask, int function,
         * bitmask based on the appraise/audit/measurement policy.
         * Included is the appraise submask.
         */
-       action = ima_get_action(inode, mask, function);
-       violation_check = ((function == FILE_CHECK || function == MMAP_CHECK) &&
+       action = ima_get_action(inode, mask, func);
+       violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
                           (ima_policy_flag & IMA_MEASURE));
        if (!action && !violation_check)
                return 0;
@@ -184,7 +184,7 @@ static int process_measurement(struct file *file, int mask, int function,
 
        /*  Is the appraise rule hook specific?  */
        if (action & IMA_FILE_APPRAISE)
-               function = FILE_CHECK;
+               func = FILE_CHECK;
 
        inode_lock(inode);
 
@@ -214,16 +214,19 @@ static int process_measurement(struct file *file, int mask, int function,
        /* Nothing to do, just return existing appraised status */
        if (!action) {
                if (must_appraise)
-                       rc = ima_get_cache_status(iint, function);
+                       rc = ima_get_cache_status(iint, func);
                goto out_digsig;
        }
 
        template_desc = ima_template_desc_current();
        if ((action & IMA_APPRAISE_SUBMASK) ||
                    strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
-               xattr_ptr = &xattr_value;
+               /* read 'security.ima' */
+               xattr_len = ima_read_xattr(file->f_path.dentry, &xattr_value);
 
-       rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len);
+       hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
+
+       rc = ima_collect_measurement(iint, file, buf, size, hash_algo);
        if (rc != 0) {
                if (file->f_flags & O_DIRECT)
                        rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES;
@@ -237,7 +240,7 @@ static int process_measurement(struct file *file, int mask, int function,
                ima_store_measurement(iint, file, pathname,
                                      xattr_value, xattr_len);
        if (action & IMA_APPRAISE_SUBMASK)
-               rc = ima_appraise_measurement(function, iint, file, pathname,
+               rc = ima_appraise_measurement(func, iint, file, pathname,
                                              xattr_value, xattr_len, opened);
        if (action & IMA_AUDIT)
                ima_audit_measurement(iint, pathname);
@@ -270,7 +273,8 @@ out:
 int ima_file_mmap(struct file *file, unsigned long prot)
 {
        if (file && (prot & PROT_EXEC))
-               return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0);
+               return process_measurement(file, NULL, 0, MAY_EXEC,
+                                          MMAP_CHECK, 0);
        return 0;
 }
 
@@ -289,7 +293,8 @@ int ima_file_mmap(struct file *file, unsigned long prot)
  */
 int ima_bprm_check(struct linux_binprm *bprm)
 {
-       return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0);
+       return process_measurement(bprm->file, NULL, 0, MAY_EXEC,
+                                  BPRM_CHECK, 0);
 }
 
 /**
@@ -304,24 +309,26 @@ int ima_bprm_check(struct linux_binprm *bprm)
  */
 int ima_file_check(struct file *file, int mask, int opened)
 {
-       return process_measurement(file,
+       return process_measurement(file, NULL, 0,
                                   mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
                                   FILE_CHECK, opened);
 }
 EXPORT_SYMBOL_GPL(ima_file_check);
 
 /**
- * ima_module_check - based on policy, collect/store/appraise measurement.
- * @file: pointer to the file to be measured/appraised
+ * ima_read_file - pre-measure/appraise hook decision based on policy
+ * @file: pointer to the file to be measured/appraised/audit
+ * @read_id: caller identifier
  *
- * Measure/appraise kernel modules based on policy.
+ * Permit reading a file based on policy. The policy rules are written
+ * in terms of the policy identifier.  Appraising the integrity of
+ * a file requires a file descriptor.
  *
- * On success return 0.  On integrity appraisal error, assuming the file
- * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
+ * For permission return 0, otherwise return -EACCES.
  */
-int ima_module_check(struct file *file)
+int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
 {
-       if (!file) {
+       if (!file && read_id == READING_MODULE) {
 #ifndef CONFIG_MODULE_SIG_FORCE
                if ((ima_appraise & IMA_APPRAISE_MODULES) &&
                    (ima_appraise & IMA_APPRAISE_ENFORCE))
@@ -329,18 +336,53 @@ int ima_module_check(struct file *file)
 #endif
                return 0;       /* We rely on module signature checking */
        }
-       return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0);
+       return 0;
 }
 
-int ima_fw_from_file(struct file *file, char *buf, size_t size)
+static int read_idmap[READING_MAX_ID] = {
+       [READING_FIRMWARE] = FIRMWARE_CHECK,
+       [READING_MODULE] = MODULE_CHECK,
+       [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
+       [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
+       [READING_POLICY] = POLICY_CHECK
+};
+
+/**
+ * ima_post_read_file - in memory collect/appraise/audit measurement
+ * @file: pointer to the file to be measured/appraised/audit
+ * @buf: pointer to in memory file contents
+ * @size: size of in memory file contents
+ * @read_id: caller identifier
+ *
+ * Measure/appraise/audit in memory file based on policy.  Policy rules
+ * are written in terms of a policy identifier.
+ *
+ * On success return 0.  On integrity appraisal error, assuming the file
+ * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
+ */
+int ima_post_read_file(struct file *file, void *buf, loff_t size,
+                      enum kernel_read_file_id read_id)
 {
-       if (!file) {
+       enum ima_hooks func;
+
+       if (!file && read_id == READING_FIRMWARE) {
                if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
                    (ima_appraise & IMA_APPRAISE_ENFORCE))
                        return -EACCES; /* INTEGRITY_UNKNOWN */
                return 0;
        }
-       return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0);
+
+       if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */
+               return 0;
+
+       if (!file || !buf || size == 0) { /* should never happen */
+               if (ima_appraise & IMA_APPRAISE_ENFORCE)
+                       return -EACCES;
+               return 0;
+       }
+
+       func = read_idmap[read_id] ?: FILE_CHECK;
+       return process_measurement(file, buf, size, MAY_READ, func, 0);
 }
 
 static int __init init_ima(void)
index 0a3b781f18e55771e0204b7a95e42dbe6fc4f161..be09e2cacf828d32c75028ccf04f31e88657da70 100644 (file)
@@ -12,6 +12,7 @@
  */
 #include <linux/module.h>
 #include <linux/list.h>
+#include <linux/fs.h>
 #include <linux/security.h>
 #include <linux/magic.h>
 #include <linux/parser.h>
@@ -113,6 +114,7 @@ static struct ima_rule_entry default_measurement_rules[] = {
         .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
        {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
        {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
+       {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC},
 };
 
 static struct ima_rule_entry default_appraise_rules[] = {
@@ -127,6 +129,10 @@ static struct ima_rule_entry default_appraise_rules[] = {
        {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
        {.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
        {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
+#ifdef CONFIG_IMA_WRITE_POLICY
+       {.action = APPRAISE, .func = POLICY_CHECK,
+       .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
+#endif
 #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
        {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
 #else
@@ -207,8 +213,8 @@ static void ima_lsm_update_rules(void)
  *
  * Returns true on rule match, false on failure.
  */
-static bool ima_match_rules(struct ima_rule_entry *rule,
-                           struct inode *inode, enum ima_hooks func, int mask)
+static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
+                           enum ima_hooks func, int mask)
 {
        struct task_struct *tsk = current;
        const struct cred *cred = current_cred();
@@ -289,7 +295,7 @@ retry:
  * In addition to knowing that we need to appraise the file in general,
  * we need to differentiate between calling hooks, for hook specific rules.
  */
-static int get_subaction(struct ima_rule_entry *rule, int func)
+static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
 {
        if (!(rule->flags & IMA_FUNC))
                return IMA_FILE_APPRAISE;
@@ -299,13 +305,12 @@ static int get_subaction(struct ima_rule_entry *rule, int func)
                return IMA_MMAP_APPRAISE;
        case BPRM_CHECK:
                return IMA_BPRM_APPRAISE;
-       case MODULE_CHECK:
-               return IMA_MODULE_APPRAISE;
-       case FIRMWARE_CHECK:
-               return IMA_FIRMWARE_APPRAISE;
        case FILE_CHECK:
-       default:
+       case POST_SETATTR:
                return IMA_FILE_APPRAISE;
+       case MODULE_CHECK ... MAX_CHECK - 1:
+       default:
+               return IMA_READ_APPRAISE;
        }
 }
 
@@ -411,13 +416,16 @@ void __init ima_init_policy(void)
        for (i = 0; i < appraise_entries; i++) {
                list_add_tail(&default_appraise_rules[i].list,
                              &ima_default_rules);
+               if (default_appraise_rules[i].func == POLICY_CHECK)
+                       temp_ima_appraise |= IMA_APPRAISE_POLICY;
        }
 
        ima_rules = &ima_default_rules;
+       ima_update_policy_flag();
 }
 
 /* Make sure we have a valid policy, at least containing some rules. */
-int ima_check_policy()
+int ima_check_policy(void)
 {
        if (list_empty(&ima_temp_rules))
                return -EINVAL;
@@ -612,6 +620,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                                entry->func = MMAP_CHECK;
                        else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
                                entry->func = BPRM_CHECK;
+                       else if (strcmp(args[0].from, "KEXEC_KERNEL_CHECK") ==
+                                0)
+                               entry->func = KEXEC_KERNEL_CHECK;
+                       else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
+                                == 0)
+                               entry->func = KEXEC_INITRAMFS_CHECK;
+                       else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
+                               entry->func = POLICY_CHECK;
                        else
                                result = -EINVAL;
                        if (!result)
@@ -770,6 +786,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                temp_ima_appraise |= IMA_APPRAISE_MODULES;
        else if (entry->func == FIRMWARE_CHECK)
                temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
+       else if (entry->func == POLICY_CHECK)
+               temp_ima_appraise |= IMA_APPRAISE_POLICY;
        audit_log_format(ab, "res=%d", !result);
        audit_log_end(ab);
        return result;
@@ -855,7 +873,9 @@ static char *mask_tokens[] = {
 
 enum {
        func_file = 0, func_mmap, func_bprm,
-       func_module, func_firmware, func_post
+       func_module, func_firmware, func_post,
+       func_kexec_kernel, func_kexec_initramfs,
+       func_policy
 };
 
 static char *func_tokens[] = {
@@ -864,6 +884,9 @@ static char *func_tokens[] = {
        "BPRM_CHECK",
        "MODULE_CHECK",
        "FIRMWARE_CHECK",
+       "KEXEC_KERNEL_CHECK",
+       "KEXEC_INITRAMFS_CHECK",
+       "POLICY_CHECK",
        "POST_SETATTR"
 };
 
@@ -903,6 +926,49 @@ void ima_policy_stop(struct seq_file *m, void *v)
 #define mt(token)      mask_tokens[token]
 #define ft(token)      func_tokens[token]
 
+/*
+ * policy_func_show - display the ima_hooks policy rule
+ */
+static void policy_func_show(struct seq_file *m, enum ima_hooks func)
+{
+       char tbuf[64] = {0,};
+
+       switch (func) {
+       case FILE_CHECK:
+               seq_printf(m, pt(Opt_func), ft(func_file));
+               break;
+       case MMAP_CHECK:
+               seq_printf(m, pt(Opt_func), ft(func_mmap));
+               break;
+       case BPRM_CHECK:
+               seq_printf(m, pt(Opt_func), ft(func_bprm));
+               break;
+       case MODULE_CHECK:
+               seq_printf(m, pt(Opt_func), ft(func_module));
+               break;
+       case FIRMWARE_CHECK:
+               seq_printf(m, pt(Opt_func), ft(func_firmware));
+               break;
+       case POST_SETATTR:
+               seq_printf(m, pt(Opt_func), ft(func_post));
+               break;
+       case KEXEC_KERNEL_CHECK:
+               seq_printf(m, pt(Opt_func), ft(func_kexec_kernel));
+               break;
+       case KEXEC_INITRAMFS_CHECK:
+               seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
+               break;
+       case POLICY_CHECK:
+               seq_printf(m, pt(Opt_func), ft(func_policy));
+               break;
+       default:
+               snprintf(tbuf, sizeof(tbuf), "%d", func);
+               seq_printf(m, pt(Opt_func), tbuf);
+               break;
+       }
+       seq_puts(m, " ");
+}
+
 int ima_policy_show(struct seq_file *m, void *v)
 {
        struct ima_rule_entry *entry = v;
@@ -924,33 +990,8 @@ int ima_policy_show(struct seq_file *m, void *v)
 
        seq_puts(m, " ");
 
-       if (entry->flags & IMA_FUNC) {
-               switch (entry->func) {
-               case FILE_CHECK:
-                       seq_printf(m, pt(Opt_func), ft(func_file));
-                       break;
-               case MMAP_CHECK:
-                       seq_printf(m, pt(Opt_func), ft(func_mmap));
-                       break;
-               case BPRM_CHECK:
-                       seq_printf(m, pt(Opt_func), ft(func_bprm));
-                       break;
-               case MODULE_CHECK:
-                       seq_printf(m, pt(Opt_func), ft(func_module));
-                       break;
-               case FIRMWARE_CHECK:
-                       seq_printf(m, pt(Opt_func), ft(func_firmware));
-                       break;
-               case POST_SETATTR:
-                       seq_printf(m, pt(Opt_func), ft(func_post));
-                       break;
-               default:
-                       snprintf(tbuf, sizeof(tbuf), "%d", entry->func);
-                       seq_printf(m, pt(Opt_func), tbuf);
-                       break;
-               }
-               seq_puts(m, " ");
-       }
+       if (entry->flags & IMA_FUNC)
+               policy_func_show(m, entry->func);
 
        if (entry->flags & IMA_MASK) {
                if (entry->mask & MAY_EXEC)
index 0b7404ebfa80baf9a3741fa36f74aca5548f8405..febd12ed9b55ab4d6009176c355655c646272437 100644 (file)
@@ -15,8 +15,6 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <crypto/hash_info.h>
-
 #include "ima.h"
 #include "ima_template_lib.h"
 
index 2934e3d377f1e0c1c20e6d97e8651b19154569da..f9bae04ba1762cd3e91728e4506719739b541e7d 100644 (file)
@@ -12,7 +12,6 @@
  * File: ima_template_lib.c
  *      Library of supported template fields.
  */
-#include <crypto/hash_info.h>
 
 #include "ima_template_lib.h"
 
index 5efe2ecc538d327818e48ec7c865bb03bc63322f..e08935cf343f44cd0e9815e8655b0222a92eda83 100644 (file)
 #define IMA_MMAP_APPRAISED     0x00000800
 #define IMA_BPRM_APPRAISE      0x00001000
 #define IMA_BPRM_APPRAISED     0x00002000
-#define IMA_MODULE_APPRAISE    0x00004000
-#define IMA_MODULE_APPRAISED   0x00008000
-#define IMA_FIRMWARE_APPRAISE  0x00010000
-#define IMA_FIRMWARE_APPRAISED 0x00020000
+#define IMA_READ_APPRAISE      0x00004000
+#define IMA_READ_APPRAISED     0x00008000
 #define IMA_APPRAISE_SUBMASK   (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \
-                                IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE | \
-                                IMA_FIRMWARE_APPRAISE)
+                                IMA_BPRM_APPRAISE | IMA_READ_APPRAISE)
 #define IMA_APPRAISED_SUBMASK  (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \
-                                IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED | \
-                                IMA_FIRMWARE_APPRAISED)
+                                IMA_BPRM_APPRAISED | IMA_READ_APPRAISED)
 
 enum evm_ima_xattr_type {
        IMA_XATTR_DIGEST = 0x01,
@@ -94,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 */
@@ -109,8 +105,7 @@ struct integrity_iint_cache {
        enum integrity_status ima_file_status:4;
        enum integrity_status ima_mmap_status:4;
        enum integrity_status ima_bprm_status:4;
-       enum integrity_status ima_module_status:4;
-       enum integrity_status ima_firmware_status:4;
+       enum integrity_status ima_read_status:4;
        enum integrity_status evm_status:4;
        struct ima_digest_data *ima_hash;
 };
index 907c1522ee469b05d42bcf9a839c0a80bf7eff6c..c721e398893add4712d891a9dabeeee117048782 100644 (file)
@@ -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);
index 09ef276c4bdcaf8e0c419df61d1cd7b07bf5253c..b28755131687ea89de81ff5813c3fa9eb4acee74 100644 (file)
@@ -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;
index 0dcab20cdacdf9dbd4061fd589c872501fee5d01..90d61751ff12f3e9d4015900c39ac7b595411240 100644 (file)
@@ -744,6 +744,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
        unsigned long handle;
        unsigned long lock;
        unsigned long token_mask = 0;
+       unsigned int digest_len;
        int i;
        int tpm2;
 
@@ -752,7 +753,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
                return tpm2;
 
        opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
-       opt->digest_len = hash_digest_size[opt->hash];
 
        while ((p = strsep(&c, " \t"))) {
                if (*p == '\0' || *p == ' ' || *p == '\t')
@@ -812,8 +812,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
                        for (i = 0; i < HASH_ALGO__LAST; i++) {
                                if (!strcmp(args[0].from, hash_algo_name[i])) {
                                        opt->hash = i;
-                                       opt->digest_len =
-                                               hash_digest_size[opt->hash];
                                        break;
                                }
                        }
@@ -825,13 +823,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
                        }
                        break;
                case Opt_policydigest:
-                       if (!tpm2 ||
-                           strlen(args[0].from) != (2 * opt->digest_len))
+                       digest_len = hash_digest_size[opt->hash];
+                       if (!tpm2 || strlen(args[0].from) != (2 * digest_len))
                                return -EINVAL;
                        res = hex2bin(opt->policydigest, args[0].from,
-                                     opt->digest_len);
+                                     digest_len);
                        if (res < 0)
                                return -EINVAL;
+                       opt->policydigest_len = digest_len;
                        break;
                case Opt_policyhandle:
                        if (!tpm2)
index e8ffd92ae2eb5a761bfafab5556df9c54c8bd32e..3644b0344d29f3a17ef4f94b1156c9dffff02e65 100644 (file)
@@ -884,31 +884,33 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode)
        return call_int_hook(kernel_create_files_as, 0, new, inode);
 }
 
-int security_kernel_fw_from_file(struct file *file, char *buf, size_t size)
+int security_kernel_module_request(char *kmod_name)
+{
+       return call_int_hook(kernel_module_request, 0, kmod_name);
+}
+
+int security_kernel_read_file(struct file *file, enum kernel_read_file_id id)
 {
        int ret;
 
-       ret = call_int_hook(kernel_fw_from_file, 0, file, buf, size);
+       ret = call_int_hook(kernel_read_file, 0, file, id);
        if (ret)
                return ret;
-       return ima_fw_from_file(file, buf, size);
-}
-EXPORT_SYMBOL_GPL(security_kernel_fw_from_file);
-
-int security_kernel_module_request(char *kmod_name)
-{
-       return call_int_hook(kernel_module_request, 0, kmod_name);
+       return ima_read_file(file, id);
 }
+EXPORT_SYMBOL_GPL(security_kernel_read_file);
 
-int security_kernel_module_from_file(struct file *file)
+int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
+                                  enum kernel_read_file_id id)
 {
        int ret;
 
-       ret = call_int_hook(kernel_module_from_file, 0, file);
+       ret = call_int_hook(kernel_post_read_file, 0, file, buf, size, id);
        if (ret)
                return ret;
-       return ima_module_check(file);
+       return ima_post_read_file(file, buf, size, id);
 }
+EXPORT_SYMBOL_GPL(security_kernel_post_read_file);
 
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
                             int flags)
@@ -1691,12 +1693,12 @@ struct security_hook_heads security_hook_heads = {
                LIST_HEAD_INIT(security_hook_heads.kernel_act_as),
        .kernel_create_files_as =
                LIST_HEAD_INIT(security_hook_heads.kernel_create_files_as),
-       .kernel_fw_from_file =
-               LIST_HEAD_INIT(security_hook_heads.kernel_fw_from_file),
        .kernel_module_request =
                LIST_HEAD_INIT(security_hook_heads.kernel_module_request),
-       .kernel_module_from_file =
-               LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file),
+       .kernel_read_file =
+               LIST_HEAD_INIT(security_hook_heads.kernel_read_file),
+       .kernel_post_read_file =
+               LIST_HEAD_INIT(security_hook_heads.kernel_post_read_file),
        .task_fix_setuid =
                LIST_HEAD_INIT(security_hook_heads.task_fix_setuid),
        .task_setpgid = LIST_HEAD_INIT(security_hook_heads.task_setpgid),
index ad5cd76ec231cd14f02b2fb15f07a3d8a069972f..3411c33e2a445f28282aa5315e4b17a42a69ad23 100644 (file)
@@ -13,7 +13,7 @@ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
 
 selinux-$(CONFIG_NETLABEL) += netlabel.o
 
-ccflags-y := -Isecurity/selinux -Isecurity/selinux/include
+ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
 
 $(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
 
index 2d6e9bdea398c69fd7f55bb7615e486078557231..11f79013ae1f09c908072d42a0f85aa628710284 100644 (file)
@@ -1442,9 +1442,13 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
         * Don't do anything special for these.
         *      XATTR_NAME_SMACKIPIN
         *      XATTR_NAME_SMACKIPOUT
-        *      XATTR_NAME_SMACKEXEC
         */
-       if (strcmp(name, XATTR_NAME_SMACK) == 0)
+       if (strcmp(name, XATTR_NAME_SMACK) == 0) {
+               struct super_block *sbp = d_backing_inode(dentry)->i_sb;
+               struct superblock_smack *sbsp = sbp->s_security;
+
+               isp->smk_inode = sbsp->smk_default;
+       } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0)
                isp->smk_task = NULL;
        else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0)
                isp->smk_mmap = NULL;
@@ -1545,12 +1549,8 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid)
  * File Hooks
  */
 
-/**
- * smack_file_permission - Smack check on file operations
- * @file: unused
- * @mask: unused
- *
- * Returns 0
+/*
+ * There is no smack_file_permission hook
  *
  * Should access checks be done on each read or write?
  * UNICOS and SELinux say yes.
@@ -1559,10 +1559,6 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid)
  * I'll say no for now. Smack does not do the frequent
  * label changing that SELinux does.
  */
-static int smack_file_permission(struct file *file, int mask)
-{
-       return 0;
-}
 
 /**
  * smack_file_alloc_security - assign a file security blob
@@ -4503,16 +4499,10 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
        return 0;
 }
 
-/**
- * smack_audit_rule_free - free smack rule representation
- * @vrule: rule to be freed.
- *
+/*
+ * There is no need for a smack_audit_rule_free hook.
  * No memory was allocated.
  */
-static void smack_audit_rule_free(void *vrule)
-{
-       /* No-op */
-}
 
 #endif /* CONFIG_AUDIT */
 
@@ -4563,16 +4553,11 @@ static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
        return 0;
 }
 
-/**
- * smack_release_secctx - don't do anything.
- * @secdata: unused
- * @seclen: unused
- *
- * Exists to make sure nothing gets done, and properly
+/*
+ * There used to be a smack_release_secctx hook
+ * that did nothing back when hooks were in a vector.
+ * Now that there's a list such a hook adds cost.
  */
-static void smack_release_secctx(char *secdata, u32 seclen)
-{
-}
 
 static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
 {
@@ -4631,7 +4616,6 @@ static struct security_hook_list smack_hooks[] = {
        LSM_HOOK_INIT(inode_listsecurity, smack_inode_listsecurity),
        LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid),
 
-       LSM_HOOK_INIT(file_permission, smack_file_permission),
        LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security),
        LSM_HOOK_INIT(file_free_security, smack_file_free_security),
        LSM_HOOK_INIT(file_ioctl, smack_file_ioctl),
@@ -4726,13 +4710,11 @@ static struct security_hook_list smack_hooks[] = {
        LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init),
        LSM_HOOK_INIT(audit_rule_known, smack_audit_rule_known),
        LSM_HOOK_INIT(audit_rule_match, smack_audit_rule_match),
-       LSM_HOOK_INIT(audit_rule_free, smack_audit_rule_free),
 #endif /* CONFIG_AUDIT */
 
        LSM_HOOK_INIT(ismaclabel, smack_ismaclabel),
        LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx),
        LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid),
-       LSM_HOOK_INIT(release_secctx, smack_release_secctx),
        LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx),
        LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx),
        LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx),