[PATCH v4 3/3] ima: enable loading of build time generated key on .ima keyring

2021-04-09 Thread Nayna Jain
The kernel currently only loads the kernel module signing key onto the
builtin trusted keyring. Load the module signing key onto the IMA keyring
as well.

Signed-off-by: Nayna Jain 
Acked-by: Stefan Berger 
---
 certs/system_certificates.S   | 13 -
 certs/system_keyring.c| 50 ---
 include/keys/system_keyring.h |  7 +
 security/integrity/digsig.c   |  2 ++
 4 files changed, 61 insertions(+), 11 deletions(-)

diff --git a/certs/system_certificates.S b/certs/system_certificates.S
index 8f29058adf93..dcad27ea8527 100644
--- a/certs/system_certificates.S
+++ b/certs/system_certificates.S
@@ -8,9 +8,11 @@
.globl system_certificate_list
 system_certificate_list:
 __cert_list_start:
-#ifdef CONFIG_MODULE_SIG
+__module_cert_start:
+#if defined(CONFIG_MODULE_SIG) || defined(CONFIG_IMA_APPRAISE_MODSIG)
.incbin "certs/signing_key.x509"
 #endif
+__module_cert_end:
.incbin "certs/x509_certificate_list"
 __cert_list_end:
 
@@ -35,3 +37,12 @@ system_certificate_list_size:
 #else
.long __cert_list_end - __cert_list_start
 #endif
+
+   .align 8
+   .globl module_cert_size
+module_cert_size:
+#ifdef CONFIG_64BIT
+   .quad __module_cert_end - __module_cert_start
+#else
+   .long __module_cert_end - __module_cert_start
+#endif
diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index 4b693da488f1..2b3ad375ecc1 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -27,6 +27,7 @@ static struct key *platform_trusted_keys;
 
 extern __initconst const u8 system_certificate_list[];
 extern __initconst const unsigned long system_certificate_list_size;
+extern __initconst const unsigned long module_cert_size;
 
 /**
  * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
@@ -132,19 +133,11 @@ static __init int system_trusted_keyring_init(void)
  */
 device_initcall(system_trusted_keyring_init);
 
-/*
- * Load the compiled-in list of X.509 certificates.
- */
-static __init int load_system_certificate_list(void)
+static __init int load_cert(const u8 *p, const u8 *end, struct key *keyring)
 {
key_ref_t key;
-   const u8 *p, *end;
size_t plen;
 
-   pr_notice("Loading compiled-in X.509 certificates\n");
-
-   p = system_certificate_list;
-   end = p + system_certificate_list_size;
while (p < end) {
/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
 * than 256 bytes in size.
@@ -159,7 +152,7 @@ static __init int load_system_certificate_list(void)
if (plen > end - p)
goto dodgy_cert;
 
-   key = key_create_or_update(make_key_ref(builtin_trusted_keys, 
1),
+   key = key_create_or_update(make_key_ref(keyring, 1),
   "asymmetric",
   NULL,
   p,
@@ -186,6 +179,43 @@ static __init int load_system_certificate_list(void)
pr_err("Problem parsing in-kernel X.509 certificate list\n");
return 0;
 }
+
+__init int load_module_cert(struct key *keyring)
+{
+   const u8 *p, *end;
+
+   if (!IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG))
+   return 0;
+
+   pr_notice("Loading compiled-in module X.509 certificates\n");
+
+   p = system_certificate_list;
+   end = p + module_cert_size;
+
+   return load_cert(p, end, keyring);
+}
+
+/*
+ * Load the compiled-in list of X.509 certificates.
+ */
+static __init int load_system_certificate_list(void)
+{
+   const u8 *p, *end;
+   unsigned long size;
+
+   pr_notice("Loading compiled-in X.509 certificates\n");
+
+#ifdef CONFIG_MODULE_SIG
+   p = system_certificate_list;
+   size = system_certificate_list_size;
+#else
+   p = system_certificate_list + module_cert_size;
+   size = system_certificate_list_size - module_cert_size;
+#endif
+
+   end = p + size;
+   return load_cert(p, end, builtin_trusted_keys);
+}
 late_initcall(load_system_certificate_list);
 
 #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index fb8b07daa9d1..f954276c616a 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -16,9 +16,16 @@ extern int restrict_link_by_builtin_trusted(struct key 
*keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key);
+extern __init int load_module_cert(struct key *keyring);
 
 #else
 #define restrict_link_by_builtin_trusted restrict_link_reject
+
+static inline __init int load_module_cert(struct key *keyring)
+{
+   return 0;
+}
+
 #endif
 
 #ifdef CONFIG_SECONDARY_TRUSTED_KE

[PATCH v4 1/3] keys: cleanup build time module signing keys

2021-04-09 Thread Nayna Jain
The "mrproper" target is still looking for build time generated keys in
the kernel root directory instead of certs directory. Fix the path and
remove the names of the files which are no longer generated.

Fixes: cfc411e7fff3 ("Move certificate handling to its own directory")
Signed-off-by: Nayna Jain 
Reviewed-by: Stefan Berger 
Reviewed-by: Mimi Zohar 
Reviewed-by: Jarkko Sakkinen 
---
 Makefile | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index cc77fd45ca64..d64c94f41edb 100644
--- a/Makefile
+++ b/Makefile
@@ -1523,9 +1523,9 @@ MRPROPER_FILES += include/config include/generated
  \
  debian snap tar-install \
  .config .config.old .version \
  Module.symvers \
- signing_key.pem signing_key.priv signing_key.x509 \
- x509.genkey extra_certificates signing_key.x509.keyid \
- signing_key.x509.signer vmlinux-gdb.py \
+ certs/signing_key.pem certs/signing_key.x509 \
+ certs/x509.genkey \
+ vmlinux-gdb.py \
  *.spec
 
 # Directories & files removed with 'make distclean'
-- 
2.29.2



[PATCH v4 2/3] ima: enable signing of modules with build time generated key

2021-04-09 Thread Nayna Jain
The kernel build process currently only signs kernel modules when
MODULE_SIG is enabled. Also, sign the kernel modules at build time when
IMA_APPRAISE_MODSIG is enabled.

Signed-off-by: Nayna Jain 
Acked-by: Stefan Berger 
---
 certs/Kconfig  | 2 +-
 certs/Makefile | 8 
 init/Kconfig   | 6 +++---
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/certs/Kconfig b/certs/Kconfig
index c94e93d8bccf..48675ad319db 100644
--- a/certs/Kconfig
+++ b/certs/Kconfig
@@ -4,7 +4,7 @@ menu "Certificates for signature checking"
 config MODULE_SIG_KEY
string "File name or PKCS#11 URI of module signing key"
default "certs/signing_key.pem"
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  Provide the file name of a private key/certificate in PEM format,
  or a PKCS#11 URI according to RFC7512. The file should contain, or
diff --git a/certs/Makefile b/certs/Makefile
index f4c25b67aad9..e3185c57fbd8 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -32,6 +32,14 @@ endif # CONFIG_SYSTEM_TRUSTED_KEYRING
 clean-files := x509_certificate_list .x509.list
 
 ifeq ($(CONFIG_MODULE_SIG),y)
+   SIGN_KEY = y
+endif
+
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+   SIGN_KEY = y
+endif
+
+ifdef SIGN_KEY
 ###
 #
 # If module signing is requested, say by allyesconfig, but a key has not been
diff --git a/init/Kconfig b/init/Kconfig
index 5f5c776ef192..85e48a578f90 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2164,7 +2164,7 @@ config MODULE_SIG_FORCE
 config MODULE_SIG_ALL
bool "Automatically sign all modules"
default y
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  Sign all modules during make modules_install. Without this option,
  modules must be signed manually, using the scripts/sign-file tool.
@@ -2174,7 +2174,7 @@ comment "Do not forget to sign required modules with 
scripts/sign-file"
 
 choice
prompt "Which hash algorithm should modules be signed with?"
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  This determines which sort of hashing algorithm will be used during
  signature generation.  This algorithm _must_ be built into the kernel
@@ -2206,7 +2206,7 @@ endchoice
 
 config MODULE_SIG_HASH
string
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
default "sha1" if MODULE_SIG_SHA1
default "sha224" if MODULE_SIG_SHA224
default "sha256" if MODULE_SIG_SHA256
-- 
2.29.2



[PATCH v4 0/3] ima: kernel build support for loading the kernel module signing key

2021-04-09 Thread Nayna Jain
Kernel modules are currently only signed when CONFIG_MODULE_SIG is enabled.
The kernel module signing key is a self-signed CA only loaded onto the
.builtin_trusted_key keyring.  On secure boot enabled systems with an arch
specific IMA policy enabled, but without MODULE_SIG enabled, kernel modules
are not signed, nor is the kernel module signing public key loaded onto the
IMA keyring.

In order to load the the kernel module signing key onto the IMA trusted
keyring ('.ima'), the certificate needs to be signed by a CA key either on
the builtin or secondary keyrings. The original version of this patch set
created and loaded a kernel-CA key onto the builtin keyring. The kernel-CA
key signed the kernel module signing key, allowing it to be loaded onto the
IMA trusted keyring.

However, missing from this version was support for the kernel-CA to sign the
hardware token certificate. Adding that support would add additional
complexity.

Since the kernel module signing key is embedded into the Linux kernel at
build time, instead of creating and loading a kernel-CA onto the builtin
trusted keyring, this version makes an exception and allows the 
self-signed kernel module signing key to be loaded directly onto the 
trusted IMA keyring.

v4:
* Updated Jarkko's Reviewed-by and Stefan's Ack-by. 
* Fixed a bug where size was miscalculated for the case when only
IMA_APPRAISE_MODSIG is enabled. Thanks Mimi for noticing it.

v3:

* Fix the "Fixes" tag as suggested by Stefan for Patch 1/3.
* Revert back the CA signed module signing key to only self-signed.
* Allow self signed key as exception only for build time generated
module signing key onto .ima keyring.

v2:

* Include feedback from Stefan - corrected the Fixes commit id in Patch 1
and cleaned Patch 5/5.
* Fix the issue reported by kernel test bot.
* Include Jarkko's feedback on patch description.

Nayna Jain (3):
  keys: cleanup build time module signing keys
  ima: enable signing of modules with build time generated key
  ima: enable loading of build time generated key on .ima keyring

 Makefile  |  6 ++---
 certs/Kconfig |  2 +-
 certs/Makefile|  8 ++
 certs/system_certificates.S   | 13 -
 certs/system_keyring.c| 50 ---
 include/keys/system_keyring.h |  7 +
 init/Kconfig  |  6 ++---
 security/integrity/digsig.c   |  2 ++
 8 files changed, 76 insertions(+), 18 deletions(-)

-- 
2.29.2


[PATCH v3 0/3] ima: kernel build support for loading the kernel module signing key

2021-03-30 Thread Nayna Jain
Kernel modules are currently only signed when CONFIG_MODULE_SIG is enabled.
The kernel module signing key is a self-signed CA only loaded onto the
.builtin_trusted_key keyring.  On secure boot enabled systems with an arch
specific IMA policy enabled, but without MODULE_SIG enabled, kernel modules
are not signed, nor is the kernel module signing public key loaded onto the
IMA keyring.

In order to load the the kernel module signing key onto the IMA trusted
keyring ('.ima'), the certificate needs to be signed by a CA key either on
the builtin or secondary keyrings. The original version of this patch set
created and loaded a kernel-CA key onto the builtin keyring. The kernel-CA
key signed the kernel module signing key, allowing it to be loaded onto the
IMA trusted keyring.

However, missing from this version was support for the kernel-CA to sign the
hardware token certificate. Adding that support would add additional
complexity.

Since the kernel module signing key is embedded into the Linux kernel at
build time, instead of creating and loading a kernel-CA onto the builtin
trusted keyring, this version makes an exception and allows the 
self-signed kernel module signing key to be loaded directly onto the 
trusted IMA keyring

v3:

* Fix the "Fixes" tag as suggested by Stefan for Patch 1/3.
* Revert back the CA signed module signing key to only self-signed.
* Allow self signed key as exception only for build time generated
module signing key onto .ima keyring.

v2:

* Include feedback from Stefan - corrected the Fixes commit id in Patch 1
and cleaned Patch 5/5.
* Fix the issue reported by kernel test bot.
* Include Jarkko's feedback on patch description.

Nayna Jain (3):
  keys: cleanup build time module signing keys
  ima: enable signing of modules with build time generated key
  ima: enable loading of build time generated key on .ima keyring

 Makefile  |  6 ++---
 certs/Kconfig |  2 +-
 certs/Makefile|  8 ++
 certs/system_certificates.S   | 13 +-
 certs/system_keyring.c| 47 +++
 include/keys/system_keyring.h |  7 ++
 init/Kconfig  |  6 ++---
 security/integrity/digsig.c   |  2 ++
 8 files changed, 73 insertions(+), 18 deletions(-)

-- 
2.29.2


[PATCH v3 3/3] ima: enable loading of build time generated key on .ima keyring

2021-03-30 Thread Nayna Jain
The kernel currently only loads the kernel module signing key onto the
builtin trusted keyring. Load the module signing key onto the IMA keyring
as well.

Signed-off-by: Nayna Jain 
---
 certs/system_certificates.S   | 13 +-
 certs/system_keyring.c| 47 +++
 include/keys/system_keyring.h |  7 ++
 security/integrity/digsig.c   |  2 ++
 4 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/certs/system_certificates.S b/certs/system_certificates.S
index 8f29058adf93..dcad27ea8527 100644
--- a/certs/system_certificates.S
+++ b/certs/system_certificates.S
@@ -8,9 +8,11 @@
.globl system_certificate_list
 system_certificate_list:
 __cert_list_start:
-#ifdef CONFIG_MODULE_SIG
+__module_cert_start:
+#if defined(CONFIG_MODULE_SIG) || defined(CONFIG_IMA_APPRAISE_MODSIG)
.incbin "certs/signing_key.x509"
 #endif
+__module_cert_end:
.incbin "certs/x509_certificate_list"
 __cert_list_end:
 
@@ -35,3 +37,12 @@ system_certificate_list_size:
 #else
.long __cert_list_end - __cert_list_start
 #endif
+
+   .align 8
+   .globl module_cert_size
+module_cert_size:
+#ifdef CONFIG_64BIT
+   .quad __module_cert_end - __module_cert_start
+#else
+   .long __module_cert_end - __module_cert_start
+#endif
diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index 4b693da488f1..bb122bf4cc17 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -27,6 +27,7 @@ static struct key *platform_trusted_keys;
 
 extern __initconst const u8 system_certificate_list[];
 extern __initconst const unsigned long system_certificate_list_size;
+extern __initconst const unsigned long module_cert_size;
 
 /**
  * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
@@ -132,19 +133,11 @@ static __init int system_trusted_keyring_init(void)
  */
 device_initcall(system_trusted_keyring_init);
 
-/*
- * Load the compiled-in list of X.509 certificates.
- */
-static __init int load_system_certificate_list(void)
+static __init int load_cert(const u8 *p, const u8 *end, struct key *keyring)
 {
key_ref_t key;
-   const u8 *p, *end;
size_t plen;
 
-   pr_notice("Loading compiled-in X.509 certificates\n");
-
-   p = system_certificate_list;
-   end = p + system_certificate_list_size;
while (p < end) {
/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
 * than 256 bytes in size.
@@ -159,7 +152,7 @@ static __init int load_system_certificate_list(void)
if (plen > end - p)
goto dodgy_cert;
 
-   key = key_create_or_update(make_key_ref(builtin_trusted_keys, 
1),
+   key = key_create_or_update(make_key_ref(keyring, 1),
   "asymmetric",
   NULL,
   p,
@@ -186,6 +179,40 @@ static __init int load_system_certificate_list(void)
pr_err("Problem parsing in-kernel X.509 certificate list\n");
return 0;
 }
+
+__init int load_module_cert(struct key *keyring)
+{
+   const u8 *p, *end;
+
+   if (!IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG))
+   return 0;
+
+   pr_notice("Loading compiled-in module X.509 certificates\n");
+
+   p = system_certificate_list;
+   end = p + module_cert_size;
+
+   return load_cert(p, end, keyring);
+}
+
+/*
+ * Load the compiled-in list of X.509 certificates.
+ */
+static __init int load_system_certificate_list(void)
+{
+   const u8 *p, *end;
+
+   pr_notice("Loading compiled-in X.509 certificates\n");
+
+#ifdef CONFIG_MODULE_SIG
+   p = system_certificate_list;
+#else
+   p = system_certificate_list + module_cert_size;
+#endif
+
+   end = p + system_certificate_list_size;
+   return load_cert(p, end, builtin_trusted_keys);
+}
 late_initcall(load_system_certificate_list);
 
 #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index fb8b07daa9d1..f954276c616a 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -16,9 +16,16 @@ extern int restrict_link_by_builtin_trusted(struct key 
*keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key);
+extern __init int load_module_cert(struct key *keyring);
 
 #else
 #define restrict_link_by_builtin_trusted restrict_link_reject
+
+static inline __init int load_module_cert(struct key *keyring)
+{
+   return 0;
+}
+
 #endif
 
 #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 250fb0836156..3b06a01bd0fd 100644
--- a/security/integri

[PATCH v3 2/3] ima: enable signing of modules with build time generated key

2021-03-30 Thread Nayna Jain
The kernel build process currently only signs kernel modules when
MODULE_SIG is enabled. Also, sign the kernel modules at build time when
IMA_APPRAISE_MODSIG is enabled.

Signed-off-by: Nayna Jain 
---
 certs/Kconfig  | 2 +-
 certs/Makefile | 8 
 init/Kconfig   | 6 +++---
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/certs/Kconfig b/certs/Kconfig
index c94e93d8bccf..48675ad319db 100644
--- a/certs/Kconfig
+++ b/certs/Kconfig
@@ -4,7 +4,7 @@ menu "Certificates for signature checking"
 config MODULE_SIG_KEY
string "File name or PKCS#11 URI of module signing key"
default "certs/signing_key.pem"
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  Provide the file name of a private key/certificate in PEM format,
  or a PKCS#11 URI according to RFC7512. The file should contain, or
diff --git a/certs/Makefile b/certs/Makefile
index f4c25b67aad9..e3185c57fbd8 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -32,6 +32,14 @@ endif # CONFIG_SYSTEM_TRUSTED_KEYRING
 clean-files := x509_certificate_list .x509.list
 
 ifeq ($(CONFIG_MODULE_SIG),y)
+   SIGN_KEY = y
+endif
+
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+   SIGN_KEY = y
+endif
+
+ifdef SIGN_KEY
 ###
 #
 # If module signing is requested, say by allyesconfig, but a key has not been
diff --git a/init/Kconfig b/init/Kconfig
index 5f5c776ef192..85e48a578f90 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2164,7 +2164,7 @@ config MODULE_SIG_FORCE
 config MODULE_SIG_ALL
bool "Automatically sign all modules"
default y
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  Sign all modules during make modules_install. Without this option,
  modules must be signed manually, using the scripts/sign-file tool.
@@ -2174,7 +2174,7 @@ comment "Do not forget to sign required modules with 
scripts/sign-file"
 
 choice
prompt "Which hash algorithm should modules be signed with?"
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  This determines which sort of hashing algorithm will be used during
  signature generation.  This algorithm _must_ be built into the kernel
@@ -2206,7 +2206,7 @@ endchoice
 
 config MODULE_SIG_HASH
string
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
default "sha1" if MODULE_SIG_SHA1
default "sha224" if MODULE_SIG_SHA224
default "sha256" if MODULE_SIG_SHA256
-- 
2.29.2



[PATCH v3 1/3] keys: cleanup build time module signing keys

2021-03-30 Thread Nayna Jain
The "mrproper" target is still looking for build time generated keys in
the kernel root directory instead of certs directory. Fix the path and
remove the names of the files which are no longer generated.

Fixes: cfc411e7fff3 ("Move certificate handling to its own directory")
Signed-off-by: Nayna Jain 
Reviewed-by: Stefan Berger 
Reviewed-by: Mimi Zohar 
---
 Makefile | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index d4784d181123..b7c2ed2a8684 100644
--- a/Makefile
+++ b/Makefile
@@ -1523,9 +1523,9 @@ MRPROPER_FILES += include/config include/generated
  \
  debian snap tar-install \
  .config .config.old .version \
  Module.symvers \
- signing_key.pem signing_key.priv signing_key.x509 \
- x509.genkey extra_certificates signing_key.x509.keyid \
- signing_key.x509.signer vmlinux-gdb.py \
+ certs/signing_key.pem certs/signing_key.x509 \
+ certs/x509.genkey \
+ vmlinux-gdb.py \
  *.spec
 
 # Directories & files removed with 'make distclean'
-- 
2.29.2



[PATCH v2 5/5] ima: enable loading of build time generated key on .ima keyring

2021-02-18 Thread Nayna Jain
The kernel currently only loads the kernel module signing key onto
the builtin trusted keyring. To support IMA, load the module signing
key selectively either onto the builtin or IMA keyring based on MODULE_SIG
or MODULE_APPRAISE_MODSIG config respectively; and loads the CA kernel
key onto the builtin trusted keyring.

Signed-off-by: Nayna Jain 
---
 certs/system_keyring.c| 55 ++-
 include/keys/system_keyring.h |  9 +-
 security/integrity/digsig.c   |  4 +++
 3 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index 798291177186..ea3826627729 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -26,6 +26,7 @@ static struct key *platform_trusted_keys;
 
 extern __initconst const u8 system_certificate_list[];
 extern __initconst const unsigned long system_certificate_list_size;
+extern __initconst const unsigned long module_cert_size;
 
 /**
  * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
@@ -131,19 +132,12 @@ static __init int system_trusted_keyring_init(void)
  */
 device_initcall(system_trusted_keyring_init);
 
-/*
- * Load the compiled-in list of X.509 certificates.
- */
-static __init int load_system_certificate_list(void)
+static __init int load_cert(const u8 *p, const u8 *end, struct key *keyring,
+   unsigned long flags)
 {
key_ref_t key;
-   const u8 *p, *end;
size_t plen;
 
-   pr_notice("Loading compiled-in X.509 certificates\n");
-
-   p = system_certificate_list;
-   end = p + system_certificate_list_size;
while (p < end) {
/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
 * than 256 bytes in size.
@@ -158,16 +152,15 @@ static __init int load_system_certificate_list(void)
if (plen > end - p)
goto dodgy_cert;
 
-   key = key_create_or_update(make_key_ref(builtin_trusted_keys, 
1),
+   key = key_create_or_update(make_key_ref(keyring, 1),
   "asymmetric",
   NULL,
   p,
   plen,
   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
   KEY_USR_VIEW | KEY_USR_READ),
-  KEY_ALLOC_NOT_IN_QUOTA |
-  KEY_ALLOC_BUILT_IN |
-  KEY_ALLOC_BYPASS_RESTRICTION);
+  flags);
+
if (IS_ERR(key)) {
pr_err("Problem loading in-kernel X.509 certificate 
(%ld)\n",
   PTR_ERR(key));
@@ -185,6 +178,42 @@ static __init int load_system_certificate_list(void)
pr_err("Problem parsing in-kernel X.509 certificate list\n");
return 0;
 }
+
+__init int load_module_cert(struct key *keyring, unsigned long flags)
+{
+   const u8 *p, *end;
+
+   if (!IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG))
+   return 0;
+
+   pr_notice("Loading compiled-in module X.509 certificates\n");
+
+   p = system_certificate_list;
+   end = p + module_cert_size;
+
+   return load_cert(p, end, keyring, flags);
+}
+
+/*
+ * Load the compiled-in list of X.509 certificates.
+ */
+static __init int load_system_certificate_list(void)
+{
+   const u8 *p, *end;
+
+   pr_notice("Loading compiled-in X.509 certificates\n");
+
+#ifdef CONFIG_MODULE_SIG
+   p = system_certificate_list;
+#else
+   p = system_certificate_list + module_cert_size;
+#endif
+   end = p + system_certificate_list_size;
+
+   return load_cert(p, end, builtin_trusted_keys, KEY_ALLOC_NOT_IN_QUOTA |
+   KEY_ALLOC_BUILT_IN |
+   KEY_ALLOC_BYPASS_RESTRICTION);
+}
 late_initcall(load_system_certificate_list);
 
 #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index fb8b07daa9d1..e91c03376599 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -16,9 +16,16 @@ extern int restrict_link_by_builtin_trusted(struct key 
*keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key);
-
+extern __init int load_module_cert(struct key *keyring, unsigned long flags);
 #else
 #define restrict_link_by_builtin_trusted restrict_link_reject
+
+static inline __init int load_module_cert(struct key *keyring,
+   

[PATCH v2 4/5] keys: define build time generated ephemeral kernel CA key

2021-02-18 Thread Nayna Jain
Certificates being loaded onto the IMA trusted keyring must be signed by
a key on either the builtin or secondary trusted keyring. Create and
include in the kernel image an ephemeral CA key at build time when
IMA_APPRAISE_MODSIG is enabled.

Reported-by: kernel test robot  (redirect openssl stderr)
Signed-off-by: Nayna Jain 
---
 Makefile|  2 ++
 certs/Makefile  | 68 ++---
 certs/system_certificates.S | 16 -
 3 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index a971d4ae40bd..15e8344836b1 100644
--- a/Makefile
+++ b/Makefile
@@ -1475,6 +1475,8 @@ MRPROPER_FILES += include/config include/generated
  \
  certs/signing_key.pem certs/signing_key.x509 \
  certs/x509.genkey certs/signing_key.key \
  certs/signing_key.crt certs/signing_key.csr \
+ certs/ca_signing_key.pem certs/ca_signing_key.x509 \
+ certs/ca_signing_key.srl \
  vmlinux-gdb.py \
  *.spec
 
diff --git a/certs/Makefile b/certs/Makefile
index b2be7eb413d3..3fe6b73786fa 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -32,6 +32,14 @@ endif # CONFIG_SYSTEM_TRUSTED_KEYRING
 clean-files := x509_certificate_list .x509.list
 
 ifeq ($(CONFIG_MODULE_SIG),y)
+SIGN_KEY = y
+endif
+
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+SIGN_KEY = y
+endif
+
+ifdef SIGN_KEY
 ###
 #
 # If module signing is requested, say by allyesconfig, but a key has not been
@@ -51,6 +59,16 @@ silent_redirect_openssl = 2>/dev/null
 # 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")
+
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+# openssl arguments for CA Signed certificate.
+CA_KEY = certs/ca_signing_key.pem
+SIGNER = -CA $(CA_KEY) -CAkey $(CA_KEY) -CAcreateserial
+else
+# openssl arguments for Self Signed certificate.
+SIGNER = -signkey $(obj)/signing_key.key
+endif # CONFIG_IMA_APPRAISE_MODSIG
+
 $(obj)/signing_key.pem: $(obj)/x509.genkey
@$(kecho) "###"
@$(kecho) "### Now generating an X.509 key pair to be used for signing 
modules."
@@ -60,14 +78,23 @@ $(obj)/signing_key.pem: $(obj)/x509.genkey
@$(kecho) "### needs to be run as root, and uses a hardware random"
@$(kecho) "### number generator if one is available."
@$(kecho) "###"
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+   # Generate kernel build time CA Certificate.
+   @$(Q)openssl req -new -nodes -utf8 \
+   -$(CONFIG_MODULE_SIG_HASH) -days 36500 \
+   -subj "/CN=Build time autogenerated kernel CA key" \
+   -batch -x509 -config $(obj)/x509.genkey \
+   -outform PEM -out $(CA_KEY) \
+   -keyout $(CA_KEY) -extensions ca_ext \
+   $($(quiet)redirect_openssl)
+endif # CONFIG_IMA_APPRAISE_MODSIG
$(Q)openssl req -new -nodes -utf8 \
-batch -config $(obj)/x509.genkey \
-outform PEM -out $(obj)/signing_key.csr \
-keyout $(obj)/signing_key.key -extensions myexts \
$($(quiet)redirect_openssl)
$(Q)openssl x509 -req -days 36500 -in $(obj)/signing_key.csr \
-   -outform PEM -out $(obj)/signing_key.crt \
-   -signkey $(obj)/signing_key.key \
+   -outform PEM -out $(obj)/signing_key.crt $(SIGNER) \
-$(CONFIG_MODULE_SIG_HASH) -extensions myexts \
-extfile $(obj)/x509.genkey \
$($(quiet)redirect_openssl)
@@ -95,19 +122,50 @@ $(obj)/x509.genkey:
@echo >>$@ "keyUsage=digitalSignature"
@echo >>$@ "subjectKeyIdentifier=hash"
@echo >>$@ "authorityKeyIdentifier=keyid"
+   @echo >>$@
+   @echo >>$@ "[ ca_ext ]"
+   @echo >>$@ "keyUsage=critical,keyCertSign"
+   @echo >>$@ "basicConstraints=critical,CA:TRUE,pathlen:0"
+   @echo >>$@ "subjectKeyIdentifier=hash"
+   @echo >>$@ "authorityKeyIdentifier=keyid"
 endif # CONFIG_MODULE_SIG_KEY
 
 $(eval $(call config_filename,MODULE_SIG_KEY))
+SUBJECT=CN = Build time autogenerated kernel key
+ISSUER=$(shell openssl x509 -in certs/signing_key.crt -noout -issuer 
$($(quiet)redirect_openssl))
 
 # If CONFIG_MODULE_SIG_KEY isn't a PKCS#11 URI, depend on it
+
+# GCC PR#66871 again.
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+
+# Remove existing keys if it is self-signed.
+$(if $(findstring $(SUBJECT),$(ISSUER)),$(shell rm -f certs/signing_key.* 
certs/x509.genkey))
+CA_KEY = certs/ca_signing_key.pem
+
+$(obj)/system_certificates.o: $(obj)/

[PATCH v2 3/5] ima: update kernel module signing process during build

2021-02-18 Thread Nayna Jain
The kernel build process currently only signs kernel modules when
MODULE_SIG is enabled. Also, sign the kernel modules at build time when
IMA_APPRAISE_MODSIG is enabled.

Signed-off-by: Nayna Jain 
---
 certs/Kconfig | 2 +-
 init/Kconfig  | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/certs/Kconfig b/certs/Kconfig
index c94e93d8bccf..48675ad319db 100644
--- a/certs/Kconfig
+++ b/certs/Kconfig
@@ -4,7 +4,7 @@ menu "Certificates for signature checking"
 config MODULE_SIG_KEY
string "File name or PKCS#11 URI of module signing key"
default "certs/signing_key.pem"
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  Provide the file name of a private key/certificate in PEM format,
  or a PKCS#11 URI according to RFC7512. The file should contain, or
diff --git a/init/Kconfig b/init/Kconfig
index 29ad68325028..68147bbda5f9 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2162,7 +2162,7 @@ config MODULE_SIG_FORCE
 config MODULE_SIG_ALL
bool "Automatically sign all modules"
default y
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  Sign all modules during make modules_install. Without this option,
  modules must be signed manually, using the scripts/sign-file tool.
@@ -2172,7 +2172,7 @@ comment "Do not forget to sign required modules with 
scripts/sign-file"
 
 choice
prompt "Which hash algorithm should modules be signed with?"
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  This determines which sort of hashing algorithm will be used during
  signature generation.  This algorithm _must_ be built into the kernel
@@ -2204,7 +2204,7 @@ endchoice
 
 config MODULE_SIG_HASH
string
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
default "sha1" if MODULE_SIG_SHA1
default "sha224" if MODULE_SIG_SHA224
default "sha256" if MODULE_SIG_SHA256
-- 
2.29.2



[PATCH v2 0/5] ima: kernel build support for loading the kernel module signing key

2021-02-18 Thread Nayna Jain
Kernel modules are currently only signed when CONFIG_MODULE_SIG is enabled.
The kernel module signing key is a self-signed CA only loaded onto the
.builtin_trusted_key keyring.  On secure boot enabled systems with an arch
specific IMA policy enabled, but without MODULE_SIG enabled, kernel modules
are not signed, nor is the kernel module signing public key loaded onto the
IMA keyring.

In order to load the the kernel module signing key onto the IMA trusted
keyring ('.ima'), the certificate needs to be signed by a CA key either on
the builtin or secondary keyrings.  This series of patches enables IMA
verification of signed kernel modules by:

* Defining a kernel CA key. The CA key signs the kernel module signing key
and is loaded onto the .builtin_trusted_key keyring, only when the kernel
module signing key is loaded onto the .ima keyring.

* Enable module signing at build time for IMA_APPRAISE_MODSIG as well

v2:

* Include feedback from Stefan - corrected the Fixes commit id in Patch 1
and cleaned Patch 5/5.
* Fix the issue reported by kernel test bot.
* Include Jarkko's feedback on patch description.

Nayna Jain (5):
  keys: cleanup build time module signing keys
  keys: generate self-signed module signing key using CSR
  ima: update kernel module signing process during build
  keys: define build time generated ephemeral kernel CA key
  ima: enable loading of build time generated key on .ima keyring

 Makefile  |  9 ++--
 certs/Kconfig |  2 +-
 certs/Makefile| 77 ---
 certs/system_certificates.S   | 16 +++-
 certs/system_keyring.c| 55 +++--
 include/keys/system_keyring.h |  9 +++-
 init/Kconfig  |  6 +--
 security/integrity/digsig.c   |  4 ++
 8 files changed, 150 insertions(+), 28 deletions(-)

-- 
2.29.2


[PATCH v2 2/5] keys: generate self-signed module signing key using CSR

2021-02-18 Thread Nayna Jain
Loading a key on the IMA trusted keyring requires the key be signed
by an existing key on the builtin or secondary trusted keyring.
Creating a Certificate Signing Request (CSR) allows the certificate
to be self-signed or signed by a CA.

Generate a self-signed module signing key using CSR.

Signed-off-by: Nayna Jain 
---
 Makefile   |  3 ++-
 certs/Makefile | 15 +++
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index 004163a4e6b3..a971d4ae40bd 100644
--- a/Makefile
+++ b/Makefile
@@ -1473,7 +1473,8 @@ MRPROPER_FILES += include/config include/generated
  \
  .config .config.old .version \
  Module.symvers \
  certs/signing_key.pem certs/signing_key.x509 \
- certs/x509.genkey \
+ certs/x509.genkey certs/signing_key.key \
+ certs/signing_key.crt certs/signing_key.csr \
  vmlinux-gdb.py \
  *.spec
 
diff --git a/certs/Makefile b/certs/Makefile
index f4c25b67aad9..b2be7eb413d3 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -60,11 +60,18 @@ $(obj)/signing_key.pem: $(obj)/x509.genkey
@$(kecho) "### needs to be run as root, and uses a hardware random"
@$(kecho) "### number generator if one is available."
@$(kecho) "###"
-   $(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 \
+   $(Q)openssl req -new -nodes -utf8 \
+   -batch -config $(obj)/x509.genkey \
+   -outform PEM -out $(obj)/signing_key.csr \
+   -keyout $(obj)/signing_key.key -extensions myexts \
$($(quiet)redirect_openssl)
+   $(Q)openssl x509 -req -days 36500 -in $(obj)/signing_key.csr \
+   -outform PEM -out $(obj)/signing_key.crt \
+   -signkey $(obj)/signing_key.key \
+   -$(CONFIG_MODULE_SIG_HASH) -extensions myexts \
+   -extfile $(obj)/x509.genkey \
+   $($(quiet)redirect_openssl)
+   @cat $(obj)/signing_key.key $(obj)/signing_key.crt >> 
$(obj)/signing_key.pem
@$(kecho) "###"
@$(kecho) "### Key pair generated."
@$(kecho) "###"
-- 
2.29.2



[PATCH v2 1/5] keys: cleanup build time module signing keys

2021-02-18 Thread Nayna Jain
The "mrproper" target is still looking for build time generated keys in
the old path instead of certs/ directory. Fix the path and remove the
names of the files which are no longer generated.

Fixes: fb1179499134 ("modsign: Use single PEM file for autogenerated key")
Signed-off-by: Nayna Jain 
---
 Makefile | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index de1acaefe87e..004163a4e6b3 100644
--- a/Makefile
+++ b/Makefile
@@ -1472,9 +1472,9 @@ MRPROPER_FILES += include/config include/generated
  \
  debian snap tar-install \
  .config .config.old .version \
  Module.symvers \
- signing_key.pem signing_key.priv signing_key.x509 \
- x509.genkey extra_certificates signing_key.x509.keyid \
- signing_key.x509.signer vmlinux-gdb.py \
+ certs/signing_key.pem certs/signing_key.x509 \
+ certs/x509.genkey \
+ vmlinux-gdb.py \
  *.spec
 
 # Directories & files removed with 'make distclean'
-- 
2.29.2



[PATCH 5/5] ima: enable loading of build time generated key to .ima keyring

2021-02-11 Thread Nayna Jain
The kernel currently only loads the kernel module signing key onto
the builtin trusted keyring. To support IMA, load the module signing
key selectively either onto builtin or ima keyring based on MODULE_SIG
or MODULE_APPRAISE_MODSIG config respectively; and loads the CA kernel
key onto builtin trusted keyring.

Signed-off-by: Nayna Jain 
---
 certs/system_keyring.c| 56 +++
 include/keys/system_keyring.h |  9 +-
 security/integrity/digsig.c   |  4 +++
 3 files changed, 55 insertions(+), 14 deletions(-)

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index 798291177186..0bbbe501f8a7 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -26,6 +26,7 @@ static struct key *platform_trusted_keys;
 
 extern __initconst const u8 system_certificate_list[];
 extern __initconst const unsigned long system_certificate_list_size;
+extern __initconst const unsigned long module_cert_size;
 
 /**
  * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
@@ -131,19 +132,12 @@ static __init int system_trusted_keyring_init(void)
  */
 device_initcall(system_trusted_keyring_init);
 
-/*
- * Load the compiled-in list of X.509 certificates.
- */
-static __init int load_system_certificate_list(void)
+static __init int load_cert(const u8 *p, const u8 *end, struct key *keyring,
+   unsigned long flags)
 {
key_ref_t key;
-   const u8 *p, *end;
size_t plen;
 
-   pr_notice("Loading compiled-in X.509 certificates\n");
-
-   p = system_certificate_list;
-   end = p + system_certificate_list_size;
while (p < end) {
/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
 * than 256 bytes in size.
@@ -158,16 +152,15 @@ static __init int load_system_certificate_list(void)
if (plen > end - p)
goto dodgy_cert;
 
-   key = key_create_or_update(make_key_ref(builtin_trusted_keys, 
1),
+   key = key_create_or_update(make_key_ref(keyring, 1),
   "asymmetric",
   NULL,
   p,
   plen,
   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
   KEY_USR_VIEW | KEY_USR_READ),
-  KEY_ALLOC_NOT_IN_QUOTA |
-  KEY_ALLOC_BUILT_IN |
-  KEY_ALLOC_BYPASS_RESTRICTION);
+  flags);
+
if (IS_ERR(key)) {
pr_err("Problem loading in-kernel X.509 certificate 
(%ld)\n",
   PTR_ERR(key));
@@ -185,6 +178,43 @@ static __init int load_system_certificate_list(void)
pr_err("Problem parsing in-kernel X.509 certificate list\n");
return 0;
 }
+
+__init int load_module_cert(struct key *keyring, unsigned long flags)
+{
+   const u8 *p, *end;
+
+   if (!IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG))
+   return 0;
+
+   pr_notice("Loading compiled-in module X.509 certificates\n");
+
+   p = system_certificate_list;
+   end = p + module_cert_size;
+   load_cert(p, end, keyring, flags);
+
+   return 0;
+}
+
+/*
+ * Load the compiled-in list of X.509 certificates.
+ */
+static __init int load_system_certificate_list(void)
+{
+   const u8 *p, *end;
+
+   pr_notice("Loading compiled-in X.509 certificates\n");
+
+#ifdef CONFIG_MODULE_SIG
+   p = system_certificate_list;
+#else
+   p = system_certificate_list + module_cert_size;
+#endif
+   end = p + system_certificate_list_size;
+   load_cert(p, end, builtin_trusted_keys, KEY_ALLOC_NOT_IN_QUOTA |
+   KEY_ALLOC_BUILT_IN |
+   KEY_ALLOC_BYPASS_RESTRICTION);
+   return 0;
+}
 late_initcall(load_system_certificate_list);
 
 #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index fb8b07daa9d1..e91c03376599 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -16,9 +16,16 @@ extern int restrict_link_by_builtin_trusted(struct key 
*keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key);
-
+extern __init int load_module_cert(struct key *keyring, unsigned long flags);
 #else
 #define restrict_link_by_builtin_trusted restrict_link_reject
+
+static inline __init int load_module_cert(struct key *keyring,
+   

[PATCH 4/5] keys: define build time generated ephemeral kernel CA key

2021-02-11 Thread Nayna Jain
Certificates being loaded onto the IMA trusted keyring must be signed by
a key on either the builtin and secondary trusted keyring.

This patch creates and includes in the kernel image an ephemeral CA
key, at build time when IMA_APPRAISE_MODSIG is enabled.

Signed-off-by: Nayna Jain 
---
 Makefile|  2 ++
 certs/Makefile  | 68 ++---
 certs/system_certificates.S | 16 -
 3 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 9c87fdd600d8..a1d4b0a1745e 100644
--- a/Makefile
+++ b/Makefile
@@ -1475,6 +1475,8 @@ MRPROPER_FILES += include/config include/generated
  \
  certs/signing_key.pem certs/signing_key.x509 \
  certs/x509.genkey certs/signing_key.key \
  certs/signing_key.crt certs/signing_key.csr \
+ certs/ca_signing_key.pem certs/ca_signing_key.x509 \
+ certs/ca_signing_key.srl \
  vmlinux-gdb.py \
  *.spec
 
diff --git a/certs/Makefile b/certs/Makefile
index b2be7eb413d3..c3592ba63a05 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -32,6 +32,14 @@ endif # CONFIG_SYSTEM_TRUSTED_KEYRING
 clean-files := x509_certificate_list .x509.list
 
 ifeq ($(CONFIG_MODULE_SIG),y)
+SIGN_KEY = y
+endif
+
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+SIGN_KEY = y
+endif
+
+ifdef SIGN_KEY
 ###
 #
 # If module signing is requested, say by allyesconfig, but a key has not been
@@ -51,6 +59,16 @@ silent_redirect_openssl = 2>/dev/null
 # 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")
+
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+# openssl arguments for CA Signed certificate.
+CA_KEY = certs/ca_signing_key.pem
+SIGNER = -CA $(CA_KEY) -CAkey $(CA_KEY) -CAcreateserial
+else
+# openssl arguments for Self Signed certificate.
+SIGNER = -signkey $(obj)/signing_key.key
+endif # CONFIG_IMA_APPRAISE_MODSIG
+
 $(obj)/signing_key.pem: $(obj)/x509.genkey
@$(kecho) "###"
@$(kecho) "### Now generating an X.509 key pair to be used for signing 
modules."
@@ -60,14 +78,23 @@ $(obj)/signing_key.pem: $(obj)/x509.genkey
@$(kecho) "### needs to be run as root, and uses a hardware random"
@$(kecho) "### number generator if one is available."
@$(kecho) "###"
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+   # Generate kernel build time CA Certificate.
+   @$(Q)openssl req -new -nodes -utf8 \
+   -$(CONFIG_MODULE_SIG_HASH) -days 36500 \
+   -subj "/CN=Build time autogenerated kernel CA key" \
+   -batch -x509 -config $(obj)/x509.genkey \
+   -outform PEM -out $(CA_KEY) \
+   -keyout $(CA_KEY) -extensions ca_ext \
+   $($(quiet)redirect_openssl)
+endif # CONFIG_IMA_APPRAISE_MODSIG
$(Q)openssl req -new -nodes -utf8 \
-batch -config $(obj)/x509.genkey \
-outform PEM -out $(obj)/signing_key.csr \
-keyout $(obj)/signing_key.key -extensions myexts \
$($(quiet)redirect_openssl)
$(Q)openssl x509 -req -days 36500 -in $(obj)/signing_key.csr \
-   -outform PEM -out $(obj)/signing_key.crt \
-   -signkey $(obj)/signing_key.key \
+   -outform PEM -out $(obj)/signing_key.crt $(SIGNER) \
-$(CONFIG_MODULE_SIG_HASH) -extensions myexts \
-extfile $(obj)/x509.genkey \
$($(quiet)redirect_openssl)
@@ -95,19 +122,50 @@ $(obj)/x509.genkey:
@echo >>$@ "keyUsage=digitalSignature"
@echo >>$@ "subjectKeyIdentifier=hash"
@echo >>$@ "authorityKeyIdentifier=keyid"
+   @echo >>$@
+   @echo >>$@ "[ ca_ext ]"
+   @echo >>$@ "keyUsage=critical,keyCertSign"
+   @echo >>$@ "basicConstraints=critical,CA:TRUE,pathlen:0"
+   @echo >>$@ "subjectKeyIdentifier=hash"
+   @echo >>$@ "authorityKeyIdentifier=keyid"
 endif # CONFIG_MODULE_SIG_KEY
 
 $(eval $(call config_filename,MODULE_SIG_KEY))
+SUBJECT=CN = Build time autogenerated kernel key
+ISSUER=$(shell openssl x509 -in certs/signing_key.crt -noout -issuer)
 
 # If CONFIG_MODULE_SIG_KEY isn't a PKCS#11 URI, depend on it
+
+# GCC PR#66871 again.
+ifeq ($(CONFIG_IMA_APPRAISE_MODSIG),y)
+
+# Remove existing keys if it is self-signed.
+$(if $(findstring $(SUBJECT),$(ISSUER)),$(shell rm -f certs/signing_key.* 
certs/x509.genkey))
+CA_KEY = certs/ca_signing_key.pem
+
+$(obj)/system_certificates.o: $(obj)/ca_signing_key.x509 
$(obj)/signing_key.x509
+
+targets += ca_sig

[PATCH 3/5] ima: update kernel module signing process during build

2021-02-11 Thread Nayna Jain
The kernel build process currently only signs kernel modules when
MODULE_SIG is enabled. Also, sign the kernel modules at build time when
IMA_APPRAISE_MODSIG is enabled.

Signed-off-by: Nayna Jain 
---
 certs/Kconfig | 2 +-
 init/Kconfig  | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/certs/Kconfig b/certs/Kconfig
index c94e93d8bccf..48675ad319db 100644
--- a/certs/Kconfig
+++ b/certs/Kconfig
@@ -4,7 +4,7 @@ menu "Certificates for signature checking"
 config MODULE_SIG_KEY
string "File name or PKCS#11 URI of module signing key"
default "certs/signing_key.pem"
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  Provide the file name of a private key/certificate in PEM format,
  or a PKCS#11 URI according to RFC7512. The file should contain, or
diff --git a/init/Kconfig b/init/Kconfig
index 29ad68325028..68147bbda5f9 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -2162,7 +2162,7 @@ config MODULE_SIG_FORCE
 config MODULE_SIG_ALL
bool "Automatically sign all modules"
default y
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  Sign all modules during make modules_install. Without this option,
  modules must be signed manually, using the scripts/sign-file tool.
@@ -2172,7 +2172,7 @@ comment "Do not forget to sign required modules with 
scripts/sign-file"
 
 choice
prompt "Which hash algorithm should modules be signed with?"
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
help
  This determines which sort of hashing algorithm will be used during
  signature generation.  This algorithm _must_ be built into the kernel
@@ -2204,7 +2204,7 @@ endchoice
 
 config MODULE_SIG_HASH
string
-   depends on MODULE_SIG
+   depends on MODULE_SIG || IMA_APPRAISE_MODSIG
default "sha1" if MODULE_SIG_SHA1
default "sha224" if MODULE_SIG_SHA224
default "sha256" if MODULE_SIG_SHA256
-- 
2.18.1



[PATCH 2/5] keys: generate self-signed module signing key using CSR

2021-02-11 Thread Nayna Jain
Loading a key on the IMA trusted keyring requires the key be signed
by an existing key on the builtin or secondary trusted keyring.
Creating a Certificate Signing Request (CSR) allows the certificate
to be self-signed or signed by a CA.

This patch generates a self-signed module signing key using CSR.

Signed-off-by: Nayna Jain 
---
 Makefile   |  3 ++-
 certs/Makefile | 15 +++
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index af18aab6bbee..9c87fdd600d8 100644
--- a/Makefile
+++ b/Makefile
@@ -1473,7 +1473,8 @@ MRPROPER_FILES += include/config include/generated
  \
  .config .config.old .version \
  Module.symvers \
  certs/signing_key.pem certs/signing_key.x509 \
- certs/x509.genkey \
+ certs/x509.genkey certs/signing_key.key \
+ certs/signing_key.crt certs/signing_key.csr \
  vmlinux-gdb.py \
  *.spec
 
diff --git a/certs/Makefile b/certs/Makefile
index f4c25b67aad9..b2be7eb413d3 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -60,11 +60,18 @@ $(obj)/signing_key.pem: $(obj)/x509.genkey
@$(kecho) "### needs to be run as root, and uses a hardware random"
@$(kecho) "### number generator if one is available."
@$(kecho) "###"
-   $(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 \
+   $(Q)openssl req -new -nodes -utf8 \
+   -batch -config $(obj)/x509.genkey \
+   -outform PEM -out $(obj)/signing_key.csr \
+   -keyout $(obj)/signing_key.key -extensions myexts \
$($(quiet)redirect_openssl)
+   $(Q)openssl x509 -req -days 36500 -in $(obj)/signing_key.csr \
+   -outform PEM -out $(obj)/signing_key.crt \
+   -signkey $(obj)/signing_key.key \
+   -$(CONFIG_MODULE_SIG_HASH) -extensions myexts \
+   -extfile $(obj)/x509.genkey \
+   $($(quiet)redirect_openssl)
+   @cat $(obj)/signing_key.key $(obj)/signing_key.crt >> 
$(obj)/signing_key.pem
@$(kecho) "###"
@$(kecho) "### Key pair generated."
@$(kecho) "###"
-- 
2.18.1



[PATCH 1/5] keys: cleanup build time module signing keys

2021-02-11 Thread Nayna Jain
The "mrproper" target is still looking for build time generated keys
in the old path instead of certs/ directory.
This patch fixes the path as well removes the names of the files which
are no longer generated.

Signed-off-by: Nayna Jain 
Fixes: 28a68f828266 ("modsign: Use single PEM file for autogenerated key")
---
 Makefile | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index ade44ac4cc2f..af18aab6bbee 100644
--- a/Makefile
+++ b/Makefile
@@ -1472,9 +1472,9 @@ MRPROPER_FILES += include/config include/generated
  \
  debian snap tar-install \
  .config .config.old .version \
  Module.symvers \
- signing_key.pem signing_key.priv signing_key.x509 \
- x509.genkey extra_certificates signing_key.x509.keyid \
- signing_key.x509.signer vmlinux-gdb.py \
+ certs/signing_key.pem certs/signing_key.x509 \
+ certs/x509.genkey \
+ vmlinux-gdb.py \
  *.spec
 
 # Directories & files removed with 'make distclean'
-- 
2.18.1



[PATCH 0/5] ima: kernel build support for loading the kernel module signing key

2021-02-11 Thread Nayna Jain
Kernel modules are currently only signed when CONFIG_MODULE_SIG is enabled.
The kernel module signing key is a self-signed CA only loaded onto the
.builtin_trusted_key keyring.  On secure boot enabled systems with an arch
specific IMA policy enabled, but without MODULE_SIG enabled, kernel modules
are not signed, nor is the kernel module signing public key loaded onto the
IMA keyring.

In order to load the the kernel module signing key onto the IMA trusted
keyring ('.ima'), the certificate needs to be signed by a CA key either on
the builtin or secondary keyrings.  This series of patches enables IMA
verification of signed kernel modules by:

* Defining a kernel CA key. The CA key signs the kernel module signing key
and is loaded onto .builtin_trusted_key keyring, only when the kernel
module signing key is loaded onto the .ima keyring.

* Enable module signing at build time for IMA_APPRAISE_MODSIG as well

Nayna Jain (5):
  keys: cleanup build time module signing keys
  keys: generate self-signed module signing key using CSR
  ima: update kernel module signing process during build
  keys: define build time generated ephemeral kernel CA key
  ima: enable loading of build time generated key to .ima keyring

 Makefile  |  9 ++--
 certs/Kconfig |  2 +-
 certs/Makefile| 77 ---
 certs/system_certificates.S   | 16 +++-
 certs/system_keyring.c| 56 +++--
 include/keys/system_keyring.h |  9 +++-
 init/Kconfig  |  6 +--
 security/integrity/digsig.c   |  4 ++
 8 files changed, 151 insertions(+), 28 deletions(-)

-- 
2.18.1


[PATCH v3] powerpc/pseries: detect secure and trusted boot state of the system.

2020-07-15 Thread Nayna Jain
The device-tree property to check secure and trusted boot state is
different for guests(pseries) compared to baremetal(powernv).

This patch updates the existing is_ppc_secureboot_enabled() and
is_ppc_trustedboot_enabled() functions to add support for pseries.

The secureboot and trustedboot state are exposed via device-tree property:
/proc/device-tree/ibm,secure-boot and /proc/device-tree/ibm,trusted-boot

The values of ibm,secure-boot under pseries are interpreted as:

0 - Disabled
1 - Enabled in Log-only mode. This patch interprets this value as
disabled, since audit mode is currently not supported for Linux.
2 - Enabled and enforced.
3-9 - Enabled and enforcing; requirements are at the discretion of the
operating system.

The values of ibm,trusted-boot under pseries are interpreted as:
0 - Disabled
1 - Enabled

Signed-off-by: Nayna Jain 
Reviewed-by: Daniel Axtens 
---
v3:
* fixed double check. Thanks Daniel for noticing it.
* updated patch description.

v2:
* included Michael Ellerman's feedback.
* added Daniel Axtens's Reviewed-by.

 arch/powerpc/kernel/secure_boot.c | 19 +--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
index 4b982324d368..118bcb5f79c4 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct device_node *get_ppc_fw_sb_node(void)
 {
@@ -23,12 +24,19 @@ bool is_ppc_secureboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   u32 secureboot;
 
node = get_ppc_fw_sb_node();
enabled = of_property_read_bool(node, "os-secureboot-enforcing");
-
of_node_put(node);
 
+   if (enabled)
+   goto out;
+
+   if (!of_property_read_u32(of_root, "ibm,secure-boot", ))
+   enabled = (secureboot > 1);
+
+out:
pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
 
return enabled;
@@ -38,12 +46,19 @@ bool is_ppc_trustedboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   u32 trustedboot;
 
node = get_ppc_fw_sb_node();
enabled = of_property_read_bool(node, "trusted-enabled");
-
of_node_put(node);
 
+   if (enabled)
+   goto out;
+
+   if (!of_property_read_u32(of_root, "ibm,trusted-boot", ))
+   enabled = (trustedboot > 0);
+
+out:
pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
 
return enabled;
-- 
2.26.2



[PATCH v2] powerpc/pseries: detect secure and trusted boot state of the system.

2020-07-10 Thread Nayna Jain
The device-tree property to check secure and trusted boot state is
different for guests(pseries) compared to baremetal(powernv).

This patch updates the existing is_ppc_secureboot_enabled() and
is_ppc_trustedboot_enabled() function to add support for pseries.

Signed-off-by: Nayna Jain 
Reviewed-by: Daniel Axtens 
---
v2:
* included Michael Ellerman's feedback.
* added Daniel Axtens's Reviewed-by.

 arch/powerpc/kernel/secure_boot.c | 23 +--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
index 4b982324d368..efb325cbd42f 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct device_node *get_ppc_fw_sb_node(void)
 {
@@ -23,12 +24,21 @@ bool is_ppc_secureboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   u32 secureboot;
 
node = get_ppc_fw_sb_node();
enabled = of_property_read_bool(node, "os-secureboot-enforcing");
-
of_node_put(node);
 
+   if (enabled)
+   goto out;
+
+   if (!of_property_read_u32(of_root, "ibm,secure-boot", )) {
+   if (secureboot)
+   enabled = (secureboot > 1) ? true : false;
+   }
+
+out:
pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
 
return enabled;
@@ -38,12 +48,21 @@ bool is_ppc_trustedboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   u32 trustedboot;
 
node = get_ppc_fw_sb_node();
enabled = of_property_read_bool(node, "trusted-enabled");
-
of_node_put(node);
 
+   if (enabled)
+   goto out;
+
+   if (!of_property_read_u32(of_root, "ibm,trusted-boot", )) {
+   if (trustedboot)
+   enabled = (trustedboot > 0) ? true : false;
+   }
+
+out:
pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
 
return enabled;
-- 
2.26.2



[PATCH] powerpc/pseries: detect secure and trusted boot state of the system.

2020-07-04 Thread Nayna Jain
The device-tree property to check secure and trusted boot state is
different for guests(pseries) compared to baremetal(powernv).

This patch updates the existing is_ppc_secureboot_enabled() and
is_ppc_trustedboot_enabled() function to add support for pseries.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/kernel/secure_boot.c | 31 +--
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
index 4b982324d368..43fc6607c7a5 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct device_node *get_ppc_fw_sb_node(void)
 {
@@ -23,11 +24,20 @@ bool is_ppc_secureboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   const u32 *secureboot;
 
-   node = get_ppc_fw_sb_node();
-   enabled = of_property_read_bool(node, "os-secureboot-enforcing");
+   if (machine_is(powernv)) {
+   node = get_ppc_fw_sb_node();
+   enabled =
+   of_property_read_bool(node, "os-secureboot-enforcing");
+   of_node_put(node);
+   }
 
-   of_node_put(node);
+   if (machine_is(pseries)) {
+   secureboot = of_get_property(of_root, "ibm,secure-boot", NULL);
+   if (secureboot)
+   enabled = (*secureboot > 1) ? true : false;
+   }
 
pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
 
@@ -38,11 +48,20 @@ bool is_ppc_trustedboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   const u32 *trustedboot;
 
-   node = get_ppc_fw_sb_node();
-   enabled = of_property_read_bool(node, "trusted-enabled");
+   if (machine_is(powernv)) {
+   node = get_ppc_fw_sb_node();
+   enabled = of_property_read_bool(node, "trusted-enabled");
+   of_node_put(node);
+   }
 
-   of_node_put(node);
+   if (machine_is(pseries)) {
+   trustedboot =
+   of_get_property(of_root, "ibm,trusted-boot", NULL);
+   if (trustedboot)
+   enabled = (*trustedboot > 0) ? true : false;
+   }
 
pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
 
-- 
2.18.1



[PATCH v2] powerpc/ima: fix secure boot rules in ima arch policy

2020-05-01 Thread Nayna Jain
To prevent verifying the kernel module appended signature twice
(finit_module), once by the module_sig_check() and again by IMA, powerpc
secure boot rules define an IMA architecture specific policy rule
only if CONFIG_MODULE_SIG_FORCE is not enabled. This, unfortunately, does
not take into account the ability of enabling "sig_enforce" on the boot
command line (module.sig_enforce=1).

Including the IMA module appraise rule results in failing the finit_module
syscall, unless the module signing public key is loaded onto the IMA
keyring.

This patch fixes secure boot policy rules to be based on CONFIG_MODULE_SIG
instead.

Fixes: 4238fad366a6 ("powerpc/ima: Add support to initialize ima policy rules")
Signed-off-by: Nayna Jain 
---
v2:
* Fixes the patch description to specify the problem more clearly as asked 
by Michael Ellerman.

 arch/powerpc/kernel/ima_arch.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index e34116255ced..957abd592075 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -19,12 +19,12 @@ bool arch_ima_get_secureboot(void)
  * to be stored as an xattr or as an appended signature.
  *
  * To avoid duplicate signature verification as much as possible, the IMA
- * policy rule for module appraisal is added only if CONFIG_MODULE_SIG_FORCE
+ * policy rule for module appraisal is added only if CONFIG_MODULE_SIG
  * is not enabled.
  */
 static const char *const secure_rules[] = {
"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
-#ifndef CONFIG_MODULE_SIG_FORCE
+#ifndef CONFIG_MODULE_SIG
"appraise func=MODULE_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #endif
NULL
@@ -50,7 +50,7 @@ static const char *const secure_and_trusted_rules[] = {
"measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
"measure func=MODULE_CHECK template=ima-modsig",
"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
-#ifndef CONFIG_MODULE_SIG_FORCE
+#ifndef CONFIG_MODULE_SIG
"appraise func=MODULE_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #endif
NULL
-- 
2.18.1



[PATCH v6 9/9] powerpc/ima: update ima arch policy to check for blacklist

2019-09-27 Thread Nayna Jain
This patch updates the arch specific policies for PowernV systems
to add check against blacklisted hashes before doing the verification.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/kernel/ima_arch.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index 77c61b142042..3f57433c0824 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -24,9 +24,9 @@ bool arch_ima_get_secureboot(void)
 static const char *const arch_rules[] = {
"measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
"measure func=MODULE_CHECK template=ima-modsig",
-   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+   "appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #if !IS_ENABLED(CONFIG_MODULE_SIG)
-   "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+   "appraise func=MODULE_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #endif
NULL
 };
-- 
2.20.1



[PATCH v6 8/9] ima: deprecate permit_directio, instead use appraise_flag

2019-09-27 Thread Nayna Jain
This patch deprecates the existing permit_directio flag, instead adds
it as possible value to appraise_flag parameter.
For eg.
appraise_flag=permit_directio

Signed-off-by: Nayna Jain 
---
 Documentation/ABI/testing/ima_policy | 4 ++--
 security/integrity/ima/ima_policy.c  | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index 4c97afcc0f3c..9a2a140dc561 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -24,8 +24,8 @@ Description:
[euid=] [fowner=] [fsname=]]
lsm:[[subj_user=] [subj_role=] [subj_type=]
 [obj_user=] [obj_role=] [obj_type=]]
-   option: [[appraise_type=]] [template=] [permit_directio]
-   [appraise_flag=[check_blacklist]]
+   option: [[appraise_type=]] [template=] 
[permit_directio(deprecated)]
+   
[appraise_flag=[check_blacklist]|[permit_directio]]
base:   func:= 
[BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index ad3b3af69460..d9df54c75d46 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -1177,6 +1177,8 @@ static int ima_parse_rule(char *rule, struct 
ima_rule_entry *entry)
ima_log_string(ab, "appraise_flag", args[0].from);
if (strstr(args[0].from, "blacklist"))
entry->flags |= IMA_CHECK_BLACKLIST;
+   if (strstr(args[0].from, "permit_directio"))
+   entry->flags |= IMA_PERMIT_DIRECTIO;
break;
case Opt_permit_directio:
entry->flags |= IMA_PERMIT_DIRECTIO;
-- 
2.20.1



[PATCH v5 2/2] powerpc: Add support to initialize ima policy rules

2019-08-19 Thread Nayna Jain
POWER secure boot relies on the kernel IMA security subsystem to
perform the OS kernel image signature verification. Since each secure
boot mode has different IMA policy requirements, dynamic definition of
the policy rules based on the runtime secure boot mode of the system is
required. On systems that support secure boot, but have it disabled,
only measurement policy rules of the kernel image and modules are
defined.

This patch defines the arch-specific implementation to retrieve the
secure boot mode of the system and accordingly configures the IMA policy
rules.

This patch provides arch-specific IMA policies if PPC_SECURE_BOOT
config is enabled.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/Kconfig   |  2 ++
 arch/powerpc/kernel/Makefile   |  2 +-
 arch/powerpc/kernel/ima_arch.c | 50 ++
 include/linux/ima.h|  3 +-
 4 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/kernel/ima_arch.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c902a39124dc..42109682b727 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -917,6 +917,8 @@ config PPC_SECURE_BOOT
bool
default n
depends on PPC64
+   depends on IMA
+   depends on IMA_ARCH_POLICY
help
  Linux on POWER with firmware secure boot enabled needs to define
  security policies to extend secure boot to the OS.This config
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index d310ebb4e526..520b1c814197 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -157,7 +157,7 @@ endif
 obj-$(CONFIG_EPAPR_PARAVIRT)   += epapr_paravirt.o epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)+= kvm.o kvm_emul.o
 
-obj-$(CONFIG_PPC_SECURE_BOOT)  += secboot.o
+obj-$(CONFIG_PPC_SECURE_BOOT)  += secboot.o ima_arch.o
 
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
new file mode 100644
index ..ac90fac83338
--- /dev/null
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * ima_arch.c
+ *  - initialize ima policies for PowerPC Secure Boot
+ */
+
+#include 
+#include 
+
+bool arch_ima_get_secureboot(void)
+{
+   return get_powerpc_secureboot();
+}
+
+/*
+ * File signature verification is not needed, include only measurements
+ */
+static const char *const default_arch_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK",
+   "measure func=MODULE_CHECK",
+   NULL
+};
+
+/* Both file signature verification and measurements are needed */
+static const char *const sb_arch_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+#if IS_ENABLED(CONFIG_MODULE_SIG)
+   "measure func=MODULE_CHECK",
+#else
+   "measure func=MODULE_CHECK template=ima-modsig",
+   "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+#endif
+   NULL
+};
+
+/*
+ * On PowerPC, file measurements are to be added to the IMA measurement list
+ * irrespective of the secure boot state of the system. Signature verification
+ * is conditionally enabled based on the secure boot state.
+ */
+const char *const *arch_get_ima_policy(void)
+{
+   if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot())
+   return sb_arch_rules;
+   return default_arch_rules;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index a20ad398d260..10af09b5b478 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -29,7 +29,8 @@ extern void ima_kexec_cmdline(const void *buf, int size);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
-#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390)
+#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390) \
+   || defined(CONFIG_PPC_SECURE_BOOT)
 extern bool arch_ima_get_secureboot(void);
 extern const char * const *arch_get_ima_policy(void);
 #else
-- 
2.20.1



[PATCH v5 1/2] powerpc: detect the secure boot mode of the system

2019-08-19 Thread Nayna Jain
Secure boot on POWER defines different IMA policies based on the secure
boot state of the system.

This patch defines a function to detect the secure boot state of the
system.

The PPC_SECURE_BOOT config represents the base enablement of secureboot
on POWER.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/Kconfig   | 11 +
 arch/powerpc/include/asm/secboot.h | 27 
 arch/powerpc/kernel/Makefile   |  2 +
 arch/powerpc/kernel/secboot.c  | 71 ++
 4 files changed, 111 insertions(+)
 create mode 100644 arch/powerpc/include/asm/secboot.h
 create mode 100644 arch/powerpc/kernel/secboot.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 77f6ebf97113..c902a39124dc 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -912,6 +912,17 @@ config PPC_MEM_KEYS
 
  If unsure, say y.
 
+config PPC_SECURE_BOOT
+   prompt "Enable PowerPC Secure Boot"
+   bool
+   default n
+   depends on PPC64
+   help
+ Linux on POWER with firmware secure boot enabled needs to define
+ security policies to extend secure boot to the OS.This config
+ allows user to enable OS Secure Boot on PowerPC systems that
+ have firmware secure boot support.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/include/asm/secboot.h 
b/arch/powerpc/include/asm/secboot.h
new file mode 100644
index ..e726261bb00b
--- /dev/null
+++ b/arch/powerpc/include/asm/secboot.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PowerPC secure boot definitions
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+#ifndef POWERPC_SECBOOT_H
+#define POWERPC_SECBOOT_H
+
+#ifdef CONFIG_PPC_SECURE_BOOT
+extern struct device_node *is_powerpc_secvar_supported(void);
+extern bool get_powerpc_secureboot(void);
+#else
+static inline struct device_node *is_powerpc_secvar_supported(void)
+{
+   return NULL;
+}
+
+static inline bool get_powerpc_secureboot(void)
+{
+   return false;
+}
+
+#endif
+#endif
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index ea0c69236789..d310ebb4e526 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -157,6 +157,8 @@ endif
 obj-$(CONFIG_EPAPR_PARAVIRT)   += epapr_paravirt.o epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)+= kvm.o kvm_emul.o
 
+obj-$(CONFIG_PPC_SECURE_BOOT)  += secboot.o
+
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
 KCOV_INSTRUMENT_prom_init.o := n
diff --git a/arch/powerpc/kernel/secboot.c b/arch/powerpc/kernel/secboot.c
new file mode 100644
index ..5ea0d52d64ef
--- /dev/null
+++ b/arch/powerpc/kernel/secboot.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * secboot.c
+ *  - util function to get powerpc secboot state
+ */
+#include 
+#include 
+#include 
+
+struct device_node *is_powerpc_secvar_supported(void)
+{
+   struct device_node *np;
+   int status;
+
+   np = of_find_node_by_name(NULL, "ibm,secureboot");
+   if (!np) {
+   pr_info("secureboot node is not found\n");
+   return NULL;
+   }
+
+   status = of_device_is_compatible(np, "ibm,secureboot-v3");
+   if (!status) {
+   pr_info("Secure variables are not supported by this 
firmware\n");
+   return NULL;
+   }
+
+   return np;
+}
+
+bool get_powerpc_secureboot(void)
+{
+   struct device_node *np;
+   struct device_node *secvar_np;
+   const u64 *psecboot;
+   u64 secboot = 0;
+
+   np = is_powerpc_secvar_supported();
+   if (!np)
+   goto disabled;
+
+   /* Fail-safe for any failure related to secvar */
+   secvar_np = of_get_child_by_name(np, "secvar");
+   if (!secvar_np) {
+   pr_err("Expected secure variables support, fail-safe\n");
+   goto enabled;
+   }
+
+   if (!of_device_is_available(secvar_np)) {
+   pr_err("Secure variables support is in error state, 
fail-safe\n");
+   goto enabled;
+   }
+
+   psecboot = of_get_property(secvar_np, "secure-mode", NULL);
+   if (!psecboot)
+   goto enabled;
+
+   secboot = be64_to_cpup((__be64 *)psecboot);
+   if (!(secboot & (~0x0)))
+   goto disabled;
+
+enabled:
+   pr_info("secureboot mode enabled\n");
+   return true;
+
+disabled:
+   pr_info("secureboot mode disabled\n");
+   return false;
+}
-- 
2.20.1



[PATCH v5 0/2] powerpc: Enabling IMA arch specific secure boot policies

2019-08-19 Thread Nayna Jain
IMA subsystem supports custom, built-in, arch-specific policies to define
the files to be measured and appraised. These policies are honored based
on the priority where arch-specific policies is the highest and custom
is the lowest.

OpenPOWER systems rely on IMA for signature verification of the kernel.
This patchset adds support for powerpc specific arch policies that are
defined based on system's OS secureboot state. The OS secureboot state
of the system is determined via device-tree entry.

Changelog:
v5:
* secureboot state is now read via device tree entry rather than OPAL
secure variables
* ima arch policies are updated to use policy based template for
measurement rules

v4:
* Fixed the build issue as reported by Satheesh Rajendran.

v3:
* OPAL APIs in Patch 1 are updated to provide generic interface based on
key/keylen. This patchset updates kernel OPAL APIs to be compatible with
generic interface.
* Patch 2 is cleaned up to use new OPAL APIs.
* Since OPAL can support different types of backend which can vary in the
variable interpretation, the Patch 2 is updated to add a check for the
backend version
* OPAL API now expects consumer to first check the supported backend version
before calling other secvar OPAL APIs. This check is now added in patch 2.
* IMA policies in Patch 3 is updated to specify appended signature and
per policy template.
* The patches now are free of any EFIisms.

v2:

* Removed Patch 1: powerpc/include: Override unneeded early ioremap
functions
* Updated Subject line and patch description of the Patch 1 of this series
* Removed dependency of OPAL_SECVAR on EFI, CPU_BIG_ENDIAN and UCS2_STRING
* Changed OPAL APIs from static to non-static. Added opal-secvar.h for the
same
* Removed EFI hooks from opal_secvar.c
* Removed opal_secvar_get_next(), opal_secvar_enqueue() and
opal_query_variable_info() function
* get_powerpc_sb_mode() in secboot.c now directly calls OPAL Runtime API
rather than via EFI hooks.
* Fixed log messages in get_powerpc_sb_mode() function.
* Added dependency for PPC_SECURE_BOOT on configs PPC64 and OPAL_SECVAR
* Replaced obj-$(CONFIG_IMA) with obj-$(CONFIG_PPC_SECURE_BOOT) in
arch/powerpc/kernel/Makefile

Nayna Jain (2):
  powerpc: detect the secure boot mode of the system
  powerpc: Add support to initialize ima policy rules

 arch/powerpc/Kconfig   | 13 ++
 arch/powerpc/include/asm/secboot.h | 27 
 arch/powerpc/kernel/Makefile   |  2 +
 arch/powerpc/kernel/ima_arch.c | 50 +
 arch/powerpc/kernel/secboot.c  | 71 ++
 include/linux/ima.h|  3 +-
 6 files changed, 165 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/secboot.h
 create mode 100644 arch/powerpc/kernel/ima_arch.c
 create mode 100644 arch/powerpc/kernel/secboot.c

-- 
2.20.1



[PATCH v3] tpm: tpm_ibm_vtpm: Fix unallocated banks

2019-07-11 Thread Nayna Jain
The nr_allocated_banks and allocated banks are initialized as part of
tpm_chip_register. Currently, this is done as part of auto startup
function. However, some drivers, like the ibm vtpm driver, do not run
auto startup during initialization. This results in uninitialized memory
issue and causes a kernel panic during boot.

This patch moves the pcr allocation outside the auto startup function
into tpm_chip_register. This ensures that allocated banks are initialized
in any case.

Fixes: 879b589210a9 ("tpm: retrieve digest size of unknown algorithms with
PCR read")
Reported-by: Michal Suchanek 
Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Tested-by: Sachin Sant 
Tested-by: Michal Suchánek 
---
Changelog:
v3:
* Includes Stefan's feedback correctly:
  * Fixed handling of rc > 0 error
* Includes Jarkko's feedback related to comment and the function.

v2:
* Includes Jarkko's feedbacks
  * fixes the function name to tpm_get_pcr_allocation()
  * adds new function tpm1_get_pcr_allocation()
  * updates patch summary line
  * fixes alignment
  * adds Reported-by: Michal Suchanek 
* Includes Stefan's feedbacks
  * Fixes overwriting of return code
  * Fixes misplacing of tpm_chip_stop()
* Adds Reviewed-by, Tested-by

 drivers/char/tpm/tpm-chip.c | 20 
 drivers/char/tpm/tpm.h  |  2 ++
 drivers/char/tpm/tpm1-cmd.c | 36 
 drivers/char/tpm/tpm2-cmd.c |  6 +-
 4 files changed, 47 insertions(+), 17 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 8804c9e916fd..5a0396d6560d 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -550,6 +550,20 @@ static int tpm_add_hwrng(struct tpm_chip *chip)
return hwrng_register(>hwrng);
 }
 
+static int tpm_get_pcr_allocation(struct tpm_chip *chip)
+{
+   int rc;
+
+   rc = (chip->flags & TPM_CHIP_FLAG_TPM2) ?
+tpm2_get_pcr_allocation(chip) :
+tpm1_get_pcr_allocation(chip);
+
+   if (rc > 0)
+   return -ENODEV;
+
+   return rc;
+}
+
 /*
  * tpm_chip_register() - create a character device for the TPM chip
  * @chip: TPM chip to use.
@@ -569,6 +583,12 @@ int tpm_chip_register(struct tpm_chip *chip)
if (rc)
return rc;
rc = tpm_auto_startup(chip);
+   if (rc) {
+   tpm_chip_stop(chip);
+   return rc;
+   }
+
+   rc = tpm_get_pcr_allocation(chip);
tpm_chip_stop(chip);
if (rc)
return rc;
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2cce072f25b5..d571df3694c3 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -399,6 +399,7 @@ int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 
*res_buf);
 ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length);
 int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);
+int tpm1_get_pcr_allocation(struct tpm_chip *chip);
 unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
 int tpm_pm_suspend(struct device *dev);
 int tpm_pm_resume(struct device *dev);
@@ -454,6 +455,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
u32 *value, const char *desc);
 
+ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
 int tpm2_auto_startup(struct tpm_chip *chip);
 void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 85dcf2654d11..260a3917f0fe 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -696,18 +696,6 @@ int tpm1_auto_startup(struct tpm_chip *chip)
goto out;
}
 
-   chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
-   GFP_KERNEL);
-   if (!chip->allocated_banks) {
-   rc = -ENOMEM;
-   goto out;
-   }
-
-   chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
-   chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
-   chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
-   chip->nr_allocated_banks = 1;
-
return rc;
 out:
if (rc > 0)
@@ -776,3 +764,27 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 
tpm_suspend_pcr)
return rc;
 }
 
+/**
+ * tpm1_get_pcr_allocation() - initialize the allocated bank
+ * @chip: TPM chip to use.
+ *
+ * The function initializes the SHA1 allocated bank to extend PCR
+ *
+ * Return:
+ * * 0 on success,
+ * * < 0 on error.
+ */
+int tpm1_get_pcr_allocation(struct tpm_chip *chip)
+{
+   chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
+   

[PATCH v2] tpm: tpm_ibm_vtpm: Fix unallocated banks

2019-07-06 Thread Nayna Jain
The nr_allocated_banks and allocated banks are initialized as part of
tpm_chip_register. Currently, this is done as part of auto startup
function. However, some drivers, like the ibm vtpm driver, do not run
auto startup during initialization. This results in uninitialized memory
issue and causes a kernel panic during boot.

This patch moves the pcr allocation outside the auto startup function
into tpm_chip_register. This ensures that allocated banks are initialized
in any case.

Fixes: 879b589210a9 ("tpm: retrieve digest size of unknown algorithms with
PCR read")
Reported-by: Michal Suchanek 
Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Tested-by: Sachin Sant 
Tested-by: Michal Suchánek 
---
Changelog:

v2:
* Includes Jarkko's feedbacks
  * fixes the function name to tpm_get_pcr_allocation()
  * adds new function tpm1_get_pcr_allocation()
  * updates patch summary line
  * fixes alignment
  * adds Reported-by: Michal Suchanek 
* Includes Stefan's feedbacks
  * Fixes overwriting of return code
  * Fixes misplacing of tpm_chip_stop()
* Adds Reviewed-by, Tested-by

 drivers/char/tpm/tpm-chip.c | 22 ++
 drivers/char/tpm/tpm.h  |  2 ++
 drivers/char/tpm/tpm1-cmd.c | 36 
 drivers/char/tpm/tpm2-cmd.c |  6 +-
 4 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 8804c9e916fd..6589291df355 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -550,6 +550,22 @@ static int tpm_add_hwrng(struct tpm_chip *chip)
return hwrng_register(>hwrng);
 }
 
+/*
+ * tpm_get_pcr_allocation() - initialize the chip allocated banks for PCRs
+ * @chip: TPM chip to use.
+ */
+static int tpm_get_pcr_allocation(struct tpm_chip *chip)
+{
+   int rc;
+
+   if (chip->flags & TPM_CHIP_FLAG_TPM2)
+   rc = tpm2_get_pcr_allocation(chip);
+   else
+   rc = tpm1_get_pcr_allocation(chip);
+
+   return rc;
+}
+
 /*
  * tpm_chip_register() - create a character device for the TPM chip
  * @chip: TPM chip to use.
@@ -569,6 +585,12 @@ int tpm_chip_register(struct tpm_chip *chip)
if (rc)
return rc;
rc = tpm_auto_startup(chip);
+   if (rc) {
+   tpm_chip_stop(chip);
+   return rc;
+   }
+
+   rc = tpm_get_pcr_allocation(chip);
tpm_chip_stop(chip);
if (rc)
return rc;
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2cce072f25b5..d571df3694c3 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -399,6 +399,7 @@ int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 
*res_buf);
 ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length);
 int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);
+int tpm1_get_pcr_allocation(struct tpm_chip *chip);
 unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
 int tpm_pm_suspend(struct device *dev);
 int tpm_pm_resume(struct device *dev);
@@ -454,6 +455,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
u32 *value, const char *desc);
 
+ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
 int tpm2_auto_startup(struct tpm_chip *chip);
 void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 85dcf2654d11..260a3917f0fe 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -696,18 +696,6 @@ int tpm1_auto_startup(struct tpm_chip *chip)
goto out;
}
 
-   chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
-   GFP_KERNEL);
-   if (!chip->allocated_banks) {
-   rc = -ENOMEM;
-   goto out;
-   }
-
-   chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
-   chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
-   chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
-   chip->nr_allocated_banks = 1;
-
return rc;
 out:
if (rc > 0)
@@ -776,3 +764,27 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 
tpm_suspend_pcr)
return rc;
 }
 
+/**
+ * tpm1_get_pcr_allocation() - initialize the allocated bank
+ * @chip: TPM chip to use.
+ *
+ * The function initializes the SHA1 allocated bank to extend PCR
+ *
+ * Return:
+ * * 0 on success,
+ * * < 0 on error.
+ */
+int tpm1_get_pcr_allocation(struct tpm_chip *chip)
+{
+   chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
+   GFP_KERNEL);
+   if (!chip->allocated_banks)
+   r

[PATCH] tpm: fixes uninitialized allocated banks for IBM vtpm driver

2019-07-03 Thread Nayna Jain
The nr_allocated_banks and allocated banks are initialized as part of
tpm_chip_register. Currently, this is done as part of auto startup
function. However, some drivers, like the ibm vtpm driver, do not run
auto startup during initialization. This results in uninitialized memory
issue and causes a kernel panic during boot.

This patch moves the pcr allocation outside the auto startup function
into tpm_chip_register. This ensures that allocated banks are initialized
in any case.

Fixes: 879b589210a9 ("tpm: retrieve digest size of unknown algorithms with
PCR read")
Signed-off-by: Nayna Jain 
---
 drivers/char/tpm/tpm-chip.c | 37 +
 drivers/char/tpm/tpm.h  |  1 +
 drivers/char/tpm/tpm1-cmd.c | 12 
 drivers/char/tpm/tpm2-cmd.c |  6 +-
 4 files changed, 39 insertions(+), 17 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 8804c9e916fd..958508bb8379 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -550,6 +550,39 @@ static int tpm_add_hwrng(struct tpm_chip *chip)
return hwrng_register(>hwrng);
 }
 
+/*
+ * tpm_pcr_allocation() - initializes the chip allocated banks for PCRs
+ */
+static int tpm_pcr_allocation(struct tpm_chip *chip)
+{
+   int rc = 0;
+
+   if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+   rc = tpm2_get_pcr_allocation(chip);
+   if (rc)
+   goto out;
+   }
+
+   /* Initialize TPM 1.2 */
+   chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
+   GFP_KERNEL);
+   if (!chip->allocated_banks) {
+   rc = -ENOMEM;
+   goto out;
+   }
+
+   chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
+   chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
+   chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
+   chip->nr_allocated_banks = 1;
+
+   return 0;
+out:
+   if (rc < 0)
+   rc = -ENODEV;
+   return rc;
+}
+
 /*
  * tpm_chip_register() - create a character device for the TPM chip
  * @chip: TPM chip to use.
@@ -573,6 +606,10 @@ int tpm_chip_register(struct tpm_chip *chip)
if (rc)
return rc;
 
+   rc = tpm_pcr_allocation(chip);
+   if (rc)
+   return rc;
+
tpm_sysfs_add_device(chip);
 
rc = tpm_bios_log_setup(chip);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2cce072f25b5..eabe6b755fa6 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -454,6 +454,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
u32 *value, const char *desc);
 
+ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
 int tpm2_auto_startup(struct tpm_chip *chip);
 void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 85dcf2654d11..ec5f3693c096 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -696,18 +696,6 @@ int tpm1_auto_startup(struct tpm_chip *chip)
goto out;
}
 
-   chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
-   GFP_KERNEL);
-   if (!chip->allocated_banks) {
-   rc = -ENOMEM;
-   goto out;
-   }
-
-   chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
-   chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
-   chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
-   chip->nr_allocated_banks = 1;
-
return rc;
 out:
if (rc > 0)
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index e74c5b7b64bf..b4384d0e3741 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -841,7 +841,7 @@ struct tpm2_pcr_selection {
u8  pcr_select[3];
 } __packed;
 
-static ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
+ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
 {
struct tpm2_pcr_selection pcr_selection;
struct tpm_buf buf;
@@ -1041,10 +1041,6 @@ int tpm2_auto_startup(struct tpm_chip *chip)
goto out;
}
 
-   rc = tpm2_get_pcr_allocation(chip);
-   if (rc)
-   goto out;
-
rc = tpm2_get_cc_attrs_tbl(chip);
 
 out:
-- 
2.20.1



[PATCH] x86/ima: fix the Kconfig dependency for IMA_ARCH_POLICY

2019-06-07 Thread Nayna Jain
If enabled, ima arch specific policies always adds the measurements rules,
this makes it dependent on CONFIG_IMA. CONFIG_IMA_APPRAISE implicitly takes
care of this, however it is needed explicitly for CONFIG_KEXEC_VERIFY_SIG.

This patch adds the CONFIG_IMA dependency in combination with
CONFIG_KEXEC_VERIFY_SIG for CONFIG_IMA_ARCH_POLICY

Fixes: d958083a8f640 (x86/ima: define arch_get_ima_policy() for x86)
Signed-off-by: Nayna Jain 
Cc: Eric Biederman 
Cc: Dave Young 
---
 security/integrity/ima/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index a18f8c6d13b5..df65d2d41905 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -159,7 +159,8 @@ config IMA_APPRAISE
 
 config IMA_ARCH_POLICY
 bool "Enable loading an IMA architecture specific policy"
-depends on KEXEC_VERIFY_SIG || IMA_APPRAISE && 
INTEGRITY_ASYMMETRIC_KEYS
+depends on (KEXEC_VERIFY_SIG && IMA) || IMA_APPRAISE \
+  && INTEGRITY_ASYMMETRIC_KEYS
 default n
 help
   This option enables loading an IMA architecture specific policy
-- 
2.17.1



[PATCH v2a 5/7] efi: Import certificates from UEFI Secure Boot

2018-12-12 Thread Nayna Jain
From: Josh Boyer 

Secure Boot stores a list of allowed certificates in the 'db' variable.
This patch imports those certificates into the platform keyring. The shim
UEFI bootloader has a similar certificate list stored in the 'MokListRT'
variable. We import those as well.

Secure Boot also maintains a list of disallowed certificates in the 'dbx'
variable. We load those certificates into the system blacklist keyring
and forbid any kernel signed with those from loading.

[zo...@linux.ibm.com: dropped Josh's original patch description]
Signed-off-by: Josh Boyer 
Signed-off-by: David Howells 
Signed-off-by: Nayna Jain 
Acked-by: Serge Hallyn 
Signed-off-by: Mimi Zohar 
---
Changelog:

v2a:
- refactored uefi_blacklist_x509_tbs() and  uefi_blacklist_binary()

v2:
- Fixed the checkpatch.pl warnings

v0:
- This patch replaces the loading of certificates onto the secondary
  keyring with platform keyring
- removed the CONFIG LOAD_UEFI_KEYS
- moved the file load_uefi.o from certs to security/integrity/platform_certs

 security/integrity/Makefile   |   5 +-
 security/integrity/platform_certs/load_uefi.c | 169 ++
 2 files changed, 173 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/load_uefi.c

diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 6ee9058866cd..86df9aba8c0f 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -10,7 +10,10 @@ integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
 integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o \
- platform_certs/efi_parser.o
+ platform_certs/efi_parser.o \
+ platform_certs/load_uefi.o
+obj-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/load_uefi.o
+$(obj)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/load_uefi.c 
b/security/integrity/platform_certs/load_uefi.c
new file mode 100644
index ..8ceafa58d98c
--- /dev/null
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../integrity.h"
+
+static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
+static efi_guid_t efi_cert_x509_sha256_guid __initdata =
+   EFI_CERT_X509_SHA256_GUID;
+static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
+
+/*
+ * Get a certificate list blob from the named EFI variable.
+ */
+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
+ unsigned long *size)
+{
+   efi_status_t status;
+   unsigned long lsize = 4;
+   unsigned long tmpdb[4];
+   void *db;
+
+   status = efi.get_variable(name, guid, NULL, , );
+   if (status != EFI_BUFFER_TOO_SMALL) {
+   pr_err("Couldn't get size: 0x%lx\n", status);
+   return NULL;
+   }
+
+   db = kmalloc(lsize, GFP_KERNEL);
+   if (!db)
+   return NULL;
+
+   status = efi.get_variable(name, guid, NULL, , db);
+   if (status != EFI_SUCCESS) {
+   kfree(db);
+   pr_err("Error reading db var: 0x%lx\n", status);
+   return NULL;
+   }
+
+   *size = lsize;
+   return db;
+}
+
+/*
+ * Blacklist a hash.
+ */
+static __init void uefi_blacklist_hash(const char *source, const void *data,
+  size_t len, const char *type,
+  size_t type_len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(type_len + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, type, type_len);
+   p += type_len;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash);
+}
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "tbs:", 4);
+}
+
+/*
+ * Blacklist the hash of an executable.
+ */
+static __init void uefi_blacklist_binary(const char *source,
+const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "bin:", 4);
+}
+
+/*
+ * Return the appropriate handler for particular signature list types found in
+ * the UEFI db and MokListRT tables.
+ */
+static __init efi_ele

Re: [PATCH v2 5/7] efi: Import certificates from UEFI Secure Boot

2018-12-12 Thread Nayna Jain




On 12/12/2018 12:17 AM, James Morris wrote:

On Sun, 9 Dec 2018, Nayna Jain wrote:


+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, "tbs:", 4);
+   p += 4;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash);
+}
+
+/*
+ * Blacklist the hash of an executable.
+ */
+static __init void uefi_blacklist_binary(const char *source,
+const void *data, size_t len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, "bin:", 4);
+   p += 4;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash);
+}


These could be refactored into one function.




Thanks James for reviewing.

Yes, the code should be refactored.  However, I think making it a single 
function would require adding a new field to the function callback 
definitions as well. Probably, a simpler approach would be to define a 
common function uefi_blacklist_hash(...)  which can then be used by the 
two functions uefi_blacklist_x509_tbs(...) and 
uefi_blacklist_binary(...). These two functions now act as wrapper 
functions. Below is the example code:


+/*
+ * Blacklist a hash.
+ */
+static __init void uefi_blacklist_hash(const char *source, const void 
*data,

+ size_t len, char *type, size_t type_len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(type_len + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, type, type_len);
+   p += type_len;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash);
+}
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "tbs:" , 4);
+}
+
+/*
+ * Blacklist the hash of an executable.
+ */
+static __init void uefi_blacklist_binary(const char *source,
+    const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "bin:" , 4);
+}


Thanks & Regards,
   - Nayna





Re: [PATCH v6 2/7] tpm: add _head suffix to tcg_efi_specid_event and tcg_pcr_event2

2018-12-09 Thread Nayna Jain




On 12/04/2018 01:51 PM, Roberto Sassu wrote:

TCG defines two structures, TCG_EfiSpecIDEventStruct and TCG_PCR_EVENT2,
which contain variable-sized arrays in the middle of the definition.

Since these structures are not suitable for type casting, this patch
removes structure members after the variable-sized arrays and adds the
_head suffix to the structure name, to indicate that the renamed structures
do not contain all fields defined by TCG.

Lastly, given that variable-sized arrays are now in the last position, and
given that the size of the arrays cannot be determined in advance, this
patch also sets the size of those arrays to zero and removes the definition
of TPM2_ACTIVE_PCR_BANKS.

Signed-off-by: Roberto Sassu 



Tested-by: Nayna Jain 

Thanks & Regards,
    - Nayna




Re: [PATCH v6 4/7] tpm: modify tpm_pcr_read() definition to pass a TPM hash algorithm

2018-12-09 Thread Nayna Jain




On 12/05/2018 05:10 AM, Jarkko Sakkinen wrote:

On Tue, Dec 04, 2018 at 09:21:35AM +0100, Roberto Sassu wrote:

Currently the TPM driver allows other kernel subsystems to read only the
SHA1 PCR bank. This patch modifies the parameters of tpm_pcr_read() and
tpm2_pcr_read() to pass a tpm_digest structure, which contains the desired
hash algorithm. Also, since commit 125a22105410 ("tpm: React correctly to
RC_TESTING from TPM 2.0 self tests") removed the call to tpm2_pcr_read(),
the new parameter is expected to be always not NULL.

Due to the API change, IMA functions have been modified.

Signed-off-by: Roberto Sassu 
Acked-by: Mimi Zohar 

Reviewed-by: Jarkko Sakkinen 

Mimi, Nayna, can you help with testing this (because of the IMA change)?



Tested-by: Nayna Jain 

Thanks & Regards,
    - Nayna





/Jarkko





[PATCH v2 1/7] integrity: Define a trusted platform keyring

2018-12-08 Thread Nayna Jain
On secure boot enabled systems, a verified kernel may need to kexec
additional kernels. For example, it may be used as a bootloader needing
to kexec a target kernel or it may need to kexec a crashdump kernel. In
such cases, it may want to verify the signature of the next kernel
image.

It is further possible that the kernel image is signed with third party
keys which are stored as platform or firmware keys in the 'db' variable.
The kernel, however, can not directly verify these platform keys, and an
administrator may therefore not want to trust them for arbitrary usage.
In order to differentiate platform keys from other keys and provide the
necessary separation of trust, the kernel needs an additional keyring to
store platform keys.

This patch creates the new keyring called ".platform" to isolate keys
provided by platform from keys by kernel. These keys are used to
facilitate signature verification during kexec. Since the scope of this
keyring is only the platform/firmware keys, it cannot be updated from
userspace.

This keyring can be enabled by setting CONFIG_INTEGRITY_PLATFORM_KEYRING.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Acked-by: Serge Hallyn 
---
 security/integrity/Kconfig | 11 +
 security/integrity/Makefile|  1 +
 security/integrity/digsig.c| 48 +++---
 security/integrity/integrity.h |  3 +-
 .../integrity/platform_certs/platform_keyring.c| 35 
 5 files changed, 83 insertions(+), 15 deletions(-)
 create mode 100644 security/integrity/platform_certs/platform_keyring.c

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index da9565891738..4b4d2aeef539 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -51,6 +51,17 @@ config INTEGRITY_TRUSTED_KEYRING
   .evm keyrings be signed by a key on the system trusted
   keyring.
 
+config INTEGRITY_PLATFORM_KEYRING
+bool "Provide keyring for platform/firmware trusted keys"
+depends on INTEGRITY_ASYMMETRIC_KEYS
+depends on SYSTEM_BLACKLIST_KEYRING
+depends on EFI
+help
+ Provide a separate, distinct keyring for platform trusted keys, which
+ the kernel automatically populates during initialization from values
+ provided by the platform for verifying the kexec'ed kerned image
+ and, possibly, the initramfs signature.
+
 config INTEGRITY_AUDIT
bool "Enables integrity auditing support "
depends on AUDIT
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 04d6e462b079..046ffc1bb42d 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -9,6 +9,7 @@ integrity-y := iint.o
 integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
+integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 5eacba858e4b..fef2a858300c 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -35,6 +35,7 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] 
= {
".ima",
 #endif
"_module",
+   ".platform",
 };
 
 #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
@@ -73,12 +74,39 @@ int integrity_digsig_verify(const unsigned int id, const 
char *sig, int siglen,
return -EOPNOTSUPP;
 }
 
-int __init integrity_init_keyring(const unsigned int id)
+static int __integrity_init_keyring(const unsigned int id, key_perm_t perm,
+   struct key_restriction *restriction)
 {
const struct cred *cred = current_cred();
+   int err = 0;
+
+   keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
+   KGIDT_INIT(0), cred, perm,
+   KEY_ALLOC_NOT_IN_QUOTA,
+   restriction, NULL);
+   if (IS_ERR(keyring[id])) {
+   err = PTR_ERR(keyring[id]);
+   pr_info("Can't allocate %s keyring (%d)\n",
+   keyring_name[id], err);
+   keyring[id] = NULL;
+   }
+
+   return err;
+}
+
+int __init integrity_init_keyring(const unsigned int id)
+{
struct key_restriction *restriction;
+   key_perm_t perm;
int err = 0;
 
+   if (id == INTEGRITY_KEYRING_PLATFORM) {
+   restriction = NULL;
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
+   | KEY_USR_READ | KEY_USR_SEARCH;
+   goto out;
+   }
+
if (!IS_ENABLED(CONFIG

[PATCH v2 3/7] efi: Add EFI signature data types

2018-12-08 Thread Nayna Jain
From: Dave Howells 

Add the data types that are used for containing hashes, keys and
certificates for cryptographic verification along with their corresponding
type GUIDs.

Signed-off-by: David Howells 
Acked-by: Nayna Jain 
Acked-by: Serge Hallyn 
---
Changelog:

v0:
- No changes

 include/linux/efi.h | 25 +
 1 file changed, 25 insertions(+)

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 845174e113ce..214516b29b36 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -663,6 +663,10 @@ void efi_native_runtime_setup(void);
 #define EFI_IMAGE_SECURITY_DATABASE_GUID   EFI_GUID(0xd719b2cb, 0x3d3a, 
0x4596,  0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f)
 #define EFI_SHIM_LOCK_GUID EFI_GUID(0x605dab50, 0xe046, 
0x4300,  0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)
 
+#define EFI_CERT_SHA256_GUID   EFI_GUID(0xc1c41626, 0x504c, 
0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28)
+#define EFI_CERT_X509_GUID EFI_GUID(0xa5c059a1, 0x94e4, 
0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72)
+#define EFI_CERT_X509_SHA256_GUID  EFI_GUID(0x3bd2a492, 0x96c0, 
0x4079, 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed)
+
 /*
  * This GUID is used to pass to the kernel proper the struct screen_info
  * structure that was populated by the stub based on the GOP protocol instance
@@ -934,6 +938,27 @@ typedef struct {
efi_memory_desc_t entry[0];
 } efi_memory_attributes_table_t;
 
+typedef struct  {
+   efi_guid_t signature_owner;
+   u8 signature_data[];
+} efi_signature_data_t;
+
+typedef struct {
+   efi_guid_t signature_type;
+   u32 signature_list_size;
+   u32 signature_header_size;
+   u32 signature_size;
+   u8 signature_header[];
+   /* efi_signature_data_t signatures[][] */
+} efi_signature_list_t;
+
+typedef u8 efi_sha256_hash_t[32];
+
+typedef struct {
+   efi_sha256_hash_t to_be_signed_hash;
+   efi_time_t time_of_revocation;
+} efi_cert_x509_sha256_t;
+
 /*
  * All runtime access to EFI goes through this structure:
  */
-- 
2.13.6



[PATCH v2 4/7] efi: Add an EFI signature blob parser

2018-12-08 Thread Nayna Jain
From: Dave Howells 

Add a function to parse an EFI signature blob looking for elements of
interest. A list is made up of a series of sublists, where all the
elements in a sublist are of the same type, but sublists can be of
different types.

For each sublist encountered, the function pointed to by the
get_handler_for_guid argument is called with the type specifier GUID and
returns either a pointer to a function to handle elements of that type or
NULL if the type is not of interest.

If the sublist is of interest, each element is passed to the handler
function in turn.

Signed-off-by: David Howells 
Signed-off-by: Nayna Jain 
Acked-by: Serge Hallyn 
---
Changelog:

v0:
- removed the CONFIG EFI_SIGNATURE_LIST_PARSER
- moved efi_parser.c from certs to security/integrity/platform_certs
  directory

v2:
- Fixed the checkpatch.pl warnings

 include/linux/efi.h|   9 +++
 security/integrity/Makefile|   3 +-
 security/integrity/platform_certs/efi_parser.c | 108 +
 3 files changed, 119 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/efi_parser.c

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 214516b29b36..c3206b134137 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1141,6 +1141,15 @@ extern int efi_memattr_apply_permissions(struct 
mm_struct *mm,
 char * __init efi_md_typeattr_format(char *buf, size_t size,
 const efi_memory_desc_t *md);
 
+
+typedef void (*efi_element_handler_t)(const char *source,
+ const void *element_data,
+ size_t element_size);
+extern int __init parse_efi_signature_list(
+   const char *source,
+   const void *data, size_t size,
+   efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *));
+
 /**
  * efi_range_is_wc - check the WC bit on an address range
  * @start: starting kvirt address
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 046ffc1bb42d..6ee9058866cd 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -9,7 +9,8 @@ integrity-y := iint.o
 integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
-integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o
+integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o \
+ platform_certs/efi_parser.o
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/efi_parser.c 
b/security/integrity/platform_certs/efi_parser.c
new file mode 100644
index ..18f01f36fe6a
--- /dev/null
+++ b/security/integrity/platform_certs/efi_parser.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* EFI signature/key/certificate list parser
+ *
+ * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#define pr_fmt(fmt) "EFI: "fmt
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * parse_efi_signature_list - Parse an EFI signature list for certificates
+ * @source: The source of the key
+ * @data: The data blob to parse
+ * @size: The size of the data blob
+ * @get_handler_for_guid: Get the handler func for the sig type (or NULL)
+ *
+ * Parse an EFI signature list looking for elements of interest.  A list is
+ * made up of a series of sublists, where all the elements in a sublist are of
+ * the same type, but sublists can be of different types.
+ *
+ * For each sublist encountered, the @get_handler_for_guid function is called
+ * with the type specifier GUID and returns either a pointer to a function to
+ * handle elements of that type or NULL if the type is not of interest.
+ *
+ * If the sublist is of interest, each element is passed to the handler
+ * function in turn.
+ *
+ * Error EBADMSG is returned if the list doesn't parse correctly and 0 is
+ * returned if the list was parsed correctly.  No error can be returned from
+ * the @get_handler_for_guid function or the element handler function it
+ * returns.
+ */
+int __init parse_efi_signature_list(
+   const char *source,
+   const void *data, size_t size,
+   efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *))
+{
+   efi_element_handler_t handler;
+   unsigned int offs = 0;
+
+   pr_devel("-->%s(,%zu)\n", __func__, size);
+
+   while (size > 0) {
+   const efi_signature_data_t *elem;
+   efi_signature_list_t list;
+   size_t lsize, esize, hsize, elsize;
+
+   if (size < sizeof(list))
+   return -EBADMSG;
+
+   memcpy(, data, sizeof(list));
+ 

[PATCH v2 6/7] efi: Allow the "db" UEFI variable to be suppressed

2018-12-08 Thread Nayna Jain
From: Josh Boyer 

If a user tells shim to not use the certs/hashes in the UEFI db variable
for verification purposes, shim will set a UEFI variable called
MokIgnoreDB. Have the uefi import code look for this and ignore the db
variable if it is found.

Signed-off-by: Josh Boyer 
Signed-off-by: David Howells 
Acked-by: Nayna Jain 
Acked-by: Serge Hallyn 
---
Changelog:

v0:
- No changes

v2:
- Fixed the checkpatch.pl warnings

 security/integrity/platform_certs/load_uefi.c | 45 +--
 1 file changed, 35 insertions(+), 10 deletions(-)

diff --git a/security/integrity/platform_certs/load_uefi.c 
b/security/integrity/platform_certs/load_uefi.c
index acd9db90dde7..8bd2e9b421e1 100644
--- a/security/integrity/platform_certs/load_uefi.c
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -16,6 +16,26 @@ static efi_guid_t efi_cert_x509_sha256_guid __initdata =
 static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
 
 /*
+ * Look to see if a UEFI variable called MokIgnoreDB exists and return true if
+ * it does.
+ *
+ * This UEFI variable is set by the shim if a user tells the shim to not use
+ * the certs/hashes in the UEFI db variable for verification purposes.  If it
+ * is set, we should ignore the db variable also and the true return indicates
+ * this.
+ */
+static __init bool uefi_check_ignore_db(void)
+{
+   efi_status_t status;
+   unsigned int db = 0;
+   unsigned long size = sizeof(db);
+   efi_guid_t guid = EFI_SHIM_LOCK_GUID;
+
+   status = efi.get_variable(L"MokIgnoreDB", , NULL, , );
+   return status == EFI_SUCCESS;
+}
+
+/*
  * Get a certificate list blob from the named EFI variable.
  */
 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
@@ -116,7 +136,9 @@ static __init efi_element_handler_t 
get_handler_for_dbx(const efi_guid_t *
 }
 
 /*
- * Load the certs contained in the UEFI databases
+ * Load the certs contained in the UEFI databases into the secondary trusted
+ * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist
+ * keyring.
  */
 static int __init load_uefi_certs(void)
 {
@@ -132,15 +154,18 @@ static int __init load_uefi_certs(void)
/* Get db, MokListRT, and dbx.  They might not exist, so it isn't
 * an error if we can't get them.
 */
-   db = get_cert_list(L"db", _var, );
-   if (!db) {
-   pr_err("Couldn't get UEFI db list\n");
-   } else {
-   rc = parse_efi_signature_list("UEFI:db",
- db, dbsize, get_handler_for_db);
-   if (rc)
-   pr_err("Couldn't parse db signatures: %d\n", rc);
-   kfree(db);
+   if (!uefi_check_ignore_db()) {
+   db = get_cert_list(L"db", _var, );
+   if (!db) {
+   pr_err("MODSIGN: Couldn't get UEFI db list\n");
+   } else {
+   rc = parse_efi_signature_list("UEFI:db",
+   db, dbsize, get_handler_for_db);
+   if (rc)
+   pr_err("Couldn't parse db signatures: %d\n",
+  rc);
+   kfree(db);
+   }
}
 
mok = get_cert_list(L"MokListRT", _var, );
-- 
2.13.6



[PATCH v2 5/7] efi: Import certificates from UEFI Secure Boot

2018-12-08 Thread Nayna Jain
From: Josh Boyer 

New Patch Description:
==

Secure Boot stores a list of allowed certificates in the 'db' variable.
This patch imports those certificates into the platform keyring. The shim
UEFI bootloader has a similar certificate list stored in the 'MokListRT'
variable. We import those as well.

Secure Boot also maintains a list of disallowed certificates in the 'dbx'
variable. We load those certificates into the system blacklist keyring
and forbid any kernel signed with those from loading.

Original Patch Description:


Secure Boot stores a list of allowed certificates in the 'db' variable.
This imports those certificates into the system trusted keyring.  This
allows for a third party signing certificate to be used in conjunction
with signed modules. By importing the public certificate into the 'db'
variable, a user can allow a module signed with that certificate to
load. The shim UEFI bootloader has a similar certificate list stored
in the 'MokListRT' variable. We import those as well.

Secure Boot also maintains a list of disallowed certificates in the 'dbx'
variable. We load those certificates into the newly introduced system
blacklist keyring and forbid any module signed with those from loading and
forbid the use within the kernel of any key with a matching hash.

This facility is enabled by setting CONFIG_LOAD_UEFI_KEYS.

Signed-off-by: Josh Boyer 
Signed-off-by: David Howells 
Signed-off-by: Nayna Jain 
Acked-by: Serge Hallyn 
---
Changelog:

v0:
- This patch replaces the loading of certificates onto the secondary
  keyring with platform keyring
- removed the CONFIG LOAD_UEFI_KEYS
- moved the file load_uefi.o from certs to security/integrity/platform_certs

v2:
- Fixed the checkpatch.pl warnings

 security/integrity/Makefile   |   5 +-
 security/integrity/platform_certs/load_uefi.c | 171 ++
 2 files changed, 175 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/load_uefi.c

diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 6ee9058866cd..86df9aba8c0f 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -10,7 +10,10 @@ integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
 integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o \
- platform_certs/efi_parser.o
+ platform_certs/efi_parser.o \
+ platform_certs/load_uefi.o
+obj-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/load_uefi.o
+$(obj)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/load_uefi.c 
b/security/integrity/platform_certs/load_uefi.c
new file mode 100644
index ..acd9db90dde7
--- /dev/null
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../integrity.h"
+
+static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
+static efi_guid_t efi_cert_x509_sha256_guid __initdata =
+   EFI_CERT_X509_SHA256_GUID;
+static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
+
+/*
+ * Get a certificate list blob from the named EFI variable.
+ */
+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
+ unsigned long *size)
+{
+   efi_status_t status;
+   unsigned long lsize = 4;
+   unsigned long tmpdb[4];
+   void *db;
+
+   status = efi.get_variable(name, guid, NULL, , );
+   if (status != EFI_BUFFER_TOO_SMALL) {
+   pr_err("Couldn't get size: 0x%lx\n", status);
+   return NULL;
+   }
+
+   db = kmalloc(lsize, GFP_KERNEL);
+   if (!db)
+   return NULL;
+
+   status = efi.get_variable(name, guid, NULL, , db);
+   if (status != EFI_SUCCESS) {
+   kfree(db);
+   pr_err("Error reading db var: 0x%lx\n", status);
+   return NULL;
+   }
+
+   *size = lsize;
+   return db;
+}
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, "tbs:", 4);
+   p += 4;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfre

[PATCH v2 7/7] ima: Support platform keyring for kernel appraisal

2018-12-08 Thread Nayna Jain
On secure boot enabled systems, the bootloader verifies the kernel
image and possibly the initramfs signatures based on a set of keys. A
soft reboot(kexec) of the system, with the same kernel image and
initramfs, requires access to the original keys to verify the
signatures.

This patch allows IMA-appraisal access to those original keys, now
loaded on the platform keyring, needed for verifying the kernel image
and initramfs signatures.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Acked-by: Serge Hallyn 
- replace 'rc' with 'xattr_len' when calling integrity_digsig_verify()
with INTEGRITY_KEYRING_IMA for readability
Suggested-by: Serge Hallyn 
---
Changelog:

v2:
- replace 'rc' with 'xattr_len' when calling integrity_digsig_verify()
with INTEGRITY_KEYRING_IMA for readability

 security/integrity/ima/ima_appraise.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index deec1804a00a..e8f520450895 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -289,12 +289,21 @@ int ima_appraise_measurement(enum ima_hooks func,
case EVM_IMA_XATTR_DIGSIG:
set_bit(IMA_DIGSIG, >atomic_flags);
rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
-(const char *)xattr_value, rc,
+(const char *)xattr_value,
+xattr_len,
 iint->ima_hash->digest,
 iint->ima_hash->length);
if (rc == -EOPNOTSUPP) {
status = INTEGRITY_UNKNOWN;
-   } else if (rc) {
+   break;
+   }
+   if (rc && func == KEXEC_KERNEL_CHECK)
+   rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM,
+(const char *)xattr_value,
+xattr_len,
+iint->ima_hash->digest,
+iint->ima_hash->length);
+   if (rc) {
cause = "invalid-signature";
status = INTEGRITY_FAIL;
} else {
-- 
2.13.6



[PATCH v2 2/7] integrity: Load certs to the platform keyring

2018-12-08 Thread Nayna Jain
The patch refactors integrity_load_x509(), making it a wrapper for a new
function named integrity_add_key(). This patch also defines a new
function named integrity_load_cert() for loading the platform keys.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Acked-by: Serge Hallyn 
---
 security/integrity/digsig.c| 71 ++
 security/integrity/integrity.h | 20 ++
 .../integrity/platform_certs/platform_keyring.c| 23 +++
 3 files changed, 90 insertions(+), 24 deletions(-)

diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index b5b180ff1434..4ba167255225 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -82,8 +82,7 @@ static int __integrity_init_keyring(const unsigned int id, 
key_perm_t perm,
 
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
KGIDT_INIT(0), cred, perm,
-   KEY_ALLOC_NOT_IN_QUOTA,
-   restriction, NULL);
+   KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL);
if (IS_ERR(keyring[id])) {
err = PTR_ERR(keyring[id]);
pr_info("Can't allocate %s keyring (%d)\n",
@@ -124,16 +123,38 @@ int __init integrity_init_keyring(const unsigned int id)
return err;
 }
 
-int __init integrity_load_x509(const unsigned int id, const char *path)
+int __init integrity_add_key(const unsigned int id, const void *data,
+off_t size, key_perm_t perm)
 {
key_ref_t key;
-   void *data;
-   loff_t size;
-   int rc;
+   int rc = 0;
 
if (!keyring[id])
return -EINVAL;
 
+   key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric",
+  NULL, data, size, perm,
+  KEY_ALLOC_NOT_IN_QUOTA);
+   if (IS_ERR(key)) {
+   rc = PTR_ERR(key);
+   pr_err("Problem loading X.509 certificate %d\n", rc);
+   } else {
+   pr_notice("Loaded X.509 cert '%s'\n",
+ key_ref_to_ptr(key)->description);
+   key_ref_put(key);
+   }
+
+   return rc;
+
+}
+
+int __init integrity_load_x509(const unsigned int id, const char *path)
+{
+   void *data;
+   loff_t size;
+   int rc;
+   key_perm_t perm;
+
rc = kernel_read_file_from_path(path, , , 0,
READING_X509_CERTIFICATE);
if (rc < 0) {
@@ -141,23 +162,25 @@ int __init integrity_load_x509(const unsigned int id, 
const char *path)
return rc;
}
 
-   key = key_create_or_update(make_key_ref(keyring[id], 1),
-  "asymmetric",
-  NULL,
-  data,
-  size,
-  ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-   KEY_USR_VIEW | KEY_USR_READ),
-  KEY_ALLOC_NOT_IN_QUOTA);
-   if (IS_ERR(key)) {
-   rc = PTR_ERR(key);
-   pr_err("Problem loading X.509 certificate (%d): %s\n",
-  rc, path);
-   } else {
-   pr_notice("Loaded X.509 cert '%s': %s\n",
- key_ref_to_ptr(key)->description, path);
-   key_ref_put(key);
-   }
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ;
+
+   pr_info("Loading X.509 certificate: %s\n", path);
+   rc = integrity_add_key(id, (const void *)data, size, perm);
+
vfree(data);
-   return 0;
+   return rc;
+}
+
+int __init integrity_load_cert(const unsigned int id, const char *source,
+  const void *data, size_t len, key_perm_t perm)
+{
+   int rc;
+
+   if (!data)
+   return -EINVAL;
+
+   pr_info("Loading X.509 certificate: %s\n", source);
+   rc = integrity_add_key(id, data, len, perm);
+
+   return rc;
 }
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index c2332a44799e..3517d2852a07 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -154,6 +154,8 @@ int integrity_digsig_verify(const unsigned int id, const 
char *sig, int siglen,
 
 int __init integrity_init_keyring(const unsigned int id);
 int __init integrity_load_x509(const unsigned int id, const char *path);
+int __init integrity_load_cert(const unsigned int id, const char *source,
+  const void *data, size_t len, key_perm_t perm);
 #else
 
 static inline int integrity_digsig_verify(const unsigned int id,
@@ -167,6 +169,14 @@ static inline int integrity_init_keyring(const unsi

[PATCH v2 0/7] add platform/firmware keys support for kernel verification by IMA

2018-12-08 Thread Nayna Jain
On secure boot enabled systems, a verified kernel may need to kexec
additional kernels. For example, it may be used as a bootloader needing
to kexec a target kernel or it may need to kexec a crashdump kernel.
In such cases, it may want to verify the signature of the next kernel
image.

It is possible that the new kernel image is signed with third party keys
which are stored as platform or firmware keys in the 'db' variable. The
kernel, however, can not directly verify these platform keys, and an
administrator may therefore not want to trust them for arbitrary usage.
In order to differentiate platform keys from other keys and provide the
necessary separation of trust the kernel needs an additional keyring to
store platform/firmware keys.

The secure boot key database is expected to store the keys as EFI
Signature List(ESL). The patch set uses David Howells and Josh Boyer's
patch to access and parse the ESL to extract the certificates and load
them onto the platform keyring.

The last patch in this patch set adds support for IMA-appraisal to
verify the kexec'ed kernel image based on keys stored in the platform
keyring.

Changelog:

v0:
- The original patches loaded the certificates onto the secondary
  trusted keyring. This patch set defines a new keyring named
  ".platform" and adds the certificates to this new keyring  
- removed CONFIG EFI_SIGNATURE_LIST_PARSER and LOAD_UEFI_KEYS
- moved files from certs/ to security/integrity/platform_certs/

v2:
- fixed the checkpatch warnings and other formatting as suggested by
  Mimi Zohar 
- fixed coding style as suggested by Serge Hallyn in Patch "ima: Support
  platform keyring for kernel appraisal"

Dave Howells (2):
  efi: Add EFI signature data types
  efi: Add an EFI signature blob parser

Josh Boyer (2):
  efi: Import certificates from UEFI Secure Boot
  efi: Allow the "db" UEFI variable to be suppressed

Nayna Jain (3):
  integrity: Define a trusted platform keyring
  integrity: Load certs to the platform keyring
  ima: Support platform keyring for kernel appraisal

 include/linux/efi.h|  34 
 security/integrity/Kconfig |  11 ++
 security/integrity/Makefile|   5 +
 security/integrity/digsig.c| 115 
 security/integrity/ima/ima_appraise.c  |  13 +-
 security/integrity/integrity.h |  23 ++-
 security/integrity/platform_certs/efi_parser.c | 108 
 security/integrity/platform_certs/load_uefi.c  | 196 +
 .../integrity/platform_certs/platform_keyring.c|  62 +++
 9 files changed, 528 insertions(+), 39 deletions(-)
 create mode 100644 security/integrity/platform_certs/efi_parser.c
 create mode 100644 security/integrity/platform_certs/load_uefi.c
 create mode 100644 security/integrity/platform_certs/platform_keyring.c

-- 
2.13.6



[PATCH v2 1/7] integrity: Define a trusted platform keyring

2018-12-08 Thread Nayna Jain
On secure boot enabled systems, a verified kernel may need to kexec
additional kernels. For example, it may be used as a bootloader needing
to kexec a target kernel or it may need to kexec a crashdump kernel. In
such cases, it may want to verify the signature of the next kernel
image.

It is further possible that the kernel image is signed with third party
keys which are stored as platform or firmware keys in the 'db' variable.
The kernel, however, can not directly verify these platform keys, and an
administrator may therefore not want to trust them for arbitrary usage.
In order to differentiate platform keys from other keys and provide the
necessary separation of trust, the kernel needs an additional keyring to
store platform keys.

This patch creates the new keyring called ".platform" to isolate keys
provided by platform from keys by kernel. These keys are used to
facilitate signature verification during kexec. Since the scope of this
keyring is only the platform/firmware keys, it cannot be updated from
userspace.

This keyring can be enabled by setting CONFIG_INTEGRITY_PLATFORM_KEYRING.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Acked-by: Serge Hallyn 
---
 security/integrity/Kconfig | 11 +
 security/integrity/Makefile|  1 +
 security/integrity/digsig.c| 48 +++---
 security/integrity/integrity.h |  3 +-
 .../integrity/platform_certs/platform_keyring.c| 39 ++
 5 files changed, 87 insertions(+), 15 deletions(-)
 create mode 100644 security/integrity/platform_certs/platform_keyring.c

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index da9565891738..4b4d2aeef539 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -51,6 +51,17 @@ config INTEGRITY_TRUSTED_KEYRING
   .evm keyrings be signed by a key on the system trusted
   keyring.
 
+config INTEGRITY_PLATFORM_KEYRING
+bool "Provide keyring for platform/firmware trusted keys"
+depends on INTEGRITY_ASYMMETRIC_KEYS
+depends on SYSTEM_BLACKLIST_KEYRING
+depends on EFI
+help
+ Provide a separate, distinct keyring for platform trusted keys, which
+ the kernel automatically populates during initialization from values
+ provided by the platform for verifying the kexec'ed kerned image
+ and, possibly, the initramfs signature.
+
 config INTEGRITY_AUDIT
bool "Enables integrity auditing support "
depends on AUDIT
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 04d6e462b079..046ffc1bb42d 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -9,6 +9,7 @@ integrity-y := iint.o
 integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
+integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 5eacba858e4b..b5b180ff1434 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -35,6 +35,7 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] 
= {
".ima",
 #endif
"_module",
+   ".platform",
 };
 
 #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
@@ -73,12 +74,40 @@ int integrity_digsig_verify(const unsigned int id, const 
char *sig, int siglen,
return -EOPNOTSUPP;
 }
 
-int __init integrity_init_keyring(const unsigned int id)
+static int __integrity_init_keyring(const unsigned int id, key_perm_t perm,
+   struct key_restriction *restriction)
 {
const struct cred *cred = current_cred();
+   int err = 0;
+
+   keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
+   KGIDT_INIT(0), cred, perm,
+   KEY_ALLOC_NOT_IN_QUOTA,
+   restriction, NULL);
+   if (IS_ERR(keyring[id])) {
+   err = PTR_ERR(keyring[id]);
+   pr_info("Can't allocate %s keyring (%d)\n",
+   keyring_name[id], err);
+   keyring[id] = NULL;
+   }
+
+   return err;
+}
+
+int __init integrity_init_keyring(const unsigned int id)
+{
struct key_restriction *restriction;
+   key_perm_t perm;
int err = 0;
 
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
+   | KEY_USR_READ | KEY_USR_SEARCH;
+
+   if (id == INTEGRITY_KEYRING_PLATFORM) {
+   restriction = NULL;
+   goto out;
+   }
+
if (!IS_ENABLED(CONFIG_INTEGR

Re: [PATCH v6 4/7] tpm: modify tpm_pcr_read() definition to pass a TPM hash algorithm

2018-12-06 Thread Nayna Jain



On 12/05/2018 05:10 AM, Jarkko Sakkinen wrote:

On Tue, Dec 04, 2018 at 09:21:35AM +0100, Roberto Sassu wrote:

Currently the TPM driver allows other kernel subsystems to read only the
SHA1 PCR bank. This patch modifies the parameters of tpm_pcr_read() and
tpm2_pcr_read() to pass a tpm_digest structure, which contains the desired
hash algorithm. Also, since commit 125a22105410 ("tpm: React correctly to
RC_TESTING from TPM 2.0 self tests") removed the call to tpm2_pcr_read(),
the new parameter is expected to be always not NULL.

Due to the API change, IMA functions have been modified.

Signed-off-by: Roberto Sassu 
Acked-by: Mimi Zohar 

Reviewed-by: Jarkko Sakkinen 

Mimi, Nayna, can you help with testing this (because of the IMA change)?


Sure, I will try to do by end of my day tomorrow,

Thanks & Regards,
    - Nayna



/Jarkko





Re: [PATCH v6 4/7] tpm: modify tpm_pcr_read() definition to pass a TPM hash algorithm

2018-12-06 Thread Nayna Jain



On 12/05/2018 05:10 AM, Jarkko Sakkinen wrote:

On Tue, Dec 04, 2018 at 09:21:35AM +0100, Roberto Sassu wrote:

Currently the TPM driver allows other kernel subsystems to read only the
SHA1 PCR bank. This patch modifies the parameters of tpm_pcr_read() and
tpm2_pcr_read() to pass a tpm_digest structure, which contains the desired
hash algorithm. Also, since commit 125a22105410 ("tpm: React correctly to
RC_TESTING from TPM 2.0 self tests") removed the call to tpm2_pcr_read(),
the new parameter is expected to be always not NULL.

Due to the API change, IMA functions have been modified.

Signed-off-by: Roberto Sassu 
Acked-by: Mimi Zohar 

Reviewed-by: Jarkko Sakkinen 

Mimi, Nayna, can you help with testing this (because of the IMA change)?


Sure, I will try to do by end of my day tomorrow,

Thanks & Regards,
    - Nayna



/Jarkko





Re: [PATCH v4 1/6] tpm: dynamically allocate active_banks array

2018-11-08 Thread Nayna Jain




On 11/07/2018 03:11 PM, Roberto Sassu wrote:

On 11/7/2018 7:14 AM, Nayna Jain wrote:



On 11/06/2018 08:31 PM, Roberto Sassu wrote:

This patch removes the hard-coded limit of the active_banks array size.



The hard-coded limit in static array active_banks[] represents the 
maximum possible banks.

A TPM might have three banks, but only one bank may be active.

To confirm my understanding, is the idea for this patch is to 
dynamically identify the number of possible banks or the number of 
active banks ?


The idea is to dynamically identify the number of active banks.

In the TPM Commands specification (section 30.2.1), I found:

TPM_CAP_PCRS – Returns the current allocation of PCR in a
TPML_PCR_SELECTION.

You mentioned:

#TPM_RC_SIZE response code when count is greater
than the possible number of banks

but TPML_PCR_SELECTION is provided by the TPM.


Based on a discussion with Ken, the count in the TPML_PCR_SELECTION 
returns the number of possible algorithms supported. In the example 
below, two possible algorithms - SHA1 and SHA256 - are returned.


# /usr/local/bin/tssgetcapability -cap 5
2 PCR selections
hash TPM_ALG_SHA1
TPMS_PCR_SELECTION length 3
ff ff ff
hash TPM_ALG_SHA256
TPMS_PCR_SELECTION length 3
00 00 00

The pcr_select fields - "ff ff ff" and "00 00 00" - are bit masks for 
the enabled PCRs. The SHA1 bank is enabled for all PCRs (0-23), while 
the SHA256 bank is not enabled.


The current code works, but it unnecessarily extends some banks. Instead 
of basing the number of active banks on the number of algorithms 
returned, it should be based on the pcr_select field.


   - Mimi & Nayna




Roberto



It stores in the tpm_chip structure the number of active PCR banks,
determined in tpm2_get_pcr_allocation(), and replaces the static array
with a pointer to a dynamically allocated array.

As a consequence of the introduction of nr_active_banks, 
tpm_pcr_extend()

does not check anymore if the algorithm stored in tpm_chip is equal to
zero. The active_banks array always contains valid algorithms.

Fixes: 1db15344f874 ("tpm: implement TPM 2.0 capability to get active
PCR banks")

Signed-off-by: Roberto Sassu 
---
  drivers/char/tpm/tpm-chip.c  |  1 +
  drivers/char/tpm/tpm-interface.c | 19 ---
  drivers/char/tpm/tpm.h   |  3 ++-
  drivers/char/tpm/tpm2-cmd.c  | 17 -
  4 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 46caadca916a..2a9e8b744436 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -160,6 +160,7 @@ static void tpm_dev_release(struct device *dev)
  kfree(chip->log.bios_event_log);
  kfree(chip->work_space.context_buf);
  kfree(chip->work_space.session_buf);
+    kfree(chip->active_banks);
  kfree(chip);
  }

diff --git a/drivers/char/tpm/tpm-interface.c 
b/drivers/char/tpm/tpm-interface.c

index 1a803b0cf980..ba7ca6b3e664 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1039,8 +1039,7 @@ static int tpm1_pcr_extend(struct tpm_chip 
*chip, int pcr_idx, const u8 *hash,
  int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 
*hash)

  {
  int rc;
-    struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)];
-    u32 count = 0;
+    struct tpm2_digest *digest_list;
  int i;

  chip = tpm_find_get_ops(chip);
@@ -1048,16 +1047,22 @@ int tpm_pcr_extend(struct tpm_chip *chip, 
int pcr_idx, const u8 *hash)

  return -ENODEV;

  if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-    memset(digest_list, 0, sizeof(digest_list));
+    digest_list = kmalloc_array(chip->nr_active_banks,
+    sizeof(*digest_list), GFP_KERNEL);
+    if (!digest_list)
+    return -ENOMEM;

-    for (i = 0; i < ARRAY_SIZE(chip->active_banks) &&
-    chip->active_banks[i] != TPM2_ALG_ERROR; i++) {
+    memset(digest_list, 0,
+   chip->nr_active_banks * sizeof(*digest_list));
+
+    for (i = 0; i < chip->nr_active_banks; i++) {
  digest_list[i].alg_id = chip->active_banks[i];
  memcpy(digest_list[i].digest, hash, TPM_DIGEST_SIZE);
-    count++;
  }

-    rc = tpm2_pcr_extend(chip, pcr_idx, count, digest_list);
+    rc = tpm2_pcr_extend(chip, pcr_idx, chip->nr_active_banks,
+ digest_list);
+    kfree(digest_list);
  tpm_put_ops(chip);
  return rc;
  }
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f3501d05264f..98368c3a6ff7 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -248,7 +248,8 @@ struct tpm_chip {
  const struct attribute_group *groups[3];
  unsigned int groups_cnt;

-    u16 active_banks[7];
+    u32 nr_active_banks;
+    u16 *a

Re: [PATCH v4 1/6] tpm: dynamically allocate active_banks array

2018-11-08 Thread Nayna Jain




On 11/07/2018 03:11 PM, Roberto Sassu wrote:

On 11/7/2018 7:14 AM, Nayna Jain wrote:



On 11/06/2018 08:31 PM, Roberto Sassu wrote:

This patch removes the hard-coded limit of the active_banks array size.



The hard-coded limit in static array active_banks[] represents the 
maximum possible banks.

A TPM might have three banks, but only one bank may be active.

To confirm my understanding, is the idea for this patch is to 
dynamically identify the number of possible banks or the number of 
active banks ?


The idea is to dynamically identify the number of active banks.

In the TPM Commands specification (section 30.2.1), I found:

TPM_CAP_PCRS – Returns the current allocation of PCR in a
TPML_PCR_SELECTION.

You mentioned:

#TPM_RC_SIZE response code when count is greater
than the possible number of banks

but TPML_PCR_SELECTION is provided by the TPM.


Based on a discussion with Ken, the count in the TPML_PCR_SELECTION 
returns the number of possible algorithms supported. In the example 
below, two possible algorithms - SHA1 and SHA256 - are returned.


# /usr/local/bin/tssgetcapability -cap 5
2 PCR selections
hash TPM_ALG_SHA1
TPMS_PCR_SELECTION length 3
ff ff ff
hash TPM_ALG_SHA256
TPMS_PCR_SELECTION length 3
00 00 00

The pcr_select fields - "ff ff ff" and "00 00 00" - are bit masks for 
the enabled PCRs. The SHA1 bank is enabled for all PCRs (0-23), while 
the SHA256 bank is not enabled.


The current code works, but it unnecessarily extends some banks. Instead 
of basing the number of active banks on the number of algorithms 
returned, it should be based on the pcr_select field.


   - Mimi & Nayna




Roberto



It stores in the tpm_chip structure the number of active PCR banks,
determined in tpm2_get_pcr_allocation(), and replaces the static array
with a pointer to a dynamically allocated array.

As a consequence of the introduction of nr_active_banks, 
tpm_pcr_extend()

does not check anymore if the algorithm stored in tpm_chip is equal to
zero. The active_banks array always contains valid algorithms.

Fixes: 1db15344f874 ("tpm: implement TPM 2.0 capability to get active
PCR banks")

Signed-off-by: Roberto Sassu 
---
  drivers/char/tpm/tpm-chip.c  |  1 +
  drivers/char/tpm/tpm-interface.c | 19 ---
  drivers/char/tpm/tpm.h   |  3 ++-
  drivers/char/tpm/tpm2-cmd.c  | 17 -
  4 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 46caadca916a..2a9e8b744436 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -160,6 +160,7 @@ static void tpm_dev_release(struct device *dev)
  kfree(chip->log.bios_event_log);
  kfree(chip->work_space.context_buf);
  kfree(chip->work_space.session_buf);
+    kfree(chip->active_banks);
  kfree(chip);
  }

diff --git a/drivers/char/tpm/tpm-interface.c 
b/drivers/char/tpm/tpm-interface.c

index 1a803b0cf980..ba7ca6b3e664 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1039,8 +1039,7 @@ static int tpm1_pcr_extend(struct tpm_chip 
*chip, int pcr_idx, const u8 *hash,
  int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 
*hash)

  {
  int rc;
-    struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)];
-    u32 count = 0;
+    struct tpm2_digest *digest_list;
  int i;

  chip = tpm_find_get_ops(chip);
@@ -1048,16 +1047,22 @@ int tpm_pcr_extend(struct tpm_chip *chip, 
int pcr_idx, const u8 *hash)

  return -ENODEV;

  if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-    memset(digest_list, 0, sizeof(digest_list));
+    digest_list = kmalloc_array(chip->nr_active_banks,
+    sizeof(*digest_list), GFP_KERNEL);
+    if (!digest_list)
+    return -ENOMEM;

-    for (i = 0; i < ARRAY_SIZE(chip->active_banks) &&
-    chip->active_banks[i] != TPM2_ALG_ERROR; i++) {
+    memset(digest_list, 0,
+   chip->nr_active_banks * sizeof(*digest_list));
+
+    for (i = 0; i < chip->nr_active_banks; i++) {
  digest_list[i].alg_id = chip->active_banks[i];
  memcpy(digest_list[i].digest, hash, TPM_DIGEST_SIZE);
-    count++;
  }

-    rc = tpm2_pcr_extend(chip, pcr_idx, count, digest_list);
+    rc = tpm2_pcr_extend(chip, pcr_idx, chip->nr_active_banks,
+ digest_list);
+    kfree(digest_list);
  tpm_put_ops(chip);
  return rc;
  }
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f3501d05264f..98368c3a6ff7 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -248,7 +248,8 @@ struct tpm_chip {
  const struct attribute_group *groups[3];
  unsigned int groups_cnt;

-    u16 active_banks[7];
+    u32 nr_active_banks;
+    u16 *a

Re: [PATCH v4 1/6] tpm: dynamically allocate active_banks array

2018-11-06 Thread Nayna Jain




On 11/06/2018 08:31 PM, Roberto Sassu wrote:

This patch removes the hard-coded limit of the active_banks array size.



The hard-coded limit in static array active_banks[] represents the 
maximum possible banks.

A TPM might have three banks, but only one bank may be active.

To confirm my understanding, is the idea for this patch is to 
dynamically identify the number of possible banks or the number of 
active banks ?




It stores in the tpm_chip structure the number of active PCR banks,
determined in tpm2_get_pcr_allocation(), and replaces the static array
with a pointer to a dynamically allocated array.

As a consequence of the introduction of nr_active_banks, tpm_pcr_extend()
does not check anymore if the algorithm stored in tpm_chip is equal to
zero. The active_banks array always contains valid algorithms.

Fixes: 1db15344f874 ("tpm: implement TPM 2.0 capability to get active
PCR banks")

Signed-off-by: Roberto Sassu 
---
  drivers/char/tpm/tpm-chip.c  |  1 +
  drivers/char/tpm/tpm-interface.c | 19 ---
  drivers/char/tpm/tpm.h   |  3 ++-
  drivers/char/tpm/tpm2-cmd.c  | 17 -
  4 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 46caadca916a..2a9e8b744436 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -160,6 +160,7 @@ static void tpm_dev_release(struct device *dev)
kfree(chip->log.bios_event_log);
kfree(chip->work_space.context_buf);
kfree(chip->work_space.session_buf);
+   kfree(chip->active_banks);
kfree(chip);
  }

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 1a803b0cf980..ba7ca6b3e664 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1039,8 +1039,7 @@ static int tpm1_pcr_extend(struct tpm_chip *chip, int 
pcr_idx, const u8 *hash,
  int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
  {
int rc;
-   struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)];
-   u32 count = 0;
+   struct tpm2_digest *digest_list;
int i;

chip = tpm_find_get_ops(chip);
@@ -1048,16 +1047,22 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, 
const u8 *hash)
return -ENODEV;

if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-   memset(digest_list, 0, sizeof(digest_list));
+   digest_list = kmalloc_array(chip->nr_active_banks,
+   sizeof(*digest_list), GFP_KERNEL);
+   if (!digest_list)
+   return -ENOMEM;

-   for (i = 0; i < ARRAY_SIZE(chip->active_banks) &&
-   chip->active_banks[i] != TPM2_ALG_ERROR; i++) {
+   memset(digest_list, 0,
+  chip->nr_active_banks * sizeof(*digest_list));
+
+   for (i = 0; i < chip->nr_active_banks; i++) {
digest_list[i].alg_id = chip->active_banks[i];
memcpy(digest_list[i].digest, hash, TPM_DIGEST_SIZE);
-   count++;
}

-   rc = tpm2_pcr_extend(chip, pcr_idx, count, digest_list);
+   rc = tpm2_pcr_extend(chip, pcr_idx, chip->nr_active_banks,
+digest_list);
+   kfree(digest_list);
tpm_put_ops(chip);
return rc;
}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f3501d05264f..98368c3a6ff7 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -248,7 +248,8 @@ struct tpm_chip {
const struct attribute_group *groups[3];
unsigned int groups_cnt;

-   u16 active_banks[7];
+   u32 nr_active_banks;
+   u16 *active_banks;
  #ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index c31b490bd41d..533089cede07 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -242,7 +242,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 
count,
int i;
int j;

-   if (count > ARRAY_SIZE(chip->active_banks))
+   if (count > chip->nr_active_banks)
return -EINVAL;

rc = tpm_buf_init(, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
@@ -859,7 +859,6 @@ static ssize_t tpm2_get_pcr_allocation(struct tpm_chip 
*chip)
void *marker;
void *end;
void *pcr_select_offset;
-   unsigned int count;
u32 sizeof_pcr_selection;
u32 rsp_len;
int rc;
@@ -878,11 +877,14 @@ static ssize_t tpm2_get_pcr_allocation(struct tpm_chip 
*chip)
if (rc)
goto out;

-   count = be32_to_cpup(
+   chip->nr_active_banks = be32_to_cpup(
(__be32 *)[TPM_HEADER_SIZE + 5]);



As per 

Re: [PATCH v4 1/6] tpm: dynamically allocate active_banks array

2018-11-06 Thread Nayna Jain




On 11/06/2018 08:31 PM, Roberto Sassu wrote:

This patch removes the hard-coded limit of the active_banks array size.



The hard-coded limit in static array active_banks[] represents the 
maximum possible banks.

A TPM might have three banks, but only one bank may be active.

To confirm my understanding, is the idea for this patch is to 
dynamically identify the number of possible banks or the number of 
active banks ?




It stores in the tpm_chip structure the number of active PCR banks,
determined in tpm2_get_pcr_allocation(), and replaces the static array
with a pointer to a dynamically allocated array.

As a consequence of the introduction of nr_active_banks, tpm_pcr_extend()
does not check anymore if the algorithm stored in tpm_chip is equal to
zero. The active_banks array always contains valid algorithms.

Fixes: 1db15344f874 ("tpm: implement TPM 2.0 capability to get active
PCR banks")

Signed-off-by: Roberto Sassu 
---
  drivers/char/tpm/tpm-chip.c  |  1 +
  drivers/char/tpm/tpm-interface.c | 19 ---
  drivers/char/tpm/tpm.h   |  3 ++-
  drivers/char/tpm/tpm2-cmd.c  | 17 -
  4 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 46caadca916a..2a9e8b744436 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -160,6 +160,7 @@ static void tpm_dev_release(struct device *dev)
kfree(chip->log.bios_event_log);
kfree(chip->work_space.context_buf);
kfree(chip->work_space.session_buf);
+   kfree(chip->active_banks);
kfree(chip);
  }

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 1a803b0cf980..ba7ca6b3e664 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1039,8 +1039,7 @@ static int tpm1_pcr_extend(struct tpm_chip *chip, int 
pcr_idx, const u8 *hash,
  int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
  {
int rc;
-   struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)];
-   u32 count = 0;
+   struct tpm2_digest *digest_list;
int i;

chip = tpm_find_get_ops(chip);
@@ -1048,16 +1047,22 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, 
const u8 *hash)
return -ENODEV;

if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-   memset(digest_list, 0, sizeof(digest_list));
+   digest_list = kmalloc_array(chip->nr_active_banks,
+   sizeof(*digest_list), GFP_KERNEL);
+   if (!digest_list)
+   return -ENOMEM;

-   for (i = 0; i < ARRAY_SIZE(chip->active_banks) &&
-   chip->active_banks[i] != TPM2_ALG_ERROR; i++) {
+   memset(digest_list, 0,
+  chip->nr_active_banks * sizeof(*digest_list));
+
+   for (i = 0; i < chip->nr_active_banks; i++) {
digest_list[i].alg_id = chip->active_banks[i];
memcpy(digest_list[i].digest, hash, TPM_DIGEST_SIZE);
-   count++;
}

-   rc = tpm2_pcr_extend(chip, pcr_idx, count, digest_list);
+   rc = tpm2_pcr_extend(chip, pcr_idx, chip->nr_active_banks,
+digest_list);
+   kfree(digest_list);
tpm_put_ops(chip);
return rc;
}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f3501d05264f..98368c3a6ff7 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -248,7 +248,8 @@ struct tpm_chip {
const struct attribute_group *groups[3];
unsigned int groups_cnt;

-   u16 active_banks[7];
+   u32 nr_active_banks;
+   u16 *active_banks;
  #ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index c31b490bd41d..533089cede07 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -242,7 +242,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 
count,
int i;
int j;

-   if (count > ARRAY_SIZE(chip->active_banks))
+   if (count > chip->nr_active_banks)
return -EINVAL;

rc = tpm_buf_init(, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND);
@@ -859,7 +859,6 @@ static ssize_t tpm2_get_pcr_allocation(struct tpm_chip 
*chip)
void *marker;
void *end;
void *pcr_select_offset;
-   unsigned int count;
u32 sizeof_pcr_selection;
u32 rsp_len;
int rc;
@@ -878,11 +877,14 @@ static ssize_t tpm2_get_pcr_allocation(struct tpm_chip 
*chip)
if (rc)
goto out;

-   count = be32_to_cpup(
+   chip->nr_active_banks = be32_to_cpup(
(__be32 *)[TPM_HEADER_SIZE + 5]);



As per 

Re: [PATCH] tpm: tpm_i2c_nuvoton: use correct command duration for TPM 2.x

2018-10-18 Thread Nayna Jain




On 10/17/2018 10:02 PM, Tomas Winkler wrote:

diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c 
b/drivers/char/tpm/tpm_i2c_nuvoton.c
index caa86b19c76d..f74f451baf6a 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -369,6 +369,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, 
size_t len)
struct device *dev = chip->dev.parent;
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
+   unsigned long duration;
size_t count = 0;
int burst_count, bytes2write, retries, rc = -EIO;

@@ -455,10 +456,12 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 
*buf, size_t len)
return rc;
}
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
-   rc = i2c_nuvoton_wait_for_data_avail(chip,
-tpm_calc_ordinal_duration(chip,
-  ordinal),
->read_queue);
+   if (chip->flags & TPM_CHIP_FLAG_TPM2)
+   duration = tpm2_calc_ordinal_duration(chip, ordinal);
+   else
+   duration = tpm_calc_ordinal_duration(chip, ordinal);
+
+   rc = i2c_nuvoton_wait_for_data_avail(chip, duration, >read_queue);
if (rc) {
dev_err(dev, "%s() timeout command duration\n", __func__);
i2c_nuvoton_ready(chip);


I only have Nuvoton TPM 2.0, tested for that.

Reviewed-by: Nayna Jain 
Tested-by: Nayna Jain  (For TPM 2.0)


Thanks & Regards,
    - Nayna




Re: [PATCH] tpm: tpm_i2c_nuvoton: use correct command duration for TPM 2.x

2018-10-18 Thread Nayna Jain




On 10/17/2018 10:02 PM, Tomas Winkler wrote:

diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c 
b/drivers/char/tpm/tpm_i2c_nuvoton.c
index caa86b19c76d..f74f451baf6a 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -369,6 +369,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, 
size_t len)
struct device *dev = chip->dev.parent;
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
+   unsigned long duration;
size_t count = 0;
int burst_count, bytes2write, retries, rc = -EIO;

@@ -455,10 +456,12 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 
*buf, size_t len)
return rc;
}
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
-   rc = i2c_nuvoton_wait_for_data_avail(chip,
-tpm_calc_ordinal_duration(chip,
-  ordinal),
->read_queue);
+   if (chip->flags & TPM_CHIP_FLAG_TPM2)
+   duration = tpm2_calc_ordinal_duration(chip, ordinal);
+   else
+   duration = tpm_calc_ordinal_duration(chip, ordinal);
+
+   rc = i2c_nuvoton_wait_for_data_avail(chip, duration, >read_queue);
if (rc) {
dev_err(dev, "%s() timeout command duration\n", __func__);
i2c_nuvoton_ready(chip);


I only have Nuvoton TPM 2.0, tested for that.

Reviewed-by: Nayna Jain 
Tested-by: Nayna Jain  (For TPM 2.0)


Thanks & Regards,
    - Nayna




Re: [PATCH v6 03/20] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

2018-10-17 Thread Nayna Jain




On 10/17/2018 05:54 PM, Winkler, Tomas wrote:



ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
-   rc = i2c_nuvoton_wait_for_data_avail(chip,
-tpm_calc_ordinal_duration(chip,
-  ordinal),
->read_queue);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);


This version of the patch didn't address my previous comment - "The original
code in the nuvoton driver does not differentiate between TPM 1.2 and TPM
2.0 as it does in tpm_tis_core.c.
Before making any changes, I would first fix it, so that it could easily be
backported. Only then do the refactoring."

This patch doesn't change the original behavior, just change the name of the 
function,  so there is no regression.
I would suggest there is another bug in those drivers/devices that is 
orthogonal to this refactoring and should not block this from merging.


The problem is that you are inadvertently fixing a bug without realizing 
it - [Patch 04/20]. Bug fixes should be addressed independently

of this change, so that they can be backported properly.


According to what you say  it can call just tpm_calc_oridnal_duration() instead 
of tpm1_calc_ordinal_duration(chip, ordinal),
but I prefer that someone that has those devices will do that change on top of 
this series as  I cannot test it.


The problem is:

1. This patch calls tpm1_calc_ordinal_duration for both the TPM 1.2 and 
TPM 2.0.
2. In the next patch, it adds a new function tpm_calc_ordinal_duration 
as a wrapper for both the TPM 1.2 and TPM 2.0. After this change when it 
calls tpm_calc_ordinal_duration(),
it now calls different functions for TPM 1.2 and TPM 2.0. This is a 
change in behavior.


Thanks & Regards,
   - Nayna


Thanks
Tomas





Re: [PATCH v6 03/20] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

2018-10-17 Thread Nayna Jain




On 10/17/2018 05:54 PM, Winkler, Tomas wrote:



ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
-   rc = i2c_nuvoton_wait_for_data_avail(chip,
-tpm_calc_ordinal_duration(chip,
-  ordinal),
->read_queue);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);


This version of the patch didn't address my previous comment - "The original
code in the nuvoton driver does not differentiate between TPM 1.2 and TPM
2.0 as it does in tpm_tis_core.c.
Before making any changes, I would first fix it, so that it could easily be
backported. Only then do the refactoring."

This patch doesn't change the original behavior, just change the name of the 
function,  so there is no regression.
I would suggest there is another bug in those drivers/devices that is 
orthogonal to this refactoring and should not block this from merging.


The problem is that you are inadvertently fixing a bug without realizing 
it - [Patch 04/20]. Bug fixes should be addressed independently

of this change, so that they can be backported properly.


According to what you say  it can call just tpm_calc_oridnal_duration() instead 
of tpm1_calc_ordinal_duration(chip, ordinal),
but I prefer that someone that has those devices will do that change on top of 
this series as  I cannot test it.


The problem is:

1. This patch calls tpm1_calc_ordinal_duration for both the TPM 1.2 and 
TPM 2.0.
2. In the next patch, it adds a new function tpm_calc_ordinal_duration 
as a wrapper for both the TPM 1.2 and TPM 2.0. After this change when it 
calls tpm_calc_ordinal_duration(),
it now calls different functions for TPM 1.2 and TPM 2.0. This is a 
change in behavior.


Thanks & Regards,
   - Nayna


Thanks
Tomas





Re: [PATCH v6 03/20] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

2018-10-17 Thread Nayna Jain




On 10/17/2018 12:15 PM, Tomas Winkler wrote:

diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c 
b/drivers/char/tpm/tpm_i2c_nuvoton.c
index caa86b19c76d..5d20e98b844f 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -370,6 +370,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, 
size_t len)
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
size_t count = 0;
+   unsigned long duration;
int burst_count, bytes2write, retries, rc = -EIO;

for (retries = 0; retries < TPM_RETRY; retries++) {
@@ -455,12 +456,11 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 
*buf, size_t len)
return rc;
}
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
-   rc = i2c_nuvoton_wait_for_data_avail(chip,
-tpm_calc_ordinal_duration(chip,
-  ordinal),
->read_queue);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);



This version of the patch didn't address my previous comment -
"The original code in the nuvoton driver does not differentiate between 
TPM 1.2 and TPM 2.0 as it does in tpm_tis_core.c.
Before making any changes, I would first fix it, so that it could easily 
be backported. Only then do the refactoring."


Thanks & Regards,
   - Nayna



+   rc = i2c_nuvoton_wait_for_data_avail(chip, duration, >read_queue);
if (rc) {
-   dev_err(dev, "%s() timeout command duration\n", __func__);
+   dev_err(dev, "%s() timeout command duration %ld\n",
+   __func__, duration);
i2c_nuvoton_ready(chip);
return rc;
}
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index d2345d9fd7b5..14c332104de4 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -476,7 +476,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const 
u8 *buf, size_t len)
if (chip->flags & TPM_CHIP_FLAG_TPM2)
dur = tpm2_calc_ordinal_duration(chip, ordinal);
else
-   dur = tpm_calc_ordinal_duration(chip, ordinal);
+   dur = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index b150f87f38f5..77097229bf49 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -164,7 +164,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t 
count)
notify_remote_via_evtchn(priv->evtchn);

ordinal = be32_to_cpu(((struct tpm_input_header*)buf)->ordinal);
-   duration = tpm_calc_ordinal_duration(chip, ordinal);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration,
>read_queue, true) < 0) {




Re: [PATCH v6 03/20] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

2018-10-17 Thread Nayna Jain




On 10/17/2018 12:15 PM, Tomas Winkler wrote:

diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c 
b/drivers/char/tpm/tpm_i2c_nuvoton.c
index caa86b19c76d..5d20e98b844f 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -370,6 +370,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, 
size_t len)
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
size_t count = 0;
+   unsigned long duration;
int burst_count, bytes2write, retries, rc = -EIO;

for (retries = 0; retries < TPM_RETRY; retries++) {
@@ -455,12 +456,11 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 
*buf, size_t len)
return rc;
}
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
-   rc = i2c_nuvoton_wait_for_data_avail(chip,
-tpm_calc_ordinal_duration(chip,
-  ordinal),
->read_queue);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);



This version of the patch didn't address my previous comment -
"The original code in the nuvoton driver does not differentiate between 
TPM 1.2 and TPM 2.0 as it does in tpm_tis_core.c.
Before making any changes, I would first fix it, so that it could easily 
be backported. Only then do the refactoring."


Thanks & Regards,
   - Nayna



+   rc = i2c_nuvoton_wait_for_data_avail(chip, duration, >read_queue);
if (rc) {
-   dev_err(dev, "%s() timeout command duration\n", __func__);
+   dev_err(dev, "%s() timeout command duration %ld\n",
+   __func__, duration);
i2c_nuvoton_ready(chip);
return rc;
}
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index d2345d9fd7b5..14c332104de4 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -476,7 +476,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const 
u8 *buf, size_t len)
if (chip->flags & TPM_CHIP_FLAG_TPM2)
dur = tpm2_calc_ordinal_duration(chip, ordinal);
else
-   dur = tpm_calc_ordinal_duration(chip, ordinal);
+   dur = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index b150f87f38f5..77097229bf49 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -164,7 +164,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t 
count)
notify_remote_via_evtchn(priv->evtchn);

ordinal = be32_to_cpu(((struct tpm_input_header*)buf)->ordinal);
-   duration = tpm_calc_ordinal_duration(chip, ordinal);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration,
>read_queue, true) < 0) {




Re: [PATCH v5 20/21] tpm1: reimplement tpm1_continue_selftest() using tpm_buf

2018-10-17 Thread Nayna Jain




On 09/29/2018 04:00 AM, Tomas Winkler wrote:

Reimplement tpm1_continue_selftest() using tpm_buf structure.
This is the last command using the old tpm_cmd_t structure
and now the structure can be removed.

Cc: Nayna Jain 
Signed-off-by: Tomas Winkler 
Reviewed-by: Jarkko Sakkinen 
Tested-by: Jarkko Sakkinen 
---

V3: New in the series.
V4: Resend.
V5: Fix  -> buf.data in tpm1_continue_selftest()

  drivers/char/tpm/tpm.h  |  9 -
  drivers/char/tpm/tpm1-cmd.c | 21 ++---
  2 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2f06740f993d..7ada00f067f1 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -377,15 +377,6 @@ enum tpm_sub_capabilities {
TPM_CAP_PROP_TIS_DURATION = 0x120,
  };

-typedef union {
-   struct  tpm_input_header in;
-   struct  tpm_output_header out;
-} tpm_cmd_header;
-
-struct tpm_cmd_t {
-   tpm_cmd_header  header;
-} __packed;
-

  /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
   * bytes, but 128 is still a relatively large number of random bytes and
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index d418a27a75e0..6b04648f8184 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -602,15 +602,8 @@ int tpm1_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 
*res_buf)
  }

  #define TPM_ORD_CONTINUE_SELFTEST 83
-#define CONTINUE_SELFTEST_RESULT_SIZE 10
-static const struct tpm_input_header continue_selftest_header = {
-   .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-   .length = cpu_to_be32(10),
-   .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
-};
-
  /**
- * tpm_continue_selftest -- run TPM's selftest
+ * tpm_continue_selftest() - run TPM's selftest
   * @chip: TPM chip to use
   *
   * Returns 0 on success, < 0 in case of fatal error or a value > 0 
representing
@@ -618,12 +611,18 @@ static const struct tpm_input_header 
continue_selftest_header = {
   */
  static int tpm1_continue_selftest(struct tpm_chip *chip)
  {
+   struct tpm_buf buf;
int rc;
-   struct tpm_cmd_t cmd;

-   cmd.header.in = continue_selftest_header;
-   rc = tpm_transmit_cmd(chip, NULL, , CONTINUE_SELFTEST_RESULT_SIZE,
+   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST);
+   if (rc)
+   return rc;
+
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
  0, 0, "continue selftest");
+
+   tpm_buf_destroy();
+
return rc;
  }




Reviewed-by: Nayna Jain 
Tested-by: Nayna Jain 


Thanks & Regards,
    - Nayna



Re: [PATCH v5 20/21] tpm1: reimplement tpm1_continue_selftest() using tpm_buf

2018-10-17 Thread Nayna Jain




On 09/29/2018 04:00 AM, Tomas Winkler wrote:

Reimplement tpm1_continue_selftest() using tpm_buf structure.
This is the last command using the old tpm_cmd_t structure
and now the structure can be removed.

Cc: Nayna Jain 
Signed-off-by: Tomas Winkler 
Reviewed-by: Jarkko Sakkinen 
Tested-by: Jarkko Sakkinen 
---

V3: New in the series.
V4: Resend.
V5: Fix  -> buf.data in tpm1_continue_selftest()

  drivers/char/tpm/tpm.h  |  9 -
  drivers/char/tpm/tpm1-cmd.c | 21 ++---
  2 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2f06740f993d..7ada00f067f1 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -377,15 +377,6 @@ enum tpm_sub_capabilities {
TPM_CAP_PROP_TIS_DURATION = 0x120,
  };

-typedef union {
-   struct  tpm_input_header in;
-   struct  tpm_output_header out;
-} tpm_cmd_header;
-
-struct tpm_cmd_t {
-   tpm_cmd_header  header;
-} __packed;
-

  /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
   * bytes, but 128 is still a relatively large number of random bytes and
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index d418a27a75e0..6b04648f8184 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -602,15 +602,8 @@ int tpm1_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 
*res_buf)
  }

  #define TPM_ORD_CONTINUE_SELFTEST 83
-#define CONTINUE_SELFTEST_RESULT_SIZE 10
-static const struct tpm_input_header continue_selftest_header = {
-   .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-   .length = cpu_to_be32(10),
-   .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
-};
-
  /**
- * tpm_continue_selftest -- run TPM's selftest
+ * tpm_continue_selftest() - run TPM's selftest
   * @chip: TPM chip to use
   *
   * Returns 0 on success, < 0 in case of fatal error or a value > 0 
representing
@@ -618,12 +611,18 @@ static const struct tpm_input_header 
continue_selftest_header = {
   */
  static int tpm1_continue_selftest(struct tpm_chip *chip)
  {
+   struct tpm_buf buf;
int rc;
-   struct tpm_cmd_t cmd;

-   cmd.header.in = continue_selftest_header;
-   rc = tpm_transmit_cmd(chip, NULL, , CONTINUE_SELFTEST_RESULT_SIZE,
+   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST);
+   if (rc)
+   return rc;
+
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
  0, 0, "continue selftest");
+
+   tpm_buf_destroy();
+
return rc;
  }




Reviewed-by: Nayna Jain 
Tested-by: Nayna Jain 


Thanks & Regards,
    - Nayna



Re: [PATCH v5 06/21] tpm: move tpm1_pcr_extend to tpm1-cmd.c

2018-10-12 Thread Nayna Jain




On 09/29/2018 04:00 AM, Tomas Winkler wrote:

Move tpm1_pcr_extend to tpm1-cmd.c and remove
unused pcrextend_header structure and
EXTEND_PCR_RESULT_SIZE and EXTEND_PCR_RESULT_BODY_SIZE
defines.

Fixes warning:
drivers/char/tpm/tpm-interface.c:609:38: warning: ‘pcrextend_header’ defined 
but not used [-Wunused-const-variable=]
  static const struct tpm_input_header pcrextend_header = {
   ^~~~

Signed-off-by: Tomas Winkler 
Reviewed-by: Jarkko Sakkinen 
---

V2-V3: Rebase
V4: Remove defines.
V5: Resend.

  drivers/char/tpm/tpm-interface.c | 28 
  drivers/char/tpm/tpm.h   |  2 ++
  drivers/char/tpm/tpm1-cmd.c  | 21 +
  3 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 1fa0300f3829..ac73e6ac3d83 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -614,34 +614,6 @@ int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 
*res_buf)
  }
  EXPORT_SYMBOL_GPL(tpm_pcr_read);

-#define TPM_ORD_PCR_EXTEND 20
-#define EXTEND_PCR_RESULT_SIZE 34
-#define EXTEND_PCR_RESULT_BODY_SIZE 20
-static const struct tpm_input_header pcrextend_header = {
-   .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-   .length = cpu_to_be32(34),
-   .ordinal = cpu_to_be32(TPM_ORD_PCR_EXTEND)
-};
-
-static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
-  char *log_msg)
-{
-   struct tpm_buf buf;
-   int rc;
-
-   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND);
-   if (rc)
-   return rc;
-
-   tpm_buf_append_u32(, pcr_idx);
-   tpm_buf_append(, hash, TPM_DIGEST_SIZE);
-
-   rc = tpm_transmit_cmd(chip, NULL, buf.data, EXTEND_PCR_RESULT_SIZE,
- EXTEND_PCR_RESULT_BODY_SIZE, 0, log_msg);
-   tpm_buf_destroy();
-   return rc;
-}
-
  /**
   * tpm_pcr_extend - extend a PCR value in SHA1 bank.
   * @chip: a  tpm_chip instance, %NULL for the default chip
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index a97d72fcda5b..3fb268f43955 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -549,6 +549,8 @@ int tpm_do_selftest(struct tpm_chip *chip);
  int tpm1_auto_startup(struct tpm_chip *chip);
  int tpm1_get_timeouts(struct tpm_chip *chip);
  unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
+int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
+   const char *log_msg);
  unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
  int tpm_pm_suspend(struct device *dev);
  int tpm_pm_resume(struct device *dev);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 978946748ea3..ec242397e6dc 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -413,3 +413,24 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
return 0;
  }
+
+#define TPM_ORD_PCR_EXTEND 20
+int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
+   const char *log_msg)
+{
+   struct tpm_buf buf;
+   int rc;
+
+   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND);
+   if (rc)
+   return rc;
+
+   tpm_buf_append_u32(, pcr_idx);
+   tpm_buf_append(, hash, TPM_DIGEST_SIZE);
+
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+ TPM_DIGEST_SIZE, 0, log_msg);
+
+   tpm_buf_destroy();
+   return rc;
+}



Reviewed-by: Nayna Jain 
Tested-by: Nayna Jain 

Sorry for bit delay in testing.

Thanks & Regards,
   - Nayna






Re: [PATCH v5 06/21] tpm: move tpm1_pcr_extend to tpm1-cmd.c

2018-10-12 Thread Nayna Jain




On 09/29/2018 04:00 AM, Tomas Winkler wrote:

Move tpm1_pcr_extend to tpm1-cmd.c and remove
unused pcrextend_header structure and
EXTEND_PCR_RESULT_SIZE and EXTEND_PCR_RESULT_BODY_SIZE
defines.

Fixes warning:
drivers/char/tpm/tpm-interface.c:609:38: warning: ‘pcrextend_header’ defined 
but not used [-Wunused-const-variable=]
  static const struct tpm_input_header pcrextend_header = {
   ^~~~

Signed-off-by: Tomas Winkler 
Reviewed-by: Jarkko Sakkinen 
---

V2-V3: Rebase
V4: Remove defines.
V5: Resend.

  drivers/char/tpm/tpm-interface.c | 28 
  drivers/char/tpm/tpm.h   |  2 ++
  drivers/char/tpm/tpm1-cmd.c  | 21 +
  3 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 1fa0300f3829..ac73e6ac3d83 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -614,34 +614,6 @@ int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 
*res_buf)
  }
  EXPORT_SYMBOL_GPL(tpm_pcr_read);

-#define TPM_ORD_PCR_EXTEND 20
-#define EXTEND_PCR_RESULT_SIZE 34
-#define EXTEND_PCR_RESULT_BODY_SIZE 20
-static const struct tpm_input_header pcrextend_header = {
-   .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-   .length = cpu_to_be32(34),
-   .ordinal = cpu_to_be32(TPM_ORD_PCR_EXTEND)
-};
-
-static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
-  char *log_msg)
-{
-   struct tpm_buf buf;
-   int rc;
-
-   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND);
-   if (rc)
-   return rc;
-
-   tpm_buf_append_u32(, pcr_idx);
-   tpm_buf_append(, hash, TPM_DIGEST_SIZE);
-
-   rc = tpm_transmit_cmd(chip, NULL, buf.data, EXTEND_PCR_RESULT_SIZE,
- EXTEND_PCR_RESULT_BODY_SIZE, 0, log_msg);
-   tpm_buf_destroy();
-   return rc;
-}
-
  /**
   * tpm_pcr_extend - extend a PCR value in SHA1 bank.
   * @chip: a  tpm_chip instance, %NULL for the default chip
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index a97d72fcda5b..3fb268f43955 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -549,6 +549,8 @@ int tpm_do_selftest(struct tpm_chip *chip);
  int tpm1_auto_startup(struct tpm_chip *chip);
  int tpm1_get_timeouts(struct tpm_chip *chip);
  unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
+int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
+   const char *log_msg);
  unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
  int tpm_pm_suspend(struct device *dev);
  int tpm_pm_resume(struct device *dev);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 978946748ea3..ec242397e6dc 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -413,3 +413,24 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
return 0;
  }
+
+#define TPM_ORD_PCR_EXTEND 20
+int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
+   const char *log_msg)
+{
+   struct tpm_buf buf;
+   int rc;
+
+   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND);
+   if (rc)
+   return rc;
+
+   tpm_buf_append_u32(, pcr_idx);
+   tpm_buf_append(, hash, TPM_DIGEST_SIZE);
+
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+ TPM_DIGEST_SIZE, 0, log_msg);
+
+   tpm_buf_destroy();
+   return rc;
+}



Reviewed-by: Nayna Jain 
Tested-by: Nayna Jain 

Sorry for bit delay in testing.

Thanks & Regards,
   - Nayna






Re: [PATCH v5 05/21] tpm: factor out tpm_get_timeouts()

2018-10-11 Thread Nayna Jain




On 09/29/2018 04:00 AM, Tomas Winkler wrote:


diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 73511cd89bef..a97d72fcda5b 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -544,8 +544,10 @@ int tpm_startup(struct tpm_chip *chip);
  ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
   const char *desc, size_t min_cap_length);
  int tpm_get_timeouts(struct tpm_chip *);
-int tpm1_auto_startup(struct tpm_chip *chip);
  int tpm_do_selftest(struct tpm_chip *chip);
+
+int tpm1_auto_startup(struct tpm_chip *chip);


What is different in this tpm1_auto_startup(...) and the original one ?

Is this needed ?

Thanks & Regards,
   - Nayna



+int tpm1_get_timeouts(struct tpm_chip *chip);
  unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
  unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
  int tpm_pm_suspend(struct device *dev);
@@ -585,6 +587,7 @@ static inline u32 tpm2_rc_value(u32 rc)
return (rc & BIT(7)) ? rc & 0xff : rc;
  }

+int tpm2_get_timeouts(struct tpm_chip *chip);
  int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
  int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
struct tpm2_digest *digests);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index dfbe9c60cbcf..978946748ea3 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -307,3 +307,109 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip 
*chip, u32 ordinal)
else
return duration;
  }
+
+int tpm1_get_timeouts(struct tpm_chip *chip)
+{
+   cap_t cap;
+   unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4];
+   ssize_t rc;
+
+   rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, , NULL,
+   sizeof(cap.timeout));
+   if (rc == TPM_ERR_INVALID_POSTINIT) {
+   if (tpm_startup(chip))
+   return rc;
+
+   rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, ,
+   "attempting to determine the timeouts",
+   sizeof(cap.timeout));
+   }
+
+   if (rc) {
+   dev_err(>dev, "A TPM error (%zd) occurred attempting to 
determine the timeouts\n",
+   rc);
+   return rc;
+   }
+
+   timeout_old[0] = jiffies_to_usecs(chip->timeout_a);
+   timeout_old[1] = jiffies_to_usecs(chip->timeout_b);
+   timeout_old[2] = jiffies_to_usecs(chip->timeout_c);
+   timeout_old[3] = jiffies_to_usecs(chip->timeout_d);
+   timeout_chip[0] = be32_to_cpu(cap.timeout.a);
+   timeout_chip[1] = be32_to_cpu(cap.timeout.b);
+   timeout_chip[2] = be32_to_cpu(cap.timeout.c);
+   timeout_chip[3] = be32_to_cpu(cap.timeout.d);
+   memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff));
+
+   /*
+* Provide ability for vendor overrides of timeout values in case
+* of misreporting.
+*/
+   if (chip->ops->update_timeouts)
+   chip->timeout_adjusted =
+   chip->ops->update_timeouts(chip, timeout_eff);
+
+   if (!chip->timeout_adjusted) {
+   /* Restore default if chip reported 0 */
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) {
+   if (timeout_eff[i])
+   continue;
+
+   timeout_eff[i] = timeout_old[i];
+   chip->timeout_adjusted = true;
+   }
+
+   if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) {
+   /* timeouts in msec rather usec */
+   for (i = 0; i != ARRAY_SIZE(timeout_eff); i++)
+   timeout_eff[i] *= 1000;
+   chip->timeout_adjusted = true;
+   }
+   }
+
+   /* Report adjusted timeouts */
+   if (chip->timeout_adjusted) {
+   dev_info(>dev, HW_ERR "Adjusting reported timeouts: A %lu->%luus B 
%lu->%luus C %lu->%luus D %lu->%luus\n",
+timeout_chip[0], timeout_eff[0],
+timeout_chip[1], timeout_eff[1],
+timeout_chip[2], timeout_eff[2],
+timeout_chip[3], timeout_eff[3]);
+   }
+
+   chip->timeout_a = usecs_to_jiffies(timeout_eff[0]);
+   chip->timeout_b = usecs_to_jiffies(timeout_eff[1]);
+   chip->timeout_c = usecs_to_jiffies(timeout_eff[2]);
+   chip->timeout_d = usecs_to_jiffies(timeout_eff[3]);
+
+   rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, ,
+   "attempting to determine the durations",
+   sizeof(cap.duration));
+   if (rc)
+   return rc;
+
+   chip->duration[TPM_SHORT] =
+   usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short));
+   

Re: [PATCH v5 05/21] tpm: factor out tpm_get_timeouts()

2018-10-11 Thread Nayna Jain




On 09/29/2018 04:00 AM, Tomas Winkler wrote:


diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 73511cd89bef..a97d72fcda5b 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -544,8 +544,10 @@ int tpm_startup(struct tpm_chip *chip);
  ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
   const char *desc, size_t min_cap_length);
  int tpm_get_timeouts(struct tpm_chip *);
-int tpm1_auto_startup(struct tpm_chip *chip);
  int tpm_do_selftest(struct tpm_chip *chip);
+
+int tpm1_auto_startup(struct tpm_chip *chip);


What is different in this tpm1_auto_startup(...) and the original one ?

Is this needed ?

Thanks & Regards,
   - Nayna



+int tpm1_get_timeouts(struct tpm_chip *chip);
  unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
  unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
  int tpm_pm_suspend(struct device *dev);
@@ -585,6 +587,7 @@ static inline u32 tpm2_rc_value(u32 rc)
return (rc & BIT(7)) ? rc & 0xff : rc;
  }

+int tpm2_get_timeouts(struct tpm_chip *chip);
  int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
  int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
struct tpm2_digest *digests);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index dfbe9c60cbcf..978946748ea3 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -307,3 +307,109 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip 
*chip, u32 ordinal)
else
return duration;
  }
+
+int tpm1_get_timeouts(struct tpm_chip *chip)
+{
+   cap_t cap;
+   unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4];
+   ssize_t rc;
+
+   rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, , NULL,
+   sizeof(cap.timeout));
+   if (rc == TPM_ERR_INVALID_POSTINIT) {
+   if (tpm_startup(chip))
+   return rc;
+
+   rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, ,
+   "attempting to determine the timeouts",
+   sizeof(cap.timeout));
+   }
+
+   if (rc) {
+   dev_err(>dev, "A TPM error (%zd) occurred attempting to 
determine the timeouts\n",
+   rc);
+   return rc;
+   }
+
+   timeout_old[0] = jiffies_to_usecs(chip->timeout_a);
+   timeout_old[1] = jiffies_to_usecs(chip->timeout_b);
+   timeout_old[2] = jiffies_to_usecs(chip->timeout_c);
+   timeout_old[3] = jiffies_to_usecs(chip->timeout_d);
+   timeout_chip[0] = be32_to_cpu(cap.timeout.a);
+   timeout_chip[1] = be32_to_cpu(cap.timeout.b);
+   timeout_chip[2] = be32_to_cpu(cap.timeout.c);
+   timeout_chip[3] = be32_to_cpu(cap.timeout.d);
+   memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff));
+
+   /*
+* Provide ability for vendor overrides of timeout values in case
+* of misreporting.
+*/
+   if (chip->ops->update_timeouts)
+   chip->timeout_adjusted =
+   chip->ops->update_timeouts(chip, timeout_eff);
+
+   if (!chip->timeout_adjusted) {
+   /* Restore default if chip reported 0 */
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) {
+   if (timeout_eff[i])
+   continue;
+
+   timeout_eff[i] = timeout_old[i];
+   chip->timeout_adjusted = true;
+   }
+
+   if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) {
+   /* timeouts in msec rather usec */
+   for (i = 0; i != ARRAY_SIZE(timeout_eff); i++)
+   timeout_eff[i] *= 1000;
+   chip->timeout_adjusted = true;
+   }
+   }
+
+   /* Report adjusted timeouts */
+   if (chip->timeout_adjusted) {
+   dev_info(>dev, HW_ERR "Adjusting reported timeouts: A %lu->%luus B 
%lu->%luus C %lu->%luus D %lu->%luus\n",
+timeout_chip[0], timeout_eff[0],
+timeout_chip[1], timeout_eff[1],
+timeout_chip[2], timeout_eff[2],
+timeout_chip[3], timeout_eff[3]);
+   }
+
+   chip->timeout_a = usecs_to_jiffies(timeout_eff[0]);
+   chip->timeout_b = usecs_to_jiffies(timeout_eff[1]);
+   chip->timeout_c = usecs_to_jiffies(timeout_eff[2]);
+   chip->timeout_d = usecs_to_jiffies(timeout_eff[3]);
+
+   rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, ,
+   "attempting to determine the durations",
+   sizeof(cap.duration));
+   if (rc)
+   return rc;
+
+   chip->duration[TPM_SHORT] =
+   usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short));
+   

Re: [PATCH v5 03/21] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

2018-10-11 Thread Nayna Jain




On 09/29/2018 04:00 AM, Tomas Winkler wrote:

+unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
+{
+   int duration_idx = TPM_UNDEFINED;
+   int duration = 0;
+
+   /*
+* We only have a duration table for protected commands, where the upper
+* 16 bits are 0. For the few other ordinals the fallback will be used.
+*/
+   if (ordinal < TPM_MAX_ORDINAL)
+   duration_idx = tpm1_ordinal_duration[ordinal];
+
+   if (duration_idx != TPM_UNDEFINED)
+   duration = chip->duration[duration_idx];
+   if (duration <= 0)
+   return 2 * 60 * HZ;
+   else
+   return duration;
+}
+EXPORT_SYMBOL_GPL(tpm1_calc_ordinal_duration);
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c 
b/drivers/char/tpm/tpm_i2c_nuvoton.c
index caa86b19c76d..5d20e98b844f 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -370,6 +370,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, 
size_t len)
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
size_t count = 0;
+   unsigned long duration;
int burst_count, bytes2write, retries, rc = -EIO;

for (retries = 0; retries < TPM_RETRY; retries++) {
@@ -455,12 +456,11 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 
*buf, size_t len)
return rc;
}
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
-   rc = i2c_nuvoton_wait_for_data_avail(chip,
-tpm_calc_ordinal_duration(chip,
-  ordinal),
->read_queue);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);


The original code in the nuvoton driver does not differentiate between 
TPM 1.2 and TPM 2.0 as it does in tpm_tis_core.c.  Before making any 
changes, I would first fix it, so that it could easily be backported. 
Only then do the refactoring


Thanks & Regards,
   - Nayna



+   rc = i2c_nuvoton_wait_for_data_avail(chip, duration, >read_queue);
if (rc) {
-   dev_err(dev, "%s() timeout command duration\n", __func__);
+   dev_err(dev, "%s() timeout command duration %ld\n",
+   __func__, duration);
i2c_nuvoton_ready(chip);
return rc;
}
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index d2345d9fd7b5..14c332104de4 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -476,7 +476,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const 
u8 *buf, size_t len)
if (chip->flags & TPM_CHIP_FLAG_TPM2)
dur = tpm2_calc_ordinal_duration(chip, ordinal);
else
-   dur = tpm_calc_ordinal_duration(chip, ordinal);
+   dur = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index b150f87f38f5..77097229bf49 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -164,7 +164,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t 
count)
notify_remote_via_evtchn(priv->evtchn);

ordinal = be32_to_cpu(((struct tpm_input_header*)buf)->ordinal);
-   duration = tpm_calc_ordinal_duration(chip, ordinal);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration,
>read_queue, true) < 0) {




Re: [PATCH v5 03/21] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

2018-10-11 Thread Nayna Jain




On 09/29/2018 04:00 AM, Tomas Winkler wrote:

+unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
+{
+   int duration_idx = TPM_UNDEFINED;
+   int duration = 0;
+
+   /*
+* We only have a duration table for protected commands, where the upper
+* 16 bits are 0. For the few other ordinals the fallback will be used.
+*/
+   if (ordinal < TPM_MAX_ORDINAL)
+   duration_idx = tpm1_ordinal_duration[ordinal];
+
+   if (duration_idx != TPM_UNDEFINED)
+   duration = chip->duration[duration_idx];
+   if (duration <= 0)
+   return 2 * 60 * HZ;
+   else
+   return duration;
+}
+EXPORT_SYMBOL_GPL(tpm1_calc_ordinal_duration);
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c 
b/drivers/char/tpm/tpm_i2c_nuvoton.c
index caa86b19c76d..5d20e98b844f 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -370,6 +370,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, 
size_t len)
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
size_t count = 0;
+   unsigned long duration;
int burst_count, bytes2write, retries, rc = -EIO;

for (retries = 0; retries < TPM_RETRY; retries++) {
@@ -455,12 +456,11 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 
*buf, size_t len)
return rc;
}
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
-   rc = i2c_nuvoton_wait_for_data_avail(chip,
-tpm_calc_ordinal_duration(chip,
-  ordinal),
->read_queue);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);


The original code in the nuvoton driver does not differentiate between 
TPM 1.2 and TPM 2.0 as it does in tpm_tis_core.c.  Before making any 
changes, I would first fix it, so that it could easily be backported. 
Only then do the refactoring


Thanks & Regards,
   - Nayna



+   rc = i2c_nuvoton_wait_for_data_avail(chip, duration, >read_queue);
if (rc) {
-   dev_err(dev, "%s() timeout command duration\n", __func__);
+   dev_err(dev, "%s() timeout command duration %ld\n",
+   __func__, duration);
i2c_nuvoton_ready(chip);
return rc;
}
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index d2345d9fd7b5..14c332104de4 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -476,7 +476,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const 
u8 *buf, size_t len)
if (chip->flags & TPM_CHIP_FLAG_TPM2)
dur = tpm2_calc_ordinal_duration(chip, ordinal);
else
-   dur = tpm_calc_ordinal_duration(chip, ordinal);
+   dur = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index b150f87f38f5..77097229bf49 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -164,7 +164,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t 
count)
notify_remote_via_evtchn(priv->evtchn);

ordinal = be32_to_cpu(((struct tpm_input_header*)buf)->ordinal);
-   duration = tpm_calc_ordinal_duration(chip, ordinal);
+   duration = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration,
>read_queue, true) < 0) {




[PATCH v6 3/5] ima: refactor ima_init_policy()

2018-10-09 Thread Nayna Jain
From: Nayna Jain 

This patch removes the code duplication in ima_init_policy() by defining
a new function named add_rules(). The new function adds the rules to the
initial IMA policy, the custom policy or both based on the policy mask
(IMA_DEFAULT_POLICY, IMA_CUSTOM_POLICY).

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima_policy.c | 97 +
 1 file changed, 56 insertions(+), 41 deletions(-)

diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 8c9499867c91..1e30d09a56db 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -58,6 +58,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, 
LSM_OBJ_TYPE,
 
 enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
 
+enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY };
+
 struct ima_rule_entry {
struct list_head list;
int action;
@@ -473,6 +475,32 @@ static int ima_appraise_flag(enum ima_hooks func)
return 0;
 }
 
+static void add_rules(struct ima_rule_entry *entries, int count,
+ enum policy_rule_list policy_rule)
+{
+   int i = 0;
+
+   for (i = 0; i < count; i++) {
+   struct ima_rule_entry *entry;
+
+   if (policy_rule & IMA_DEFAULT_POLICY)
+   list_add_tail([i].list, _default_rules);
+
+   if (policy_rule & IMA_CUSTOM_POLICY) {
+   entry = kmemdup([i], sizeof(*entry),
+   GFP_KERNEL);
+   if (!entry)
+   continue;
+
+   list_add_tail(>list, _policy_rules);
+   }
+   if (entries[i].action == APPRAISE)
+   temp_ima_appraise |= ima_appraise_flag(entries[i].func);
+   if (entries[i].func == POLICY_CHECK)
+   temp_ima_appraise |= IMA_APPRAISE_POLICY;
+   }
+}
+
 /**
  * ima_init_policy - initialize the default measure rules.
  *
@@ -481,28 +509,23 @@ static int ima_appraise_flag(enum ima_hooks func)
  */
 void __init ima_init_policy(void)
 {
-   int i, measure_entries, appraise_entries, secure_boot_entries;
-
-   /* if !ima_policy set entries = 0 so we load NO default rules */
-   measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
-   appraise_entries = ima_use_appraise_tcb ?
-ARRAY_SIZE(default_appraise_rules) : 0;
-   secure_boot_entries = ima_use_secure_boot ?
-   ARRAY_SIZE(secure_boot_rules) : 0;
+   int build_appraise_entries;
 
-   for (i = 0; i < measure_entries; i++)
-   list_add_tail(_measure_rules[i].list, _default_rules);
+   /* if !ima_policy, we load NO default rules */
+   if (ima_policy)
+   add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules),
+ IMA_DEFAULT_POLICY);
 
switch (ima_policy) {
case ORIGINAL_TCB:
-   for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(original_measurement_rules,
+ ARRAY_SIZE(original_measurement_rules),
+ IMA_DEFAULT_POLICY);
break;
case DEFAULT_TCB:
-   for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(default_measurement_rules,
+ ARRAY_SIZE(default_measurement_rules),
+ IMA_DEFAULT_POLICY);
default:
break;
}
@@ -511,38 +534,30 @@ void __init ima_init_policy(void)
 * Insert the builtin "secure_boot" policy rules requiring file
 * signatures, prior to any other appraise rules.
 */
-   for (i = 0; i < secure_boot_entries; i++) {
-   list_add_tail(_boot_rules[i].list, _default_rules);
-   temp_ima_appraise |=
-   ima_appraise_flag(secure_boot_rules[i].func);
-   }
+   if (ima_use_secure_boot)
+   add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
+ IMA_DEFAULT_POLICY);
 
/*
 * Insert the build time appraise rules requiring file signatures
 * for both the initial and custom policies, prior to other appraise
-* rules.
+* rules. As the secure boot rules includes all of the build time
+* rules, include either one or the other set of rules, but not both.
 */
-   for (i = 0; i < ARRAY_SIZE(build_appraise_rules); i++) {
-   struct ima_rule_entry *entry;
-
-   if (!secure_boot_entries

[PATCH v6 3/5] ima: refactor ima_init_policy()

2018-10-09 Thread Nayna Jain
From: Nayna Jain 

This patch removes the code duplication in ima_init_policy() by defining
a new function named add_rules(). The new function adds the rules to the
initial IMA policy, the custom policy or both based on the policy mask
(IMA_DEFAULT_POLICY, IMA_CUSTOM_POLICY).

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima_policy.c | 97 +
 1 file changed, 56 insertions(+), 41 deletions(-)

diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 8c9499867c91..1e30d09a56db 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -58,6 +58,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, 
LSM_OBJ_TYPE,
 
 enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
 
+enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY };
+
 struct ima_rule_entry {
struct list_head list;
int action;
@@ -473,6 +475,32 @@ static int ima_appraise_flag(enum ima_hooks func)
return 0;
 }
 
+static void add_rules(struct ima_rule_entry *entries, int count,
+ enum policy_rule_list policy_rule)
+{
+   int i = 0;
+
+   for (i = 0; i < count; i++) {
+   struct ima_rule_entry *entry;
+
+   if (policy_rule & IMA_DEFAULT_POLICY)
+   list_add_tail([i].list, _default_rules);
+
+   if (policy_rule & IMA_CUSTOM_POLICY) {
+   entry = kmemdup([i], sizeof(*entry),
+   GFP_KERNEL);
+   if (!entry)
+   continue;
+
+   list_add_tail(>list, _policy_rules);
+   }
+   if (entries[i].action == APPRAISE)
+   temp_ima_appraise |= ima_appraise_flag(entries[i].func);
+   if (entries[i].func == POLICY_CHECK)
+   temp_ima_appraise |= IMA_APPRAISE_POLICY;
+   }
+}
+
 /**
  * ima_init_policy - initialize the default measure rules.
  *
@@ -481,28 +509,23 @@ static int ima_appraise_flag(enum ima_hooks func)
  */
 void __init ima_init_policy(void)
 {
-   int i, measure_entries, appraise_entries, secure_boot_entries;
-
-   /* if !ima_policy set entries = 0 so we load NO default rules */
-   measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
-   appraise_entries = ima_use_appraise_tcb ?
-ARRAY_SIZE(default_appraise_rules) : 0;
-   secure_boot_entries = ima_use_secure_boot ?
-   ARRAY_SIZE(secure_boot_rules) : 0;
+   int build_appraise_entries;
 
-   for (i = 0; i < measure_entries; i++)
-   list_add_tail(_measure_rules[i].list, _default_rules);
+   /* if !ima_policy, we load NO default rules */
+   if (ima_policy)
+   add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules),
+ IMA_DEFAULT_POLICY);
 
switch (ima_policy) {
case ORIGINAL_TCB:
-   for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(original_measurement_rules,
+ ARRAY_SIZE(original_measurement_rules),
+ IMA_DEFAULT_POLICY);
break;
case DEFAULT_TCB:
-   for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(default_measurement_rules,
+ ARRAY_SIZE(default_measurement_rules),
+ IMA_DEFAULT_POLICY);
default:
break;
}
@@ -511,38 +534,30 @@ void __init ima_init_policy(void)
 * Insert the builtin "secure_boot" policy rules requiring file
 * signatures, prior to any other appraise rules.
 */
-   for (i = 0; i < secure_boot_entries; i++) {
-   list_add_tail(_boot_rules[i].list, _default_rules);
-   temp_ima_appraise |=
-   ima_appraise_flag(secure_boot_rules[i].func);
-   }
+   if (ima_use_secure_boot)
+   add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
+ IMA_DEFAULT_POLICY);
 
/*
 * Insert the build time appraise rules requiring file signatures
 * for both the initial and custom policies, prior to other appraise
-* rules.
+* rules. As the secure boot rules includes all of the build time
+* rules, include either one or the other set of rules, but not both.
 */
-   for (i = 0; i < ARRAY_SIZE(build_appraise_rules); i++) {
-   struct ima_rule_entry *entry;
-
-   if (!secure_boot_entries

Re: [PATCH v5 06/21] tpm: move tpm1_pcr_extend to tpm1-cmd.c

2018-10-02 Thread Nayna Jain




On 10/02/2018 06:12 AM, Jarkko Sakkinen wrote:

On Sat, Sep 29, 2018 at 01:30:20AM +0300, Tomas Winkler wrote:

Move tpm1_pcr_extend to tpm1-cmd.c and remove
unused pcrextend_header structure and
EXTEND_PCR_RESULT_SIZE and EXTEND_PCR_RESULT_BODY_SIZE
defines.

Fixes warning:
drivers/char/tpm/tpm-interface.c:609:38: warning: ‘pcrextend_header’ defined 
but not used [-Wunused-const-variable=]
  static const struct tpm_input_header pcrextend_header = {
   ^~~~

Signed-off-by: Tomas Winkler 
Reviewed-by: Jarkko Sakkinen 

Would need help with this from someone with a working IMA setup
on testing.



My test system is down for now.. I think it will be up later in this 
week. I can test it then.


Thanks & Regards,
    - Nayna




/Jarkko





Re: [PATCH v5 06/21] tpm: move tpm1_pcr_extend to tpm1-cmd.c

2018-10-02 Thread Nayna Jain




On 10/02/2018 06:12 AM, Jarkko Sakkinen wrote:

On Sat, Sep 29, 2018 at 01:30:20AM +0300, Tomas Winkler wrote:

Move tpm1_pcr_extend to tpm1-cmd.c and remove
unused pcrextend_header structure and
EXTEND_PCR_RESULT_SIZE and EXTEND_PCR_RESULT_BODY_SIZE
defines.

Fixes warning:
drivers/char/tpm/tpm-interface.c:609:38: warning: ‘pcrextend_header’ defined 
but not used [-Wunused-const-variable=]
  static const struct tpm_input_header pcrextend_header = {
   ^~~~

Signed-off-by: Tomas Winkler 
Reviewed-by: Jarkko Sakkinen 

Would need help with this from someone with a working IMA setup
on testing.



My test system is down for now.. I think it will be up later in this 
week. I can test it then.


Thanks & Regards,
    - Nayna




/Jarkko





Re: [PATCH v4 03/21] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

2018-09-26 Thread Nayna Jain




On 09/21/2018 07:28 PM, Tomas Winkler wrote:

Factor out TPM 1.x commands calculation into tpm1-cmd.c file.
and change the prefix from tpm_ to tpm1_.
No functional change is done here.

Signed-off-by: Tomas Winkler 
Tested-by: Jarkko Sakkinen 
---
V2-V3: Rebase
V4: 1. Remove the licence statement it's already covered by SPDX.
 2. Add kdoc to tpm1_calc_ordinal_duration().

  drivers/char/tpm/Makefile|   1 +
  drivers/char/tpm/st33zp24/st33zp24.c |   2 +-
  drivers/char/tpm/tpm-interface.c | 284 +---
  drivers/char/tpm/tpm.h   |   2 +-
  drivers/char/tpm/tpm1-cmd.c  | 310 +++
  drivers/char/tpm/tpm_i2c_nuvoton.c   |  10 +-
  drivers/char/tpm/tpm_tis_core.c  |   2 +-
  drivers/char/tpm/xen-tpmfront.c  |   2 +-
  8 files changed, 322 insertions(+), 291 deletions(-)
  create mode 100644 drivers/char/tpm/tpm1-cmd.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index efc785053627..a01c4cab902a 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -7,6 +7,7 @@ tpm-y := tpm-chip.o
  tpm-y += tpm-dev-common.o
  tpm-y += tpm-dev.o
  tpm-y += tpm-interface.o
+tpm-y += tpm1-cmd.o
  tpm-y += tpm2-cmd.o
  tpm-y += tpmrm-dev.o
  tpm-y += tpm2-space.o
diff --git a/drivers/char/tpm/st33zp24/st33zp24.c 
b/drivers/char/tpm/st33zp24/st33zp24.c
index abd675bec88c..16be974955ea 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -430,7 +430,7 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned 
char *buf,
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));

ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
-   tpm_calc_ordinal_duration(chip, ordinal),
+   tpm1_calc_ordinal_duration(chip, ordinal),
_dev->read_queue, false);
if (ret < 0)
goto out_err;
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 129f640424b7..bb3eed907c72 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -33,7 +33,6 @@

  #include "tpm.h"

-#define TPM_MAX_ORDINAL 243
  #define TSC_MAX_ORDINAL 12
  #define TPM_PROTECTED_COMMAND 0x00
  #define TPM_CONNECTION_COMMAND 0x40
@@ -48,285 +47,6 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 
0644);
  MODULE_PARM_DESC(suspend_pcr,
 "PCR to use for dummy writes to facilitate flush on suspend.");

-/*
- * Array with one entry per ordinal defining the maximum amount
- * of time the chip could take to return the result.  The ordinal
- * designation of short, medium or long is defined in a table in
- * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
- * values of the SHORT, MEDIUM, and LONG durations are retrieved
- * from the chip during initialization with a call to tpm_get_timeouts.
- */
-static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
-   TPM_UNDEFINED,  /* 0 */
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,  /* 5 */
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_SHORT,  /* 10 */
-   TPM_SHORT,
-   TPM_MEDIUM,
-   TPM_LONG,
-   TPM_LONG,
-   TPM_MEDIUM, /* 15 */
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_MEDIUM,
-   TPM_LONG,
-   TPM_SHORT,  /* 20 */
-   TPM_SHORT,
-   TPM_MEDIUM,
-   TPM_MEDIUM,
-   TPM_MEDIUM,
-   TPM_SHORT,  /* 25 */
-   TPM_SHORT,
-   TPM_MEDIUM,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_MEDIUM, /* 30 */
-   TPM_LONG,
-   TPM_MEDIUM,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_SHORT,  /* 35 */
-   TPM_MEDIUM,
-   TPM_MEDIUM,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_MEDIUM, /* 40 */
-   TPM_LONG,
-   TPM_MEDIUM,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_SHORT,  /* 45 */
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_LONG,
-   TPM_MEDIUM, /* 50 */
-   TPM_MEDIUM,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,  /* 55 */
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_MEDIUM, /* 60 */
-   TPM_MEDIUM,
-   TPM_MEDIUM,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_MEDIUM, /* 65 */
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_SHORT,  /* 70 */
-   TPM_SHORT,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,  /* 75 */
-   TPM_UNDEFINED,
-   

Re: [PATCH v4 03/21] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

2018-09-26 Thread Nayna Jain




On 09/21/2018 07:28 PM, Tomas Winkler wrote:

Factor out TPM 1.x commands calculation into tpm1-cmd.c file.
and change the prefix from tpm_ to tpm1_.
No functional change is done here.

Signed-off-by: Tomas Winkler 
Tested-by: Jarkko Sakkinen 
---
V2-V3: Rebase
V4: 1. Remove the licence statement it's already covered by SPDX.
 2. Add kdoc to tpm1_calc_ordinal_duration().

  drivers/char/tpm/Makefile|   1 +
  drivers/char/tpm/st33zp24/st33zp24.c |   2 +-
  drivers/char/tpm/tpm-interface.c | 284 +---
  drivers/char/tpm/tpm.h   |   2 +-
  drivers/char/tpm/tpm1-cmd.c  | 310 +++
  drivers/char/tpm/tpm_i2c_nuvoton.c   |  10 +-
  drivers/char/tpm/tpm_tis_core.c  |   2 +-
  drivers/char/tpm/xen-tpmfront.c  |   2 +-
  8 files changed, 322 insertions(+), 291 deletions(-)
  create mode 100644 drivers/char/tpm/tpm1-cmd.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index efc785053627..a01c4cab902a 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -7,6 +7,7 @@ tpm-y := tpm-chip.o
  tpm-y += tpm-dev-common.o
  tpm-y += tpm-dev.o
  tpm-y += tpm-interface.o
+tpm-y += tpm1-cmd.o
  tpm-y += tpm2-cmd.o
  tpm-y += tpmrm-dev.o
  tpm-y += tpm2-space.o
diff --git a/drivers/char/tpm/st33zp24/st33zp24.c 
b/drivers/char/tpm/st33zp24/st33zp24.c
index abd675bec88c..16be974955ea 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -430,7 +430,7 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned 
char *buf,
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));

ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
-   tpm_calc_ordinal_duration(chip, ordinal),
+   tpm1_calc_ordinal_duration(chip, ordinal),
_dev->read_queue, false);
if (ret < 0)
goto out_err;
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 129f640424b7..bb3eed907c72 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -33,7 +33,6 @@

  #include "tpm.h"

-#define TPM_MAX_ORDINAL 243
  #define TSC_MAX_ORDINAL 12
  #define TPM_PROTECTED_COMMAND 0x00
  #define TPM_CONNECTION_COMMAND 0x40
@@ -48,285 +47,6 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 
0644);
  MODULE_PARM_DESC(suspend_pcr,
 "PCR to use for dummy writes to facilitate flush on suspend.");

-/*
- * Array with one entry per ordinal defining the maximum amount
- * of time the chip could take to return the result.  The ordinal
- * designation of short, medium or long is defined in a table in
- * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
- * values of the SHORT, MEDIUM, and LONG durations are retrieved
- * from the chip during initialization with a call to tpm_get_timeouts.
- */
-static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
-   TPM_UNDEFINED,  /* 0 */
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,  /* 5 */
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_SHORT,  /* 10 */
-   TPM_SHORT,
-   TPM_MEDIUM,
-   TPM_LONG,
-   TPM_LONG,
-   TPM_MEDIUM, /* 15 */
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_MEDIUM,
-   TPM_LONG,
-   TPM_SHORT,  /* 20 */
-   TPM_SHORT,
-   TPM_MEDIUM,
-   TPM_MEDIUM,
-   TPM_MEDIUM,
-   TPM_SHORT,  /* 25 */
-   TPM_SHORT,
-   TPM_MEDIUM,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_MEDIUM, /* 30 */
-   TPM_LONG,
-   TPM_MEDIUM,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_SHORT,  /* 35 */
-   TPM_MEDIUM,
-   TPM_MEDIUM,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_MEDIUM, /* 40 */
-   TPM_LONG,
-   TPM_MEDIUM,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_SHORT,  /* 45 */
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_LONG,
-   TPM_MEDIUM, /* 50 */
-   TPM_MEDIUM,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,  /* 55 */
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_MEDIUM, /* 60 */
-   TPM_MEDIUM,
-   TPM_MEDIUM,
-   TPM_SHORT,
-   TPM_SHORT,
-   TPM_MEDIUM, /* 65 */
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_SHORT,  /* 70 */
-   TPM_SHORT,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,
-   TPM_UNDEFINED,  /* 75 */
-   TPM_UNDEFINED,
-   

Re: [PATCH v4 01/21] tpm2: add new tpm2 commands according to TCG 1.36

2018-09-26 Thread Nayna Jain




On 09/21/2018 07:28 PM, Tomas Winkler wrote:

1. TPM2_CC_LAST has moved from 182 to 193
2. Convert tpm2_ordinal_duration from an array into a switch statement,
as there are not so many commands that require special duration
relative to a number of commands, the switch statement function
is called tpm2_ordinal_duration_index().
3. Fix kdoc comments for tpm2_calc_ordinal_duration().

Signed-off-by: Tomas Winkler 
Tested-by: Jarkko Sakkinen 
---
V2-V3: Rebase.
V4: 1. Fix kdoc
 2. Rename tpm2_ordinal_duration() to tpm2_ordinal_duration_index()
 3. Move the two functions close to each other in the file.

  drivers/char/tpm/tpm.h  |  41 +---
  drivers/char/tpm/tpm2-cmd.c | 236 +---
  2 files changed, 113 insertions(+), 164 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f20dc8ece348..0f08518b525d 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -134,22 +134,31 @@ enum tpm2_algorithms {
  };

  enum tpm2_command_codes {
-   TPM2_CC_FIRST   = 0x011F,
-   TPM2_CC_CREATE_PRIMARY  = 0x0131,
-   TPM2_CC_SELF_TEST   = 0x0143,
-   TPM2_CC_STARTUP = 0x0144,
-   TPM2_CC_SHUTDOWN= 0x0145,
-   TPM2_CC_CREATE  = 0x0153,
-   TPM2_CC_LOAD= 0x0157,
-   TPM2_CC_UNSEAL  = 0x015E,
-   TPM2_CC_CONTEXT_LOAD= 0x0161,
-   TPM2_CC_CONTEXT_SAVE= 0x0162,
-   TPM2_CC_FLUSH_CONTEXT   = 0x0165,
-   TPM2_CC_GET_CAPABILITY  = 0x017A,
-   TPM2_CC_GET_RANDOM  = 0x017B,
-   TPM2_CC_PCR_READ= 0x017E,
-   TPM2_CC_PCR_EXTEND  = 0x0182,
-   TPM2_CC_LAST= 0x018F,
+   TPM2_CC_FIRST   = 0x011F,
+   TPM2_CC_HIERARCHY_CONTROL   = 0x0121,
+   TPM2_CC_HIERARCHY_CHANGE_AUTH   = 0x0129,
+   TPM2_CC_CREATE_PRIMARY  = 0x0131,
+   TPM2_CC_SEQUENCE_COMPLETE   = 0x013E,
+   TPM2_CC_SELF_TEST   = 0x0143,
+   TPM2_CC_STARTUP = 0x0144,
+   TPM2_CC_SHUTDOWN= 0x0145,
+   TPM2_CC_NV_READ = 0x014E,
+   TPM2_CC_CREATE  = 0x0153,
+   TPM2_CC_LOAD= 0x0157,
+   TPM2_CC_SEQUENCE_UPDATE = 0x015C,
+   TPM2_CC_UNSEAL  = 0x015E,
+   TPM2_CC_CONTEXT_LOAD= 0x0161,
+   TPM2_CC_CONTEXT_SAVE= 0x0162,
+   TPM2_CC_FLUSH_CONTEXT   = 0x0165,
+   TPM2_CC_VERIFY_SIGNATURE= 0x0177,
+   TPM2_CC_GET_CAPABILITY  = 0x017A,
+   TPM2_CC_GET_RANDOM  = 0x017B,
+   TPM2_CC_PCR_READ= 0x017E,
+   TPM2_CC_PCR_EXTEND  = 0x0182,
+   TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185,
+   TPM2_CC_HASH_SEQUENCE_START = 0x0186,
+   TPM2_CC_CREATE_LOADED   = 0x0191,
+   TPM2_CC_LAST= 0x0193, /* Spec 1.36 */
  };

  enum tpm2_permanent_handles {
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 3acf4fd4e5a5..be0a9ebcd7d7 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -40,129 +40,95 @@ static struct tpm2_hash tpm2_hash_map[] = {
{HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},
  };

-/*
- * Array with one entry per ordinal defining the maximum amount
- * of time the chip could take to return the result. The values
- * of the SHORT, MEDIUM, and LONG durations are taken from the
- * PC Client Profile (PTP) specification.
- * LONG_LONG is for commands that generates keys which empirically
- * takes longer time on some systems.
+/**
+ * tpm2_ordinal_duration_index() - returns an index to the chip duration
+ * table (enum tpm_duration), that describes the maximum amount of
+ * time the chip could take to return the result for a  particular ordinal.
+ *
+ * The values of the MEDIUM, and LONG durations are taken
+ * from the PC Client Profile (PTP) specification (750, 2000 msec)
+ *
+ * LONG_LONG is for commands that generates keys which empirically takes
+ * a longer time on some systems.
+ *
+ * @ordinal: TPM command ordinal.
+ *
+ * Return: TPM_MEDIUM, TPM_LONG, TPM_LONG_LONG, and TPM_UNDEFINED.
   */
-static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = {
-   TPM_UNDEFINED,  /* 11F */
-   TPM_UNDEFINED,  /* 120 */
-   TPM_LONG,   /* 121 */
-   TPM_UNDEFINED,  /* 122 */
-   TPM_UNDEFINED,  /* 123 */
-   TPM_UNDEFINED,  /* 124 */
-   TPM_UNDEFINED,  /* 125 */
-   TPM_UNDEFINED,  /* 126 */
-   TPM_UNDEFINED,  /* 127 */
-   TPM_UNDEFINED,  /* 128 */
-   TPM_LONG,   /* 129 */
-   TPM_UNDEFINED,  /* 12a */
-   TPM_UNDEFINED,  /* 12b */
-   TPM_UNDEFINED,  /* 12c */
-   TPM_UNDEFINED,  /* 12d */
-   TPM_UNDEFINED,  /* 

Re: [PATCH v4 01/21] tpm2: add new tpm2 commands according to TCG 1.36

2018-09-26 Thread Nayna Jain




On 09/21/2018 07:28 PM, Tomas Winkler wrote:

1. TPM2_CC_LAST has moved from 182 to 193
2. Convert tpm2_ordinal_duration from an array into a switch statement,
as there are not so many commands that require special duration
relative to a number of commands, the switch statement function
is called tpm2_ordinal_duration_index().
3. Fix kdoc comments for tpm2_calc_ordinal_duration().

Signed-off-by: Tomas Winkler 
Tested-by: Jarkko Sakkinen 
---
V2-V3: Rebase.
V4: 1. Fix kdoc
 2. Rename tpm2_ordinal_duration() to tpm2_ordinal_duration_index()
 3. Move the two functions close to each other in the file.

  drivers/char/tpm/tpm.h  |  41 +---
  drivers/char/tpm/tpm2-cmd.c | 236 +---
  2 files changed, 113 insertions(+), 164 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f20dc8ece348..0f08518b525d 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -134,22 +134,31 @@ enum tpm2_algorithms {
  };

  enum tpm2_command_codes {
-   TPM2_CC_FIRST   = 0x011F,
-   TPM2_CC_CREATE_PRIMARY  = 0x0131,
-   TPM2_CC_SELF_TEST   = 0x0143,
-   TPM2_CC_STARTUP = 0x0144,
-   TPM2_CC_SHUTDOWN= 0x0145,
-   TPM2_CC_CREATE  = 0x0153,
-   TPM2_CC_LOAD= 0x0157,
-   TPM2_CC_UNSEAL  = 0x015E,
-   TPM2_CC_CONTEXT_LOAD= 0x0161,
-   TPM2_CC_CONTEXT_SAVE= 0x0162,
-   TPM2_CC_FLUSH_CONTEXT   = 0x0165,
-   TPM2_CC_GET_CAPABILITY  = 0x017A,
-   TPM2_CC_GET_RANDOM  = 0x017B,
-   TPM2_CC_PCR_READ= 0x017E,
-   TPM2_CC_PCR_EXTEND  = 0x0182,
-   TPM2_CC_LAST= 0x018F,
+   TPM2_CC_FIRST   = 0x011F,
+   TPM2_CC_HIERARCHY_CONTROL   = 0x0121,
+   TPM2_CC_HIERARCHY_CHANGE_AUTH   = 0x0129,
+   TPM2_CC_CREATE_PRIMARY  = 0x0131,
+   TPM2_CC_SEQUENCE_COMPLETE   = 0x013E,
+   TPM2_CC_SELF_TEST   = 0x0143,
+   TPM2_CC_STARTUP = 0x0144,
+   TPM2_CC_SHUTDOWN= 0x0145,
+   TPM2_CC_NV_READ = 0x014E,
+   TPM2_CC_CREATE  = 0x0153,
+   TPM2_CC_LOAD= 0x0157,
+   TPM2_CC_SEQUENCE_UPDATE = 0x015C,
+   TPM2_CC_UNSEAL  = 0x015E,
+   TPM2_CC_CONTEXT_LOAD= 0x0161,
+   TPM2_CC_CONTEXT_SAVE= 0x0162,
+   TPM2_CC_FLUSH_CONTEXT   = 0x0165,
+   TPM2_CC_VERIFY_SIGNATURE= 0x0177,
+   TPM2_CC_GET_CAPABILITY  = 0x017A,
+   TPM2_CC_GET_RANDOM  = 0x017B,
+   TPM2_CC_PCR_READ= 0x017E,
+   TPM2_CC_PCR_EXTEND  = 0x0182,
+   TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185,
+   TPM2_CC_HASH_SEQUENCE_START = 0x0186,
+   TPM2_CC_CREATE_LOADED   = 0x0191,
+   TPM2_CC_LAST= 0x0193, /* Spec 1.36 */
  };

  enum tpm2_permanent_handles {
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 3acf4fd4e5a5..be0a9ebcd7d7 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -40,129 +40,95 @@ static struct tpm2_hash tpm2_hash_map[] = {
{HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},
  };

-/*
- * Array with one entry per ordinal defining the maximum amount
- * of time the chip could take to return the result. The values
- * of the SHORT, MEDIUM, and LONG durations are taken from the
- * PC Client Profile (PTP) specification.
- * LONG_LONG is for commands that generates keys which empirically
- * takes longer time on some systems.
+/**
+ * tpm2_ordinal_duration_index() - returns an index to the chip duration
+ * table (enum tpm_duration), that describes the maximum amount of
+ * time the chip could take to return the result for a  particular ordinal.
+ *
+ * The values of the MEDIUM, and LONG durations are taken
+ * from the PC Client Profile (PTP) specification (750, 2000 msec)
+ *
+ * LONG_LONG is for commands that generates keys which empirically takes
+ * a longer time on some systems.
+ *
+ * @ordinal: TPM command ordinal.
+ *
+ * Return: TPM_MEDIUM, TPM_LONG, TPM_LONG_LONG, and TPM_UNDEFINED.
   */
-static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = {
-   TPM_UNDEFINED,  /* 11F */
-   TPM_UNDEFINED,  /* 120 */
-   TPM_LONG,   /* 121 */
-   TPM_UNDEFINED,  /* 122 */
-   TPM_UNDEFINED,  /* 123 */
-   TPM_UNDEFINED,  /* 124 */
-   TPM_UNDEFINED,  /* 125 */
-   TPM_UNDEFINED,  /* 126 */
-   TPM_UNDEFINED,  /* 127 */
-   TPM_UNDEFINED,  /* 128 */
-   TPM_LONG,   /* 129 */
-   TPM_UNDEFINED,  /* 12a */
-   TPM_UNDEFINED,  /* 12b */
-   TPM_UNDEFINED,  /* 12c */
-   TPM_UNDEFINED,  /* 12d */
-   TPM_UNDEFINED,  /* 

Re: [PATCH v3 06/20] tpm: move tpm1_pcr_extend to tpm1-cmd.c

2018-09-25 Thread Nayna Jain




On 09/19/2018 07:36 PM, Jarkko Sakkinen wrote:

On Tue, Sep 18, 2018 at 12:34:45PM +0300, Tomas Winkler wrote:

Move tpm1_pcr_extend to tpm1-cmd.c and remove
unused pcrextend_header structure.

Fixes warning:
drivers/char/tpm/tpm-interface.c:609:38: warning: ‘pcrextend_header’ defined 
but not used [-Wunused-const-variable=]
  static const struct tpm_input_header pcrextend_header = {
   ^~~~
Signed-off-by: Tomas Winkler 

Reviewed-by: Jarkko Sakkinen 

Can someone with a working IMA environment to test it? Don't have one
right now (should probably setup).


I think I can try testing this patch sometime next week. I will test the 
updated version.


Thanks & Regards,
    - Nayna



/Jarkko





Re: [PATCH v3 06/20] tpm: move tpm1_pcr_extend to tpm1-cmd.c

2018-09-25 Thread Nayna Jain




On 09/19/2018 07:36 PM, Jarkko Sakkinen wrote:

On Tue, Sep 18, 2018 at 12:34:45PM +0300, Tomas Winkler wrote:

Move tpm1_pcr_extend to tpm1-cmd.c and remove
unused pcrextend_header structure.

Fixes warning:
drivers/char/tpm/tpm-interface.c:609:38: warning: ‘pcrextend_header’ defined 
but not used [-Wunused-const-variable=]
  static const struct tpm_input_header pcrextend_header = {
   ^~~~
Signed-off-by: Tomas Winkler 

Reviewed-by: Jarkko Sakkinen 

Can someone with a working IMA environment to test it? Don't have one
right now (should probably setup).


I think I can try testing this patch sometime next week. I will test the 
updated version.


Thanks & Regards,
    - Nayna



/Jarkko





Re: [PATCH v4 20/21] tpm1: reimplement tpm1_continue_selftest() using tpm_buf

2018-09-25 Thread Nayna Jain




On 09/21/2018 07:28 PM, Tomas Winkler wrote:

Reimplement tpm1_continue_selftest() using tpm_buf structure.
This is the last command using the old tpm_cmd_t structure
and now the structure can be removed.

Signed-off-by: Tomas Winkler 
Reviewed-by: Jarkko Sakkinen 
Tested-by: Jarkko Sakkinen 
---
V3: New in the series.
V4: Resend.

  drivers/char/tpm/tpm.h  |  9 -
  drivers/char/tpm/tpm1-cmd.c | 21 ++---
  2 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2f06740f993d..7ada00f067f1 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -377,15 +377,6 @@ enum tpm_sub_capabilities {
TPM_CAP_PROP_TIS_DURATION = 0x120,
  };

-typedef union {
-   struct  tpm_input_header in;
-   struct  tpm_output_header out;
-} tpm_cmd_header;
-
-struct tpm_cmd_t {
-   tpm_cmd_header  header;
-} __packed;
-

  /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
   * bytes, but 128 is still a relatively large number of random bytes and
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index cde9a01ad31f..6d7d70b0d130 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -604,15 +604,8 @@ int tpm1_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 
*res_buf)
  }

  #define TPM_ORD_CONTINUE_SELFTEST 83
-#define CONTINUE_SELFTEST_RESULT_SIZE 10
-static const struct tpm_input_header continue_selftest_header = {
-   .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-   .length = cpu_to_be32(10),
-   .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
-};
-
  /**
- * tpm_continue_selftest -- run TPM's selftest
+ * tpm_continue_selftest() - run TPM's selftest
   * @chip: TPM chip to use
   *
   * Returns 0 on success, < 0 in case of fatal error or a value > 0 
representing
@@ -620,12 +613,18 @@ static const struct tpm_input_header 
continue_selftest_header = {
   */
  static int tpm1_continue_selftest(struct tpm_chip *chip)
  {
+   struct tpm_buf buf;
int rc;
-   struct tpm_cmd_t cmd;

-   cmd.header.in = continue_selftest_header;
-   rc = tpm_transmit_cmd(chip, NULL, , CONTINUE_SELFTEST_RESULT_SIZE,
+   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST);
+   if (rc)
+   return rc;
+
+   rc = tpm_transmit_cmd(chip, NULL, , PAGE_SIZE,

I think this needs to buf.data instead of 

Thanks & Regards,
 - Nayna


  0, 0, "continue selftest");
+
+   tpm_buf_destroy();
+
return rc;
  }





Re: [PATCH v4 20/21] tpm1: reimplement tpm1_continue_selftest() using tpm_buf

2018-09-25 Thread Nayna Jain




On 09/21/2018 07:28 PM, Tomas Winkler wrote:

Reimplement tpm1_continue_selftest() using tpm_buf structure.
This is the last command using the old tpm_cmd_t structure
and now the structure can be removed.

Signed-off-by: Tomas Winkler 
Reviewed-by: Jarkko Sakkinen 
Tested-by: Jarkko Sakkinen 
---
V3: New in the series.
V4: Resend.

  drivers/char/tpm/tpm.h  |  9 -
  drivers/char/tpm/tpm1-cmd.c | 21 ++---
  2 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2f06740f993d..7ada00f067f1 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -377,15 +377,6 @@ enum tpm_sub_capabilities {
TPM_CAP_PROP_TIS_DURATION = 0x120,
  };

-typedef union {
-   struct  tpm_input_header in;
-   struct  tpm_output_header out;
-} tpm_cmd_header;
-
-struct tpm_cmd_t {
-   tpm_cmd_header  header;
-} __packed;
-

  /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
   * bytes, but 128 is still a relatively large number of random bytes and
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index cde9a01ad31f..6d7d70b0d130 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -604,15 +604,8 @@ int tpm1_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 
*res_buf)
  }

  #define TPM_ORD_CONTINUE_SELFTEST 83
-#define CONTINUE_SELFTEST_RESULT_SIZE 10
-static const struct tpm_input_header continue_selftest_header = {
-   .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-   .length = cpu_to_be32(10),
-   .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
-};
-
  /**
- * tpm_continue_selftest -- run TPM's selftest
+ * tpm_continue_selftest() - run TPM's selftest
   * @chip: TPM chip to use
   *
   * Returns 0 on success, < 0 in case of fatal error or a value > 0 
representing
@@ -620,12 +613,18 @@ static const struct tpm_input_header 
continue_selftest_header = {
   */
  static int tpm1_continue_selftest(struct tpm_chip *chip)
  {
+   struct tpm_buf buf;
int rc;
-   struct tpm_cmd_t cmd;

-   cmd.header.in = continue_selftest_header;
-   rc = tpm_transmit_cmd(chip, NULL, , CONTINUE_SELFTEST_RESULT_SIZE,
+   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST);
+   if (rc)
+   return rc;
+
+   rc = tpm_transmit_cmd(chip, NULL, , PAGE_SIZE,

I think this needs to buf.data instead of 

Thanks & Regards,
 - Nayna


  0, 0, "continue selftest");
+
+   tpm_buf_destroy();
+
return rc;
  }





Re: [PATCH v4 11/21] tpm: factor out tpm_startup function

2018-09-24 Thread Nayna Jain




On 09/21/2018 07:28 PM, Tomas Winkler wrote:

TPM manual startup is used only from within TPM 1.x or TPM 2.x
code, hence remove tpm_startup() function from tpm-interface.c
and add two static functions implementations tpm1_startup()
and tpm2_startup() into to tpm1-cmd.c and tpm2-cmd.c respectively.

Signed-off-by: Tomas Winkler 
Tested-by: Jarkko Sakkine 


Typo in Jarkko's last name -  "Sakkinen"

Thanks & Regards,
    - Nayna


---
V2-V3: Resend.
V4: Fix the commit message.

  drivers/char/tpm/tpm-interface.c | 41 
  drivers/char/tpm/tpm.h   |  1 -
  drivers/char/tpm/tpm1-cmd.c  | 37 +++-
  drivers/char/tpm/tpm2-cmd.c  | 34 +++--
  4 files changed, 68 insertions(+), 45 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index dfa972bbdd81..686b5316dad5 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -413,47 +413,6 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct 
tpm_space *space,
  }
  EXPORT_SYMBOL_GPL(tpm_transmit_cmd);

-#define TPM_ORD_STARTUP 153
-#define TPM_ST_CLEAR 1
-
-/**
- * tpm_startup - turn on the TPM
- * @chip: TPM chip to use
- *
- * Normally the firmware should start the TPM. This function is provided as a
- * workaround if this does not happen. A legal case for this could be for
- * example when a TPM emulator is used.
- *
- * Return: same as tpm_transmit_cmd()
- */
-int tpm_startup(struct tpm_chip *chip)
-{
-   struct tpm_buf buf;
-   int rc;
-
-   dev_info(>dev, "starting up the TPM manually\n");
-
-   if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
-   if (rc < 0)
-   return rc;
-
-   tpm_buf_append_u16(, TPM2_SU_CLEAR);
-   } else {
-   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
-   if (rc < 0)
-   return rc;
-
-   tpm_buf_append_u16(, TPM_ST_CLEAR);
-   }
-
-   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
- "attempting to start the TPM");
-
-   tpm_buf_destroy();
-   return rc;
-}
-
  int tpm_get_timeouts(struct tpm_chip *chip)
  {
if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 862c9262e037..fa88102a0cab 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -540,7 +540,6 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct 
tpm_space *space,
 void *buf, size_t bufsiz,
 size_t min_rsp_body_length, unsigned int flags,
 const char *desc);
-int tpm_startup(struct tpm_chip *chip);
  int tpm_get_timeouts(struct tpm_chip *);

  int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index d118adbcd2a7..6deae4595277 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -308,6 +308,40 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip 
*chip, u32 ordinal)
return duration;
  }

+#define TPM_ORD_STARTUP 153
+#define TPM_ST_CLEAR 1
+
+/**
+ * tpm_startup - turn on the TPM
+ * @chip: TPM chip to use
+ *
+ * Normally the firmware should start the TPM. This function is provided as a
+ * workaround if this does not happen. A legal case for this could be for
+ * example when a TPM emulator is used.
+ *
+ * Return: same as tpm_transmit_cmd()
+ */
+static int tpm1_startup(struct tpm_chip *chip)
+{
+   struct tpm_buf buf;
+   int rc;
+
+   dev_info(>dev, "starting up the TPM manually\n");
+
+   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
+   if (rc < 0)
+   return rc;
+
+   tpm_buf_append_u16(, TPM_ST_CLEAR);
+
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
+ "attempting to start the TPM");
+
+   tpm_buf_destroy();
+
+   return rc;
+}
+
  int tpm1_get_timeouts(struct tpm_chip *chip)
  {
cap_t cap;
@@ -317,7 +351,7 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, , NULL,
 sizeof(cap.timeout));
if (rc == TPM_ERR_INVALID_POSTINIT) {
-   if (tpm_startup(chip))
+   if (tpm1_startup(chip))
return rc;

rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, ,
@@ -726,3 +760,4 @@ int tpm1_pm_suspend(struct tpm_chip *chip, int 
tpm_suspend_pcr)

return rc;
  }
+
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 65ce463a6f92..8da5a16e7c8c 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -943,6 +943,36 @@ static int 

Re: [PATCH v4 11/21] tpm: factor out tpm_startup function

2018-09-24 Thread Nayna Jain




On 09/21/2018 07:28 PM, Tomas Winkler wrote:

TPM manual startup is used only from within TPM 1.x or TPM 2.x
code, hence remove tpm_startup() function from tpm-interface.c
and add two static functions implementations tpm1_startup()
and tpm2_startup() into to tpm1-cmd.c and tpm2-cmd.c respectively.

Signed-off-by: Tomas Winkler 
Tested-by: Jarkko Sakkine 


Typo in Jarkko's last name -  "Sakkinen"

Thanks & Regards,
    - Nayna


---
V2-V3: Resend.
V4: Fix the commit message.

  drivers/char/tpm/tpm-interface.c | 41 
  drivers/char/tpm/tpm.h   |  1 -
  drivers/char/tpm/tpm1-cmd.c  | 37 +++-
  drivers/char/tpm/tpm2-cmd.c  | 34 +++--
  4 files changed, 68 insertions(+), 45 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index dfa972bbdd81..686b5316dad5 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -413,47 +413,6 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct 
tpm_space *space,
  }
  EXPORT_SYMBOL_GPL(tpm_transmit_cmd);

-#define TPM_ORD_STARTUP 153
-#define TPM_ST_CLEAR 1
-
-/**
- * tpm_startup - turn on the TPM
- * @chip: TPM chip to use
- *
- * Normally the firmware should start the TPM. This function is provided as a
- * workaround if this does not happen. A legal case for this could be for
- * example when a TPM emulator is used.
- *
- * Return: same as tpm_transmit_cmd()
- */
-int tpm_startup(struct tpm_chip *chip)
-{
-   struct tpm_buf buf;
-   int rc;
-
-   dev_info(>dev, "starting up the TPM manually\n");
-
-   if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
-   if (rc < 0)
-   return rc;
-
-   tpm_buf_append_u16(, TPM2_SU_CLEAR);
-   } else {
-   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
-   if (rc < 0)
-   return rc;
-
-   tpm_buf_append_u16(, TPM_ST_CLEAR);
-   }
-
-   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
- "attempting to start the TPM");
-
-   tpm_buf_destroy();
-   return rc;
-}
-
  int tpm_get_timeouts(struct tpm_chip *chip)
  {
if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 862c9262e037..fa88102a0cab 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -540,7 +540,6 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct 
tpm_space *space,
 void *buf, size_t bufsiz,
 size_t min_rsp_body_length, unsigned int flags,
 const char *desc);
-int tpm_startup(struct tpm_chip *chip);
  int tpm_get_timeouts(struct tpm_chip *);

  int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index d118adbcd2a7..6deae4595277 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -308,6 +308,40 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip 
*chip, u32 ordinal)
return duration;
  }

+#define TPM_ORD_STARTUP 153
+#define TPM_ST_CLEAR 1
+
+/**
+ * tpm_startup - turn on the TPM
+ * @chip: TPM chip to use
+ *
+ * Normally the firmware should start the TPM. This function is provided as a
+ * workaround if this does not happen. A legal case for this could be for
+ * example when a TPM emulator is used.
+ *
+ * Return: same as tpm_transmit_cmd()
+ */
+static int tpm1_startup(struct tpm_chip *chip)
+{
+   struct tpm_buf buf;
+   int rc;
+
+   dev_info(>dev, "starting up the TPM manually\n");
+
+   rc = tpm_buf_init(, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
+   if (rc < 0)
+   return rc;
+
+   tpm_buf_append_u16(, TPM_ST_CLEAR);
+
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
+ "attempting to start the TPM");
+
+   tpm_buf_destroy();
+
+   return rc;
+}
+
  int tpm1_get_timeouts(struct tpm_chip *chip)
  {
cap_t cap;
@@ -317,7 +351,7 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, , NULL,
 sizeof(cap.timeout));
if (rc == TPM_ERR_INVALID_POSTINIT) {
-   if (tpm_startup(chip))
+   if (tpm1_startup(chip))
return rc;

rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, ,
@@ -726,3 +760,4 @@ int tpm1_pm_suspend(struct tpm_chip *chip, int 
tpm_suspend_pcr)

return rc;
  }
+
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 65ce463a6f92..8da5a16e7c8c 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -943,6 +943,36 @@ static int 

Re: [PATCH v4 3/4] tpm: migrate tpm2_get_tpm_pt() to use struct tpm_buf

2018-05-18 Thread Nayna Jain



On 03/26/2018 05:44 PM, Jarkko Sakkinen wrote:

In order to make struct tpm_buf the first class object for constructing TPM
commands, migrate tpm2_get_tpm_pt() to use it.

Signed-off-by: Jarkko Sakkinen <jarkko.sakki...@linux.intel.com>

Reviewed-by: Nayna Jain<na...@linux.vnet.ibm.com>
Tested-by: Nayna Jain<na...@linux.vnet.ibm.com>


Thanks & Regards,
   - Nayna


---
  drivers/char/tpm/tpm2-cmd.c | 63 +
  1 file changed, 23 insertions(+), 40 deletions(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 7bffd0fd1dca..b3b52f9eb65f 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -27,20 +27,6 @@ enum tpm2_session_attributes {
TPM2_SA_CONTINUE_SESSION= BIT(0),
  };

-struct tpm2_get_tpm_pt_in {
-   __be32  cap_id;
-   __be32  property_id;
-   __be32  property_cnt;
-} __packed;
-
-struct tpm2_get_tpm_pt_out {
-   u8  more_data;
-   __be32  subcap_id;
-   __be32  property_cnt;
-   __be32  property_id;
-   __be32  value;
-} __packed;
-
  struct tpm2_get_random_in {
__be16  size;
  } __packed;
@@ -51,8 +37,6 @@ struct tpm2_get_random_out {
  } __packed;

  union tpm2_cmd_params {
-   struct  tpm2_get_tpm_pt_in  get_tpm_pt_in;
-   struct  tpm2_get_tpm_pt_out get_tpm_pt_out;
struct  tpm2_get_random_in  getrandom_in;
struct  tpm2_get_random_out getrandom_out;
  };
@@ -379,19 +363,6 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t 
max)
return total ? total : -EIO;
  }

-#define TPM2_GET_TPM_PT_IN_SIZE \
-   (sizeof(struct tpm_input_header) + \
-sizeof(struct tpm2_get_tpm_pt_in))
-
-#define TPM2_GET_TPM_PT_OUT_BODY_SIZE \
-sizeof(struct tpm2_get_tpm_pt_out)
-
-static const struct tpm_input_header tpm2_get_tpm_pt_header = {
-   .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-   .length = cpu_to_be32(TPM2_GET_TPM_PT_IN_SIZE),
-   .ordinal = cpu_to_be32(TPM2_CC_GET_CAPABILITY)
-};
-
  /**
   * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command
   * @chip: TPM chip to use
@@ -725,6 +696,14 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
return rc;
  }

+struct tpm2_get_cap_out {
+   u8 more_data;
+   __be32 subcap_id;
+   __be32 property_cnt;
+   __be32 property_id;
+   __be32 value;
+} __packed;
+
  /**
   * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property
   * @chip: TPM chip to use.
@@ -737,19 +716,23 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
  ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,  u32 *value,
const char *desc)
  {
-   struct tpm2_cmd cmd;
+   struct tpm2_get_cap_out *out;
+   struct tpm_buf buf;
int rc;

-   cmd.header.in = tpm2_get_tpm_pt_header;
-   cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
-   cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
-   cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
-
-   rc = tpm_transmit_cmd(chip, NULL, , sizeof(cmd),
- TPM2_GET_TPM_PT_OUT_BODY_SIZE, 0, desc);
-   if (!rc)
-   *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
-
+   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
+   if (rc)
+   return rc;
+   tpm_buf_append_u32(, TPM2_CAP_TPM_PROPERTIES);
+   tpm_buf_append_u32(, property_id);
+   tpm_buf_append_u32(, 1);
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL);
+   if (!rc) {
+   out = (struct tpm2_get_cap_out *)
+   [TPM_HEADER_SIZE];
+   *value = be32_to_cpu(out->value);
+   }
+   tpm_buf_destroy();
return rc;
  }
  EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);




Re: [PATCH v4 3/4] tpm: migrate tpm2_get_tpm_pt() to use struct tpm_buf

2018-05-18 Thread Nayna Jain



On 03/26/2018 05:44 PM, Jarkko Sakkinen wrote:

In order to make struct tpm_buf the first class object for constructing TPM
commands, migrate tpm2_get_tpm_pt() to use it.

Signed-off-by: Jarkko Sakkinen 

Reviewed-by: Nayna Jain
Tested-by: Nayna Jain


Thanks & Regards,
   - Nayna


---
  drivers/char/tpm/tpm2-cmd.c | 63 +
  1 file changed, 23 insertions(+), 40 deletions(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 7bffd0fd1dca..b3b52f9eb65f 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -27,20 +27,6 @@ enum tpm2_session_attributes {
TPM2_SA_CONTINUE_SESSION= BIT(0),
  };

-struct tpm2_get_tpm_pt_in {
-   __be32  cap_id;
-   __be32  property_id;
-   __be32  property_cnt;
-} __packed;
-
-struct tpm2_get_tpm_pt_out {
-   u8  more_data;
-   __be32  subcap_id;
-   __be32  property_cnt;
-   __be32  property_id;
-   __be32  value;
-} __packed;
-
  struct tpm2_get_random_in {
__be16  size;
  } __packed;
@@ -51,8 +37,6 @@ struct tpm2_get_random_out {
  } __packed;

  union tpm2_cmd_params {
-   struct  tpm2_get_tpm_pt_in  get_tpm_pt_in;
-   struct  tpm2_get_tpm_pt_out get_tpm_pt_out;
struct  tpm2_get_random_in  getrandom_in;
struct  tpm2_get_random_out getrandom_out;
  };
@@ -379,19 +363,6 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t 
max)
return total ? total : -EIO;
  }

-#define TPM2_GET_TPM_PT_IN_SIZE \
-   (sizeof(struct tpm_input_header) + \
-sizeof(struct tpm2_get_tpm_pt_in))
-
-#define TPM2_GET_TPM_PT_OUT_BODY_SIZE \
-sizeof(struct tpm2_get_tpm_pt_out)
-
-static const struct tpm_input_header tpm2_get_tpm_pt_header = {
-   .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-   .length = cpu_to_be32(TPM2_GET_TPM_PT_IN_SIZE),
-   .ordinal = cpu_to_be32(TPM2_CC_GET_CAPABILITY)
-};
-
  /**
   * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command
   * @chip: TPM chip to use
@@ -725,6 +696,14 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
return rc;
  }

+struct tpm2_get_cap_out {
+   u8 more_data;
+   __be32 subcap_id;
+   __be32 property_cnt;
+   __be32 property_id;
+   __be32 value;
+} __packed;
+
  /**
   * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property
   * @chip: TPM chip to use.
@@ -737,19 +716,23 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
  ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,  u32 *value,
const char *desc)
  {
-   struct tpm2_cmd cmd;
+   struct tpm2_get_cap_out *out;
+   struct tpm_buf buf;
int rc;

-   cmd.header.in = tpm2_get_tpm_pt_header;
-   cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
-   cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
-   cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
-
-   rc = tpm_transmit_cmd(chip, NULL, , sizeof(cmd),
- TPM2_GET_TPM_PT_OUT_BODY_SIZE, 0, desc);
-   if (!rc)
-   *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
-
+   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
+   if (rc)
+   return rc;
+   tpm_buf_append_u32(, TPM2_CAP_TPM_PROPERTIES);
+   tpm_buf_append_u32(, property_id);
+   tpm_buf_append_u32(, 1);
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL);
+   if (!rc) {
+   out = (struct tpm2_get_cap_out *)
+   [TPM_HEADER_SIZE];
+   *value = be32_to_cpu(out->value);
+   }
+   tpm_buf_destroy();
return rc;
  }
  EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);




Re: [PATCH v4 2/4] tpm: migrate tpm2_probe() to use struct tpm_buf

2018-05-18 Thread Nayna Jain



On 03/26/2018 05:44 PM, Jarkko Sakkinen wrote:

In order to make struct tpm_buf the first class object for constructing TPM
commands, migrate tpm2_probe() to use it.

Signed-off-by: Jarkko Sakkinen <jarkko.sakki...@linux.intel.com>
Acked-by: Jay Freyensee <why2jjj.li...@gmail.com>


Reviewed-by: Nayna Jain<na...@linux.vnet.ibm.com>
Tested-by: Nayna Jain<na...@linux.vnet.ibm.com>


Thanks & Regards,
    - Nayna


---
  drivers/char/tpm/tpm2-cmd.c | 37 +
  1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 7665661d9230..7bffd0fd1dca 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -844,30 +844,35 @@ static int tpm2_do_selftest(struct tpm_chip *chip)

  /**
   * tpm2_probe() - probe TPM 2.0
- * @chip: TPM chip to use
+ * @chip: a TPM chip to probe
   *
- * Return: < 0 error and 0 on success.
+ * Return: 0 on success,
+ * -errno otherwise
   *
- * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based 
on
- * the reply tag.
+ * Send an idempotent TPM 2.0 command and see whether there is TPM2 chip in the
+ * other end based on the response tag. The flag TPM_CHIP_FLAG_TPM2 is set if
+ * this is the case.
   */
  int tpm2_probe(struct tpm_chip *chip)
  {
-   struct tpm2_cmd cmd;
+   struct tpm_output_header *out;
+   struct tpm_buf buf;
int rc;

-   cmd.header.in = tpm2_get_tpm_pt_header;
-   cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
-   cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
-   cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
-
-   rc = tpm_transmit_cmd(chip, NULL, , sizeof(cmd), 0, 0, NULL);
-   if (rc <  0)
+   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
+   if (rc)
return rc;
-
-   if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS)
-   chip->flags |= TPM_CHIP_FLAG_TPM2;
-
+   tpm_buf_append_u32(, TPM2_CAP_TPM_PROPERTIES);
+   tpm_buf_append_u32(, TPM_PT_TOTAL_COMMANDS);
+   tpm_buf_append_u32(, 1);
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL);
+   /* We ignore TPM return codes on purpose. */
+   if (rc >=  0) {
+   out = (struct tpm_output_header *)buf.data;
+   if (be16_to_cpu(out->tag) == TPM2_ST_NO_SESSIONS)
+   chip->flags |= TPM_CHIP_FLAG_TPM2;
+   }
+   tpm_buf_destroy();
return 0;
  }
  EXPORT_SYMBOL_GPL(tpm2_probe);




Re: [PATCH v4 2/4] tpm: migrate tpm2_probe() to use struct tpm_buf

2018-05-18 Thread Nayna Jain



On 03/26/2018 05:44 PM, Jarkko Sakkinen wrote:

In order to make struct tpm_buf the first class object for constructing TPM
commands, migrate tpm2_probe() to use it.

Signed-off-by: Jarkko Sakkinen 
Acked-by: Jay Freyensee 


Reviewed-by: Nayna Jain
Tested-by: Nayna Jain


Thanks & Regards,
    - Nayna


---
  drivers/char/tpm/tpm2-cmd.c | 37 +
  1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 7665661d9230..7bffd0fd1dca 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -844,30 +844,35 @@ static int tpm2_do_selftest(struct tpm_chip *chip)

  /**
   * tpm2_probe() - probe TPM 2.0
- * @chip: TPM chip to use
+ * @chip: a TPM chip to probe
   *
- * Return: < 0 error and 0 on success.
+ * Return: 0 on success,
+ * -errno otherwise
   *
- * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based 
on
- * the reply tag.
+ * Send an idempotent TPM 2.0 command and see whether there is TPM2 chip in the
+ * other end based on the response tag. The flag TPM_CHIP_FLAG_TPM2 is set if
+ * this is the case.
   */
  int tpm2_probe(struct tpm_chip *chip)
  {
-   struct tpm2_cmd cmd;
+   struct tpm_output_header *out;
+   struct tpm_buf buf;
int rc;

-   cmd.header.in = tpm2_get_tpm_pt_header;
-   cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
-   cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
-   cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
-
-   rc = tpm_transmit_cmd(chip, NULL, , sizeof(cmd), 0, 0, NULL);
-   if (rc <  0)
+   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
+   if (rc)
return rc;
-
-   if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS)
-   chip->flags |= TPM_CHIP_FLAG_TPM2;
-
+   tpm_buf_append_u32(, TPM2_CAP_TPM_PROPERTIES);
+   tpm_buf_append_u32(, TPM_PT_TOTAL_COMMANDS);
+   tpm_buf_append_u32(, 1);
+   rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL);
+   /* We ignore TPM return codes on purpose. */
+   if (rc >=  0) {
+   out = (struct tpm_output_header *)buf.data;
+   if (be16_to_cpu(out->tag) == TPM2_ST_NO_SESSIONS)
+   chip->flags |= TPM_CHIP_FLAG_TPM2;
+   }
+   tpm_buf_destroy();
return 0;
  }
  EXPORT_SYMBOL_GPL(tpm2_probe);




Re: [PATCH v4 1/4] tpm: migrate tpm2_shutdown() to use struct tpm_buf

2018-05-18 Thread Nayna Jain



On 03/26/2018 05:44 PM, Jarkko Sakkinen wrote:

In order to make struct tpm_buf the first class object for constructing TPM
commands, migrate tpm2_shutdown() to use it. In addition, removed the klog
entry when tpm_transmit_cmd() fails because tpm_tansmit_cmd() already
prints an error message.

Signed-off-by: Jarkko Sakkinen <jarkko.sakki...@linux.intel.com>


Reviewed-by: Nayna Jain<na...@linux.vnet.ibm.com>
Tested-by: Nayna Jain<na...@linux.vnet.ibm.com>


---
  drivers/char/tpm/tpm2-cmd.c | 44 
  1 file changed, 12 insertions(+), 32 deletions(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 96c77c8e7f40..7665661d9230 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -27,10 +27,6 @@ enum tpm2_session_attributes {
TPM2_SA_CONTINUE_SESSION= BIT(0),
  };

-struct tpm2_startup_in {
-   __be16  startup_type;
-} __packed;
-
  struct tpm2_get_tpm_pt_in {
__be32  cap_id;
__be32  property_id;
@@ -55,7 +51,6 @@ struct tpm2_get_random_out {
  } __packed;

  union tpm2_cmd_params {
-   struct  tpm2_startup_in startup_in;
struct  tpm2_get_tpm_pt_in  get_tpm_pt_in;
struct  tpm2_get_tpm_pt_out get_tpm_pt_out;
struct  tpm2_get_random_in  getrandom_in;
@@ -412,11 +407,8 @@ void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 
handle,
int rc;

rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
-   if (rc) {
-   dev_warn(>dev, "0x%08x was not flushed, out of memory\n",
-handle);
+   if (rc)
return;
-   }

tpm_buf_append_u32(, handle);

@@ -762,40 +754,28 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 
property_id,  u32 *value,
  }
  EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);

-#define TPM2_SHUTDOWN_IN_SIZE \
-   (sizeof(struct tpm_input_header) + \
-sizeof(struct tpm2_startup_in))
-
-static const struct tpm_input_header tpm2_shutdown_header = {
-   .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-   .length = cpu_to_be32(TPM2_SHUTDOWN_IN_SIZE),
-   .ordinal = cpu_to_be32(TPM2_CC_SHUTDOWN)
-};
-
  /**
   * tpm2_shutdown() - send shutdown command to the TPM chip
   *
+ * In places where shutdown command is sent there's no much we can do except
+ * print the error code on a system failure.
+ *
   * @chip: TPM chip to use.
   * @shutdown_type:shutdown type. The value is either
   *TPM_SU_CLEAR or TPM_SU_STATE.
   */
  void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
  {
-   struct tpm2_cmd cmd;
+   struct tpm_buf buf;
int rc;

-   cmd.header.in = tpm2_shutdown_header;
-   cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
-
-   rc = tpm_transmit_cmd(chip, NULL, , sizeof(cmd), 0, 0,
- "stopping the TPM");
-
-   /* In places where shutdown command is sent there's no much we can do
-* except print the error code on a system failure.
-*/
-   if (rc < 0 && rc != -EPIPE)
-   dev_warn(>dev, "transmit returned %d while stopping the 
TPM",
-rc);
+   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN);
+   if (rc)
+   return;
+   tpm_buf_append_u16(, shutdown_type);
+   tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
+"stopping the TPM");
+   tpm_buf_destroy();
  }

  /*




Re: [PATCH v4 1/4] tpm: migrate tpm2_shutdown() to use struct tpm_buf

2018-05-18 Thread Nayna Jain



On 03/26/2018 05:44 PM, Jarkko Sakkinen wrote:

In order to make struct tpm_buf the first class object for constructing TPM
commands, migrate tpm2_shutdown() to use it. In addition, removed the klog
entry when tpm_transmit_cmd() fails because tpm_tansmit_cmd() already
prints an error message.

Signed-off-by: Jarkko Sakkinen 


Reviewed-by: Nayna Jain
Tested-by: Nayna Jain


---
  drivers/char/tpm/tpm2-cmd.c | 44 
  1 file changed, 12 insertions(+), 32 deletions(-)

diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 96c77c8e7f40..7665661d9230 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -27,10 +27,6 @@ enum tpm2_session_attributes {
TPM2_SA_CONTINUE_SESSION= BIT(0),
  };

-struct tpm2_startup_in {
-   __be16  startup_type;
-} __packed;
-
  struct tpm2_get_tpm_pt_in {
__be32  cap_id;
__be32  property_id;
@@ -55,7 +51,6 @@ struct tpm2_get_random_out {
  } __packed;

  union tpm2_cmd_params {
-   struct  tpm2_startup_in startup_in;
struct  tpm2_get_tpm_pt_in  get_tpm_pt_in;
struct  tpm2_get_tpm_pt_out get_tpm_pt_out;
struct  tpm2_get_random_in  getrandom_in;
@@ -412,11 +407,8 @@ void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 
handle,
int rc;

rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
-   if (rc) {
-   dev_warn(>dev, "0x%08x was not flushed, out of memory\n",
-handle);
+   if (rc)
return;
-   }

tpm_buf_append_u32(, handle);

@@ -762,40 +754,28 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 
property_id,  u32 *value,
  }
  EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);

-#define TPM2_SHUTDOWN_IN_SIZE \
-   (sizeof(struct tpm_input_header) + \
-sizeof(struct tpm2_startup_in))
-
-static const struct tpm_input_header tpm2_shutdown_header = {
-   .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-   .length = cpu_to_be32(TPM2_SHUTDOWN_IN_SIZE),
-   .ordinal = cpu_to_be32(TPM2_CC_SHUTDOWN)
-};
-
  /**
   * tpm2_shutdown() - send shutdown command to the TPM chip
   *
+ * In places where shutdown command is sent there's no much we can do except
+ * print the error code on a system failure.
+ *
   * @chip: TPM chip to use.
   * @shutdown_type:shutdown type. The value is either
   *TPM_SU_CLEAR or TPM_SU_STATE.
   */
  void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
  {
-   struct tpm2_cmd cmd;
+   struct tpm_buf buf;
int rc;

-   cmd.header.in = tpm2_shutdown_header;
-   cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
-
-   rc = tpm_transmit_cmd(chip, NULL, , sizeof(cmd), 0, 0,
- "stopping the TPM");
-
-   /* In places where shutdown command is sent there's no much we can do
-* except print the error code on a system failure.
-*/
-   if (rc < 0 && rc != -EPIPE)
-   dev_warn(>dev, "transmit returned %d while stopping the 
TPM",
-rc);
+   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN);
+   if (rc)
+   return;
+   tpm_buf_append_u16(, shutdown_type);
+   tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
+"stopping the TPM");
+   tpm_buf_destroy();
  }

  /*




Re: [PATCH v4 4/4] tpm: migrate tpm2_get_random() to use struct tpm_buf

2018-05-18 Thread Nayna Jain
r)
+   return err;

-   err = tpm_transmit_cmd(chip, NULL, , sizeof(cmd),
+   do {
+   tpm_buf_reset(, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM);
+   tpm_buf_append_u16(, num_bytes);
+   err = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
   offsetof(struct tpm2_get_random_out,
buffer),
   0, "attempting get random");
if (err)
-   break;
+   goto out;

-   recd = min_t(u32, be16_to_cpu(cmd.params.getrandom_out.size),
-num_bytes);
-   rlength = be32_to_cpu(cmd.header.out.length);
-   if (rlength < offsetof(struct tpm2_get_random_out, buffer) +
- recd)
-   return -EFAULT;
-   memcpy(dest, cmd.params.getrandom_out.buffer, recd);
+   out = (struct tpm2_get_random_out *)
+   [TPM_HEADER_SIZE];
+   recd = min_t(u32, be16_to_cpu(out->size), num_bytes);
+   if (tpm_buf_length() <
+   offsetof(struct tpm2_get_random_out, buffer) + recd) {
+   err = -EFAULT;
+   goto out;
+   }
+   memcpy(dest_ptr, out->buffer, recd);

-   dest += recd;
+   dest_ptr += recd;
total += recd;
num_bytes -= recd;
} while (retries-- && total < max);

+   tpm_buf_destroy();
return total ? total : -EIO;
+out:
+   tpm_buf_destroy();
+   return err;
  }


How about having it as :

    if (!total)
        err = -EIO;
out:
    tpm_buf_destroy();
    return total?:err;


  /**
@@ -434,7 +418,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
  {
unsigned int blob_len;
struct tpm_buf buf;
-   u32 hash, rlength;
+   u32 hash;
int i;
int rc;

@@ -509,8 +493,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
rc = -E2BIG;
goto out;
}
-   rlength = be32_to_cpu(((struct tpm2_cmd *))->header.out.length);
-   if (rlength < TPM_HEADER_SIZE + 4 + blob_len) {
+   if (tpm_buf_length() < TPM_HEADER_SIZE + 4 + blob_len) {
rc = -EFAULT;
goto out;
}
@@ -620,7 +603,6 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
u16 data_len;
u8 *data;
int rc;
-   u32 rlength;

rc = tpm_buf_init(, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
if (rc)
@@ -648,9 +630,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
goto out;
}

-   rlength = be32_to_cpu(((struct tpm2_cmd *))
-   ->header.out.length);
-   if (rlength < TPM_HEADER_SIZE + 6 + data_len) {
+   if (tpm_buf_length() < TPM_HEADER_SIZE + 6 + data_len) {
rc = -EFAULT;
goto out;
}
Probably, all the changes related to the use of tpm_buf_length() could 
be a separate patch in itself ?


Otherwise,

Tested-by: Nayna Jain<na...@linux.vnet.ibm.com>

Thanks & Regards,
   - Nayna



Re: [PATCH v4 4/4] tpm: migrate tpm2_get_random() to use struct tpm_buf

2018-05-18 Thread Nayna Jain
  err = tpm_transmit_cmd(chip, NULL, , sizeof(cmd),
+   do {
+   tpm_buf_reset(, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM);
+   tpm_buf_append_u16(, num_bytes);
+   err = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
   offsetof(struct tpm2_get_random_out,
buffer),
   0, "attempting get random");
if (err)
-   break;
+   goto out;

-   recd = min_t(u32, be16_to_cpu(cmd.params.getrandom_out.size),
-num_bytes);
-   rlength = be32_to_cpu(cmd.header.out.length);
-   if (rlength < offsetof(struct tpm2_get_random_out, buffer) +
- recd)
-   return -EFAULT;
-   memcpy(dest, cmd.params.getrandom_out.buffer, recd);
+   out = (struct tpm2_get_random_out *)
+   [TPM_HEADER_SIZE];
+   recd = min_t(u32, be16_to_cpu(out->size), num_bytes);
+   if (tpm_buf_length() <
+   offsetof(struct tpm2_get_random_out, buffer) + recd) {
+   err = -EFAULT;
+   goto out;
+   }
+   memcpy(dest_ptr, out->buffer, recd);

-   dest += recd;
+   dest_ptr += recd;
total += recd;
num_bytes -= recd;
} while (retries-- && total < max);

+   tpm_buf_destroy();
return total ? total : -EIO;
+out:
+   tpm_buf_destroy();
+   return err;
  }


How about having it as :

    if (!total)
        err = -EIO;
out:
    tpm_buf_destroy();
    return total?:err;


  /**
@@ -434,7 +418,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
  {
unsigned int blob_len;
struct tpm_buf buf;
-   u32 hash, rlength;
+   u32 hash;
int i;
int rc;

@@ -509,8 +493,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
rc = -E2BIG;
goto out;
}
-   rlength = be32_to_cpu(((struct tpm2_cmd *))->header.out.length);
-   if (rlength < TPM_HEADER_SIZE + 4 + blob_len) {
+   if (tpm_buf_length() < TPM_HEADER_SIZE + 4 + blob_len) {
rc = -EFAULT;
goto out;
}
@@ -620,7 +603,6 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
u16 data_len;
u8 *data;
int rc;
-   u32 rlength;

rc = tpm_buf_init(, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
if (rc)
@@ -648,9 +630,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
goto out;
}

-   rlength = be32_to_cpu(((struct tpm2_cmd *))
-   ->header.out.length);
-   if (rlength < TPM_HEADER_SIZE + 6 + data_len) {
+   if (tpm_buf_length() < TPM_HEADER_SIZE + 6 + data_len) {
rc = -EFAULT;
goto out;
}
Probably, all the changes related to the use of tpm_buf_length() could 
be a separate patch in itself ?


Otherwise,

Tested-by: Nayna Jain

Thanks & Regards,
   - Nayna



[PATCH v4 0/2] tpm: improving granularity in poll sleep times

2018-05-15 Thread Nayna Jain
The existing TPM polling code sleeps in each loop iteration for time in
msecs ranging from 1 msecs to 5 msecs. However, many of the TPM commands
complete much faster, resulting in unnecessary delays.

This set of patches identifies such iterations and optimizes the sleep
time. The first patch replaces TPM_POLL_SLEEP with TPM_TIMEOUT_POLL and
moves it from tpm_tis_core.c to tpm.h as an enum with value 1 msecs. The
second patch further reduces the TPM poll sleep time in get_burstcount()
and wait_for_tpm_stat() in tpm_tis_core.c by calling usleep_range()
directly.

The change is only in the polling time, and the maximum timeout is still
maintained the same. Thus, it should not affect the overall existing
behavior.

Changelog:

v4:
tpm: reduce poll sleep time in tpm_transmit()
* added Reviewed-by, Tested-by and Ack-by

tpm: reduce polling time to usecs for even finer granularity
* included Jarkko's feedback
* added Ack-by

v3:

tpm: reduce poll sleep time in tpm_transmit()
* added testing platform information
* updated patch description for more clarity on reasoning

tpm: reduce polling time to usecs for even finer granularity
* added testing platform information
* added Jarkko's and Mimi's Reviewed-by

v2:

tpm: reduce poll sleep time in tpm_transmit()
* merged previously defined two patches into this.
* updated patch description as per Jarkko's feedback

tpm: reduce polling time to usecs for even finer granularity
* directly use usleep_range with finer granularity less than 1msec

Nayna Jain (2):
  tpm: reduce poll sleep time in tpm_transmit()
  tpm: reduce polling time to usecs for even finer granularity

 drivers/char/tpm/tpm-interface.c |  2 +-
 drivers/char/tpm/tpm.h   |  5 -
 drivers/char/tpm/tpm_tis_core.c  | 11 +++
 3 files changed, 8 insertions(+), 10 deletions(-)

-- 
2.13.3



[PATCH v4 0/2] tpm: improving granularity in poll sleep times

2018-05-15 Thread Nayna Jain
The existing TPM polling code sleeps in each loop iteration for time in
msecs ranging from 1 msecs to 5 msecs. However, many of the TPM commands
complete much faster, resulting in unnecessary delays.

This set of patches identifies such iterations and optimizes the sleep
time. The first patch replaces TPM_POLL_SLEEP with TPM_TIMEOUT_POLL and
moves it from tpm_tis_core.c to tpm.h as an enum with value 1 msecs. The
second patch further reduces the TPM poll sleep time in get_burstcount()
and wait_for_tpm_stat() in tpm_tis_core.c by calling usleep_range()
directly.

The change is only in the polling time, and the maximum timeout is still
maintained the same. Thus, it should not affect the overall existing
behavior.

Changelog:

v4:
tpm: reduce poll sleep time in tpm_transmit()
* added Reviewed-by, Tested-by and Ack-by

tpm: reduce polling time to usecs for even finer granularity
* included Jarkko's feedback
* added Ack-by

v3:

tpm: reduce poll sleep time in tpm_transmit()
* added testing platform information
* updated patch description for more clarity on reasoning

tpm: reduce polling time to usecs for even finer granularity
* added testing platform information
* added Jarkko's and Mimi's Reviewed-by

v2:

tpm: reduce poll sleep time in tpm_transmit()
* merged previously defined two patches into this.
* updated patch description as per Jarkko's feedback

tpm: reduce polling time to usecs for even finer granularity
* directly use usleep_range with finer granularity less than 1msec

Nayna Jain (2):
  tpm: reduce poll sleep time in tpm_transmit()
  tpm: reduce polling time to usecs for even finer granularity

 drivers/char/tpm/tpm-interface.c |  2 +-
 drivers/char/tpm/tpm.h   |  5 -
 drivers/char/tpm/tpm_tis_core.c  | 11 +++
 3 files changed, 8 insertions(+), 10 deletions(-)

-- 
2.13.3



[PATCH v4 1/2] tpm: reduce poll sleep time in tpm_transmit()

2018-05-15 Thread Nayna Jain
tpm_try_transmit currently checks TPM status every 5 msecs between
send and recv. It does so in a loop for the maximum timeout as defined
in the TPM Interface Specification. However, the TPM may return before
5 msecs. Thus the polling interval for each iteration can be reduced,
which improves overall performance. This patch changes the polling sleep
time from 5 msecs to 1 msec.

Additionally, this patch renames TPM_POLL_SLEEP to TPM_TIMEOUT_POLL and
moves it to tpm.h as an enum value.

After this change, performance on a system[1] with a TPM 1.2 with an 8 byte
burstcount for 1000 extends improved from ~14 sec to ~10.7 sec.

[1] All tests are performed on an x86 based, locked down, single purpose
closed system. It has Infineon TPM 1.2 using LPC Bus.

Signed-off-by: Nayna Jain <na...@linux.vnet.ibm.com>
Reviewed-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Jay Freyensee <why2jjj.li...@gmail.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakki...@linux.intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakki...@linux.intel.com>
---
 drivers/char/tpm/tpm-interface.c |  2 +-
 drivers/char/tpm/tpm.h   |  3 ++-
 drivers/char/tpm/tpm_tis_core.c  | 10 ++
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 9e80a953d693..a676d8ad5992 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -470,7 +470,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
goto out;
}
 
-   tpm_msleep(TPM_TIMEOUT);
+   tpm_msleep(TPM_TIMEOUT_POLL);
rmb();
} while (time_before(jiffies, stop));
 
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f895fba4e20d..7e797377e1eb 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -53,7 +53,8 @@ enum tpm_const {
 enum tpm_timeout {
TPM_TIMEOUT = 5,/* msecs */
TPM_TIMEOUT_RETRY = 100, /* msecs */
-   TPM_TIMEOUT_RANGE_US = 300  /* usecs */
+   TPM_TIMEOUT_RANGE_US = 300, /* usecs */
+   TPM_TIMEOUT_POLL = 1/* msecs */
 };
 
 /* TPM addresses */
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index da074e3db19b..021e6b68f2db 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -31,12 +31,6 @@
 #include "tpm.h"
 #include "tpm_tis_core.h"
 
-/* This is a polling delay to check for status and burstcount.
- * As per ddwg input, expectation is that status check and burstcount
- * check should return within few usecs.
- */
-#define TPM_POLL_SLEEP 1  /* msec */
-
 static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value);
 
 static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
@@ -90,7 +84,7 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
}
} else {
do {
-   tpm_msleep(TPM_POLL_SLEEP);
+   tpm_msleep(TPM_TIMEOUT_POLL);
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
@@ -232,7 +226,7 @@ static int get_burstcount(struct tpm_chip *chip)
burstcnt = (value >> 8) & 0x;
if (burstcnt)
return burstcnt;
-   tpm_msleep(TPM_POLL_SLEEP);
+   tpm_msleep(TPM_TIMEOUT_POLL);
} while (time_before(jiffies, stop));
return -EBUSY;
 }
-- 
2.13.3



[PATCH v4 1/2] tpm: reduce poll sleep time in tpm_transmit()

2018-05-15 Thread Nayna Jain
tpm_try_transmit currently checks TPM status every 5 msecs between
send and recv. It does so in a loop for the maximum timeout as defined
in the TPM Interface Specification. However, the TPM may return before
5 msecs. Thus the polling interval for each iteration can be reduced,
which improves overall performance. This patch changes the polling sleep
time from 5 msecs to 1 msec.

Additionally, this patch renames TPM_POLL_SLEEP to TPM_TIMEOUT_POLL and
moves it to tpm.h as an enum value.

After this change, performance on a system[1] with a TPM 1.2 with an 8 byte
burstcount for 1000 extends improved from ~14 sec to ~10.7 sec.

[1] All tests are performed on an x86 based, locked down, single purpose
closed system. It has Infineon TPM 1.2 using LPC Bus.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Acked-by: Jay Freyensee 
Reviewed-by: Jarkko Sakkinen 
Tested-by: Jarkko Sakkinen 
---
 drivers/char/tpm/tpm-interface.c |  2 +-
 drivers/char/tpm/tpm.h   |  3 ++-
 drivers/char/tpm/tpm_tis_core.c  | 10 ++
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 9e80a953d693..a676d8ad5992 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -470,7 +470,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct 
tpm_space *space,
goto out;
}
 
-   tpm_msleep(TPM_TIMEOUT);
+   tpm_msleep(TPM_TIMEOUT_POLL);
rmb();
} while (time_before(jiffies, stop));
 
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f895fba4e20d..7e797377e1eb 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -53,7 +53,8 @@ enum tpm_const {
 enum tpm_timeout {
TPM_TIMEOUT = 5,/* msecs */
TPM_TIMEOUT_RETRY = 100, /* msecs */
-   TPM_TIMEOUT_RANGE_US = 300  /* usecs */
+   TPM_TIMEOUT_RANGE_US = 300, /* usecs */
+   TPM_TIMEOUT_POLL = 1/* msecs */
 };
 
 /* TPM addresses */
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index da074e3db19b..021e6b68f2db 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -31,12 +31,6 @@
 #include "tpm.h"
 #include "tpm_tis_core.h"
 
-/* This is a polling delay to check for status and burstcount.
- * As per ddwg input, expectation is that status check and burstcount
- * check should return within few usecs.
- */
-#define TPM_POLL_SLEEP 1  /* msec */
-
 static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value);
 
 static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
@@ -90,7 +84,7 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
}
} else {
do {
-   tpm_msleep(TPM_POLL_SLEEP);
+   tpm_msleep(TPM_TIMEOUT_POLL);
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
@@ -232,7 +226,7 @@ static int get_burstcount(struct tpm_chip *chip)
burstcnt = (value >> 8) & 0x;
if (burstcnt)
return burstcnt;
-   tpm_msleep(TPM_POLL_SLEEP);
+   tpm_msleep(TPM_TIMEOUT_POLL);
} while (time_before(jiffies, stop));
return -EBUSY;
 }
-- 
2.13.3



[PATCH v4 2/2] tpm: reduce polling time to usecs for even finer granularity

2018-05-15 Thread Nayna Jain
The TPM burstcount and status commands are supposed to return very
quickly [2][3]. This patch further reduces the TPM poll sleep time to usecs
in get_burstcount() and wait_for_tpm_stat() by calling usleep_range()
directly.

After this change, performance on a system[1] with a TPM 1.2 with an 8 byte
burstcount for 1000 extends improved from ~10.7 sec to ~7 sec.

[1] All tests are performed on an x86 based, locked down, single purpose
closed system. It has Infineon TPM 1.2 using LPC Bus.

[2] From the TCG Specification "TCG PC Client Specific TPM Interface
Specification (TIS), Family 1.2":

"NOTE : It takes roughly 330 ns per byte transfer on LPC. 256 bytes would
take 84 us, which is a long time to stall the CPU. Chipsets may not be
designed to post this much data to LPC; therefore, the CPU itself is
stalled for much of this time. Sending 1 kB would take 350 μs. Therefore,
even if the TPM_STS_x.burstCount field is a high value, software SHOULD
be interruptible during this period."

[3] From the TCG Specification 2.0, "TCG PC Client Platform TPM Profile
(PTP) Specification":

"It takes roughly 330 ns per byte transfer on LPC. 256 bytes would take
84 us. Chipsets may not be designed to post this much data to LPC;
therefore, the CPU itself is stalled for much of this time. Sending 1 kB
would take 350 us. Therefore, even if the TPM_STS_x.burstCount field is a
high value, software should be interruptible during this period. For SPI,
assuming 20MHz clock and 64-byte transfers, it would take about 120 usec
to move 256B of data. Sending 1kB would take about 500 usec. If the
transactions are done using 4 bytes at a time, then it would take about
1 msec. to transfer 1kB of data."

Signed-off-by: Nayna Jain <na...@linux.vnet.ibm.com>
Reviewed-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakki...@linux.intel.com>
Acked-by: Jay Freyensee <why2jjj.li...@gmail.com>
---
 drivers/char/tpm/tpm.h  | 4 +++-
 drivers/char/tpm/tpm_tis_core.c | 5 +++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 7e797377e1eb..f0e4d290c347 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -54,7 +54,9 @@ enum tpm_timeout {
TPM_TIMEOUT = 5,/* msecs */
TPM_TIMEOUT_RETRY = 100, /* msecs */
TPM_TIMEOUT_RANGE_US = 300, /* usecs */
-   TPM_TIMEOUT_POLL = 1/* msecs */
+   TPM_TIMEOUT_POLL = 1,   /* msecs */
+   TPM_TIMEOUT_USECS_MIN = 100,  /* usecs */
+   TPM_TIMEOUT_USECS_MAX = 500  /* usecs */
 };
 
 /* TPM addresses */
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 021e6b68f2db..bbd8eed30e57 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -84,7 +84,8 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
}
} else {
do {
-   tpm_msleep(TPM_TIMEOUT_POLL);
+   usleep_range(TPM_TIMEOUT_USECS_MIN,
+TPM_TIMEOUT_USECS_MAX);
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
@@ -226,7 +227,7 @@ static int get_burstcount(struct tpm_chip *chip)
burstcnt = (value >> 8) & 0x;
if (burstcnt)
return burstcnt;
-   tpm_msleep(TPM_TIMEOUT_POLL);
+   usleep_range(TPM_TIMEOUT_USECS_MIN, TPM_TIMEOUT_USECS_MAX);
} while (time_before(jiffies, stop));
return -EBUSY;
 }
-- 
2.13.3



[PATCH v4 2/2] tpm: reduce polling time to usecs for even finer granularity

2018-05-15 Thread Nayna Jain
The TPM burstcount and status commands are supposed to return very
quickly [2][3]. This patch further reduces the TPM poll sleep time to usecs
in get_burstcount() and wait_for_tpm_stat() by calling usleep_range()
directly.

After this change, performance on a system[1] with a TPM 1.2 with an 8 byte
burstcount for 1000 extends improved from ~10.7 sec to ~7 sec.

[1] All tests are performed on an x86 based, locked down, single purpose
closed system. It has Infineon TPM 1.2 using LPC Bus.

[2] From the TCG Specification "TCG PC Client Specific TPM Interface
Specification (TIS), Family 1.2":

"NOTE : It takes roughly 330 ns per byte transfer on LPC. 256 bytes would
take 84 us, which is a long time to stall the CPU. Chipsets may not be
designed to post this much data to LPC; therefore, the CPU itself is
stalled for much of this time. Sending 1 kB would take 350 μs. Therefore,
even if the TPM_STS_x.burstCount field is a high value, software SHOULD
be interruptible during this period."

[3] From the TCG Specification 2.0, "TCG PC Client Platform TPM Profile
(PTP) Specification":

"It takes roughly 330 ns per byte transfer on LPC. 256 bytes would take
84 us. Chipsets may not be designed to post this much data to LPC;
therefore, the CPU itself is stalled for much of this time. Sending 1 kB
would take 350 us. Therefore, even if the TPM_STS_x.burstCount field is a
high value, software should be interruptible during this period. For SPI,
assuming 20MHz clock and 64-byte transfers, it would take about 120 usec
to move 256B of data. Sending 1kB would take about 500 usec. If the
transactions are done using 4 bytes at a time, then it would take about
1 msec. to transfer 1kB of data."

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Reviewed-by: Jarkko Sakkinen 
Acked-by: Jay Freyensee 
---
 drivers/char/tpm/tpm.h  | 4 +++-
 drivers/char/tpm/tpm_tis_core.c | 5 +++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 7e797377e1eb..f0e4d290c347 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -54,7 +54,9 @@ enum tpm_timeout {
TPM_TIMEOUT = 5,/* msecs */
TPM_TIMEOUT_RETRY = 100, /* msecs */
TPM_TIMEOUT_RANGE_US = 300, /* usecs */
-   TPM_TIMEOUT_POLL = 1/* msecs */
+   TPM_TIMEOUT_POLL = 1,   /* msecs */
+   TPM_TIMEOUT_USECS_MIN = 100,  /* usecs */
+   TPM_TIMEOUT_USECS_MAX = 500  /* usecs */
 };
 
 /* TPM addresses */
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 021e6b68f2db..bbd8eed30e57 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -84,7 +84,8 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
}
} else {
do {
-   tpm_msleep(TPM_TIMEOUT_POLL);
+   usleep_range(TPM_TIMEOUT_USECS_MIN,
+TPM_TIMEOUT_USECS_MAX);
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
@@ -226,7 +227,7 @@ static int get_burstcount(struct tpm_chip *chip)
burstcnt = (value >> 8) & 0x;
if (burstcnt)
return burstcnt;
-   tpm_msleep(TPM_TIMEOUT_POLL);
+   usleep_range(TPM_TIMEOUT_USECS_MIN, TPM_TIMEOUT_USECS_MAX);
} while (time_before(jiffies, stop));
return -EBUSY;
 }
-- 
2.13.3



[PATCH v3] tpm: check selftest status before retrying full selftest

2018-05-15 Thread Nayna Jain
TPM 2.0 supports TPM2_GetTestResult[1], which can be used to check the
selftest status. This patch implements the tpm2_get_selftest_result()
function to check the selftest status before trying full selftest.

[1] As per TCG Specification, Trusted Platform Module Library,
Part 2 - Commands, Section 10.4:

"This command(TPM2_GetTestResult) returns manufacturer-specific information
regarding the results of a self-test and an indication of the test status.

Signed-off-by: Nayna Jain <na...@linux.vnet.ibm.com>
Tested-by: Mimi Zohar <zo...@linux.vnet.ibm.com> (on Pi with TPM 2.0)
Tested-by: Stefan Berger <stef...@linux.vnet.ibm.com> (With QEMU with
swtpm TPM 2.0)
---

Changelog:

v3:
* modified to check the selftest status before full selftest command is run
* fixed the patch description
* includes Jarkko's feedbacks

v2:
* changed the subject and updated patch description
* removed the logs

 drivers/char/tpm/tpm.h  |  2 ++
 drivers/char/tpm/tpm2-cmd.c | 44 
 2 files changed, 46 insertions(+)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index af3bb87d3ea1..1de4240b52c4 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -114,6 +114,7 @@ enum tpm2_return_codes {
TPM2_RC_FAILURE = 0x0101,
TPM2_RC_DISABLED= 0x0120,
TPM2_RC_COMMAND_CODE= 0x0143,
+   TPM2_RC_NEEDS_TEST  = 0x0153,
TPM2_RC_TESTING = 0x090A, /* RC_WARN */
TPM2_RC_REFERENCE_H0= 0x0910,
TPM2_RC_RETRY   = 0x0922,
@@ -144,6 +145,7 @@ enum tpm2_command_codes {
TPM2_CC_FLUSH_CONTEXT   = 0x0165,
TPM2_CC_GET_CAPABILITY  = 0x017A,
TPM2_CC_GET_RANDOM  = 0x017B,
+   TPM2_CC_GET_TEST_RESULT = 0x017C,
TPM2_CC_PCR_READ= 0x017E,
TPM2_CC_PCR_EXTEND  = 0x0182,
TPM2_CC_LAST= 0x018F,
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 96c77c8e7f40..811bcf221208 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -825,6 +825,43 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip 
*chip, u32 ordinal)
 EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration);
 
 /**
+ * tpm2_get_selftest_result() - get the status of selftest
+ * @chip: TPM chip to use
+ *
+ * Return: TPM return code, errno otherwise
+ */
+static int tpm2_get_selftest_result(struct tpm_chip *chip)
+{
+   struct tpm_buf buf;
+   int rc;
+   int test_result;
+   uint16_t data_size;
+   int len;
+   const struct tpm_output_header *header;
+
+   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_TEST_RESULT);
+   if (rc)
+   return rc;
+
+   len = tpm_transmit(chip, NULL, buf.data, PAGE_SIZE, 0);
+   if (len <  0)
+   return len;
+
+   header = (struct tpm_output_header *)buf.data;
+
+   rc = be32_to_cpu(header->return_code);
+   if (rc)
+   return rc;
+
+   data_size = be16_to_cpup((__be16 *)[TPM_HEADER_SIZE]);
+
+   test_result = be32_to_cpup((__be32 *)
+   ([TPM_HEADER_SIZE + 2 + data_size]));
+
+   return test_result;
+}
+
+/**
  * tpm2_do_selftest() - ensure that all self tests have passed
  *
  * @chip: TPM chip to use
@@ -857,6 +894,13 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
rc = TPM2_RC_SUCCESS;
if (rc == TPM2_RC_INITIALIZE || rc == TPM2_RC_SUCCESS)
return rc;
+
+   rc = tpm2_get_selftest_result(chip);
+   dev_dbg(>dev, "self test result is %04x\n", rc);
+
+   if (rc == TPM2_RC_TESTING || rc == TPM2_RC_SUCCESS)
+   return TPM2_RC_SUCCESS;
+
}
 
return rc;
-- 
2.13.6



[PATCH v3] tpm: check selftest status before retrying full selftest

2018-05-15 Thread Nayna Jain
TPM 2.0 supports TPM2_GetTestResult[1], which can be used to check the
selftest status. This patch implements the tpm2_get_selftest_result()
function to check the selftest status before trying full selftest.

[1] As per TCG Specification, Trusted Platform Module Library,
Part 2 - Commands, Section 10.4:

"This command(TPM2_GetTestResult) returns manufacturer-specific information
regarding the results of a self-test and an indication of the test status.

Signed-off-by: Nayna Jain 
Tested-by: Mimi Zohar  (on Pi with TPM 2.0)
Tested-by: Stefan Berger  (With QEMU with
swtpm TPM 2.0)
---

Changelog:

v3:
* modified to check the selftest status before full selftest command is run
* fixed the patch description
* includes Jarkko's feedbacks

v2:
* changed the subject and updated patch description
* removed the logs

 drivers/char/tpm/tpm.h  |  2 ++
 drivers/char/tpm/tpm2-cmd.c | 44 
 2 files changed, 46 insertions(+)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index af3bb87d3ea1..1de4240b52c4 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -114,6 +114,7 @@ enum tpm2_return_codes {
TPM2_RC_FAILURE = 0x0101,
TPM2_RC_DISABLED= 0x0120,
TPM2_RC_COMMAND_CODE= 0x0143,
+   TPM2_RC_NEEDS_TEST  = 0x0153,
TPM2_RC_TESTING = 0x090A, /* RC_WARN */
TPM2_RC_REFERENCE_H0= 0x0910,
TPM2_RC_RETRY   = 0x0922,
@@ -144,6 +145,7 @@ enum tpm2_command_codes {
TPM2_CC_FLUSH_CONTEXT   = 0x0165,
TPM2_CC_GET_CAPABILITY  = 0x017A,
TPM2_CC_GET_RANDOM  = 0x017B,
+   TPM2_CC_GET_TEST_RESULT = 0x017C,
TPM2_CC_PCR_READ= 0x017E,
TPM2_CC_PCR_EXTEND  = 0x0182,
TPM2_CC_LAST= 0x018F,
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 96c77c8e7f40..811bcf221208 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -825,6 +825,43 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip 
*chip, u32 ordinal)
 EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration);
 
 /**
+ * tpm2_get_selftest_result() - get the status of selftest
+ * @chip: TPM chip to use
+ *
+ * Return: TPM return code, errno otherwise
+ */
+static int tpm2_get_selftest_result(struct tpm_chip *chip)
+{
+   struct tpm_buf buf;
+   int rc;
+   int test_result;
+   uint16_t data_size;
+   int len;
+   const struct tpm_output_header *header;
+
+   rc = tpm_buf_init(, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_TEST_RESULT);
+   if (rc)
+   return rc;
+
+   len = tpm_transmit(chip, NULL, buf.data, PAGE_SIZE, 0);
+   if (len <  0)
+   return len;
+
+   header = (struct tpm_output_header *)buf.data;
+
+   rc = be32_to_cpu(header->return_code);
+   if (rc)
+   return rc;
+
+   data_size = be16_to_cpup((__be16 *)[TPM_HEADER_SIZE]);
+
+   test_result = be32_to_cpup((__be32 *)
+   ([TPM_HEADER_SIZE + 2 + data_size]));
+
+   return test_result;
+}
+
+/**
  * tpm2_do_selftest() - ensure that all self tests have passed
  *
  * @chip: TPM chip to use
@@ -857,6 +894,13 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
rc = TPM2_RC_SUCCESS;
if (rc == TPM2_RC_INITIALIZE || rc == TPM2_RC_SUCCESS)
return rc;
+
+   rc = tpm2_get_selftest_result(chip);
+   dev_dbg(>dev, "self test result is %04x\n", rc);
+
+   if (rc == TPM2_RC_TESTING || rc == TPM2_RC_SUCCESS)
+   return TPM2_RC_SUCCESS;
+
}
 
return rc;
-- 
2.13.6



Re: [PATCH v3 1/2] tpm: reduce poll sleep time in tpm_transmit()

2018-05-14 Thread Nayna Jain



On 05/10/2018 06:11 PM, Nayna Jain wrote:



On 05/08/2018 10:04 PM, J Freyensee wrote:



  do {
-    tpm_msleep(TPM_POLL_SLEEP);
+    tpm_msleep(TPM_TIMEOUT_POLL);

I'm just curious why it was decided to still use tpm_msleep() here 
instead of usleep_range() which was used in the 2nd patch.


TPM_TIMEOUT_POLL is in msec i.e. 1 msec and usleep_range() is used 
only when timeout is needed in usecs.


Just to add bit more details:

usleep_range() is used in wait_for_tpm_stat() and get_burstcount() which 
are expected to return quickly. tpm_transmit() is a generic function 
used across all drivers and commands.
Some of the commands (eg. hash, key generation) take longer compared to 
other commands (eg. extend). The sleep time in tpm_transmit is reduced 
but kept in msecs to balance between the smaller and longer commands.


Thanks & Regards,
    - Nayna





Otherwise,

Acked-by: Jay Freyensee <why2jjj.li...@gmail.com>


Thanks !!

Thanks & Regards,
    - Nayna






Re: [PATCH v3 1/2] tpm: reduce poll sleep time in tpm_transmit()

2018-05-14 Thread Nayna Jain



On 05/10/2018 06:11 PM, Nayna Jain wrote:



On 05/08/2018 10:04 PM, J Freyensee wrote:



  do {
-    tpm_msleep(TPM_POLL_SLEEP);
+    tpm_msleep(TPM_TIMEOUT_POLL);

I'm just curious why it was decided to still use tpm_msleep() here 
instead of usleep_range() which was used in the 2nd patch.


TPM_TIMEOUT_POLL is in msec i.e. 1 msec and usleep_range() is used 
only when timeout is needed in usecs.


Just to add bit more details:

usleep_range() is used in wait_for_tpm_stat() and get_burstcount() which 
are expected to return quickly. tpm_transmit() is a generic function 
used across all drivers and commands.
Some of the commands (eg. hash, key generation) take longer compared to 
other commands (eg. extend). The sleep time in tpm_transmit is reduced 
but kept in msecs to balance between the smaller and longer commands.


Thanks & Regards,
    - Nayna





Otherwise,

Acked-by: Jay Freyensee 


Thanks !!

Thanks & Regards,
    - Nayna






Re: [PATCH v3 1/2] tpm: reduce poll sleep time in tpm_transmit()

2018-05-10 Thread Nayna Jain



On 05/08/2018 10:04 PM, J Freyensee wrote:



  do {
-    tpm_msleep(TPM_POLL_SLEEP);
+    tpm_msleep(TPM_TIMEOUT_POLL);

I'm just curious why it was decided to still use tpm_msleep() here 
instead of usleep_range() which was used in the 2nd patch.


TPM_TIMEOUT_POLL is in msec i.e. 1 msec and usleep_range() is used only 
when timeout is needed in usecs.




Otherwise,

Acked-by: Jay Freyensee 


Thanks !!

Thanks & Regards,
    - Nayna




Re: [PATCH v3 1/2] tpm: reduce poll sleep time in tpm_transmit()

2018-05-10 Thread Nayna Jain



On 05/08/2018 10:04 PM, J Freyensee wrote:



  do {
-    tpm_msleep(TPM_POLL_SLEEP);
+    tpm_msleep(TPM_TIMEOUT_POLL);

I'm just curious why it was decided to still use tpm_msleep() here 
instead of usleep_range() which was used in the 2nd patch.


TPM_TIMEOUT_POLL is in msec i.e. 1 msec and usleep_range() is used only 
when timeout is needed in usecs.




Otherwise,

Acked-by: Jay Freyensee 


Thanks !!

Thanks & Regards,
    - Nayna




  1   2   3   4   >