mbox series

[v7,0/5] KEYS: asymmetric: tpm2_key_{rsa,ecdsa}

Message ID 20240528210823.28798-1-jarkko@kernel.org
Headers show
Series KEYS: asymmetric: tpm2_key_{rsa,ecdsa} | expand

Message

Jarkko Sakkinen May 28, 2024, 9:08 p.m. UTC
Testing
=======

RSA
---

tpm2_createprimary --hierarchy o -G rsa2048 -c owner.txt
tpm2_evictcontrol -c owner.txt 0x81000001
tpm2_getcap handles-persistent
openssl genrsa -out private.pem 2048
tpm2_import -C 0x81000001 -G rsa -i private.pem -u key.pub -r key.priv
tpm2_encodeobject -C 0x81000001 -u key.pub -r key.priv -o key.priv.pem
openssl asn1parse -inform pem -in key.priv.pem -noout -out key.priv.der
serial=`cat key.priv.der | keyctl padd asymmetric tpm @u`
echo "abcdefg" > plaintext.txt
keyctl pkey_encrypt $serial 0 plaintext.txt enc=pkcs1 > encrypted.dat
keyctl pkey_decrypt $serial 0 encrypted.dat enc=pkcs1 > decrypted.dat
keyctl pkey_sign $serial 0 plaintext.txt enc=pkcs1 hash=sha256 > signed.dat
keyctl pkey_verify $serial 0 plaintext.txt signed.dat enc=pkcs1 hash=sha256

ECDSA
-----

tpm2_createprimary --hierarchy o -G ecc -c owner.txt
tpm2_evictcontrol -c owner.txt 0x81000001
openssl ecparam -name prime256v1 -genkey -noout -out private.pem
tpm2_import -C 0x81000001 -G ecc -i private.pem -u key.pub -r key.priv
tpm2_encodeobject -C 0x81000001 -u key.pub -r key.priv -o key.priv.pem
openssl asn1parse -inform pem -in key.priv.pem -noout -out key.priv.der
serial=`cat key.priv.der | keyctl padd asymmetric tpm @u`
echo "abcdefg" > plaintext.txt
keyctl pkey_sign $serial 0 plaintext.txt hash=sha256 > signed.dat
keyctl pkey_verify $serial 0 plaintext.txt signed.dat hash=sha256

Closed Issues
=============

* When verifying ECDSA signature, _ecdsa_verify() returns -EKEYREJECTED.
  * v7: rewrote the signature encoder with a more structured layout.

References
==========

* v6: https://lore.kernel.org/linux-integrity/20240528035136.11464-1-jarkko@kernel.org/
* v5: https://lore.kernel.org/linux-integrity/20240523212515.4875-1-jarkko@kernel.org/
* v4: https://lore.kernel.org/linux-integrity/20240522005252.17841-1-jarkko@kernel.org/
* v3: https://lore.kernel.org/linux-integrity/20240521152659.26438-1-jarkko@kernel.org/
* v2: https://lore.kernel.org/linux-integrity/336755.1716327854@warthog.procyon.org.uk/
* v1: https://lore.kernel.org/linux-integrity/20240520184727.22038-1-jarkko@kernel.org/
* Derived from https://lore.kernel.org/all/20200518172704.29608-1-prestwoj@gmail.com/

Jarkko Sakkinen (5):
  crypto: rsa-pkcs1pad: export rsa1_asn_lookup()
  KEYS: trusted: Change -EINVAL to -E2BIG
  crypto: tpm2_key: Introduce a TPM2 key type
  keys: asymmetric: Add tpm2_key_rsa
  keys: asymmetric: Add tpm2_key_ecdsa

 crypto/Kconfig                            |   7 +
 crypto/Makefile                           |   6 +
 crypto/asymmetric_keys/Kconfig            |  30 +
 crypto/asymmetric_keys/Makefile           |   2 +
 crypto/asymmetric_keys/tpm2_key_ecdsa.c   | 462 +++++++++++++++
 crypto/asymmetric_keys/tpm2_key_rsa.c     | 678 ++++++++++++++++++++++
 crypto/ecdsa.c                            |   1 -
 crypto/rsa-pkcs1pad.c                     |  16 +-
 crypto/tpm2_key.asn1                      |  11 +
 crypto/tpm2_key.c                         | 134 +++++
 drivers/char/tpm/tpm-buf.c                |   2 +-
 include/crypto/rsa-pkcs1pad.h             |  20 +
 include/crypto/tpm2_key.h                 |  46 ++
 include/linux/tpm.h                       |   9 +
 security/keys/trusted-keys/Kconfig        |   2 +-
 security/keys/trusted-keys/Makefile       |   2 -
 security/keys/trusted-keys/tpm2key.asn1   |  11 -
 security/keys/trusted-keys/trusted_tpm2.c | 141 +----
 18 files changed, 1447 insertions(+), 133 deletions(-)
 create mode 100644 crypto/asymmetric_keys/tpm2_key_ecdsa.c
 create mode 100644 crypto/asymmetric_keys/tpm2_key_rsa.c
 create mode 100644 crypto/tpm2_key.asn1
 create mode 100644 crypto/tpm2_key.c
 create mode 100644 include/crypto/rsa-pkcs1pad.h
 create mode 100644 include/crypto/tpm2_key.h
 delete mode 100644 security/keys/trusted-keys/tpm2key.asn1

Comments

Jarkko Sakkinen May 28, 2024, 11:09 p.m. UTC | #1
On Wed May 29, 2024 at 12:42 AM EEST, Jarkko Sakkinen wrote:
> On Wed May 29, 2024 at 12:08 AM EEST, Jarkko Sakkinen wrote:
> > +	/* Encode the ASN.1 signature: */
> > +#define TPM2_KEY_ECDSA_SIG_SIZE		(2 + 2 * (2 + SHA256_DIGEST_SIZE) + r_0 + s_0)
> > +	pr_info("sig_size=%d\n", TPM2_KEY_ECDSA_SIG_SIZE);
> > +	ptr[0] = 0x30; /* SEQUENCE */
> > +	ptr[1] = TPM2_KEY_ECDSA_SIG_SIZE - 2;
> > +#define TPM2_KEY_ECDSA_SIG_R_TAG	2
> > +#define TPM2_KEY_ECDSA_SIG_R_SIZE	3
> > +#define TPM2_KEY_ECDSA_SIG_R_BODY	4
> > +	ptr[TPM2_KEY_ECDSA_SIG_R_TAG] = 0x02; /* INTEGER */
> > +	ptr[TPM2_KEY_ECDSA_SIG_R_SIZE] = SHA256_DIGEST_SIZE + r_0;
> > +	ptr[TPM2_KEY_ECDSA_SIG_R_BODY] = 0x00; /* maybe dummy write */
> > +	memcpy(&ptr[TPM2_KEY_ECDSA_SIG_R_BODY + r_0], r, SHA256_DIGEST_SIZE);
> > +#define TPM2_KEY_ECDSA_SIG_S_TAG	(4 + r_0 + SHA256_DIGEST_SIZE)
> > +#define TPM2_KEY_ECDSA_SIG_S_SIZE	(5 + r_0 + SHA256_DIGEST_SIZE)
> > +#define TPM2_KEY_ECDSA_SIG_S_BODY	(6 + r_0 + SHA256_DIGEST_SIZE)
> > +	ptr[TPM2_KEY_ECDSA_SIG_S_TAG] = 0x02; /* INTEGER */
> > +	ptr[TPM2_KEY_ECDSA_SIG_S_SIZE] = SHA256_DIGEST_SIZE + s_0;
> > +	ptr[TPM2_KEY_ECDSA_SIG_S_BODY] = 0x00; /* maybe dummy write */
> > +	memcpy(&ptr[TPM2_KEY_ECDSA_SIG_S_BODY + s_0], s, SHA256_DIGEST_SIZE);
> > +	ret = TPM2_KEY_ECDSA_SIG_SIZE;
>
> Stefan, so this how I realized the signature encoding, thanks to
> your earlier remarks [1]! I found out based on that a few glitches
> and ended up with this better structured ECDSA signature encoder,
> so thank you for doing that.

1. SHA384 would fit without any significant changes.
2. SHA512 will require a single additional byte, i.e. prefix byte 0x81
   for the sequence (not for coeffients).
3. SM3 similarly is also trivial to add.

Both will be also easy to add later on. I would not enlarge this patch
set from what it is now.

So I think this is pretty well along the lines of:

https://datatracker.ietf.org/doc/draft-woodhouse-cert-best-practice/

BR, Jarkko
Stefan Berger May 28, 2024, 11:20 p.m. UTC | #2
On 5/28/24 17:08, Jarkko Sakkinen wrote:
> ASN.1 template is required for TPM2 asymmetric keys, as it needs to be
> piggy-packed with the input data before applying TPM2_RSA_Decrypt. This

piggy-backed

> patch prepares crypto subsystem for the addition of those keys.
> 
> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>

Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>

> ---
>   crypto/rsa-pkcs1pad.c         | 16 ++++++++++------
>   include/crypto/rsa-pkcs1pad.h | 20 ++++++++++++++++++++
>   2 files changed, 30 insertions(+), 6 deletions(-)
>   create mode 100644 include/crypto/rsa-pkcs1pad.h
> 
> diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
> index cd501195f34a..00b6c14f861c 100644
> --- a/crypto/rsa-pkcs1pad.c
> +++ b/crypto/rsa-pkcs1pad.c
> @@ -7,6 +7,7 @@
>   
>   #include <crypto/algapi.h>
>   #include <crypto/akcipher.h>
> +#include <crypto/rsa-pkcs1pad.h>
>   #include <crypto/internal/akcipher.h>
>   #include <crypto/internal/rsa.h>
>   #include <linux/err.h>
> @@ -79,11 +80,7 @@ static const u8 rsa_digest_info_sha3_512[] = {
>   	0x05, 0x00, 0x04, 0x40
>   };
>   
> -static const struct rsa_asn1_template {
> -	const char	*name;
> -	const u8	*data;
> -	size_t		size;
> -} rsa_asn1_templates[] = {
> +static const struct rsa_asn1_template rsa_asn1_templates[] = {
>   #define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
>   	_(md5),
>   	_(sha1),
> @@ -101,7 +98,13 @@ static const struct rsa_asn1_template {
>   	{ NULL }
>   };
>   
> -static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
> +/**
> + * rsa_lookup_asn1() - Lookup the ASN.1 digest info given the hash
> + * name:	hash algorithm name
> + *
> + * Returns the ASN.1 digest info on success, and NULL on failure.
> + */
> +const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
>   {
>   	const struct rsa_asn1_template *p;
>   
> @@ -110,6 +113,7 @@ static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
>   			return p;
>   	return NULL;
>   }
> +EXPORT_SYMBOL_GPL(rsa_lookup_asn1);
>   
>   struct pkcs1pad_ctx {
>   	struct crypto_akcipher *child;
> diff --git a/include/crypto/rsa-pkcs1pad.h b/include/crypto/rsa-pkcs1pad.h
> new file mode 100644
> index 000000000000..32c7453ff644
> --- /dev/null
> +++ b/include/crypto/rsa-pkcs1pad.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * RSA padding templates.
> + */
> +
> +#ifndef _CRYPTO_RSA_PKCS1PAD_H
> +#define _CRYPTO_RSA_PKCS1PAD_H
> +
> +/*
> + * Hash algorithm name to ASN.1 template mapping.
> + */
> +struct rsa_asn1_template {
> +	const char *name;
> +	const u8 *data;
> +	size_t size;
> +};
> +
> +const struct rsa_asn1_template *rsa_lookup_asn1(const char *name);
> +
> +#endif /* _CRYPTO_RSA_PKCS1PAD_H */
Jarkko Sakkinen May 29, 2024, 1:14 a.m. UTC | #3
On Wed May 29, 2024 at 2:15 AM EEST, Stefan Berger wrote:
> > +	ptr[TPM2_KEY_ECDSA_SIG_R_TAG] = 0x02; /* INTEGER */
> > +	ptr[TPM2_KEY_ECDSA_SIG_R_SIZE] = SHA256_DIGEST_SIZE + r_0;
>
> The size of the signature has nothing to do with the size of the hash. 
> SHA256_DIGEST_SIZE (32) happens to match the number of bytes of a 
> coordinate of prime256v1 / NIST p256 but should fail when you use 
> secp521r1 / NIST p521 since then r or s may then be 66 or 67 bytes (if 
> most sign. bit is set) long.

First remark did not go unnoticed, so thanks for both. There was not
just much to comment on it :-)

I could just replace the constant with a (range checked) variable
read from the response and overall structure woud be the same.

This will also mean that in the case of P521 also prefix byte (0x81) is
required but just for the sequence I think, not for the integers.

Finally, I need to implement p521 smoke test for testing this patch set.

One big letdown that I only now have consciously realized, is that TCG
does not have p256k1 in their algorithm repository. It is the basis for
quite a few blockchain technologies. I wonder why...

BR, Jarkko
Jarkko Sakkinen May 29, 2024, 1:25 a.m. UTC | #4
On Wed May 29, 2024 at 2:20 AM EEST, Stefan Berger wrote:
>
>
> On 5/28/24 17:08, Jarkko Sakkinen wrote:
> > ASN.1 template is required for TPM2 asymmetric keys, as it needs to be
> > piggy-packed with the input data before applying TPM2_RSA_Decrypt. This
>
> piggy-backed

Right! I consciously wrote it that way, i.e. have used wrong spelling
up to this day :-)

Thanks for the review! This is not likely to change that much. Would
not tag any other patches tho before up to p521 have been tested...

BR, Jarkko