linux-crypto.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa
@ 2024-09-10 14:30 Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements Lukas Wunner
                   ` (20 more replies)
  0 siblings, 21 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, Dimitri John Ledkov
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings,
	Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
	linux-security-module, Gonglei, Michael S. Tsirkin, Jason Wang,
	Xuan Zhuo, Eugenio Perez, virtualization, zhenwei pi, lei he,
	Neal Liu, Joel Stanley, Andrew Jeff ery, linux-aspeed, Zhiqi Song,
	Longfang Liu, Jia Jie Ho, William Qiu

The original impetus of this series is to introduce P1363 signature
decoding for ecdsa (patch [18/19]), which is needed by the upcoming
SPDM library (Security Protocol and Data Model) for PCI device
authentication.

To facilitate that, move X9.62 signature decoding out of ecdsa.c and
into a template (patch [15/19]).

New in v2:  Move the maximum signature size calculations for ecdsa
out of software_key_query() and into the X9.62 template so that
corresponding calculations can be added for P1363 without further
cluttering up software_key_query() (patch [16/19] - [17/19]).

New in v2:  Avoid inefficient copying from kernel buffers to sglists
in the new templates by introducing a sig_alg backend and migrating
all algorithms to it, per Herbert's advice (patch [02/19] - [12/19]).

Clean up various smaller issues that caught my eye in ecdsa
(patch [01/19] and [14/19]), ecrdsa (patch [19/19]) and
ASN.1 headers (patch [13/19]).

I've also accumulated various cleanups for crypto virtio on my
development branch but will leave them for another day as this
series is already nearing the "too big to review" threshold. ;)

I've run selftests on every single commit, but further testing
would be appreciated to raise the confidence.


Link to v1:

https://lore.kernel.org/all/cover.1722260176.git.lukas@wunner.de/

Changes v1 -> v2:

* [PATCH 13/19] ASN.1: Clean up include statements in public headers
  * Drop "#include <linux/bug.h>" from <linux/asn1_encoder.h> (Jonathan)

* [PATCH 14/19] crypto: ecdsa - Avoid signed integer overflow on signature
  decoding
  * Add code comment explaining why vlen may be larger than bufsize (Stefan)

* [PATCH 15/19] crypto: ecdsa - Move X9.62 signature decoding into template
  * Drop unnecessary "params", "param_len" and "algo" definitions from
    ecdsa_nist_p{192,256,384,521}_tv_template[].
  * Introduce and use struct ecdsa_raw_sig in <crypto/internal/ecc.h>.

* [PATCH 18/19] crypto: ecdsa - Support P1363 signature decoding
  * Drop unnecessary "params", "param_len" and "algo" definitions from
    p1363_ecdsa_nist_p256_tv_template[].


Lukas Wunner (19):
  crypto: ecdsa - Drop unused test vector elements
  crypto: sig - Introduce sig_alg backend
  crypto: ecdsa - Migrate to sig_alg backend
  crypto: ecrdsa - Migrate to sig_alg backend
  crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks
  crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  crypto: rsassa-pkcs1 - Harden digest length verification
  crypto: rsassa-pkcs1 - Avoid copying hash prefix
  crypto: virtio - Drop sign/verify operations
  crypto: drivers - Drop sign/verify operations
  crypto: akcipher - Drop sign/verify operations
  crypto: sig - Move crypto_sig_*() API calls to include file
  ASN.1: Clean up include statements in public headers
  crypto: ecdsa - Avoid signed integer overflow on signature decoding
  crypto: ecdsa - Move X9.62 signature decoding into template
  crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize()
  crypto: ecdsa - Move X9.62 signature size calculation into template
  crypto: ecdsa - Support P1363 signature decoding
  crypto: ecrdsa - Fix signature size calculation

 Documentation/crypto/api-akcipher.rst         |   2 +-
 Documentation/crypto/api-sig.rst              |  15 +
 Documentation/crypto/api.rst                  |   1 +
 Documentation/crypto/architecture.rst         |   2 +
 crypto/Kconfig                                |   5 +-
 crypto/Makefile                               |   5 +-
 crypto/akcipher.c                             |  64 +-
 crypto/asymmetric_keys/public_key.c           |  58 +-
 crypto/ecdsa-p1363.c                          | 159 ++++
 crypto/ecdsa-x962.c                           | 237 +++++
 crypto/ecdsa.c                                | 209 ++---
 crypto/ecrdsa.c                               |  64 +-
 crypto/internal.h                             |  19 -
 crypto/rsa-pkcs1pad.c                         | 371 +-------
 crypto/rsa.c                                  |  17 +-
 crypto/rsassa-pkcs1.c                         | 442 +++++++++
 crypto/sig.c                                  | 143 +--
 crypto/testmgr.c                              | 320 +++++--
 crypto/testmgr.h                              | 884 +++++++++++++++---
 drivers/crypto/aspeed/aspeed-acry.c           |   2 -
 drivers/crypto/hisilicon/hpre/hpre_crypto.c   |   2 -
 drivers/crypto/starfive/jh7110-rsa.c          |   2 -
 .../virtio/virtio_crypto_akcipher_algs.c      |  65 +-
 include/crypto/akcipher.h                     |  69 +-
 include/crypto/internal/akcipher.h            |   4 +-
 include/crypto/internal/ecc.h                 |  14 +
 include/crypto/internal/rsa.h                 |  29 +
 include/crypto/internal/sig.h                 |  80 ++
 include/crypto/sig.h                          | 152 ++-
 include/linux/asn1_decoder.h                  |   1 +
 include/linux/asn1_encoder.h                  |   1 -
 include/linux/slab.h                          |   1 +
 include/uapi/linux/cryptouser.h               |   5 +
 include/uapi/linux/virtio_crypto.h            |   1 +
 security/integrity/ima/ima_main.c             |   6 +-
 35 files changed, 2398 insertions(+), 1053 deletions(-)
 create mode 100644 Documentation/crypto/api-sig.rst
 create mode 100644 crypto/ecdsa-p1363.c
 create mode 100644 crypto/ecdsa-x962.c
 create mode 100644 crypto/rsassa-pkcs1.c

-- 
2.43.0


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 18:49   ` Stefan Berger
  2024-09-11 11:52   ` Jarkko Sakkinen
  2024-09-10 14:30 ` [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend Lukas Wunner
                   ` (19 subsequent siblings)
  20 siblings, 2 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

The ECDSA test vectors contain "params", "param_len" and "algo" elements
even though ecdsa.c doesn't make any use of them.  The only algorithm
implementation using those elements is ecrdsa.c.

Drop the unused test vector elements.

For the curious, "params" is an ASN.1 SEQUENCE of OID_id_ecPublicKey
and a second OID identifying the curve.  For example:

    "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
    "\xce\x3d\x03\x01\x01"

... decodes to:

    SEQUENCE (OID_id_ecPublicKey, OID_id_prime192v1)

The curve OIDs used in those "params" elements are unsurprisingly:

    OID_id_prime192v1 (2a8648ce3d030101)
    OID_id_prime256v1 (2a8648ce3d030107)
    OID_id_ansip384r1 (2b81040022)
    OID_id_ansip521r1 (2b81040023)

Those are just different names for secp192r1, secp256r1, secp384r1 and
secp521r1, respectively, per RFC 8422 appendix A:
https://www.rfc-editor.org/rfc/rfc8422#appendix-A

The entries for secp384r1 and secp521r1 curves contain a useful code
comment calling out the curve and hash.  Add analogous code comments
to secp192r1 and secp256r1 curve entries.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 crypto/testmgr.h | 115 +++++------------------------------------------
 1 file changed, 10 insertions(+), 105 deletions(-)

diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 9b38501a17b2..ed1640f3e352 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -652,21 +652,16 @@ static const struct akcipher_testvec rsa_tv_template[] = {
  */
 static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	{
-	.key =
+	.key = /* secp192r1(sha1) */
 	"\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1"
 	"\xd4\x09\x73\xcf\xea\xd0\x15\x07\x3d\xa5\x8a\x8a\x95\x43\xe4\x68"
 	"\xea\xc6\x25\xc1\xc1\x01\x25\x4c\x7e\xc3\x3c\xa6\x04\x0a\xe7\x08"
 	"\x98",
 	.key_len = 49,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x01",
-	.param_len = 21,
 	.m =
 	"\xcd\xb9\xd2\x1c\xb7\x6f\xcd\x44\xb3\xfd\x63\xea\xa3\x66\x7f\xae"
 	"\x63\x85\xe7\x82",
 	.m_size = 20,
-	.algo = OID_id_ecdsa_with_sha1,
 	.c =
 	"\x30\x35\x02\x19\x00\xba\xe5\x93\x83\x6e\xb6\x3b\x63\xa0\x27\x91"
 	"\xc6\xf6\x7f\xc3\x09\xad\x59\xad\x88\x27\xd6\x92\x6b\x02\x18\x10"
@@ -676,21 +671,16 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	.public_key_vec = true,
 	.siggen_sigver_test = true,
 	}, {
-	.key =
+	.key = /* secp192r1(sha224) */
 	"\x04\xb6\x4b\xb1\xd1\xac\xba\x24\x8f\x65\xb2\x60\x00\x90\xbf\xbd"
 	"\x78\x05\x73\xe9\x79\x1d\x6f\x7c\x0b\xd2\xc3\x93\xa7\x28\xe1\x75"
 	"\xf7\xd5\x95\x1d\x28\x10\xc0\x75\x50\x5c\x1a\x4f\x3f\x8f\xa5\xee"
 	"\xa3",
 	.key_len = 49,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x01",
-	.param_len = 21,
 	.m =
 	"\x8d\xd6\xb8\x3e\xe5\xff\x23\xf6\x25\xa2\x43\x42\x74\x45\xa7\x40"
 	"\x3a\xff\x2f\xe1\xd3\xf6\x9f\xe8\x33\xcb\x12\x11",
 	.m_size = 28,
-	.algo = OID_id_ecdsa_with_sha224,
 	.c =
 	"\x30\x34\x02\x18\x5a\x8b\x82\x69\x7e\x8a\x0a\x09\x14\xf8\x11\x2b"
 	"\x55\xdc\xae\x37\x83\x7b\x12\xe6\xb6\x5b\xcb\xd4\x02\x18\x6a\x14"
@@ -700,21 +690,16 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	.public_key_vec = true,
 	.siggen_sigver_test = true,
 	}, {
-	.key =
+	.key = /* secp192r1(sha256) */
 	"\x04\xe2\x51\x24\x9b\xf7\xb6\x32\x82\x39\x66\x3d\x5b\xec\x3b\xae"
 	"\x0c\xd5\xf2\x67\xd1\xc7\xe1\x02\xe4\xbf\x90\x62\xb8\x55\x75\x56"
 	"\x69\x20\x5e\xcb\x4e\xca\x33\xd6\xcb\x62\x6b\x94\xa9\xa2\xe9\x58"
 	"\x91",
 	.key_len = 49,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x01",
-	.param_len = 21,
 	.m =
 	"\x35\xec\xa1\xa0\x9e\x14\xde\x33\x03\xb6\xf6\xbd\x0c\x2f\xb2\xfd"
 	"\x1f\x27\x82\xa5\xd7\x70\x3f\xef\xa0\x82\x69\x8e\x73\x31\x8e\xd7",
 	.m_size = 32,
-	.algo = OID_id_ecdsa_with_sha256,
 	.c =
 	"\x30\x35\x02\x18\x3f\x72\x3f\x1f\x42\xd2\x3f\x1d\x6b\x1a\x58\x56"
 	"\xf1\x8f\xf7\xfd\x01\x48\xfb\x5f\x72\x2a\xd4\x8f\x02\x19\x00\xb3"
@@ -724,22 +709,17 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	.public_key_vec = true,
 	.siggen_sigver_test = true,
 	}, {
-	.key =
+	.key = /* secp192r1(sha384) */
 	"\x04\x5a\x13\xfe\x68\x86\x4d\xf4\x17\xc7\xa4\xe5\x8c\x65\x57\xb7"
 	"\x03\x73\x26\x57\xfb\xe5\x58\x40\xd8\xfd\x49\x05\xab\xf1\x66\x1f"
 	"\xe2\x9d\x93\x9e\xc2\x22\x5a\x8b\x4f\xf3\x77\x22\x59\x7e\xa6\x4e"
 	"\x8b",
 	.key_len = 49,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x01",
-	.param_len = 21,
 	.m =
 	"\x9d\x2e\x1a\x8f\xed\x6c\x4b\x61\xae\xac\xd5\x19\x79\xce\x67\xf9"
 	"\xa0\x34\xeb\xb0\x81\xf9\xd9\xdc\x6e\xb3\x5c\xa8\x69\xfc\x8a\x61"
 	"\x39\x81\xfb\xfd\x5c\x30\x6b\xa8\xee\xed\x89\xaf\xa3\x05\xe4\x78",
 	.m_size = 48,
-	.algo = OID_id_ecdsa_with_sha384,
 	.c =
 	"\x30\x35\x02\x19\x00\xf0\xa3\x38\xce\x2b\xf8\x9d\x1a\xcf\x7f\x34"
 	"\xb4\xb4\xe5\xc5\x00\xdd\x15\xbb\xd6\x8c\xa7\x03\x78\x02\x18\x64"
@@ -749,23 +729,18 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	.public_key_vec = true,
 	.siggen_sigver_test = true,
 	}, {
-	.key =
+	.key = /* secp192r1(sha512) */
 	"\x04\xd5\xf2\x6e\xc3\x94\x5c\x52\xbc\xdf\x86\x6c\x14\xd1\xca\xea"
 	"\xcc\x72\x3a\x8a\xf6\x7a\x3a\x56\x36\x3b\xca\xc6\x94\x0e\x17\x1d"
 	"\x9e\xa0\x58\x28\xf9\x4b\xe6\xd1\xa5\x44\x91\x35\x0d\xe7\xf5\x11"
 	"\x57",
 	.key_len = 49,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x01",
-	.param_len = 21,
 	.m =
 	"\xd5\x4b\xe9\x36\xda\xd8\x6e\xc0\x50\x03\xbe\x00\x43\xff\xf0\x23"
 	"\xac\xa2\x42\xe7\x37\x77\x79\x52\x8f\x3e\xc0\x16\xc1\xfc\x8c\x67"
 	"\x16\xbc\x8a\x5d\x3b\xd3\x13\xbb\xb6\xc0\x26\x1b\xeb\x33\xcc\x70"
 	"\x4a\xf2\x11\x37\xe8\x1b\xba\x55\xac\x69\xe1\x74\x62\x7c\x6e\xb5",
 	.m_size = 64,
-	.algo = OID_id_ecdsa_with_sha512,
 	.c =
 	"\x30\x35\x02\x19\x00\x88\x5b\x8f\x59\x43\xbf\xcf\xc6\xdd\x3f\x07"
 	"\x87\x12\xa0\xd4\xac\x2b\x11\x2d\x1c\xb6\x06\xc9\x6c\x02\x18\x73"
@@ -779,22 +754,17 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 
 static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	{
-	.key =
+	.key = /* secp256r1(sha1) */
 	"\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41"
 	"\x22\xd6\x9a\xaa\x87\x17\xec\x4f\x63\x55\x2f\x94\xba\xdd\x83\xe9"
 	"\x34\x4b\xf3\xe9\x91\x13\x50\xb6\xcb\xca\x62\x08\xe7\x3b\x09\xdc"
 	"\xc3\x63\x4b\x2d\xb9\x73\x53\xe4\x45\xe6\x7c\xad\xe7\x6b\xb0\xe8"
 	"\xaf",
 	.key_len = 65,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x07",
-	.param_len = 21,
 	.m =
 	"\xc2\x2b\x5f\x91\x78\x34\x26\x09\x42\x8d\x6f\x51\xb2\xc5\xaf\x4c"
 	"\x0b\xde\x6a\x42",
 	.m_size = 20,
-	.algo = OID_id_ecdsa_with_sha1,
 	.c =
 	"\x30\x46\x02\x21\x00\xf9\x25\xce\x9f\x3a\xa6\x35\x81\xcf\xd4\xe7"
 	"\xb7\xf0\x82\x56\x41\xf7\xd4\xad\x8d\x94\x5a\x69\x89\xee\xca\x6a"
@@ -805,22 +775,17 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	.public_key_vec = true,
 	.siggen_sigver_test = true,
 	}, {
-	.key =
+	.key = /* secp256r1(sha224) */
 	"\x04\x8b\x6d\xc0\x33\x8e\x2d\x8b\x67\xf5\xeb\xc4\x7f\xa0\xf5\xd9"
 	"\x7b\x03\xa5\x78\x9a\xb5\xea\x14\xe4\x23\xd0\xaf\xd7\x0e\x2e\xa0"
 	"\xc9\x8b\xdb\x95\xf8\xb3\xaf\xac\x00\x2c\x2c\x1f\x7a\xfd\x95\x88"
 	"\x43\x13\xbf\xf3\x1c\x05\x1a\x14\x18\x09\x3f\xd6\x28\x3e\xc5\xa0"
 	"\xd4",
 	.key_len = 65,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x07",
-	.param_len = 21,
 	.m =
 	"\x1a\x15\xbc\xa3\xe4\xed\x3a\xb8\x23\x67\xc6\xc4\x34\xf8\x6c\x41"
 	"\x04\x0b\xda\xc5\x77\xfa\x1c\x2d\xe6\x2c\x3b\xe0",
 	.m_size = 28,
-	.algo = OID_id_ecdsa_with_sha224,
 	.c =
 	"\x30\x44\x02\x20\x20\x43\xfa\xc0\x9f\x9d\x7b\xe7\xae\xce\x77\x59"
 	"\x1a\xdb\x59\xd5\x34\x62\x79\xcb\x6a\x91\x67\x2e\x7d\x25\xd8\x25"
@@ -831,22 +796,17 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	.public_key_vec = true,
 	.siggen_sigver_test = true,
 	}, {
-	.key =
+	.key = /* secp256r1(sha256) */
 	"\x04\xf1\xea\xc4\x53\xf3\xb9\x0e\x9f\x7e\xad\xe3\xea\xd7\x0e\x0f"
 	"\xd6\x98\x9a\xca\x92\x4d\x0a\x80\xdb\x2d\x45\xc7\xec\x4b\x97\x00"
 	"\x2f\xe9\x42\x6c\x29\xdc\x55\x0e\x0b\x53\x12\x9b\x2b\xad\x2c\xe9"
 	"\x80\xe6\xc5\x43\xc2\x1d\x5e\xbb\x65\x21\x50\xb6\x37\xb0\x03\x8e"
 	"\xb8",
 	.key_len = 65,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x07",
-	.param_len = 21,
 	.m =
 	"\x8f\x43\x43\x46\x64\x8f\x6b\x96\xdf\x89\xdd\xa9\x01\xc5\x17\x6b"
 	"\x10\xa6\xd8\x39\x61\xdd\x3c\x1a\xc8\x8b\x59\xb2\xdc\x32\x7a\xa4",
 	.m_size = 32,
-	.algo = OID_id_ecdsa_with_sha256,
 	.c =
 	"\x30\x45\x02\x20\x08\x31\xfa\x74\x0d\x1d\x21\x5d\x09\xdc\x29\x63"
 	"\xa8\x1a\xad\xfc\xac\x44\xc3\xe8\x24\x11\x2d\xa4\x91\xdc\x02\x67"
@@ -857,23 +817,18 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	.public_key_vec = true,
 	.siggen_sigver_test = true,
 	}, {
-	.key =
+	.key = /* secp256r1(sha384) */
 	"\x04\xc5\xc6\xea\x60\xc9\xce\xad\x02\x8d\xf5\x3e\x24\xe3\x52\x1d"
 	"\x28\x47\x3b\xc3\x6b\xa4\x99\x35\x99\x11\x88\x88\xc8\xf4\xee\x7e"
 	"\x8c\x33\x8f\x41\x03\x24\x46\x2b\x1a\x82\xf9\x9f\xe1\x97\x1b\x00"
 	"\xda\x3b\x24\x41\xf7\x66\x33\x58\x3d\x3a\x81\xad\xcf\x16\xe9\xe2"
 	"\x7c",
 	.key_len = 65,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x07",
-	.param_len = 21,
 	.m =
 	"\x3e\x78\x70\xfb\xcd\x66\xba\x91\xa1\x79\xff\x1e\x1c\x6b\x78\xe6"
 	"\xc0\x81\x3a\x65\x97\x14\x84\x36\x14\x1a\x9a\xb7\xc5\xab\x84\x94"
 	"\x5e\xbb\x1b\x34\x71\xcb\x41\xe1\xf6\xfc\x92\x7b\x34\xbb\x86\xbb",
 	.m_size = 48,
-	.algo = OID_id_ecdsa_with_sha384,
 	.c =
 	"\x30\x46\x02\x21\x00\x8e\xf3\x6f\xdc\xf8\x69\xa6\x2e\xd0\x2e\x95"
 	"\x54\xd1\x95\x64\x93\x08\xb2\x6b\x24\x94\x48\x46\x5e\xf2\xe4\x6c"
@@ -884,24 +839,19 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	.public_key_vec = true,
 	.siggen_sigver_test = true,
 	}, {
-	.key =
+	.key = /* secp256r1(sha512) */
 	"\x04\xd7\x27\x46\x49\xf6\x26\x85\x12\x40\x76\x8e\xe2\xe6\x2a\x7a"
 	"\x83\xb1\x4e\x7a\xeb\x3b\x5c\x67\x4a\xb5\xa4\x92\x8c\x69\xff\x38"
 	"\xee\xd9\x4e\x13\x29\x59\xad\xde\x6b\xbb\x45\x31\xee\xfd\xd1\x1b"
 	"\x64\xd3\xb5\xfc\xaf\x9b\x4b\x88\x3b\x0e\xb7\xd6\xdf\xf1\xd5\x92"
 	"\xbf",
 	.key_len = 65,
-	.params =
-	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
-	"\xce\x3d\x03\x01\x07",
-	.param_len = 21,
 	.m =
 	"\x57\xb7\x9e\xe9\x05\x0a\x8c\x1b\xc9\x13\xe5\x4a\x24\xc7\xe2\xe9"
 	"\x43\xc3\xd1\x76\x62\xf4\x98\x1a\x9c\x13\xb0\x20\x1b\xe5\x39\xca"
 	"\x4f\xd9\x85\x34\x95\xa2\x31\xbc\xbb\xde\xdd\x76\xbb\x61\xe3\xcf"
 	"\x9d\xc0\x49\x7a\xf3\x7a\xc4\x7d\xa8\x04\x4b\x8d\xb4\x4d\x5b\xd6",
 	.m_size = 64,
-	.algo = OID_id_ecdsa_with_sha512,
 	.c =
 	"\x30\x45\x02\x21\x00\xb8\x6d\x87\x81\x43\xdf\xfb\x9f\x40\xea\x44"
 	"\x81\x00\x4e\x29\x08\xed\x8c\x73\x30\x6c\x22\xb3\x97\x76\xf6\x04"
@@ -925,15 +875,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\x0b\x25\xd6\x80\x5c\x3b\xe6\x1a\x98\x48\x91\x45\x7a\x73\xb0\xc3"
 	"\xf1",
 	.key_len = 97,
-	.params =
-	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
-	"\x00\x22",
-	.param_len = 18,
 	.m =
 	"\x12\x55\x28\xf0\x77\xd5\xb6\x21\x71\x32\x48\xcd\x28\xa8\x25\x22"
 	"\x3a\x69\xc1\x93",
 	.m_size = 20,
-	.algo = OID_id_ecdsa_with_sha1,
 	.c =
 	"\x30\x66\x02\x31\x00\xf5\x0f\x24\x4c\x07\x93\x6f\x21\x57\x55\x07"
 	"\x20\x43\x30\xde\xa0\x8d\x26\x8e\xae\x63\x3f\xbc\x20\x3a\xc6\xf1"
@@ -955,15 +900,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\x6b\x93\x99\x6c\x66\x4c\x42\x3f\x65\x60\x6c\x1c\x0b\x93\x9b\x9d"
 	"\xe0",
 	.key_len = 97,
-	.params =
-	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
-	"\x00\x22",
-	.param_len = 18,
 	.m =
 	"\x12\x80\xb6\xeb\x25\xe2\x3d\xf0\x21\x32\x96\x17\x3a\x38\x39\xfd"
 	"\x1f\x05\x34\x7b\xb8\xf9\x71\x66\x03\x4f\xd5\xe5",
 	.m_size = 28,
-	.algo = OID_id_ecdsa_with_sha224,
 	.c =
 	"\x30\x66\x02\x31\x00\x8a\x51\x84\xce\x13\x1e\xd2\xdc\xec\xcb\xe4"
 	"\x89\x47\xb2\xf7\xbc\x97\xf1\xc8\x72\x26\xcf\x5a\x5e\xc5\xda\xb4"
@@ -985,15 +925,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\x17\xc3\x34\x29\xd6\x40\xea\x5c\xb9\x3f\xfb\x32\x2e\x12\x33\xbc"
 	"\xab",
 	.key_len = 97,
-	.params =
-	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
-	"\x00\x22",
-	.param_len = 18,
 	.m =
 	"\xaa\xe7\xfd\x03\x26\xcb\x94\x71\xe4\xce\x0f\xc5\xff\xa6\x29\xa3"
 	"\xe1\xcc\x4c\x35\x4e\xde\xca\x80\xab\x26\x0c\x25\xe6\x68\x11\xc2",
 	.m_size = 32,
-	.algo = OID_id_ecdsa_with_sha256,
 	.c =
 	"\x30\x64\x02\x30\x08\x09\x12\x9d\x6e\x96\x64\xa6\x8e\x3f\x7e\xce"
 	"\x0a\x9b\xaa\x59\xcc\x47\x53\x87\xbc\xbd\x83\x3f\xaf\x06\x3f\x84"
@@ -1015,16 +950,11 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\x21\x67\xe5\x1b\x5a\x52\x31\x68\xd6\xee\xf0\x19\xb0\x55\xed\x89"
 	"\x9e",
 	.key_len = 97,
-	.params =
-	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
-	"\x00\x22",
-	.param_len = 18,
 	.m =
 	"\x8d\xf2\xc0\xe9\xa8\xf3\x8e\x44\xc4\x8c\x1a\xa0\xb8\xd7\x17\xdf"
 	"\xf2\x37\x1b\xc6\xe3\xf5\x62\xcc\x68\xf5\xd5\x0b\xbf\x73\x2b\xb1"
 	"\xb0\x4c\x04\x00\x31\xab\xfe\xc8\xd6\x09\xc8\xf2\xea\xd3\x28\xff",
 	.m_size = 48,
-	.algo = OID_id_ecdsa_with_sha384,
 	.c =
 	"\x30\x66\x02\x31\x00\x9b\x28\x68\xc0\xa1\xea\x8c\x50\xee\x2e\x62"
 	"\x35\x46\xfa\x00\xd8\x2d\x7a\x91\x5f\x49\x2d\x22\x08\x29\xe6\xfb"
@@ -1046,17 +976,12 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\xdf\x42\x5c\xc2\x5a\xc7\x0c\xf4\x15\xf7\x1b\xa3\x2e\xd7\x00\xac"
 	"\xa3",
 	.key_len = 97,
-	.params =
-	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
-	"\x00\x22",
-	.param_len = 18,
 	.m =
 	"\xe8\xb7\x52\x7d\x1a\x44\x20\x05\x53\x6b\x3a\x68\xf2\xe7\x6c\xa1"
 	"\xae\x9d\x84\xbb\xba\x52\x43\x3e\x2c\x42\x78\x49\xbf\x78\xb2\x71"
 	"\xeb\xe1\xe0\xe8\x42\x7b\x11\xad\x2b\x99\x05\x1d\x36\xe6\xac\xfc"
 	"\x55\x73\xf0\x15\x63\x39\xb8\x6a\x6a\xc5\x91\x5b\xca\x6a\xa8\x0e",
 	.m_size = 64,
-	.algo = OID_id_ecdsa_with_sha512,
 	.c =
 	"\x30\x63\x02\x2f\x1d\x20\x94\x77\xfe\x31\xfa\x4d\xc6\xef\xda\x02"
 	"\xe7\x0f\x52\x9a\x02\xde\x93\xe8\x83\xe4\x84\x4c\xfc\x6f\x80\xe3"
@@ -1084,15 +1009,10 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
 	"\xed\x37\x0f\x99\x3f\x26\xba\xa3\x8e\xff\x79\x34\x7c\x3a\xfe\x1f"
 	"\x3b\x83\x82\x2f\x14",
 	.key_len = 133,
-	.params =
-	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
-	"\x00\x23",
-	.param_len = 18,
 	.m =
 	"\xa2\x3a\x6a\x8c\x7b\x3c\xf2\x51\xf8\xbe\x5f\x4f\x3b\x15\x05\xc4"
 	"\xb5\xbc\x19\xe7\x21\x85\xe9\x23\x06\x33\x62\xfb",
 	.m_size = 28,
-	.algo = OID_id_ecdsa_with_sha224,
 	.c =
 	"\x30\x81\x86\x02\x41\x01\xd6\x43\xe7\xff\x42\xb2\xba\x74\x35\xf6"
 	"\xdc\x6d\x02\x7b\x22\xac\xe2\xef\x07\x92\xee\x60\x94\x06\xf8\x3f"
@@ -1119,15 +1039,10 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
 	"\x8a\xe9\x53\xa8\xcf\xce\x43\x0e\x82\x20\x86\xbc\x88\x9c\xb7\xe3"
 	"\xe6\x77\x1e\x1f\x8a",
 	.key_len = 133,
-	.params =
-	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
-	"\x00\x23",
-	.param_len = 18,
 	.m =
 	"\xcc\x97\x73\x0c\x73\xa2\x53\x2b\xfa\xd7\x83\x1d\x0c\x72\x1b\x39"
 	"\x80\x71\x8d\xdd\xc5\x9b\xff\x55\x32\x98\x25\xa2\x58\x2e\xb7\x73",
 	.m_size = 32,
-	.algo = OID_id_ecdsa_with_sha256,
 	.c =
 	"\x30\x81\x88\x02\x42\x00\xcd\xa5\x5f\x57\x52\x27\x78\x3a\xb5\x06"
 	"\x0f\xfd\x83\xfc\x0e\xd9\xce\x50\x9f\x7d\x1f\xca\x8b\xa8\x2d\x56"
@@ -1154,16 +1069,11 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
 	"\x22\x6e\xd7\x35\xc7\x23\xb7\x13\xae\xb6\x34\xff\xd7\x80\xe5\x39"
 	"\xb3\x3b\x5b\x1b\x94",
 	.key_len = 133,
-	.params =
-	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
-	"\x00\x23",
-	.param_len = 18,
 	.m =
 	"\x36\x98\xd6\x82\xfa\xad\xed\x3c\xb9\x40\xb6\x4d\x9e\xb7\x04\x26"
 	"\xad\x72\x34\x44\xd2\x81\xb4\x9b\xbe\x01\x04\x7a\xd8\x50\xf8\x59"
 	"\xba\xad\x23\x85\x6b\x59\xbe\xfb\xf6\x86\xd4\x67\xa8\x43\x28\x76",
 	.m_size = 48,
-	.algo = OID_id_ecdsa_with_sha384,
 	.c =
 	"\x30\x81\x88\x02\x42\x00\x93\x96\x76\x3c\x27\xea\xaa\x9c\x26\xec"
 	"\x51\xdc\xe8\x35\x5e\xae\x16\xf2\x4b\x64\x98\xf7\xec\xda\xc7\x7e"
@@ -1190,17 +1100,12 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
 	"\xfe\x3a\x05\x1a\xdb\xa9\x0f\xc0\x6c\x76\x30\x8c\xd8\xde\x44\xae"
 	"\xd0\x17\xdf\x49\x6a",
 	.key_len = 133,
-	.params =
-	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
-	"\x00\x23",
-	.param_len = 18,
 	.m =
 	"\x5c\xa6\xbc\x79\xb8\xa0\x1e\x11\x83\xf7\xe9\x05\xdf\xba\xf7\x69"
 	"\x97\x22\x32\xe4\x94\x7c\x65\xbd\x74\xc6\x9a\x8b\xbd\x0d\xdc\xed"
 	"\xf5\x9c\xeb\xe1\xc5\x68\x40\xf2\xc7\x04\xde\x9e\x0d\x76\xc5\xa3"
 	"\xf9\x3c\x6c\x98\x08\x31\xbd\x39\xe8\x42\x7f\x80\x39\x6f\xfe\x68",
 	.m_size = 64,
-	.algo = OID_id_ecdsa_with_sha512,
 	.c =
 	"\x30\x81\x88\x02\x42\x01\x5c\x71\x86\x96\xac\x21\x33\x7e\x4e\xaa"
 	"\x86\xec\xa8\x05\x03\x52\x56\x63\x0e\x02\xcc\x94\xa9\x05\xb9\xfb"
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-11 12:12   ` Jarkko Sakkinen
  2024-09-13 18:40   ` Jonathan Cameron
  2024-09-10 14:30 ` [PATCH v2 03/19] crypto: ecdsa - Migrate to " Lukas Wunner
                   ` (18 subsequent siblings)
  20 siblings, 2 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

Commit 6cb8815f41a9 ("crypto: sig - Add interface for sign/verify")
began a transition of asymmetric sign/verify operations from
crypto_akcipher to a new crypto_sig frontend.

Internally, the crypto_sig frontend still uses akcipher_alg as backend,
however:

   "The link between sig and akcipher is meant to be temporary.  The
    plan is to create a new low-level API for sig and then migrate
    the signature code over to that from akcipher."
    https://lore.kernel.org/r/ZrG6w9wsb-iiLZIF@gondor.apana.org.au/

   "having a separate alg for sig is definitely where we want to
    be since there is very little that the two types actually share."
    https://lore.kernel.org/r/ZrHlpz4qnre0zWJO@gondor.apana.org.au/

Take the next step of that migration and augment the crypto_sig frontend
with a sig_alg backend to which all algorithms can be moved.

During the migration, there will briefly be signature algorithms that
are still based on crypto_akcipher, whilst others are already based on
crypto_sig.  Allow for that by building a fork into crypto_sig_*() API
calls (i.e. crypto_sig_maxsize() and friends) such that one of the two
backends is selected based on the transform's cra_type.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 Documentation/crypto/api-sig.rst      |  15 +++
 Documentation/crypto/api.rst          |   1 +
 Documentation/crypto/architecture.rst |   2 +
 crypto/sig.c                          | 143 +++++++++++++++++++++++++-
 crypto/testmgr.c                      | 115 +++++++++++++++++++++
 crypto/testmgr.h                      |  13 +++
 include/crypto/internal/sig.h         |  80 ++++++++++++++
 include/crypto/sig.h                  |  61 +++++++++++
 include/uapi/linux/cryptouser.h       |   5 +
 9 files changed, 433 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/crypto/api-sig.rst

diff --git a/Documentation/crypto/api-sig.rst b/Documentation/crypto/api-sig.rst
new file mode 100644
index 000000000000..e5e87e106884
--- /dev/null
+++ b/Documentation/crypto/api-sig.rst
@@ -0,0 +1,15 @@
+Asymmetric Signature Algorithm Definitions
+------------------------------------------
+
+.. kernel-doc:: include/crypto/sig.h
+   :functions: sig_alg
+
+Asymmetric Signature API
+------------------------
+
+.. kernel-doc:: include/crypto/sig.h
+   :doc: Generic Public Key Signature API
+
+.. kernel-doc:: include/crypto/sig.h
+   :functions: crypto_alloc_sig crypto_free_sig crypto_sig_set_pubkey crypto_sig_set_privkey crypto_sig_maxsize crypto_sig_sign crypto_sig_verify
+
diff --git a/Documentation/crypto/api.rst b/Documentation/crypto/api.rst
index ff31c30561d4..8b2a90521886 100644
--- a/Documentation/crypto/api.rst
+++ b/Documentation/crypto/api.rst
@@ -10,4 +10,5 @@ Programming Interface
    api-digest
    api-rng
    api-akcipher
+   api-sig
    api-kpp
diff --git a/Documentation/crypto/architecture.rst b/Documentation/crypto/architecture.rst
index 646c3380a7ed..15dcd62fd22f 100644
--- a/Documentation/crypto/architecture.rst
+++ b/Documentation/crypto/architecture.rst
@@ -214,6 +214,8 @@ the aforementioned cipher types:
 
 -  CRYPTO_ALG_TYPE_AKCIPHER Asymmetric cipher
 
+-  CRYPTO_ALG_TYPE_SIG Asymmetric signature
+
 -  CRYPTO_ALG_TYPE_PCOMPRESS Enhanced version of
    CRYPTO_ALG_TYPE_COMPRESS allowing for segmented compression /
    decompression instead of performing the operation on one segment
diff --git a/crypto/sig.c b/crypto/sig.c
index 7645bedf3a1f..4f36ceb7a90b 100644
--- a/crypto/sig.c
+++ b/crypto/sig.c
@@ -21,14 +21,38 @@
 
 static const struct crypto_type crypto_sig_type;
 
+static void crypto_sig_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_sig *sig = __crypto_sig_tfm(tfm);
+	struct sig_alg *alg = crypto_sig_alg(sig);
+
+	alg->exit(sig);
+}
+
 static int crypto_sig_init_tfm(struct crypto_tfm *tfm)
 {
 	if (tfm->__crt_alg->cra_type != &crypto_sig_type)
 		return crypto_init_akcipher_ops_sig(tfm);
 
+	struct crypto_sig *sig = __crypto_sig_tfm(tfm);
+	struct sig_alg *alg = crypto_sig_alg(sig);
+
+	if (alg->exit)
+		sig->base.exit = crypto_sig_exit_tfm;
+
+	if (alg->init)
+		return alg->init(sig);
+
 	return 0;
 }
 
+static void crypto_sig_free_instance(struct crypto_instance *inst)
+{
+	struct sig_instance *sig = sig_instance(inst);
+
+	sig->free(sig);
+}
+
 static void __maybe_unused crypto_sig_show(struct seq_file *m,
 					   struct crypto_alg *alg)
 {
@@ -38,16 +62,17 @@ static void __maybe_unused crypto_sig_show(struct seq_file *m,
 static int __maybe_unused crypto_sig_report(struct sk_buff *skb,
 					    struct crypto_alg *alg)
 {
-	struct crypto_report_akcipher rsig = {};
+	struct crypto_report_sig rsig = {};
 
 	strscpy(rsig.type, "sig", sizeof(rsig.type));
 
-	return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, sizeof(rsig), &rsig);
+	return nla_put(skb, CRYPTOCFGA_REPORT_SIG, sizeof(rsig), &rsig);
 }
 
 static const struct crypto_type crypto_sig_type = {
 	.extsize = crypto_alg_extsize,
 	.init_tfm = crypto_sig_init_tfm,
+	.free = crypto_sig_free_instance,
 #ifdef CONFIG_PROC_FS
 	.show = crypto_sig_show,
 #endif
@@ -68,6 +93,14 @@ EXPORT_SYMBOL_GPL(crypto_alloc_sig);
 
 int crypto_sig_maxsize(struct crypto_sig *tfm)
 {
+	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
+		goto akcipher;
+
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->max_size(tfm);
+
+akcipher:
 	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
 
 	return crypto_akcipher_maxsize(*ctx);
@@ -78,6 +111,14 @@ int crypto_sig_sign(struct crypto_sig *tfm,
 		    const void *src, unsigned int slen,
 		    void *dst, unsigned int dlen)
 {
+	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
+		goto akcipher;
+
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->sign(tfm, src, slen, dst, dlen);
+
+akcipher:
 	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
 	struct crypto_akcipher_sync_data data = {
 		.tfm = *ctx,
@@ -97,6 +138,14 @@ int crypto_sig_verify(struct crypto_sig *tfm,
 		      const void *src, unsigned int slen,
 		      const void *digest, unsigned int dlen)
 {
+	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
+		goto akcipher;
+
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->verify(tfm, src, slen, digest, dlen);
+
+akcipher:
 	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
 	struct crypto_akcipher_sync_data data = {
 		.tfm = *ctx,
@@ -120,6 +169,14 @@ EXPORT_SYMBOL_GPL(crypto_sig_verify);
 int crypto_sig_set_pubkey(struct crypto_sig *tfm,
 			  const void *key, unsigned int keylen)
 {
+	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
+		goto akcipher;
+
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->set_pub_key(tfm, key, keylen);
+
+akcipher:
 	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
 
 	return crypto_akcipher_set_pub_key(*ctx, key, keylen);
@@ -129,11 +186,93 @@ EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);
 int crypto_sig_set_privkey(struct crypto_sig *tfm,
 			  const void *key, unsigned int keylen)
 {
+	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
+		goto akcipher;
+
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->set_priv_key(tfm, key, keylen);
+
+akcipher:
 	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
 
 	return crypto_akcipher_set_priv_key(*ctx, key, keylen);
 }
 EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);
 
+static void sig_prepare_alg(struct sig_alg *alg)
+{
+	struct crypto_alg *base = &alg->base;
+
+	base->cra_type = &crypto_sig_type;
+	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+	base->cra_flags |= CRYPTO_ALG_TYPE_SIG;
+}
+
+static int sig_default_sign(struct crypto_sig *tfm,
+			    const void *src, unsigned int slen,
+			    void *dst, unsigned int dlen)
+{
+	return -ENOSYS;
+}
+
+static int sig_default_verify(struct crypto_sig *tfm,
+			      const void *src, unsigned int slen,
+			      const void *dst, unsigned int dlen)
+{
+	return -ENOSYS;
+}
+
+static int sig_default_set_key(struct crypto_sig *tfm,
+			       const void *key, unsigned int keylen)
+{
+	return -ENOSYS;
+}
+
+int crypto_register_sig(struct sig_alg *alg)
+{
+	struct crypto_alg *base = &alg->base;
+
+	if (!alg->sign)
+		alg->sign = sig_default_sign;
+	if (!alg->verify)
+		alg->verify = sig_default_verify;
+	if (!alg->set_priv_key)
+		alg->set_priv_key = sig_default_set_key;
+	if (!alg->set_pub_key)
+		return -EINVAL;
+	if (!alg->max_size)
+		return -EINVAL;
+
+	sig_prepare_alg(alg);
+	return crypto_register_alg(base);
+}
+EXPORT_SYMBOL_GPL(crypto_register_sig);
+
+void crypto_unregister_sig(struct sig_alg *alg)
+{
+	crypto_unregister_alg(&alg->base);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_sig);
+
+int sig_register_instance(struct crypto_template *tmpl,
+			  struct sig_instance *inst)
+{
+	if (WARN_ON(!inst->free))
+		return -EINVAL;
+	sig_prepare_alg(&inst->alg);
+	return crypto_register_instance(tmpl, sig_crypto_instance(inst));
+}
+EXPORT_SYMBOL_GPL(sig_register_instance);
+
+int crypto_grab_sig(struct crypto_sig_spawn *spawn,
+		    struct crypto_instance *inst,
+		    const char *name, u32 type, u32 mask)
+{
+	spawn->base.frontend = &crypto_sig_type;
+	return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_grab_sig);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Public Key Signature Algorithms");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index f02cb075bd68..bb21378aa510 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -33,6 +33,7 @@
 #include <crypto/akcipher.h>
 #include <crypto/kpp.h>
 #include <crypto/acompress.h>
+#include <crypto/sig.h>
 #include <crypto/internal/cipher.h>
 #include <crypto/internal/simd.h>
 
@@ -131,6 +132,11 @@ struct akcipher_test_suite {
 	unsigned int count;
 };
 
+struct sig_test_suite {
+	const struct sig_testvec *vecs;
+	unsigned int count;
+};
+
 struct kpp_test_suite {
 	const struct kpp_testvec *vecs;
 	unsigned int count;
@@ -151,6 +157,7 @@ struct alg_test_desc {
 		struct cprng_test_suite cprng;
 		struct drbg_test_suite drbg;
 		struct akcipher_test_suite akcipher;
+		struct sig_test_suite sig;
 		struct kpp_test_suite kpp;
 	} suite;
 };
@@ -4317,6 +4324,114 @@ static int alg_test_akcipher(const struct alg_test_desc *desc,
 	return err;
 }
 
+static int test_sig_one(struct crypto_sig *tfm, const struct sig_testvec *vecs)
+{
+	u8 *ptr, *key __free(kfree);
+	int err, sig_size;
+
+	key = kmalloc(vecs->key_len + 2 * sizeof(u32) + vecs->param_len,
+		      GFP_KERNEL);
+	if (!key)
+		return -ENOMEM;
+
+	/* ecrdsa expects additional parameters appended to the key */
+	memcpy(key, vecs->key, vecs->key_len);
+	ptr = key + vecs->key_len;
+	ptr = test_pack_u32(ptr, vecs->algo);
+	ptr = test_pack_u32(ptr, vecs->param_len);
+	memcpy(ptr, vecs->params, vecs->param_len);
+
+	if (vecs->public_key_vec)
+		err = crypto_sig_set_pubkey(tfm, key, vecs->key_len);
+	else
+		err = crypto_sig_set_privkey(tfm, key, vecs->key_len);
+	if (err)
+		return err;
+
+	/*
+	 * Run asymmetric signature verification first
+	 * (which does not require a private key)
+	 */
+	err = crypto_sig_verify(tfm, vecs->c, vecs->c_size,
+				vecs->m, vecs->m_size);
+	if (err) {
+		pr_err("alg: sig: verify test failed: err %d\n", err);
+		return err;
+	}
+
+	/*
+	 * Don't invoke sign test (which requires a private key)
+	 * for vectors with only a public key.
+	 */
+	if (vecs->public_key_vec)
+		return 0;
+
+	sig_size = crypto_sig_maxsize(tfm);
+	if (sig_size < vecs->c_size) {
+		pr_err("alg: sig: invalid maxsize %u\n", sig_size);
+		return -EINVAL;
+	}
+
+	u8 *sig __free(kfree) = kzalloc(sig_size, GFP_KERNEL);
+	if (!sig)
+		return -ENOMEM;
+
+	/* Run asymmetric signature generation */
+	err = crypto_sig_sign(tfm, vecs->m, vecs->m_size, sig, sig_size);
+	if (err) {
+		pr_err("alg: sig: sign test failed: err %d\n", err);
+		return err;
+	}
+
+	/* Verify that generated signature equals cooked signature */
+	if (memcmp(sig, vecs->c, vecs->c_size) ||
+	    memchr_inv(sig + vecs->c_size, 0, sig_size - vecs->c_size)) {
+		pr_err("alg: sig: sign test failed: invalid output\n");
+		hexdump(sig, sig_size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int test_sig(struct crypto_sig *tfm, const char *alg,
+		    const struct sig_testvec *vecs, unsigned int tcount)
+{
+	const char *algo = crypto_tfm_alg_driver_name(crypto_sig_tfm(tfm));
+	int ret, i;
+
+	for (i = 0; i < tcount; i++) {
+		ret = test_sig_one(tfm, vecs++);
+		if (ret) {
+			pr_err("alg: sig: test %d failed for %s: err %d\n",
+			       i + 1, algo, ret);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+__maybe_unused
+static int alg_test_sig(const struct alg_test_desc *desc, const char *driver,
+			u32 type, u32 mask)
+{
+	struct crypto_sig *tfm;
+	int err = 0;
+
+	tfm = crypto_alloc_sig(driver, type, mask);
+	if (IS_ERR(tfm)) {
+		pr_err("alg: sig: Failed to load tfm for %s: %ld\n",
+		       driver, PTR_ERR(tfm));
+		return PTR_ERR(tfm);
+	}
+	if (desc->suite.sig.vecs)
+		err = test_sig(tfm, desc->alg, desc->suite.sig.vecs,
+			       desc->suite.sig.count);
+
+	crypto_free_sig(tfm);
+	return err;
+}
+
 static int alg_test_null(const struct alg_test_desc *desc,
 			     const char *driver, u32 type, u32 mask)
 {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index ed1640f3e352..39dd1d558883 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -162,6 +162,19 @@ struct akcipher_testvec {
 	enum OID algo;
 };
 
+struct sig_testvec {
+	const unsigned char *key;
+	const unsigned char *params;
+	const unsigned char *m;
+	const unsigned char *c;
+	unsigned int key_len;
+	unsigned int param_len;
+	unsigned int m_size;
+	unsigned int c_size;
+	bool public_key_vec;
+	enum OID algo;
+};
+
 struct kpp_testvec {
 	const unsigned char *secret;
 	const unsigned char *b_secret;
diff --git a/include/crypto/internal/sig.h b/include/crypto/internal/sig.h
index 97cb26ef8115..b16648c1a986 100644
--- a/include/crypto/internal/sig.h
+++ b/include/crypto/internal/sig.h
@@ -10,8 +10,88 @@
 #include <crypto/algapi.h>
 #include <crypto/sig.h>
 
+struct sig_instance {
+	void (*free)(struct sig_instance *inst);
+	union {
+		struct {
+			char head[offsetof(struct sig_alg, base)];
+			struct crypto_instance base;
+		};
+		struct sig_alg alg;
+	};
+};
+
+struct crypto_sig_spawn {
+	struct crypto_spawn base;
+};
+
 static inline void *crypto_sig_ctx(struct crypto_sig *tfm)
 {
 	return crypto_tfm_ctx(&tfm->base);
 }
+
+/**
+ * crypto_register_sig() -- Register public key signature algorithm
+ *
+ * Function registers an implementation of a public key signature algorithm
+ *
+ * @alg:	algorithm definition
+ *
+ * Return: zero on success; error code in case of error
+ */
+int crypto_register_sig(struct sig_alg *alg);
+
+/**
+ * crypto_unregister_sig() -- Unregister public key signature algorithm
+ *
+ * Function unregisters an implementation of a public key signature algorithm
+ *
+ * @alg:	algorithm definition
+ */
+void crypto_unregister_sig(struct sig_alg *alg);
+
+int sig_register_instance(struct crypto_template *tmpl,
+			  struct sig_instance *inst);
+
+static inline struct sig_instance *sig_instance(struct crypto_instance *inst)
+{
+	return container_of(&inst->alg, struct sig_instance, alg.base);
+}
+
+static inline struct sig_instance *sig_alg_instance(struct crypto_sig *tfm)
+{
+	return sig_instance(crypto_tfm_alg_instance(&tfm->base));
+}
+
+static inline struct crypto_instance *sig_crypto_instance(struct sig_instance
+									*inst)
+{
+	return container_of(&inst->alg.base, struct crypto_instance, alg);
+}
+
+static inline void *sig_instance_ctx(struct sig_instance *inst)
+{
+	return crypto_instance_ctx(sig_crypto_instance(inst));
+}
+
+int crypto_grab_sig(struct crypto_sig_spawn *spawn,
+		    struct crypto_instance *inst,
+		    const char *name, u32 type, u32 mask);
+
+static inline struct crypto_sig *crypto_spawn_sig(struct crypto_sig_spawn
+								   *spawn)
+{
+	return crypto_spawn_tfm2(&spawn->base);
+}
+
+static inline void crypto_drop_sig(struct crypto_sig_spawn *spawn)
+{
+	crypto_drop_spawn(&spawn->base);
+}
+
+static inline struct sig_alg *crypto_spawn_sig_alg(struct crypto_sig_spawn
+								    *spawn)
+{
+	return container_of(spawn->base.alg, struct sig_alg, base);
+}
 #endif
diff --git a/include/crypto/sig.h b/include/crypto/sig.h
index d25186bb2be3..f0f52a7c5ae7 100644
--- a/include/crypto/sig.h
+++ b/include/crypto/sig.h
@@ -19,6 +19,52 @@ struct crypto_sig {
 	struct crypto_tfm base;
 };
 
+/**
+ * struct sig_alg - generic public key signature algorithm
+ *
+ * @sign:	Function performs a sign operation as defined by public key
+ *		algorithm. Optional.
+ * @verify:	Function performs a complete verify operation as defined by
+ *		public key algorithm, returning verification status. Optional.
+ * @set_pub_key: Function invokes the algorithm specific set public key
+ *		function, which knows how to decode and interpret
+ *		the BER encoded public key and parameters. Mandatory.
+ * @set_priv_key: Function invokes the algorithm specific set private key
+ *		function, which knows how to decode and interpret
+ *		the BER encoded private key and parameters. Optional.
+ * @max_size:	Function returns key size. Mandatory.
+ * @init:	Initialize the cryptographic transformation object.
+ *		This function is used to initialize the cryptographic
+ *		transformation object. This function is called only once at
+ *		the instantiation time, right after the transformation context
+ *		was allocated. In case the cryptographic hardware has some
+ *		special requirements which need to be handled by software, this
+ *		function shall check for the precise requirement of the
+ *		transformation and put any software fallbacks in place.
+ * @exit:	Deinitialize the cryptographic transformation object. This is a
+ *		counterpart to @init, used to remove various changes set in
+ *		@init.
+ *
+ * @base:	Common crypto API algorithm data structure
+ */
+struct sig_alg {
+	int (*sign)(struct crypto_sig *tfm,
+		    const void *src, unsigned int slen,
+		    void *dst, unsigned int dlen);
+	int (*verify)(struct crypto_sig *tfm,
+		      const void *src, unsigned int slen,
+		      const void *digest, unsigned int dlen);
+	int (*set_pub_key)(struct crypto_sig *tfm,
+			   const void *key, unsigned int keylen);
+	int (*set_priv_key)(struct crypto_sig *tfm,
+			    const void *key, unsigned int keylen);
+	unsigned int (*max_size)(struct crypto_sig *tfm);
+	int (*init)(struct crypto_sig *tfm);
+	void (*exit)(struct crypto_sig *tfm);
+
+	struct crypto_alg base;
+};
+
 /**
  * DOC: Generic Public Key Signature API
  *
@@ -47,6 +93,21 @@ static inline struct crypto_tfm *crypto_sig_tfm(struct crypto_sig *tfm)
 	return &tfm->base;
 }
 
+static inline struct crypto_sig *__crypto_sig_tfm(struct crypto_tfm *tfm)
+{
+	return container_of(tfm, struct crypto_sig, base);
+}
+
+static inline struct sig_alg *__crypto_sig_alg(struct crypto_alg *alg)
+{
+	return container_of(alg, struct sig_alg, base);
+}
+
+static inline struct sig_alg *crypto_sig_alg(struct crypto_sig *tfm)
+{
+	return __crypto_sig_alg(crypto_sig_tfm(tfm)->__crt_alg);
+}
+
 /**
  * crypto_free_sig() - free signature tfm handle
  *
diff --git a/include/uapi/linux/cryptouser.h b/include/uapi/linux/cryptouser.h
index 20a6c0fc149e..db05e0419972 100644
--- a/include/uapi/linux/cryptouser.h
+++ b/include/uapi/linux/cryptouser.h
@@ -64,6 +64,7 @@ enum crypto_attr_type_t {
 	CRYPTOCFGA_STAT_AKCIPHER,	/* No longer supported, do not use. */
 	CRYPTOCFGA_STAT_KPP,		/* No longer supported, do not use. */
 	CRYPTOCFGA_STAT_ACOMP,		/* No longer supported, do not use. */
+	CRYPTOCFGA_REPORT_SIG,		/* struct crypto_report_sig */
 	__CRYPTOCFGA_MAX
 
 #define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1)
@@ -207,6 +208,10 @@ struct crypto_report_acomp {
 	char type[CRYPTO_MAX_NAME];
 };
 
+struct crypto_report_sig {
+	char type[CRYPTO_MAX_NAME];
+};
+
 #define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \
 			       sizeof(struct crypto_report_blkcipher))
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 03/19] crypto: ecdsa - Migrate to sig_alg backend
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 04/19] crypto: ecrdsa " Lukas Wunner
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

A sig_alg backend has just been introduced with the intent of moving all
asymmetric sign/verify algorithms to it one by one.

Migrate ecdsa.c to the new backend.

One benefit of the new API is the use of kernel buffers instead of
sglists, which avoids the overhead of copying signature and digest
sglists back into kernel buffers.  ecdsa.c is thus simplified quite
a bit.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 crypto/Kconfig   |  2 +-
 crypto/ecdsa.c   | 99 ++++++++++++++++++++----------------------------
 crypto/testmgr.c | 17 ++++-----
 crypto/testmgr.h | 27 ++-----------
 4 files changed, 55 insertions(+), 90 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 84778611e2d7..89b728c72f07 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -290,7 +290,7 @@ config CRYPTO_ECDH
 config CRYPTO_ECDSA
 	tristate "ECDSA (Elliptic Curve Digital Signature Algorithm)"
 	select CRYPTO_ECC
-	select CRYPTO_AKCIPHER
+	select CRYPTO_SIG
 	select ASN1
 	help
 	  ECDSA (Elliptic Curve Digital Signature Algorithm) (FIPS 186,
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index d5a10959ec28..3b9873f56b0a 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -4,12 +4,11 @@
  */
 
 #include <linux/module.h>
-#include <crypto/internal/akcipher.h>
 #include <crypto/internal/ecc.h>
-#include <crypto/akcipher.h>
+#include <crypto/internal/sig.h>
 #include <crypto/ecdh.h>
+#include <crypto/sig.h>
 #include <linux/asn1_decoder.h>
-#include <linux/scatterlist.h>
 
 #include "ecdsasignature.asn1.h"
 
@@ -126,46 +125,31 @@ static int _ecdsa_verify(struct ecc_ctx *ctx, const u64 *hash, const u64 *r, con
 /*
  * Verify an ECDSA signature.
  */
-static int ecdsa_verify(struct akcipher_request *req)
+static int ecdsa_verify(struct crypto_sig *tfm,
+			const void *src, unsigned int slen,
+			const void *digest, unsigned int dlen)
 {
-	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
-	struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 	size_t bufsize = ctx->curve->g.ndigits * sizeof(u64);
 	struct ecdsa_signature_ctx sig_ctx = {
 		.curve = ctx->curve,
 	};
 	u64 hash[ECC_MAX_DIGITS];
-	unsigned char *buffer;
 	int ret;
 
 	if (unlikely(!ctx->pub_key_set))
 		return -EINVAL;
 
-	buffer = kmalloc(req->src_len + req->dst_len, GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	sg_pcopy_to_buffer(req->src,
-		sg_nents_for_len(req->src, req->src_len + req->dst_len),
-		buffer, req->src_len + req->dst_len, 0);
-
-	ret = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx,
-			       buffer, req->src_len);
+	ret = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx, src, slen);
 	if (ret < 0)
-		goto error;
-
-	if (bufsize > req->dst_len)
-		bufsize = req->dst_len;
-
-	ecc_digits_from_bytes(buffer + req->src_len, bufsize,
-			      hash, ctx->curve->g.ndigits);
+		return ret;
 
-	ret = _ecdsa_verify(ctx, hash, sig_ctx.r, sig_ctx.s);
+	if (bufsize > dlen)
+		bufsize = dlen;
 
-error:
-	kfree(buffer);
+	ecc_digits_from_bytes(digest, bufsize, hash, ctx->curve->g.ndigits);
 
-	return ret;
+	return _ecdsa_verify(ctx, hash, sig_ctx.r, sig_ctx.s);
 }
 
 static int ecdsa_ecc_ctx_init(struct ecc_ctx *ctx, unsigned int curve_id)
@@ -201,9 +185,10 @@ static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx)
  * Set the public ECC key as defined by RFC5480 section 2.2 "Subject Public
  * Key". Only the uncompressed format is supported.
  */
-static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen)
+static int ecdsa_set_pub_key(struct crypto_sig *tfm, const void *key,
+			     unsigned int keylen)
 {
-	struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 	unsigned int digitlen, ndigits;
 	const unsigned char *d = key;
 	int ret;
@@ -237,28 +222,28 @@ static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsig
 	return ret;
 }
 
-static void ecdsa_exit_tfm(struct crypto_akcipher *tfm)
+static void ecdsa_exit_tfm(struct crypto_sig *tfm)
 {
-	struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 
 	ecdsa_ecc_ctx_deinit(ctx);
 }
 
-static unsigned int ecdsa_max_size(struct crypto_akcipher *tfm)
+static unsigned int ecdsa_max_size(struct crypto_sig *tfm)
 {
-	struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 
 	return DIV_ROUND_UP(ctx->curve->nbits, 8);
 }
 
-static int ecdsa_nist_p521_init_tfm(struct crypto_akcipher *tfm)
+static int ecdsa_nist_p521_init_tfm(struct crypto_sig *tfm)
 {
-	struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 
 	return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P521);
 }
 
-static struct akcipher_alg ecdsa_nist_p521 = {
+static struct sig_alg ecdsa_nist_p521 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
 	.max_size = ecdsa_max_size,
@@ -273,14 +258,14 @@ static struct akcipher_alg ecdsa_nist_p521 = {
 	},
 };
 
-static int ecdsa_nist_p384_init_tfm(struct crypto_akcipher *tfm)
+static int ecdsa_nist_p384_init_tfm(struct crypto_sig *tfm)
 {
-	struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 
 	return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P384);
 }
 
-static struct akcipher_alg ecdsa_nist_p384 = {
+static struct sig_alg ecdsa_nist_p384 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
 	.max_size = ecdsa_max_size,
@@ -295,14 +280,14 @@ static struct akcipher_alg ecdsa_nist_p384 = {
 	},
 };
 
-static int ecdsa_nist_p256_init_tfm(struct crypto_akcipher *tfm)
+static int ecdsa_nist_p256_init_tfm(struct crypto_sig *tfm)
 {
-	struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 
 	return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P256);
 }
 
-static struct akcipher_alg ecdsa_nist_p256 = {
+static struct sig_alg ecdsa_nist_p256 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
 	.max_size = ecdsa_max_size,
@@ -317,14 +302,14 @@ static struct akcipher_alg ecdsa_nist_p256 = {
 	},
 };
 
-static int ecdsa_nist_p192_init_tfm(struct crypto_akcipher *tfm)
+static int ecdsa_nist_p192_init_tfm(struct crypto_sig *tfm)
 {
-	struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 
 	return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P192);
 }
 
-static struct akcipher_alg ecdsa_nist_p192 = {
+static struct sig_alg ecdsa_nist_p192 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
 	.max_size = ecdsa_max_size,
@@ -345,42 +330,42 @@ static int __init ecdsa_init(void)
 	int ret;
 
 	/* NIST p192 may not be available in FIPS mode */
-	ret = crypto_register_akcipher(&ecdsa_nist_p192);
+	ret = crypto_register_sig(&ecdsa_nist_p192);
 	ecdsa_nist_p192_registered = ret == 0;
 
-	ret = crypto_register_akcipher(&ecdsa_nist_p256);
+	ret = crypto_register_sig(&ecdsa_nist_p256);
 	if (ret)
 		goto nist_p256_error;
 
-	ret = crypto_register_akcipher(&ecdsa_nist_p384);
+	ret = crypto_register_sig(&ecdsa_nist_p384);
 	if (ret)
 		goto nist_p384_error;
 
-	ret = crypto_register_akcipher(&ecdsa_nist_p521);
+	ret = crypto_register_sig(&ecdsa_nist_p521);
 	if (ret)
 		goto nist_p521_error;
 
 	return 0;
 
 nist_p521_error:
-	crypto_unregister_akcipher(&ecdsa_nist_p384);
+	crypto_unregister_sig(&ecdsa_nist_p384);
 
 nist_p384_error:
-	crypto_unregister_akcipher(&ecdsa_nist_p256);
+	crypto_unregister_sig(&ecdsa_nist_p256);
 
 nist_p256_error:
 	if (ecdsa_nist_p192_registered)
-		crypto_unregister_akcipher(&ecdsa_nist_p192);
+		crypto_unregister_sig(&ecdsa_nist_p192);
 	return ret;
 }
 
 static void __exit ecdsa_exit(void)
 {
 	if (ecdsa_nist_p192_registered)
-		crypto_unregister_akcipher(&ecdsa_nist_p192);
-	crypto_unregister_akcipher(&ecdsa_nist_p256);
-	crypto_unregister_akcipher(&ecdsa_nist_p384);
-	crypto_unregister_akcipher(&ecdsa_nist_p521);
+		crypto_unregister_sig(&ecdsa_nist_p192);
+	crypto_unregister_sig(&ecdsa_nist_p256);
+	crypto_unregister_sig(&ecdsa_nist_p384);
+	crypto_unregister_sig(&ecdsa_nist_p521);
 }
 
 subsys_initcall(ecdsa_init);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index bb21378aa510..81ac32c9dd3e 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4411,7 +4411,6 @@ static int test_sig(struct crypto_sig *tfm, const char *alg,
 	return 0;
 }
 
-__maybe_unused
 static int alg_test_sig(const struct alg_test_desc *desc, const char *driver,
 			u32 type, u32 mask)
 {
@@ -5221,30 +5220,30 @@ static const struct alg_test_desc alg_test_descs[] = {
 		}
 	}, {
 		.alg = "ecdsa-nist-p192",
-		.test = alg_test_akcipher,
+		.test = alg_test_sig,
 		.suite = {
-			.akcipher = __VECS(ecdsa_nist_p192_tv_template)
+			.sig = __VECS(ecdsa_nist_p192_tv_template)
 		}
 	}, {
 		.alg = "ecdsa-nist-p256",
-		.test = alg_test_akcipher,
+		.test = alg_test_sig,
 		.fips_allowed = 1,
 		.suite = {
-			.akcipher = __VECS(ecdsa_nist_p256_tv_template)
+			.sig = __VECS(ecdsa_nist_p256_tv_template)
 		}
 	}, {
 		.alg = "ecdsa-nist-p384",
-		.test = alg_test_akcipher,
+		.test = alg_test_sig,
 		.fips_allowed = 1,
 		.suite = {
-			.akcipher = __VECS(ecdsa_nist_p384_tv_template)
+			.sig = __VECS(ecdsa_nist_p384_tv_template)
 		}
 	}, {
 		.alg = "ecdsa-nist-p521",
-		.test = alg_test_akcipher,
+		.test = alg_test_sig,
 		.fips_allowed = 1,
 		.suite = {
-			.akcipher = __VECS(ecdsa_nist_p521_tv_template)
+			.sig = __VECS(ecdsa_nist_p521_tv_template)
 		}
 	}, {
 		.alg = "ecrdsa",
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 39dd1d558883..a4987610fcb5 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -663,7 +663,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
 /*
  * ECDSA test vectors.
  */
-static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
+static const struct sig_testvec ecdsa_nist_p192_tv_template[] = {
 	{
 	.key = /* secp192r1(sha1) */
 	"\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1"
@@ -682,7 +682,6 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	"\x80\x6f\xa5\x79\x77\xda\xd0",
 	.c_size = 55,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp192r1(sha224) */
 	"\x04\xb6\x4b\xb1\xd1\xac\xba\x24\x8f\x65\xb2\x60\x00\x90\xbf\xbd"
@@ -701,7 +700,6 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	"\x5c\x99\xdb\x92\x5b\x36",
 	.c_size = 54,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp192r1(sha256) */
 	"\x04\xe2\x51\x24\x9b\xf7\xb6\x32\x82\x39\x66\x3d\x5b\xec\x3b\xae"
@@ -720,7 +718,6 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	"\x3a\x97\xd9\xcd\x1a\x6a\x49",
 	.c_size = 55,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp192r1(sha384) */
 	"\x04\x5a\x13\xfe\x68\x86\x4d\xf4\x17\xc7\xa4\xe5\x8c\x65\x57\xb7"
@@ -740,7 +737,6 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	"\x12\x3b\x3b\x28\xfb\x6d\xe1",
 	.c_size = 55,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp192r1(sha512) */
 	"\x04\xd5\xf2\x6e\xc3\x94\x5c\x52\xbc\xdf\x86\x6c\x14\xd1\xca\xea"
@@ -761,11 +757,10 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
 	"\x6a\xdf\x97\xfd\x82\x76\x24",
 	.c_size = 55,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 };
 
-static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
+static const struct sig_testvec ecdsa_nist_p256_tv_template[] = {
 	{
 	.key = /* secp256r1(sha1) */
 	"\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41"
@@ -786,7 +781,6 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	"\xfb\x9d\x8b\xde\xd4\x8d\x6f\xad",
 	.c_size = 72,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp256r1(sha224) */
 	"\x04\x8b\x6d\xc0\x33\x8e\x2d\x8b\x67\xf5\xeb\xc4\x7f\xa0\xf5\xd9"
@@ -807,7 +801,6 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	"\x2e\x8b\xde\x5a\x04\x0e",
 	.c_size = 70,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp256r1(sha256) */
 	"\x04\xf1\xea\xc4\x53\xf3\xb9\x0e\x9f\x7e\xad\xe3\xea\xd7\x0e\x0f"
@@ -828,7 +821,6 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	"\x2a\x65\x35\x23\xe3\x1d\xfa",
 	.c_size = 71,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp256r1(sha384) */
 	"\x04\xc5\xc6\xea\x60\xc9\xce\xad\x02\x8d\xf5\x3e\x24\xe3\x52\x1d"
@@ -850,7 +842,6 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	"\xc0\x60\x11\x92\xdc\x17\x89\x12",
 	.c_size = 72,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp256r1(sha512) */
 	"\x04\xd7\x27\x46\x49\xf6\x26\x85\x12\x40\x76\x8e\xe2\xe6\x2a\x7a"
@@ -873,11 +864,10 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
 	"\x31\x79\x4a\xe9\x81\x6a\xee",
 	.c_size = 71,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 };
 
-static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
+static const struct sig_testvec ecdsa_nist_p384_tv_template[] = {
 	{
 	.key = /* secp384r1(sha1) */
 	"\x04\x89\x25\xf3\x97\x88\xcb\xb0\x78\xc5\x72\x9a\x14\x6e\x7a\xb1"
@@ -902,7 +892,6 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\x79\x12\x2a\xb7\xc5\x15\x92\xc5",
 	.c_size = 104,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp384r1(sha224) */
 	"\x04\x69\x6c\xcf\x62\xee\xd0\x0d\xe5\xb5\x2f\x70\x54\xcf\x26\xa0"
@@ -927,7 +916,6 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\x88\x2b\x82\x26\x5e\x1c\xda\xfb",
 	.c_size = 104,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp384r1(sha256) */
 	"\x04\xee\xd6\xda\x3e\x94\x90\x00\x27\xed\xf8\x64\x55\xd6\x51\x9a"
@@ -952,7 +940,6 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\xf4\x1f\x39\xca\x4d\x43",
 	.c_size = 102,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp384r1(sha384) */
 	"\x04\x3a\x2f\x62\xe7\x1a\xcf\x24\xd0\x0b\x7c\xe0\xed\x46\x0a\x4f"
@@ -978,7 +965,6 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\xab\x8d\x4e\xde\xe6\x6d\x9b\x66",
 	.c_size = 104,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	}, {
 	.key = /* secp384r1(sha512) */
 	"\x04\xb4\xe7\xc1\xeb\x64\x25\x22\x46\xc3\x86\x61\x80\xbe\x1e\x46"
@@ -1005,11 +991,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
 	"\x3c\x93\xff\x50\x5d",
 	.c_size = 101,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 };
 
-static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
+static const struct sig_testvec ecdsa_nist_p521_tv_template[] = {
 	{
 	.key = /* secp521r1(sha224) */
 	"\x04\x01\x4f\x43\x18\xb6\xa9\xc9\x5d\x68\xd3\xa9\x42\xf8\x98\xc0"
@@ -1038,7 +1023,6 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
 	"\xa3\x50\xb1\xa5\x98\x92\x2a\xa5\x52",
 	.c_size = 137,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 	{
 	.key = /* secp521r1(sha256) */
@@ -1068,7 +1052,6 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
 	"\xb7\x1d\x91\x55\x38\xb6\xf6\x34\x65\xc7\xbd",
 	.c_size = 139,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 	{
 	.key = /* secp521r1(sha384) */
@@ -1099,7 +1082,6 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
 	"\x8f\xb4\x22\xc6\x4f\xab\x2b\x62\xc1\x42\xb1",
 	.c_size = 139,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 	{
 	.key = /* secp521r1(sha512) */
@@ -1131,7 +1113,6 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
 	"\xa6\xe5\x25\x46\x1e\x77\x44\x78\xe0\xd1\x04",
 	.c_size = 139,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 };
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 04/19] crypto: ecrdsa - Migrate to sig_alg backend
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (2 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 03/19] crypto: ecdsa - Migrate to " Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-11 12:49   ` Jarkko Sakkinen
  2024-09-10 14:30 ` [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks Lukas Wunner
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

A sig_alg backend has just been introduced with the intent of moving all
asymmetric sign/verify algorithms to it one by one.

Migrate ecrdsa.c to the new backend.

One benefit of the new API is the use of kernel buffers instead of
sglists, which avoids the overhead of copying signature and digest
sglists back into kernel buffers.  ecrdsa.c is thus simplified quite
a bit.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 crypto/Kconfig   |  2 +-
 crypto/ecrdsa.c  | 56 +++++++++++++++++++++---------------------------
 crypto/testmgr.c |  4 ++--
 crypto/testmgr.h |  7 +-----
 4 files changed, 28 insertions(+), 41 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 89b728c72f07..e8488b8c45e3 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -302,7 +302,7 @@ config CRYPTO_ECDSA
 config CRYPTO_ECRDSA
 	tristate "EC-RDSA (Elliptic Curve Russian Digital Signature Algorithm)"
 	select CRYPTO_ECC
-	select CRYPTO_AKCIPHER
+	select CRYPTO_SIG
 	select CRYPTO_STREEBOG
 	select OID_REGISTRY
 	select ASN1
diff --git a/crypto/ecrdsa.c b/crypto/ecrdsa.c
index 3811f3805b5d..7383dd11089b 100644
--- a/crypto/ecrdsa.c
+++ b/crypto/ecrdsa.c
@@ -18,12 +18,11 @@
 
 #include <linux/module.h>
 #include <linux/crypto.h>
+#include <crypto/sig.h>
 #include <crypto/streebog.h>
-#include <crypto/internal/akcipher.h>
 #include <crypto/internal/ecc.h>
-#include <crypto/akcipher.h>
+#include <crypto/internal/sig.h>
 #include <linux/oid_registry.h>
-#include <linux/scatterlist.h>
 #include "ecrdsa_params.asn1.h"
 #include "ecrdsa_pub_key.asn1.h"
 #include "ecrdsa_defs.h"
@@ -68,13 +67,12 @@ static const struct ecc_curve *get_curve_by_oid(enum OID oid)
 	}
 }
 
-static int ecrdsa_verify(struct akcipher_request *req)
+static int ecrdsa_verify(struct crypto_sig *tfm,
+			 const void *src, unsigned int slen,
+			 const void *digest, unsigned int dlen)
 {
-	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
-	struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
-	unsigned char sig[ECRDSA_MAX_SIG_SIZE];
-	unsigned char digest[STREEBOG512_DIGEST_SIZE];
-	unsigned int ndigits = req->dst_len / sizeof(u64);
+	struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
+	unsigned int ndigits = dlen / sizeof(u64);
 	u64 r[ECRDSA_MAX_DIGITS]; /* witness (r) */
 	u64 _r[ECRDSA_MAX_DIGITS]; /* -r */
 	u64 s[ECRDSA_MAX_DIGITS]; /* second part of sig (s) */
@@ -91,25 +89,19 @@ static int ecrdsa_verify(struct akcipher_request *req)
 	 */
 	if (!ctx->curve ||
 	    !ctx->digest ||
-	    !req->src ||
+	    !src ||
+	    !digest ||
 	    !ctx->pub_key.x ||
-	    req->dst_len != ctx->digest_len ||
-	    req->dst_len != ctx->curve->g.ndigits * sizeof(u64) ||
+	    dlen != ctx->digest_len ||
+	    dlen != ctx->curve->g.ndigits * sizeof(u64) ||
 	    ctx->pub_key.ndigits != ctx->curve->g.ndigits ||
-	    req->dst_len * 2 != req->src_len ||
-	    WARN_ON(req->src_len > sizeof(sig)) ||
-	    WARN_ON(req->dst_len > sizeof(digest)))
+	    dlen * 2 != slen ||
+	    WARN_ON(slen > ECRDSA_MAX_SIG_SIZE) ||
+	    WARN_ON(dlen > STREEBOG512_DIGEST_SIZE))
 		return -EBADMSG;
 
-	sg_copy_to_buffer(req->src, sg_nents_for_len(req->src, req->src_len),
-			  sig, req->src_len);
-	sg_pcopy_to_buffer(req->src,
-			   sg_nents_for_len(req->src,
-					    req->src_len + req->dst_len),
-			   digest, req->dst_len, req->src_len);
-
-	vli_from_be64(s, sig, ndigits);
-	vli_from_be64(r, sig + ndigits * sizeof(u64), ndigits);
+	vli_from_be64(s, src, ndigits);
+	vli_from_be64(r, src + ndigits * sizeof(u64), ndigits);
 
 	/* Step 1: verify that 0 < r < q, 0 < s < q */
 	if (vli_is_zero(r, ndigits) ||
@@ -188,10 +180,10 @@ static u8 *ecrdsa_unpack_u32(u32 *dst, void *src)
 }
 
 /* Parse BER encoded subjectPublicKey. */
-static int ecrdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+static int ecrdsa_set_pub_key(struct crypto_sig *tfm, const void *key,
 			      unsigned int keylen)
 {
-	struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
 	unsigned int ndigits;
 	u32 algo, paramlen;
 	u8 *params;
@@ -249,9 +241,9 @@ static int ecrdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
 	return 0;
 }
 
-static unsigned int ecrdsa_max_size(struct crypto_akcipher *tfm)
+static unsigned int ecrdsa_max_size(struct crypto_sig *tfm)
 {
-	struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
 
 	/*
 	 * Verify doesn't need any output, so it's just informational
@@ -260,11 +252,11 @@ static unsigned int ecrdsa_max_size(struct crypto_akcipher *tfm)
 	return ctx->pub_key.ndigits * sizeof(u64);
 }
 
-static void ecrdsa_exit_tfm(struct crypto_akcipher *tfm)
+static void ecrdsa_exit_tfm(struct crypto_sig *tfm)
 {
 }
 
-static struct akcipher_alg ecrdsa_alg = {
+static struct sig_alg ecrdsa_alg = {
 	.verify		= ecrdsa_verify,
 	.set_pub_key	= ecrdsa_set_pub_key,
 	.max_size	= ecrdsa_max_size,
@@ -280,12 +272,12 @@ static struct akcipher_alg ecrdsa_alg = {
 
 static int __init ecrdsa_mod_init(void)
 {
-	return crypto_register_akcipher(&ecrdsa_alg);
+	return crypto_register_sig(&ecrdsa_alg);
 }
 
 static void __exit ecrdsa_mod_fini(void)
 {
-	crypto_unregister_akcipher(&ecrdsa_alg);
+	crypto_unregister_sig(&ecrdsa_alg);
 }
 
 module_init(ecrdsa_mod_init);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 81ac32c9dd3e..0542817a9456 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5247,9 +5247,9 @@ static const struct alg_test_desc alg_test_descs[] = {
 		}
 	}, {
 		.alg = "ecrdsa",
-		.test = alg_test_akcipher,
+		.test = alg_test_sig,
 		.suite = {
-			.akcipher = __VECS(ecrdsa_tv_template)
+			.sig = __VECS(ecrdsa_tv_template)
 		}
 	}, {
 		.alg = "essiv(authenc(hmac(sha256),cbc(aes)),sha256)",
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index a4987610fcb5..fd4823c26d93 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -1119,7 +1119,7 @@ static const struct sig_testvec ecdsa_nist_p521_tv_template[] = {
 /*
  * EC-RDSA test vectors are generated by gost-engine.
  */
-static const struct akcipher_testvec ecrdsa_tv_template[] = {
+static const struct sig_testvec ecrdsa_tv_template[] = {
 	{
 	.key =
 	"\x04\x40\xd5\xa7\x77\xf9\x26\x2f\x8c\xbd\xcc\xe3\x1f\x01\x94\x05"
@@ -1144,7 +1144,6 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
 	"\x79\xd2\x76\x64\xa3\xbd\x66\x10\x79\x05\x5a\x06\x42\xec\xb9\xc9",
 	.m_size = 32,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 	{
 	.key =
@@ -1170,7 +1169,6 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
 	"\x11\x23\x4a\x70\x43\x52\x7a\x68\x11\x65\x45\x37\xbb\x25\xb7\x40",
 	.m_size = 32,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 	{
 	.key =
@@ -1196,7 +1194,6 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
 	"\x9f\x16\xc6\x1c\xb1\x3f\x84\x41\x69\xec\x34\xfd\xf1\xf9\xa3\x39",
 	.m_size = 32,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 	{
 	.key =
@@ -1231,7 +1228,6 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
 	"\xa8\xf6\x80\x01\xb9\x27\xac\xd8\x45\x96\x66\xa1\xee\x48\x08\x3f",
 	.m_size = 64,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 	{
 	.key =
@@ -1266,7 +1262,6 @@ static const struct akcipher_testvec ecrdsa_tv_template[] = {
 	"\x6d\xf4\xd2\x45\xc2\x83\xa0\x42\x95\x05\x9d\x89\x8e\x0a\xca\xcc",
 	.m_size = 64,
 	.public_key_vec = true,
-	.siggen_sigver_test = true,
 	},
 };
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (3 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 04/19] crypto: ecrdsa " Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 19:03   ` Stefan Berger
  2024-09-11 12:54   ` Jarkko Sakkinen
  2024-09-10 14:30 ` [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend Lukas Wunner
                   ` (15 subsequent siblings)
  20 siblings, 2 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

pkcs1pad_set_pub_key() and pkcs1pad_set_priv_key() are almost identical.

The upcoming migration of sign/verify operations from rsa-pkcs1pad.c
into a separate crypto_template will require another copy of the exact
same functions.  When RSASSA-PSS and RSAES-OAEP are introduced, each
will need yet another copy.

Deduplicate the functions into a single one which lives in a common
header file for reuse by RSASSA-PKCS1-v1_5, RSASSA-PSS and RSAES-OAEP.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 crypto/rsa-pkcs1pad.c         | 30 ++----------------------------
 include/crypto/internal/rsa.h | 28 ++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 28 deletions(-)

diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index cd501195f34a..3c5fe8c93938 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -131,42 +131,16 @@ static int pkcs1pad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
 		unsigned int keylen)
 {
 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
-	int err;
-
-	ctx->key_size = 0;
 
-	err = crypto_akcipher_set_pub_key(ctx->child, key, keylen);
-	if (err)
-		return err;
-
-	/* Find out new modulus size from rsa implementation */
-	err = crypto_akcipher_maxsize(ctx->child);
-	if (err > PAGE_SIZE)
-		return -ENOTSUPP;
-
-	ctx->key_size = err;
-	return 0;
+	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PUB, key, keylen);
 }
 
 static int pkcs1pad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
 		unsigned int keylen)
 {
 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
-	int err;
-
-	ctx->key_size = 0;
 
-	err = crypto_akcipher_set_priv_key(ctx->child, key, keylen);
-	if (err)
-		return err;
-
-	/* Find out new modulus size from rsa implementation */
-	err = crypto_akcipher_maxsize(ctx->child);
-	if (err > PAGE_SIZE)
-		return -ENOTSUPP;
-
-	ctx->key_size = err;
-	return 0;
+	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PRIV, key, keylen);
 }
 
 static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
index e870133f4b77..754f687134df 100644
--- a/include/crypto/internal/rsa.h
+++ b/include/crypto/internal/rsa.h
@@ -8,6 +8,7 @@
 #ifndef _RSA_HELPER_
 #define _RSA_HELPER_
 #include <linux/types.h>
+#include <crypto/akcipher.h>
 
 /**
  * rsa_key - RSA key structure
@@ -53,5 +54,32 @@ int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
 int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
 		       unsigned int key_len);
 
+#define RSA_PUB (true)
+#define RSA_PRIV (false)
+
+static inline int rsa_set_key(struct crypto_akcipher *child,
+			      unsigned int *key_size, bool is_pubkey,
+			      const void *key, unsigned int keylen)
+{
+	int err;
+
+	*key_size = 0;
+
+	if (is_pubkey)
+		err = crypto_akcipher_set_pub_key(child, key, keylen);
+	else
+		err = crypto_akcipher_set_priv_key(child, key, keylen);
+	if (err)
+		return err;
+
+	/* Find out new modulus size from rsa implementation */
+	err = crypto_akcipher_maxsize(child);
+	if (err > PAGE_SIZE)
+		return -ENOTSUPP;
+
+	*key_size = err;
+	return 0;
+}
+
 extern struct crypto_template rsa_pkcs1pad_tmpl;
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (4 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-11 12:56   ` Jarkko Sakkinen
  2024-10-21 16:08   ` Klara Modin
  2024-09-10 14:30 ` [PATCH v2 07/19] crypto: rsassa-pkcs1 - Harden digest length verification Lukas Wunner
                   ` (14 subsequent siblings)
  20 siblings, 2 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings,
	Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
	linux-security-module

A sig_alg backend has just been introduced with the intent of moving all
asymmetric sign/verify algorithms to it one by one.

Migrate the sign/verify operations from rsa-pkcs1pad.c to a separate
rsassa-pkcs1.c which uses the new backend.

Consequently there are now two templates which build on the "rsa"
akcipher_alg:

* The existing "pkcs1pad" template, which is instantiated as an
  akcipher_instance and retains the encrypt/decrypt operations of
  RSAES-PKCS1-v1_5 (RFC 8017 sec 7.2).

* The new "pkcs1" template, which is instantiated as a sig_instance
  and contains the sign/verify operations of RSASSA-PKCS1-v1_5
  (RFC 8017 sec 8.2).

In a separate step, rsa-pkcs1pad.c could optionally be renamed to
rsaes-pkcs1.c for clarity.  Additional "oaep" and "pss" templates
could be added for RSAES-OAEP and RSASSA-PSS.

Note that it's currently allowed to allocate a "pkcs1pad(rsa)" transform
without specifying a hash algorithm.  That makes sense if the transform
is only used for encrypt/decrypt and continues to be supported.  But for
sign/verify, such transforms previously did not insert the Full Hash
Prefix into the padding.  The resulting message encoding was incompliant
with EMSA-PKCS1-v1_5 (RFC 8017 sec 9.2) and therefore nonsensical.

From here on in, it is no longer allowed to allocate a transform without
specifying a hash algorithm if the transform is used for sign/verify
operations.  This simplifies the code because the insertion of the Full
Hash Prefix is no longer optional, so various "if (digest_info)" clauses
can be removed.

There has been a previous attempt to forbid transform allocation without
specifying a hash algorithm, namely by commit c0d20d22e0ad ("crypto:
rsa-pkcs1pad - Require hash to be present").  It had to be rolled back
with commit b3a8c8a5ebb5 ("crypto: rsa-pkcs1pad: Allow hash to be
optional [ver #2]"), presumably because it broke allocation of a
transform which was solely used for encrypt/decrypt, not sign/verify.
Avoid such breakage by allowing transform allocation for encrypt/decrypt
with and without specifying a hash algorithm (and simply ignoring the
hash algorithm in the former case).

So again, specifying a hash algorithm is now mandatory for sign/verify,
but optional and ignored for encrypt/decrypt.

The new sig_alg API uses kernel buffers instead of sglists, which
avoids the overhead of copying signature and digest from sglists back
into kernel buffers.  rsassa-pkcs1.c is thus simplified quite a bit.

sig_alg is always synchronous, whereas the underlying "rsa" akcipher_alg
may be asynchronous.  So await the result of the akcipher_alg, similar
to crypto_akcipher_sync_{en,de}crypt().

As part of the migration, rename "rsa_digest_info" to "hash_prefix" to
adhere to the spec language in RFC 9580.  Otherwise keep the code
unmodified wherever possible to ease reviewing and bisecting.  Leave
several simplification and hardening opportunities to separate commits.

rsassa-pkcs1.c uses modern __free() syntax for allocation of buffers
which need to be freed by kfree_sensitive(), hence a DEFINE_FREE()
clause for kfree_sensitive() is introduced herein as a byproduct.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 crypto/Kconfig                      |   1 +
 crypto/Makefile                     |   1 +
 crypto/asymmetric_keys/public_key.c |  10 +-
 crypto/rsa-pkcs1pad.c               | 341 ++--------------------
 crypto/rsa.c                        |  17 +-
 crypto/rsassa-pkcs1.c               | 422 ++++++++++++++++++++++++++++
 crypto/testmgr.c                    |  22 +-
 crypto/testmgr.h                    |   3 +-
 include/crypto/internal/rsa.h       |   1 +
 include/linux/slab.h                |   1 +
 security/integrity/ima/ima_main.c   |   6 +-
 11 files changed, 480 insertions(+), 345 deletions(-)
 create mode 100644 crypto/rsassa-pkcs1.c

diff --git a/crypto/Kconfig b/crypto/Kconfig
index e8488b8c45e3..94ef57c9e936 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -250,6 +250,7 @@ config CRYPTO_RSA
 	tristate "RSA (Rivest-Shamir-Adleman)"
 	select CRYPTO_AKCIPHER
 	select CRYPTO_MANAGER
+	select CRYPTO_SIG
 	select MPILIB
 	select ASN1
 	help
diff --git a/crypto/Makefile b/crypto/Makefile
index 4c99e5d376f6..7de29bf843e9 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -48,6 +48,7 @@ rsa_generic-y += rsaprivkey.asn1.o
 rsa_generic-y += rsa.o
 rsa_generic-y += rsa_helper.o
 rsa_generic-y += rsa-pkcs1pad.o
+rsa_generic-y += rsassa-pkcs1.o
 obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
 
 $(obj)/ecdsasignature.asn1.o: $(obj)/ecdsasignature.asn1.c $(obj)/ecdsasignature.asn1.h
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 422940a6706a..3fb27ecd65f6 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -83,13 +83,19 @@ software_key_determine_akcipher(const struct public_key *pkey,
 		if (strcmp(encoding, "pkcs1") == 0) {
 			*sig = op == kernel_pkey_sign ||
 			       op == kernel_pkey_verify;
-			if (!hash_algo) {
+			if (!*sig) {
+				/*
+				 * For encrypt/decrypt, hash_algo is not used
+				 * but allowed to be set for historic reasons.
+				 */
 				n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
 					     "pkcs1pad(%s)",
 					     pkey->pkey_algo);
 			} else {
+				if (!hash_algo)
+					return -EINVAL;
 				n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
-					     "pkcs1pad(%s,%s)",
+					     "pkcs1(%s,%s)",
 					     pkey->pkey_algo, hash_algo);
 			}
 			return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 3c5fe8c93938..50bdb18e7b48 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -16,101 +16,6 @@
 #include <linux/random.h>
 #include <linux/scatterlist.h>
 
-/*
- * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
- */
-static const u8 rsa_digest_info_md5[] = {
-	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
-	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
-	0x05, 0x00, 0x04, 0x10
-};
-
-static const u8 rsa_digest_info_sha1[] = {
-	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
-	0x2b, 0x0e, 0x03, 0x02, 0x1a,
-	0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 rsa_digest_info_rmd160[] = {
-	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
-	0x2b, 0x24, 0x03, 0x02, 0x01,
-	0x05, 0x00, 0x04, 0x14
-};
-
-static const u8 rsa_digest_info_sha224[] = {
-	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
-	0x05, 0x00, 0x04, 0x1c
-};
-
-static const u8 rsa_digest_info_sha256[] = {
-	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
-	0x05, 0x00, 0x04, 0x20
-};
-
-static const u8 rsa_digest_info_sha384[] = {
-	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
-	0x05, 0x00, 0x04, 0x30
-};
-
-static const u8 rsa_digest_info_sha512[] = {
-	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
-	0x05, 0x00, 0x04, 0x40
-};
-
-static const u8 rsa_digest_info_sha3_256[] = {
-	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08,
-	0x05, 0x00, 0x04, 0x20
-};
-
-static const u8 rsa_digest_info_sha3_384[] = {
-	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09,
-	0x05, 0x00, 0x04, 0x30
-};
-
-static const u8 rsa_digest_info_sha3_512[] = {
-	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
-	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0A,
-	0x05, 0x00, 0x04, 0x40
-};
-
-static const struct rsa_asn1_template {
-	const char	*name;
-	const u8	*data;
-	size_t		size;
-} rsa_asn1_templates[] = {
-#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
-	_(md5),
-	_(sha1),
-	_(rmd160),
-	_(sha256),
-	_(sha384),
-	_(sha512),
-	_(sha224),
-#undef _
-#define _(X) { "sha3-" #X, rsa_digest_info_sha3_##X, sizeof(rsa_digest_info_sha3_##X) }
-	_(256),
-	_(384),
-	_(512),
-#undef _
-	{ NULL }
-};
-
-static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
-{
-	const struct rsa_asn1_template *p;
-
-	for (p = rsa_asn1_templates; p->name; p++)
-		if (strcmp(name, p->name) == 0)
-			return p;
-	return NULL;
-}
-
 struct pkcs1pad_ctx {
 	struct crypto_akcipher *child;
 	unsigned int key_size;
@@ -118,7 +23,6 @@ struct pkcs1pad_ctx {
 
 struct pkcs1pad_inst_ctx {
 	struct crypto_akcipher_spawn spawn;
-	const struct rsa_asn1_template *digest_info;
 };
 
 struct pkcs1pad_request {
@@ -148,9 +52,9 @@ static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
 
 	/*
-	 * The maximum destination buffer size for the encrypt/sign operations
+	 * The maximum destination buffer size for the encrypt operation
 	 * will be the same as for RSA, even though it's smaller for
-	 * decrypt/verify.
+	 * decrypt.
 	 */
 
 	return ctx->key_size;
@@ -168,7 +72,7 @@ static void pkcs1pad_sg_set_buf(struct scatterlist *sg, void *buf, size_t len,
 		sg_chain(sg, nsegs, next);
 }
 
-static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
+static int pkcs1pad_encrypt_complete(struct akcipher_request *req, int err)
 {
 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
 	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
@@ -207,14 +111,14 @@ static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
 	return err;
 }
 
-static void pkcs1pad_encrypt_sign_complete_cb(void *data, int err)
+static void pkcs1pad_encrypt_complete_cb(void *data, int err)
 {
 	struct akcipher_request *req = data;
 
 	if (err == -EINPROGRESS)
 		goto out;
 
-	err = pkcs1pad_encrypt_sign_complete(req, err);
+	err = pkcs1pad_encrypt_complete(req, err);
 
 out:
 	akcipher_request_complete(req, err);
@@ -255,7 +159,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
 
 	akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
 	akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
-			pkcs1pad_encrypt_sign_complete_cb, req);
+			pkcs1pad_encrypt_complete_cb, req);
 
 	/* Reuse output buffer */
 	akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
@@ -263,7 +167,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
 
 	err = crypto_akcipher_encrypt(&req_ctx->child_req);
 	if (err != -EINPROGRESS && err != -EBUSY)
-		return pkcs1pad_encrypt_sign_complete(req, err);
+		return pkcs1pad_encrypt_complete(req, err);
 
 	return err;
 }
@@ -368,195 +272,6 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
 	return err;
 }
 
-static int pkcs1pad_sign(struct akcipher_request *req)
-{
-	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
-	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
-	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
-	struct akcipher_instance *inst = akcipher_alg_instance(tfm);
-	struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
-	const struct rsa_asn1_template *digest_info = ictx->digest_info;
-	int err;
-	unsigned int ps_end, digest_info_size = 0;
-
-	if (!ctx->key_size)
-		return -EINVAL;
-
-	if (digest_info)
-		digest_info_size = digest_info->size;
-
-	if (req->src_len + digest_info_size > ctx->key_size - 11)
-		return -EOVERFLOW;
-
-	if (req->dst_len < ctx->key_size) {
-		req->dst_len = ctx->key_size;
-		return -EOVERFLOW;
-	}
-
-	req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
-				  GFP_KERNEL);
-	if (!req_ctx->in_buf)
-		return -ENOMEM;
-
-	ps_end = ctx->key_size - digest_info_size - req->src_len - 2;
-	req_ctx->in_buf[0] = 0x01;
-	memset(req_ctx->in_buf + 1, 0xff, ps_end - 1);
-	req_ctx->in_buf[ps_end] = 0x00;
-
-	if (digest_info)
-		memcpy(req_ctx->in_buf + ps_end + 1, digest_info->data,
-		       digest_info->size);
-
-	pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
-			ctx->key_size - 1 - req->src_len, req->src);
-
-	akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
-	akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
-			pkcs1pad_encrypt_sign_complete_cb, req);
-
-	/* Reuse output buffer */
-	akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
-				   req->dst, ctx->key_size - 1, req->dst_len);
-
-	err = crypto_akcipher_decrypt(&req_ctx->child_req);
-	if (err != -EINPROGRESS && err != -EBUSY)
-		return pkcs1pad_encrypt_sign_complete(req, err);
-
-	return err;
-}
-
-static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
-{
-	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
-	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
-	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
-	struct akcipher_instance *inst = akcipher_alg_instance(tfm);
-	struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
-	const struct rsa_asn1_template *digest_info = ictx->digest_info;
-	const unsigned int sig_size = req->src_len;
-	const unsigned int digest_size = req->dst_len;
-	unsigned int dst_len;
-	unsigned int pos;
-	u8 *out_buf;
-
-	if (err)
-		goto done;
-
-	err = -EINVAL;
-	dst_len = req_ctx->child_req.dst_len;
-	if (dst_len < ctx->key_size - 1)
-		goto done;
-
-	out_buf = req_ctx->out_buf;
-	if (dst_len == ctx->key_size) {
-		if (out_buf[0] != 0x00)
-			/* Decrypted value had no leading 0 byte */
-			goto done;
-
-		dst_len--;
-		out_buf++;
-	}
-
-	err = -EBADMSG;
-	if (out_buf[0] != 0x01)
-		goto done;
-
-	for (pos = 1; pos < dst_len; pos++)
-		if (out_buf[pos] != 0xff)
-			break;
-
-	if (pos < 9 || pos == dst_len || out_buf[pos] != 0x00)
-		goto done;
-	pos++;
-
-	if (digest_info) {
-		if (digest_info->size > dst_len - pos)
-			goto done;
-		if (crypto_memneq(out_buf + pos, digest_info->data,
-				  digest_info->size))
-			goto done;
-
-		pos += digest_info->size;
-	}
-
-	err = 0;
-
-	if (digest_size != dst_len - pos) {
-		err = -EKEYREJECTED;
-		req->dst_len = dst_len - pos;
-		goto done;
-	}
-	/* Extract appended digest. */
-	sg_pcopy_to_buffer(req->src,
-			   sg_nents_for_len(req->src, sig_size + digest_size),
-			   req_ctx->out_buf + ctx->key_size,
-			   digest_size, sig_size);
-	/* Do the actual verification step. */
-	if (memcmp(req_ctx->out_buf + ctx->key_size, out_buf + pos,
-		   digest_size) != 0)
-		err = -EKEYREJECTED;
-done:
-	kfree_sensitive(req_ctx->out_buf);
-
-	return err;
-}
-
-static void pkcs1pad_verify_complete_cb(void *data, int err)
-{
-	struct akcipher_request *req = data;
-
-	if (err == -EINPROGRESS)
-		goto out;
-
-	err = pkcs1pad_verify_complete(req, err);
-
-out:
-	akcipher_request_complete(req, err);
-}
-
-/*
- * The verify operation is here for completeness similar to the verification
- * defined in RFC2313 section 10.2 except that block type 0 is not accepted,
- * as in RFC2437.  RFC2437 section 9.2 doesn't define any operation to
- * retrieve the DigestInfo from a signature, instead the user is expected
- * to call the sign operation to generate the expected signature and compare
- * signatures instead of the message-digests.
- */
-static int pkcs1pad_verify(struct akcipher_request *req)
-{
-	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
-	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
-	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
-	const unsigned int sig_size = req->src_len;
-	const unsigned int digest_size = req->dst_len;
-	int err;
-
-	if (WARN_ON(req->dst) || WARN_ON(!digest_size) ||
-	    !ctx->key_size || sig_size != ctx->key_size)
-		return -EINVAL;
-
-	req_ctx->out_buf = kmalloc(ctx->key_size + digest_size, GFP_KERNEL);
-	if (!req_ctx->out_buf)
-		return -ENOMEM;
-
-	pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf,
-			    ctx->key_size, NULL);
-
-	akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
-	akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
-			pkcs1pad_verify_complete_cb, req);
-
-	/* Reuse input buffer, output to a new buffer */
-	akcipher_request_set_crypt(&req_ctx->child_req, req->src,
-				   req_ctx->out_sg, sig_size, ctx->key_size);
-
-	err = crypto_akcipher_encrypt(&req_ctx->child_req);
-	if (err != -EINPROGRESS && err != -EBUSY)
-		return pkcs1pad_verify_complete(req, err);
-
-	return err;
-}
-
 static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
 {
 	struct akcipher_instance *inst = akcipher_alg_instance(tfm);
@@ -598,7 +313,6 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
 	struct akcipher_instance *inst;
 	struct pkcs1pad_inst_ctx *ctx;
 	struct akcipher_alg *rsa_alg;
-	const char *hash_name;
 	int err;
 
 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AKCIPHER, &mask);
@@ -624,36 +338,15 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
 	}
 
 	err = -ENAMETOOLONG;
-	hash_name = crypto_attr_alg_name(tb[2]);
-	if (IS_ERR(hash_name)) {
-		if (snprintf(inst->alg.base.cra_name,
-			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
-			     rsa_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
-			goto err_free_inst;
-
-		if (snprintf(inst->alg.base.cra_driver_name,
-			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
-			     rsa_alg->base.cra_driver_name) >=
-			     CRYPTO_MAX_ALG_NAME)
-			goto err_free_inst;
-	} else {
-		ctx->digest_info = rsa_lookup_asn1(hash_name);
-		if (!ctx->digest_info) {
-			err = -EINVAL;
-			goto err_free_inst;
-		}
-
-		if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
-			     "pkcs1pad(%s,%s)", rsa_alg->base.cra_name,
-			     hash_name) >= CRYPTO_MAX_ALG_NAME)
-			goto err_free_inst;
-
-		if (snprintf(inst->alg.base.cra_driver_name,
-			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
-			     rsa_alg->base.cra_driver_name,
-			     hash_name) >= CRYPTO_MAX_ALG_NAME)
-			goto err_free_inst;
-	}
+	if (snprintf(inst->alg.base.cra_name,
+		     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
+		     rsa_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
+		goto err_free_inst;
+
+	if (snprintf(inst->alg.base.cra_driver_name,
+		     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
+		     rsa_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+		goto err_free_inst;
 
 	inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
 	inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx);
@@ -663,8 +356,6 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
 
 	inst->alg.encrypt = pkcs1pad_encrypt;
 	inst->alg.decrypt = pkcs1pad_decrypt;
-	inst->alg.sign = pkcs1pad_sign;
-	inst->alg.verify = pkcs1pad_verify;
 	inst->alg.set_pub_key = pkcs1pad_set_pub_key;
 	inst->alg.set_priv_key = pkcs1pad_set_priv_key;
 	inst->alg.max_size = pkcs1pad_get_max_size;
diff --git a/crypto/rsa.c b/crypto/rsa.c
index d9be9e86097e..89e9fd9f6d7f 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -402,16 +402,25 @@ static int __init rsa_init(void)
 		return err;
 
 	err = crypto_register_template(&rsa_pkcs1pad_tmpl);
-	if (err) {
-		crypto_unregister_akcipher(&rsa);
-		return err;
-	}
+	if (err)
+		goto err_unregister_rsa;
+
+	err = crypto_register_template(&rsassa_pkcs1_tmpl);
+	if (err)
+		goto err_unregister_rsa_pkcs1pad;
 
 	return 0;
+
+err_unregister_rsa_pkcs1pad:
+	crypto_unregister_template(&rsa_pkcs1pad_tmpl);
+err_unregister_rsa:
+	crypto_unregister_akcipher(&rsa);
+	return err;
 }
 
 static void __exit rsa_exit(void)
 {
+	crypto_unregister_template(&rsassa_pkcs1_tmpl);
 	crypto_unregister_template(&rsa_pkcs1pad_tmpl);
 	crypto_unregister_akcipher(&rsa);
 }
diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
new file mode 100644
index 000000000000..779c080fc013
--- /dev/null
+++ b/crypto/rsassa-pkcs1.c
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * RSA Signature Scheme with Appendix - PKCS #1 v1.5 (RFC 8017 sec 8.2)
+ *
+ * https://www.rfc-editor.org/rfc/rfc8017#section-8.2
+ *
+ * Copyright (c) 2015 - 2024 Intel Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <crypto/akcipher.h>
+#include <crypto/algapi.h>
+#include <crypto/sig.h>
+#include <crypto/internal/akcipher.h>
+#include <crypto/internal/rsa.h>
+#include <crypto/internal/sig.h>
+
+/*
+ * Full Hash Prefix for EMSA-PKCS1-v1_5 encoding method (RFC 9580 table 24)
+ *
+ * RSA keys are usually much larger than the hash of the message to be signed.
+ * The hash is therefore prepended by the Full Hash Prefix and a 0xff padding.
+ * The Full Hash Prefix is an ASN.1 SEQUENCE containing the hash algorithm OID.
+ *
+ * https://www.rfc-editor.org/rfc/rfc9580#table-24
+ */
+
+static const u8 hash_prefix_md5[] = {
+	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,	  /* SEQUENCE (SEQUENCE (OID */
+	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05,	/*	<algorithm>, */
+	0x05, 0x00, 0x04, 0x10		      /* NULL), OCTET STRING <hash>) */
+};
+
+static const u8 hash_prefix_sha1[] = {
+	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+	0x2b, 0x0e, 0x03, 0x02, 0x1a,
+	0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 hash_prefix_rmd160[] = {
+	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+	0x2b, 0x24, 0x03, 0x02, 0x01,
+	0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 hash_prefix_sha224[] = {
+	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+	0x05, 0x00, 0x04, 0x1c
+};
+
+static const u8 hash_prefix_sha256[] = {
+	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+	0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 hash_prefix_sha384[] = {
+	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+	0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 hash_prefix_sha512[] = {
+	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+	0x05, 0x00, 0x04, 0x40
+};
+
+static const u8 hash_prefix_sha3_256[] = {
+	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08,
+	0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 hash_prefix_sha3_384[] = {
+	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09,
+	0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 hash_prefix_sha3_512[] = {
+	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a,
+	0x05, 0x00, 0x04, 0x40
+};
+
+static const struct hash_prefix {
+	const char	*name;
+	const u8	*data;
+	size_t		size;
+} hash_prefixes[] = {
+#define _(X) { #X, hash_prefix_##X, sizeof(hash_prefix_##X) }
+	_(md5),
+	_(sha1),
+	_(rmd160),
+	_(sha256),
+	_(sha384),
+	_(sha512),
+	_(sha224),
+#undef _
+#define _(X) { "sha3-" #X, hash_prefix_sha3_##X, sizeof(hash_prefix_sha3_##X) }
+	_(256),
+	_(384),
+	_(512),
+#undef _
+	{ NULL }
+};
+
+static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name)
+{
+	const struct hash_prefix *p;
+
+	for (p = hash_prefixes; p->name; p++)
+		if (strcmp(name, p->name) == 0)
+			return p;
+	return NULL;
+}
+
+struct rsassa_pkcs1_ctx {
+	struct crypto_akcipher *child;
+	unsigned int key_size;
+};
+
+struct rsassa_pkcs1_inst_ctx {
+	struct crypto_akcipher_spawn spawn;
+	const struct hash_prefix *hash_prefix;
+};
+
+static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
+			     const void *src, unsigned int slen,
+			     void *dst, unsigned int dlen)
+{
+	struct sig_instance *inst = sig_alg_instance(tfm);
+	struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
+	const struct hash_prefix *hash_prefix = ictx->hash_prefix;
+	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+	unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
+	struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
+	struct scatterlist in_sg[2], out_sg;
+	struct crypto_wait cwait;
+	unsigned int pad_len;
+	unsigned int ps_end;
+	unsigned int len;
+	u8 *in_buf;
+	int err;
+
+	if (!ctx->key_size)
+		return -EINVAL;
+
+	if (dlen < ctx->key_size)
+		return -EOVERFLOW;
+
+	if (slen + hash_prefix->size > ctx->key_size - 11)
+		return -EOVERFLOW;
+
+	child_req = kmalloc(sizeof(*child_req) + child_reqsize +
+			    ctx->key_size - 1 - slen, GFP_KERNEL);
+	if (!child_req)
+		return -ENOMEM;
+
+	/* RFC 8017 sec 8.2.1 step 1 - EMSA-PKCS1-v1_5 encoding generation */
+	in_buf = (u8 *)(child_req + 1) + child_reqsize;
+	ps_end = ctx->key_size - hash_prefix->size - slen - 2;
+	in_buf[0] = 0x01;
+	memset(in_buf + 1, 0xff, ps_end - 1);
+	in_buf[ps_end] = 0x00;
+	memcpy(in_buf + ps_end + 1, hash_prefix->data, hash_prefix->size);
+
+	/* RFC 8017 sec 8.2.1 step 2 - RSA signature */
+	crypto_init_wait(&cwait);
+	sg_init_table(in_sg, 2);
+	sg_set_buf(&in_sg[0], in_buf, ctx->key_size - 1 - slen);
+	sg_set_buf(&in_sg[1], src, slen);
+	sg_init_one(&out_sg, dst, dlen);
+	akcipher_request_set_tfm(child_req, ctx->child);
+	akcipher_request_set_crypt(child_req, in_sg, &out_sg,
+				   ctx->key_size - 1, dlen);
+	akcipher_request_set_callback(child_req, CRYPTO_TFM_REQ_MAY_SLEEP,
+				      crypto_req_done, &cwait);
+
+	err = crypto_akcipher_decrypt(child_req);
+	err = crypto_wait_req(err, &cwait);
+	if (err)
+		return err;
+
+	len = child_req->dst_len;
+	pad_len = ctx->key_size - len;
+
+	/* Four billion to one */
+	if (unlikely(pad_len)) {
+		memmove(dst + pad_len, dst, len);
+		memset(dst, 0, pad_len);
+	}
+
+	return 0;
+}
+
+static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
+			       const void *src, unsigned int slen,
+			       const void *digest, unsigned int dlen)
+{
+	struct sig_instance *inst = sig_alg_instance(tfm);
+	struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
+	const struct hash_prefix *hash_prefix = ictx->hash_prefix;
+	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+	unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
+	struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
+	struct scatterlist in_sg, out_sg;
+	struct crypto_wait cwait;
+	unsigned int dst_len;
+	unsigned int pos;
+	u8 *out_buf;
+	int err;
+
+	/* RFC 8017 sec 8.2.2 step 1 - length checking */
+	if (!ctx->key_size ||
+	    slen != ctx->key_size ||
+	    !dlen)
+		return -EINVAL;
+
+	/* RFC 8017 sec 8.2.2 step 2 - RSA verification */
+	child_req = kmalloc(sizeof(*child_req) + child_reqsize + ctx->key_size,
+			    GFP_KERNEL);
+	if (!child_req)
+		return -ENOMEM;
+
+	out_buf = (u8 *)(child_req + 1) + child_reqsize;
+
+	crypto_init_wait(&cwait);
+	sg_init_one(&in_sg, src, slen);
+	sg_init_one(&out_sg, out_buf, ctx->key_size);
+	akcipher_request_set_tfm(child_req, ctx->child);
+	akcipher_request_set_crypt(child_req, &in_sg, &out_sg,
+				   slen, ctx->key_size);
+	akcipher_request_set_callback(child_req, CRYPTO_TFM_REQ_MAY_SLEEP,
+				      crypto_req_done, &cwait);
+
+	err = crypto_akcipher_encrypt(child_req);
+	err = crypto_wait_req(err, &cwait);
+	if (err)
+		return err;
+
+	/* RFC 8017 sec 8.2.2 step 3 - EMSA-PKCS1-v1_5 encoding verification */
+	dst_len = child_req->dst_len;
+	if (dst_len < ctx->key_size - 1)
+		return -EINVAL;
+
+	if (dst_len == ctx->key_size) {
+		if (out_buf[0] != 0x00)
+			/* Encrypted value had no leading 0 byte */
+			return -EINVAL;
+
+		dst_len--;
+		out_buf++;
+	}
+
+	if (out_buf[0] != 0x01)
+		return -EBADMSG;
+
+	for (pos = 1; pos < dst_len; pos++)
+		if (out_buf[pos] != 0xff)
+			break;
+
+	if (pos < 9 || pos == dst_len || out_buf[pos] != 0x00)
+		return -EBADMSG;
+	pos++;
+
+	if (hash_prefix->size > dst_len - pos)
+		return -EBADMSG;
+	if (crypto_memneq(out_buf + pos, hash_prefix->data, hash_prefix->size))
+		return -EBADMSG;
+	pos += hash_prefix->size;
+
+	/* RFC 8017 sec 8.2.2 step 4 - comparison of digest with out_buf */
+	if (dlen != dst_len - pos)
+		return -EKEYREJECTED;
+	if (memcmp(digest, out_buf + pos, dlen) != 0)
+		return -EKEYREJECTED;
+
+	return 0;
+}
+
+static unsigned int rsassa_pkcs1_max_size(struct crypto_sig *tfm)
+{
+	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return ctx->key_size;
+}
+
+static int rsassa_pkcs1_set_pub_key(struct crypto_sig *tfm,
+				    const void *key, unsigned int keylen)
+{
+	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PUB, key, keylen);
+}
+
+static int rsassa_pkcs1_set_priv_key(struct crypto_sig *tfm,
+				     const void *key, unsigned int keylen)
+{
+	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PRIV, key, keylen);
+}
+
+static int rsassa_pkcs1_init_tfm(struct crypto_sig *tfm)
+{
+	struct sig_instance *inst = sig_alg_instance(tfm);
+	struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
+	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+	struct crypto_akcipher *child_tfm;
+
+	child_tfm = crypto_spawn_akcipher(&ictx->spawn);
+	if (IS_ERR(child_tfm))
+		return PTR_ERR(child_tfm);
+
+	ctx->child = child_tfm;
+
+	return 0;
+}
+
+static void rsassa_pkcs1_exit_tfm(struct crypto_sig *tfm)
+{
+	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
+
+	crypto_free_akcipher(ctx->child);
+}
+
+static void rsassa_pkcs1_free(struct sig_instance *inst)
+{
+	struct rsassa_pkcs1_inst_ctx *ctx = sig_instance_ctx(inst);
+	struct crypto_akcipher_spawn *spawn = &ctx->spawn;
+
+	crypto_drop_akcipher(spawn);
+	kfree(inst);
+}
+
+static int rsassa_pkcs1_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	struct rsassa_pkcs1_inst_ctx *ctx;
+	struct akcipher_alg *rsa_alg;
+	struct sig_instance *inst;
+	const char *hash_name;
+	u32 mask;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SIG, &mask);
+	if (err)
+		return err;
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	ctx = sig_instance_ctx(inst);
+
+	err = crypto_grab_akcipher(&ctx->spawn, sig_crypto_instance(inst),
+				   crypto_attr_alg_name(tb[1]), 0, mask);
+	if (err)
+		goto err_free_inst;
+
+	rsa_alg = crypto_spawn_akcipher_alg(&ctx->spawn);
+
+	if (strcmp(rsa_alg->base.cra_name, "rsa") != 0) {
+		err = -EINVAL;
+		goto err_free_inst;
+	}
+
+	hash_name = crypto_attr_alg_name(tb[2]);
+	if (IS_ERR(hash_name)) {
+		err = PTR_ERR(hash_name);
+		goto err_free_inst;
+	}
+
+	ctx->hash_prefix = rsassa_pkcs1_find_hash_prefix(hash_name);
+	if (!ctx->hash_prefix) {
+		err = -EINVAL;
+		goto err_free_inst;
+	}
+
+	err = -ENAMETOOLONG;
+	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
+		     "pkcs1(%s,%s)", rsa_alg->base.cra_name,
+		     hash_name) >= CRYPTO_MAX_ALG_NAME)
+		goto err_free_inst;
+
+	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+		     "pkcs1(%s,%s)", rsa_alg->base.cra_driver_name,
+		     hash_name) >= CRYPTO_MAX_ALG_NAME)
+		goto err_free_inst;
+
+	inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
+	inst->alg.base.cra_ctxsize = sizeof(struct rsassa_pkcs1_ctx);
+
+	inst->alg.init = rsassa_pkcs1_init_tfm;
+	inst->alg.exit = rsassa_pkcs1_exit_tfm;
+
+	inst->alg.sign = rsassa_pkcs1_sign;
+	inst->alg.verify = rsassa_pkcs1_verify;
+	inst->alg.max_size = rsassa_pkcs1_max_size;
+	inst->alg.set_pub_key = rsassa_pkcs1_set_pub_key;
+	inst->alg.set_priv_key = rsassa_pkcs1_set_priv_key;
+
+	inst->free = rsassa_pkcs1_free;
+
+	err = sig_register_instance(tmpl, inst);
+	if (err) {
+err_free_inst:
+		rsassa_pkcs1_free(inst);
+	}
+	return err;
+}
+
+struct crypto_template rsassa_pkcs1_tmpl = {
+	.name = "pkcs1",
+	.create = rsassa_pkcs1_create,
+	.module = THIS_MODULE,
+};
+
+MODULE_ALIAS_CRYPTO("pkcs1");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 0542817a9456..91dc29e79dd6 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5548,34 +5548,38 @@ static const struct alg_test_desc alg_test_descs[] = {
 			.cipher = __VECS(fcrypt_pcbc_tv_template)
 		}
 	}, {
-		.alg = "pkcs1pad(rsa,sha224)",
+		.alg = "pkcs1(rsa,sha224)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
-		.alg = "pkcs1pad(rsa,sha256)",
-		.test = alg_test_akcipher,
+		.alg = "pkcs1(rsa,sha256)",
+		.test = alg_test_sig,
 		.fips_allowed = 1,
 		.suite = {
-			.akcipher = __VECS(pkcs1pad_rsa_tv_template)
+			.sig = __VECS(pkcs1_rsa_tv_template)
 		}
 	}, {
-		.alg = "pkcs1pad(rsa,sha3-256)",
+		.alg = "pkcs1(rsa,sha3-256)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "pkcs1(rsa,sha3-384)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
-		.alg = "pkcs1pad(rsa,sha3-384)",
+		.alg = "pkcs1(rsa,sha3-512)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
-		.alg = "pkcs1pad(rsa,sha3-512)",
+		.alg = "pkcs1(rsa,sha384)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
-		.alg = "pkcs1pad(rsa,sha384)",
+		.alg = "pkcs1(rsa,sha512)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
-		.alg = "pkcs1pad(rsa,sha512)",
+		.alg = "pkcs1pad(rsa)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
 	}, {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index fd4823c26d93..d29d03fec852 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -1268,7 +1268,7 @@ static const struct sig_testvec ecrdsa_tv_template[] = {
 /*
  * PKCS#1 RSA test vectors. Obtained from CAVS testing.
  */
-static const struct akcipher_testvec pkcs1pad_rsa_tv_template[] = {
+static const struct sig_testvec pkcs1_rsa_tv_template[] = {
 	{
 	.key =
 	"\x30\x82\x04\xa5\x02\x01\x00\x02\x82\x01\x01\x00\xd7\x1e\x77\x82"
@@ -1380,7 +1380,6 @@ static const struct akcipher_testvec pkcs1pad_rsa_tv_template[] = {
 	"\xda\x62\x8d\xe1\x2a\x71\x91\x43\x40\x61\x3c\x5a\xbe\x86\xfc\x5b"
 	"\xe6\xf9\xa9\x16\x31\x1f\xaf\x25\x6d\xc2\x4a\x23\x6e\x63\x02\xa2",
 	.c_size = 256,
-	.siggen_sigver_test = true,
 	}
 };
 
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
index 754f687134df..071a1951b992 100644
--- a/include/crypto/internal/rsa.h
+++ b/include/crypto/internal/rsa.h
@@ -82,4 +82,5 @@ static inline int rsa_set_key(struct crypto_akcipher *child,
 }
 
 extern struct crypto_template rsa_pkcs1pad_tmpl;
+extern struct crypto_template rsassa_pkcs1_tmpl;
 #endif
diff --git a/include/linux/slab.h b/include/linux/slab.h
index eb2bf4629157..11b620b0ba1d 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -280,6 +280,7 @@ void kfree_sensitive(const void *objp);
 size_t __ksize(const void *objp);
 
 DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T))
+DEFINE_FREE(kfree_sensitive, void *, if (_T) kfree_sensitive(_T))
 
 /**
  * ksize - Report actual allocation size of associated object
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index f04f43af651c..280a3feeba45 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -1114,7 +1114,7 @@ EXPORT_SYMBOL_GPL(ima_measure_critical_data);
 #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
 
 /**
- * ima_kernel_module_request - Prevent crypto-pkcs1pad(rsa,*) requests
+ * ima_kernel_module_request - Prevent crypto-pkcs1(rsa,*) requests
  * @kmod_name: kernel module name
  *
  * Avoid a verification loop where verifying the signature of the modprobe
@@ -1128,7 +1128,7 @@ EXPORT_SYMBOL_GPL(ima_measure_critical_data);
  * algorithm on the fly, but crypto_larval_lookup() will try to use alg_name
  * in order to load a kernel module with same name.
  *
- * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
+ * Since we don't have any real "crypto-pkcs1(rsa,*)" kernel modules,
  * we are safe to fail such module request from crypto_larval_lookup(), and
  * avoid the verification loop.
  *
@@ -1136,7 +1136,7 @@ EXPORT_SYMBOL_GPL(ima_measure_critical_data);
  */
 static int ima_kernel_module_request(char *kmod_name)
 {
-	if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
+	if (strncmp(kmod_name, "crypto-pkcs1(rsa,", 17) == 0)
 		return -EINVAL;
 
 	return 0;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 07/19] crypto: rsassa-pkcs1 - Harden digest length verification
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (5 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-11 12:58   ` Jarkko Sakkinen
  2024-09-10 14:30 ` [PATCH v2 08/19] crypto: rsassa-pkcs1 - Avoid copying hash prefix Lukas Wunner
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

The RSASSA-PKCS1-v1_5 sign operation currently only checks that the
digest length is less than "key_size - hash_prefix->size - 11".
The verify operation merely checks that it's more than zero.

Actually the precise digest length is known because the hash algorithm
is specified upon instance creation and the digest length is encoded
into the final byte of the hash algorithm's Full Hash Prefix.

So check for the exact digest length rather than solely relying on
imprecise maximum/minimum checks.

Keep the maximum length check for the sign operation as a safety net,
but drop the now unnecessary minimum check for the verify operation.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 crypto/rsassa-pkcs1.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
index 779c080fc013..8f42a5712806 100644
--- a/crypto/rsassa-pkcs1.c
+++ b/crypto/rsassa-pkcs1.c
@@ -11,6 +11,7 @@
 #include <linux/scatterlist.h>
 #include <crypto/akcipher.h>
 #include <crypto/algapi.h>
+#include <crypto/hash.h>
 #include <crypto/sig.h>
 #include <crypto/internal/akcipher.h>
 #include <crypto/internal/rsa.h>
@@ -118,6 +119,20 @@ static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name)
 	return NULL;
 }
 
+static unsigned int rsassa_pkcs1_hash_len(const struct hash_prefix *p)
+{
+	/*
+	 * The final byte of the Full Hash Prefix encodes the hash length.
+	 *
+	 * This needs to be revisited should hash algorithms with more than
+	 * 1016 bits (127 bytes * 8) ever be added.  The length would then
+	 * be encoded into more than one byte by ASN.1.
+	 */
+	static_assert(HASH_MAX_DIGESTSIZE <= 127);
+
+	return p->data[p->size - 1];
+}
+
 struct rsassa_pkcs1_ctx {
 	struct crypto_akcipher *child;
 	unsigned int key_size;
@@ -152,6 +167,9 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
 	if (dlen < ctx->key_size)
 		return -EOVERFLOW;
 
+	if (slen != rsassa_pkcs1_hash_len(hash_prefix))
+		return -EINVAL;
+
 	if (slen + hash_prefix->size > ctx->key_size - 11)
 		return -EOVERFLOW;
 
@@ -217,7 +235,7 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
 	/* RFC 8017 sec 8.2.2 step 1 - length checking */
 	if (!ctx->key_size ||
 	    slen != ctx->key_size ||
-	    !dlen)
+	    dlen != rsassa_pkcs1_hash_len(hash_prefix))
 		return -EINVAL;
 
 	/* RFC 8017 sec 8.2.2 step 2 - RSA verification */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 08/19] crypto: rsassa-pkcs1 - Avoid copying hash prefix
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (6 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 07/19] crypto: rsassa-pkcs1 - Harden digest length verification Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-11 13:00   ` Jarkko Sakkinen
  2024-09-10 14:30 ` [PATCH v2 09/19] crypto: virtio - Drop sign/verify operations Lukas Wunner
                   ` (12 subsequent siblings)
  20 siblings, 1 reply; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

When constructing the EMSA-PKCS1-v1_5 padding for the sign operation,
a buffer for the padding is allocated and the Full Hash Prefix is copied
into it.  The padding is then passed to the RSA decrypt operation as an
sglist entry which is succeeded by a second sglist entry for the hash.

Actually copying the hash prefix around is completely unnecessary.
It can simply be referenced from a third sglist entry which sits
in-between the padding and the digest.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 crypto/rsassa-pkcs1.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
index 8f42a5712806..b291ec0944a2 100644
--- a/crypto/rsassa-pkcs1.c
+++ b/crypto/rsassa-pkcs1.c
@@ -153,7 +153,7 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
 	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
 	unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
 	struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
-	struct scatterlist in_sg[2], out_sg;
+	struct scatterlist in_sg[3], out_sg;
 	struct crypto_wait cwait;
 	unsigned int pad_len;
 	unsigned int ps_end;
@@ -173,24 +173,26 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
 	if (slen + hash_prefix->size > ctx->key_size - 11)
 		return -EOVERFLOW;
 
-	child_req = kmalloc(sizeof(*child_req) + child_reqsize +
-			    ctx->key_size - 1 - slen, GFP_KERNEL);
+	pad_len = ctx->key_size - slen - hash_prefix->size - 1;
+
+	child_req = kmalloc(sizeof(*child_req) + child_reqsize + pad_len,
+			    GFP_KERNEL);
 	if (!child_req)
 		return -ENOMEM;
 
 	/* RFC 8017 sec 8.2.1 step 1 - EMSA-PKCS1-v1_5 encoding generation */
 	in_buf = (u8 *)(child_req + 1) + child_reqsize;
-	ps_end = ctx->key_size - hash_prefix->size - slen - 2;
+	ps_end = pad_len - 1;
 	in_buf[0] = 0x01;
 	memset(in_buf + 1, 0xff, ps_end - 1);
 	in_buf[ps_end] = 0x00;
-	memcpy(in_buf + ps_end + 1, hash_prefix->data, hash_prefix->size);
 
 	/* RFC 8017 sec 8.2.1 step 2 - RSA signature */
 	crypto_init_wait(&cwait);
-	sg_init_table(in_sg, 2);
-	sg_set_buf(&in_sg[0], in_buf, ctx->key_size - 1 - slen);
-	sg_set_buf(&in_sg[1], src, slen);
+	sg_init_table(in_sg, 3);
+	sg_set_buf(&in_sg[0], in_buf, pad_len);
+	sg_set_buf(&in_sg[1], hash_prefix->data, hash_prefix->size);
+	sg_set_buf(&in_sg[2], src, slen);
 	sg_init_one(&out_sg, dst, dlen);
 	akcipher_request_set_tfm(child_req, ctx->child);
 	akcipher_request_set_crypt(child_req, in_sg, &out_sg,
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 09/19] crypto: virtio - Drop sign/verify operations
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (7 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 08/19] crypto: rsassa-pkcs1 - Avoid copying hash prefix Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 10/19] crypto: drivers " Lukas Wunner
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings, Gonglei,
	Michael S. Tsirkin, Jason Wang, Xuan Zhuo, Eugenio Perez,
	virtualization, zhenwei pi

The virtio crypto driver exposes akcipher sign/verify operations in a
user space ABI.  This blocks removal of sign/verify from akcipher_alg.

Herbert opines:

   "I would say that this is something that we can break.  Breaking it
    is no different to running virtio on a host that does not support
    these algorithms.  After all, a software implementation must always
    be present.

    I deliberately left akcipher out of crypto_user because the API
    is still in flux.  We should not let virtio constrain ourselves."
    https://lore.kernel.org/all/ZtqoNAgcnXnrYhZZ@gondor.apana.org.au/

   "I would remove virtio akcipher support in its entirety.  This API
    was never meant to be exposed outside of the kernel."
    https://lore.kernel.org/all/Ztqql_gqgZiMW8zz@gondor.apana.org.au/

Drop sign/verify support from virtio crypto.  There's no strong reason
to also remove encrypt/decrypt support, so keep it.

A key selling point of virtio crypto is to allow guest access to crypto
accelerators on the host.  So far the only akcipher algorithm supported
by virtio crypto is RSA.  Dropping sign/verify merely means that the
PKCS#1 padding is now always generated or verified inside the guest,
but the actual signature generation/verification (which is an RSA
decrypt/encrypt operation) may still use an accelerator on the host.

Generating or verifying the PKCS#1 padding is cheap, so a hardware
accelerator won't be of much help there.  Which begs the question
whether virtio crypto support for sign/verify makes sense at all.

It would make sense for the sign operation if the host has a security
chip to store asymmetric private keys.  But the kernel doesn't even
have an asymmetric_key_subtype yet for hardware-based private keys.
There's at least one rudimentary driver for such chips (atmel-ecc.c for
ATECC508A), but it doesn't implement the sign operation.  The kernel
would first have to grow support for a hardware asymmetric_key_subtype
and at least one driver implementing the sign operation before exposure
to guests via virtio makes sense.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 .../virtio/virtio_crypto_akcipher_algs.c      | 65 ++++++-------------
 include/uapi/linux/virtio_crypto.h            |  1 +
 2 files changed, 22 insertions(+), 44 deletions(-)

diff --git a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
index cb92b7fa99c6..48fee07b7e51 100644
--- a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
+++ b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
@@ -83,23 +83,16 @@ static void virtio_crypto_dataq_akcipher_callback(struct virtio_crypto_request *
 	case VIRTIO_CRYPTO_BADMSG:
 		error = -EBADMSG;
 		break;
-
-	case VIRTIO_CRYPTO_KEY_REJECTED:
-		error = -EKEYREJECTED;
-		break;
-
 	default:
 		error = -EIO;
 		break;
 	}
 
 	akcipher_req = vc_akcipher_req->akcipher_req;
-	if (vc_akcipher_req->opcode != VIRTIO_CRYPTO_AKCIPHER_VERIFY) {
-		/* actuall length maybe less than dst buffer */
-		akcipher_req->dst_len = len - sizeof(vc_req->status);
-		sg_copy_from_buffer(akcipher_req->dst, sg_nents(akcipher_req->dst),
-				    vc_akcipher_req->dst_buf, akcipher_req->dst_len);
-	}
+	/* actual length maybe less than dst buffer */
+	akcipher_req->dst_len = len - sizeof(vc_req->status);
+	sg_copy_from_buffer(akcipher_req->dst, sg_nents(akcipher_req->dst),
+			    vc_akcipher_req->dst_buf, akcipher_req->dst_len);
 	virtio_crypto_akcipher_finalize_req(vc_akcipher_req, akcipher_req, error);
 }
 
@@ -230,36 +223,27 @@ static int __virtio_crypto_akcipher_do_req(struct virtio_crypto_akcipher_request
 	int node = dev_to_node(&vcrypto->vdev->dev);
 	unsigned long flags;
 	int ret;
-	bool verify = vc_akcipher_req->opcode == VIRTIO_CRYPTO_AKCIPHER_VERIFY;
-	unsigned int src_len = verify ? req->src_len + req->dst_len : req->src_len;
 
 	/* out header */
 	sg_init_one(&outhdr_sg, req_data, sizeof(*req_data));
 	sgs[num_out++] = &outhdr_sg;
 
 	/* src data */
-	src_buf = kcalloc_node(src_len, 1, GFP_KERNEL, node);
+	src_buf = kcalloc_node(req->src_len, 1, GFP_KERNEL, node);
 	if (!src_buf)
 		return -ENOMEM;
 
-	if (verify) {
-		/* for verify operation, both src and dst data work as OUT direction */
-		sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, src_len);
-		sg_init_one(&srcdata_sg, src_buf, src_len);
-		sgs[num_out++] = &srcdata_sg;
-	} else {
-		sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, src_len);
-		sg_init_one(&srcdata_sg, src_buf, src_len);
-		sgs[num_out++] = &srcdata_sg;
+	sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, req->src_len);
+	sg_init_one(&srcdata_sg, src_buf, req->src_len);
+	sgs[num_out++] = &srcdata_sg;
 
-		/* dst data */
-		dst_buf = kcalloc_node(req->dst_len, 1, GFP_KERNEL, node);
-		if (!dst_buf)
-			goto free_src;
+	/* dst data */
+	dst_buf = kcalloc_node(req->dst_len, 1, GFP_KERNEL, node);
+	if (!dst_buf)
+		goto free_src;
 
-		sg_init_one(&dstdata_sg, dst_buf, req->dst_len);
-		sgs[num_out + num_in++] = &dstdata_sg;
-	}
+	sg_init_one(&dstdata_sg, dst_buf, req->dst_len);
+	sgs[num_out + num_in++] = &dstdata_sg;
 
 	vc_akcipher_req->src_buf = src_buf;
 	vc_akcipher_req->dst_buf = dst_buf;
@@ -352,16 +336,6 @@ static int virtio_crypto_rsa_decrypt(struct akcipher_request *req)
 	return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_DECRYPT);
 }
 
-static int virtio_crypto_rsa_sign(struct akcipher_request *req)
-{
-	return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_SIGN);
-}
-
-static int virtio_crypto_rsa_verify(struct akcipher_request *req)
-{
-	return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_VERIFY);
-}
-
 static int virtio_crypto_rsa_set_key(struct crypto_akcipher *tfm,
 				     const void *key,
 				     unsigned int keylen,
@@ -524,16 +498,19 @@ static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = {
 		.algo.base = {
 			.encrypt = virtio_crypto_rsa_encrypt,
 			.decrypt = virtio_crypto_rsa_decrypt,
-			.sign = virtio_crypto_rsa_sign,
-			.verify = virtio_crypto_rsa_verify,
+			/*
+			 * Must specify an arbitrary hash algorithm upon
+			 * set_{pub,priv}_key (even though it's not used
+			 * by encrypt/decrypt) because qemu checks for it.
+			 */
 			.set_pub_key = virtio_crypto_p1pad_rsa_sha1_set_pub_key,
 			.set_priv_key = virtio_crypto_p1pad_rsa_sha1_set_priv_key,
 			.max_size = virtio_crypto_rsa_max_size,
 			.init = virtio_crypto_rsa_init_tfm,
 			.exit = virtio_crypto_rsa_exit_tfm,
 			.base = {
-				.cra_name = "pkcs1pad(rsa,sha1)",
-				.cra_driver_name = "virtio-pkcs1-rsa-with-sha1",
+				.cra_name = "pkcs1pad(rsa)",
+				.cra_driver_name = "virtio-pkcs1-rsa",
 				.cra_priority = 150,
 				.cra_module = THIS_MODULE,
 				.cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx),
diff --git a/include/uapi/linux/virtio_crypto.h b/include/uapi/linux/virtio_crypto.h
index 71a54a6849ca..2fccb64c9d6b 100644
--- a/include/uapi/linux/virtio_crypto.h
+++ b/include/uapi/linux/virtio_crypto.h
@@ -329,6 +329,7 @@ struct virtio_crypto_op_header {
 	VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x00)
 #define VIRTIO_CRYPTO_AKCIPHER_DECRYPT \
 	VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x01)
+	/* akcipher sign/verify opcodes are deprecated */
 #define VIRTIO_CRYPTO_AKCIPHER_SIGN \
 	VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x02)
 #define VIRTIO_CRYPTO_AKCIPHER_VERIFY \
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 10/19] crypto: drivers - Drop sign/verify operations
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (8 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 09/19] crypto: virtio - Drop sign/verify operations Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 11/19] crypto: akcipher " Lukas Wunner
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings, Neal Liu,
	Joel Stanley, Andrew Jeffery, linux-aspeed, Zhiqi Song,
	Longfang Liu, Jia Jie Ho, William Qiu

The drivers aspeed-acry.c, hpre_crypto.c and jh7110-rsa.c purport to
implement sign/verify operations for raw (unpadded) "rsa".

But there is no such thing as message digests generally need to be
padded according to a predefined scheme (such as PSS or PKCS#1) to
match the size of the usually much larger RSA keys.

The bogus sign/verify operations defined by these drivers are never
called but block removal of sign/verify from akcipher_alg.  Drop them.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 drivers/crypto/aspeed/aspeed-acry.c         | 2 --
 drivers/crypto/hisilicon/hpre/hpre_crypto.c | 2 --
 drivers/crypto/starfive/jh7110-rsa.c        | 2 --
 3 files changed, 6 deletions(-)

diff --git a/drivers/crypto/aspeed/aspeed-acry.c b/drivers/crypto/aspeed/aspeed-acry.c
index b4613bd4ad96..7a1e153733e1 100644
--- a/drivers/crypto/aspeed/aspeed-acry.c
+++ b/drivers/crypto/aspeed/aspeed-acry.c
@@ -601,8 +601,6 @@ static struct aspeed_acry_alg aspeed_acry_akcipher_algs[] = {
 		.akcipher.base = {
 			.encrypt = aspeed_acry_rsa_enc,
 			.decrypt = aspeed_acry_rsa_dec,
-			.sign = aspeed_acry_rsa_dec,
-			.verify = aspeed_acry_rsa_enc,
 			.set_pub_key = aspeed_acry_rsa_set_pub_key,
 			.set_priv_key = aspeed_acry_rsa_set_priv_key,
 			.max_size = aspeed_acry_rsa_max_size,
diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
index 764532a6ca82..bdd7e1df8a06 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
@@ -2004,8 +2004,6 @@ static void hpre_curve25519_exit_tfm(struct crypto_kpp *tfm)
 }
 
 static struct akcipher_alg rsa = {
-	.sign = hpre_rsa_dec,
-	.verify = hpre_rsa_enc,
 	.encrypt = hpre_rsa_enc,
 	.decrypt = hpre_rsa_dec,
 	.set_pub_key = hpre_rsa_setpubkey,
diff --git a/drivers/crypto/starfive/jh7110-rsa.c b/drivers/crypto/starfive/jh7110-rsa.c
index a778c4846025..d109c743f076 100644
--- a/drivers/crypto/starfive/jh7110-rsa.c
+++ b/drivers/crypto/starfive/jh7110-rsa.c
@@ -565,8 +565,6 @@ static void starfive_rsa_exit_tfm(struct crypto_akcipher *tfm)
 static struct akcipher_alg starfive_rsa = {
 	.encrypt = starfive_rsa_enc,
 	.decrypt = starfive_rsa_dec,
-	.sign = starfive_rsa_dec,
-	.verify = starfive_rsa_enc,
 	.set_pub_key = starfive_rsa_set_pub_key,
 	.set_priv_key = starfive_rsa_set_priv_key,
 	.max_size = starfive_rsa_max_size,
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 11/19] crypto: akcipher - Drop sign/verify operations
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (9 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 10/19] crypto: drivers " Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 12/19] crypto: sig - Move crypto_sig_*() API calls to include file Lukas Wunner
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

A sig_alg backend has just been introduced and all asymmetric
sign/verify algorithms have been migrated to it.

The sign/verify operations can thus be dropped from akcipher_alg.
It is now purely for asymmetric encrypt/decrypt.

Move struct crypto_akcipher_sync_data from internal.h to akcipher.c and
unexport crypto_akcipher_sync_{prep,post}():  They're no longer used by
sig.c but only locally in akcipher.c.

In crypto_akcipher_sync_{prep,post}(), drop various NULL pointer checks
for data->dst as they were only necessary for the verify operation.

In the crypto_sig_*() API calls, remove the forks that were necessary
while algorithms were converted from crypto_akcipher to crypto_sig
one by one.

In struct akcipher_testvec, remove the "params", "param_len" and "algo"
elements as they were only needed for the ecrdsa verify operation.
Remove corresponding dead code from test_akcipher_one() as well.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 Documentation/crypto/api-akcipher.rst |   2 +-
 crypto/akcipher.c                     |  64 ++++----------
 crypto/internal.h                     |  19 ----
 crypto/sig.c                          |  70 ---------------
 crypto/testmgr.c                      | 119 ++++++++------------------
 crypto/testmgr.h                      |   4 -
 include/crypto/akcipher.h             |  69 ++-------------
 include/crypto/internal/akcipher.h    |   4 +-
 8 files changed, 66 insertions(+), 285 deletions(-)

diff --git a/Documentation/crypto/api-akcipher.rst b/Documentation/crypto/api-akcipher.rst
index 40aa8746e2a1..6f47cc70eca0 100644
--- a/Documentation/crypto/api-akcipher.rst
+++ b/Documentation/crypto/api-akcipher.rst
@@ -11,7 +11,7 @@ Asymmetric Cipher API
    :doc: Generic Public Key API
 
 .. kernel-doc:: include/crypto/akcipher.h
-   :functions: crypto_alloc_akcipher crypto_free_akcipher crypto_akcipher_set_pub_key crypto_akcipher_set_priv_key crypto_akcipher_maxsize crypto_akcipher_encrypt crypto_akcipher_decrypt crypto_akcipher_sign crypto_akcipher_verify
+   :functions: crypto_alloc_akcipher crypto_free_akcipher crypto_akcipher_set_pub_key crypto_akcipher_set_priv_key crypto_akcipher_maxsize crypto_akcipher_encrypt crypto_akcipher_decrypt
 
 Asymmetric Cipher Request Handle
 --------------------------------
diff --git a/crypto/akcipher.c b/crypto/akcipher.c
index e0ff5f4dda6d..72c82d9aa077 100644
--- a/crypto/akcipher.c
+++ b/crypto/akcipher.c
@@ -20,6 +20,19 @@
 
 #define CRYPTO_ALG_TYPE_AHASH_MASK	0x0000000e
 
+struct crypto_akcipher_sync_data {
+	struct crypto_akcipher *tfm;
+	const void *src;
+	void *dst;
+	unsigned int slen;
+	unsigned int dlen;
+
+	struct akcipher_request *req;
+	struct crypto_wait cwait;
+	struct scatterlist sg;
+	u8 *buf;
+};
+
 static int __maybe_unused crypto_akcipher_report(
 	struct sk_buff *skb, struct crypto_alg *alg)
 {
@@ -126,10 +139,6 @@ int crypto_register_akcipher(struct akcipher_alg *alg)
 {
 	struct crypto_alg *base = &alg->base;
 
-	if (!alg->sign)
-		alg->sign = akcipher_default_op;
-	if (!alg->verify)
-		alg->verify = akcipher_default_op;
 	if (!alg->encrypt)
 		alg->encrypt = akcipher_default_op;
 	if (!alg->decrypt)
@@ -158,7 +167,7 @@ int akcipher_register_instance(struct crypto_template *tmpl,
 }
 EXPORT_SYMBOL_GPL(akcipher_register_instance);
 
-int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
+static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
 {
 	unsigned int reqsize = crypto_akcipher_reqsize(data->tfm);
 	struct akcipher_request *req;
@@ -167,10 +176,7 @@ int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
 	unsigned int len;
 	u8 *buf;
 
-	if (data->dst)
-		mlen = max(data->slen, data->dlen);
-	else
-		mlen = data->slen + data->dlen;
+	mlen = max(data->slen, data->dlen);
 
 	len = sizeof(*req) + reqsize + mlen;
 	if (len < mlen)
@@ -189,8 +195,7 @@ int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
 
 	sg = &data->sg;
 	sg_init_one(sg, buf, mlen);
-	akcipher_request_set_crypt(req, sg, data->dst ? sg : NULL,
-				   data->slen, data->dlen);
+	akcipher_request_set_crypt(req, sg, sg, data->slen, data->dlen);
 
 	crypto_init_wait(&data->cwait);
 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
@@ -198,18 +203,16 @@ int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(crypto_akcipher_sync_prep);
 
-int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err)
+static int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data,
+				     int err)
 {
 	err = crypto_wait_req(err, &data->cwait);
-	if (data->dst)
-		memcpy(data->dst, data->buf, data->dlen);
+	memcpy(data->dst, data->buf, data->dlen);
 	data->dlen = data->req->dst_len;
 	kfree_sensitive(data->req);
 	return err;
 }
-EXPORT_SYMBOL_GPL(crypto_akcipher_sync_post);
 
 int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm,
 				 const void *src, unsigned int slen,
@@ -248,34 +251,5 @@ int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm,
 }
 EXPORT_SYMBOL_GPL(crypto_akcipher_sync_decrypt);
 
-static void crypto_exit_akcipher_ops_sig(struct crypto_tfm *tfm)
-{
-	struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
-
-	crypto_free_akcipher(*ctx);
-}
-
-int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm)
-{
-	struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
-	struct crypto_alg *calg = tfm->__crt_alg;
-	struct crypto_akcipher *akcipher;
-
-	if (!crypto_mod_get(calg))
-		return -EAGAIN;
-
-	akcipher = crypto_create_tfm(calg, &crypto_akcipher_type);
-	if (IS_ERR(akcipher)) {
-		crypto_mod_put(calg);
-		return PTR_ERR(akcipher);
-	}
-
-	*ctx = akcipher;
-	tfm->exit = crypto_exit_akcipher_ops_sig;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(crypto_init_akcipher_ops_sig);
-
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Generic public key cipher type");
diff --git a/crypto/internal.h b/crypto/internal.h
index aee31319be2e..0008621aaa98 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -22,8 +22,6 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 
-struct akcipher_request;
-struct crypto_akcipher;
 struct crypto_instance;
 struct crypto_template;
 
@@ -35,19 +33,6 @@ struct crypto_larval {
 	bool test_started;
 };
 
-struct crypto_akcipher_sync_data {
-	struct crypto_akcipher *tfm;
-	const void *src;
-	void *dst;
-	unsigned int slen;
-	unsigned int dlen;
-
-	struct akcipher_request *req;
-	struct crypto_wait cwait;
-	struct scatterlist sg;
-	u8 *buf;
-};
-
 enum {
 	CRYPTOA_UNSPEC,
 	CRYPTOA_ALG,
@@ -130,10 +115,6 @@ void *crypto_create_tfm_node(struct crypto_alg *alg,
 void *crypto_clone_tfm(const struct crypto_type *frontend,
 		       struct crypto_tfm *otfm);
 
-int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data);
-int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err);
-int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm);
-
 static inline void *crypto_create_tfm(struct crypto_alg *alg,
 			const struct crypto_type *frontend)
 {
diff --git a/crypto/sig.c b/crypto/sig.c
index 4f36ceb7a90b..1e6b0d677472 100644
--- a/crypto/sig.c
+++ b/crypto/sig.c
@@ -5,12 +5,10 @@
  * Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
  */
 
-#include <crypto/akcipher.h>
 #include <crypto/internal/sig.h>
 #include <linux/cryptouser.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/scatterlist.h>
 #include <linux/seq_file.h>
 #include <linux/string.h>
 #include <net/netlink.h>
@@ -19,8 +17,6 @@
 
 #define CRYPTO_ALG_TYPE_SIG_MASK	0x0000000e
 
-static const struct crypto_type crypto_sig_type;
-
 static void crypto_sig_exit_tfm(struct crypto_tfm *tfm)
 {
 	struct crypto_sig *sig = __crypto_sig_tfm(tfm);
@@ -31,9 +27,6 @@ static void crypto_sig_exit_tfm(struct crypto_tfm *tfm)
 
 static int crypto_sig_init_tfm(struct crypto_tfm *tfm)
 {
-	if (tfm->__crt_alg->cra_type != &crypto_sig_type)
-		return crypto_init_akcipher_ops_sig(tfm);
-
 	struct crypto_sig *sig = __crypto_sig_tfm(tfm);
 	struct sig_alg *alg = crypto_sig_alg(sig);
 
@@ -93,17 +86,9 @@ EXPORT_SYMBOL_GPL(crypto_alloc_sig);
 
 int crypto_sig_maxsize(struct crypto_sig *tfm)
 {
-	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
-		goto akcipher;
-
 	struct sig_alg *alg = crypto_sig_alg(tfm);
 
 	return alg->max_size(tfm);
-
-akcipher:
-	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
-
-	return crypto_akcipher_maxsize(*ctx);
 }
 EXPORT_SYMBOL_GPL(crypto_sig_maxsize);
 
@@ -111,26 +96,9 @@ int crypto_sig_sign(struct crypto_sig *tfm,
 		    const void *src, unsigned int slen,
 		    void *dst, unsigned int dlen)
 {
-	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
-		goto akcipher;
-
 	struct sig_alg *alg = crypto_sig_alg(tfm);
 
 	return alg->sign(tfm, src, slen, dst, dlen);
-
-akcipher:
-	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
-	struct crypto_akcipher_sync_data data = {
-		.tfm = *ctx,
-		.src = src,
-		.dst = dst,
-		.slen = slen,
-		.dlen = dlen,
-	};
-
-	return crypto_akcipher_sync_prep(&data) ?:
-	       crypto_akcipher_sync_post(&data,
-					 crypto_akcipher_sign(data.req));
 }
 EXPORT_SYMBOL_GPL(crypto_sig_sign);
 
@@ -138,65 +106,27 @@ int crypto_sig_verify(struct crypto_sig *tfm,
 		      const void *src, unsigned int slen,
 		      const void *digest, unsigned int dlen)
 {
-	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
-		goto akcipher;
-
 	struct sig_alg *alg = crypto_sig_alg(tfm);
 
 	return alg->verify(tfm, src, slen, digest, dlen);
-
-akcipher:
-	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
-	struct crypto_akcipher_sync_data data = {
-		.tfm = *ctx,
-		.src = src,
-		.slen = slen,
-		.dlen = dlen,
-	};
-	int err;
-
-	err = crypto_akcipher_sync_prep(&data);
-	if (err)
-		return err;
-
-	memcpy(data.buf + slen, digest, dlen);
-
-	return crypto_akcipher_sync_post(&data,
-					 crypto_akcipher_verify(data.req));
 }
 EXPORT_SYMBOL_GPL(crypto_sig_verify);
 
 int crypto_sig_set_pubkey(struct crypto_sig *tfm,
 			  const void *key, unsigned int keylen)
 {
-	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
-		goto akcipher;
-
 	struct sig_alg *alg = crypto_sig_alg(tfm);
 
 	return alg->set_pub_key(tfm, key, keylen);
-
-akcipher:
-	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
-
-	return crypto_akcipher_set_pub_key(*ctx, key, keylen);
 }
 EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);
 
 int crypto_sig_set_privkey(struct crypto_sig *tfm,
 			  const void *key, unsigned int keylen)
 {
-	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
-		goto akcipher;
-
 	struct sig_alg *alg = crypto_sig_alg(tfm);
 
 	return alg->set_priv_key(tfm, key, keylen);
-
-akcipher:
-	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
-
-	return crypto_akcipher_set_priv_key(*ctx, key, keylen);
 }
 EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);
 
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 91dc29e79dd6..fdebdafdf027 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4112,11 +4112,9 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
 	struct crypto_wait wait;
 	unsigned int out_len_max, out_len = 0;
 	int err = -ENOMEM;
-	struct scatterlist src, dst, src_tab[3];
-	const char *m, *c;
-	unsigned int m_size, c_size;
-	const char *op;
-	u8 *key, *ptr;
+	struct scatterlist src, dst, src_tab[2];
+	const char *c;
+	unsigned int c_size;
 
 	if (testmgr_alloc_buf(xbuf))
 		return err;
@@ -4127,92 +4125,53 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
 
 	crypto_init_wait(&wait);
 
-	key = kmalloc(vecs->key_len + sizeof(u32) * 2 + vecs->param_len,
-		      GFP_KERNEL);
-	if (!key)
-		goto free_req;
-	memcpy(key, vecs->key, vecs->key_len);
-	ptr = key + vecs->key_len;
-	ptr = test_pack_u32(ptr, vecs->algo);
-	ptr = test_pack_u32(ptr, vecs->param_len);
-	memcpy(ptr, vecs->params, vecs->param_len);
-
 	if (vecs->public_key_vec)
-		err = crypto_akcipher_set_pub_key(tfm, key, vecs->key_len);
+		err = crypto_akcipher_set_pub_key(tfm, vecs->key,
+						  vecs->key_len);
 	else
-		err = crypto_akcipher_set_priv_key(tfm, key, vecs->key_len);
+		err = crypto_akcipher_set_priv_key(tfm, vecs->key,
+						   vecs->key_len);
 	if (err)
-		goto free_key;
+		goto free_req;
 
-	/*
-	 * First run test which do not require a private key, such as
-	 * encrypt or verify.
-	 */
+	/* First run encrypt test which does not require a private key */
 	err = -ENOMEM;
 	out_len_max = crypto_akcipher_maxsize(tfm);
 	outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
 	if (!outbuf_enc)
-		goto free_key;
-
-	if (!vecs->siggen_sigver_test) {
-		m = vecs->m;
-		m_size = vecs->m_size;
-		c = vecs->c;
-		c_size = vecs->c_size;
-		op = "encrypt";
-	} else {
-		/* Swap args so we could keep plaintext (digest)
-		 * in vecs->m, and cooked signature in vecs->c.
-		 */
-		m = vecs->c; /* signature */
-		m_size = vecs->c_size;
-		c = vecs->m; /* digest */
-		c_size = vecs->m_size;
-		op = "verify";
-	}
+		goto free_req;
+
+	c = vecs->c;
+	c_size = vecs->c_size;
 
 	err = -E2BIG;
-	if (WARN_ON(m_size > PAGE_SIZE))
+	if (WARN_ON(vecs->m_size > PAGE_SIZE))
 		goto free_all;
-	memcpy(xbuf[0], m, m_size);
+	memcpy(xbuf[0], vecs->m, vecs->m_size);
 
-	sg_init_table(src_tab, 3);
+	sg_init_table(src_tab, 2);
 	sg_set_buf(&src_tab[0], xbuf[0], 8);
-	sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8);
-	if (vecs->siggen_sigver_test) {
-		if (WARN_ON(c_size > PAGE_SIZE))
-			goto free_all;
-		memcpy(xbuf[1], c, c_size);
-		sg_set_buf(&src_tab[2], xbuf[1], c_size);
-		akcipher_request_set_crypt(req, src_tab, NULL, m_size, c_size);
-	} else {
-		sg_init_one(&dst, outbuf_enc, out_len_max);
-		akcipher_request_set_crypt(req, src_tab, &dst, m_size,
-					   out_len_max);
-	}
+	sg_set_buf(&src_tab[1], xbuf[0] + 8, vecs->m_size - 8);
+	sg_init_one(&dst, outbuf_enc, out_len_max);
+	akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size,
+				   out_len_max);
 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				      crypto_req_done, &wait);
 
-	err = crypto_wait_req(vecs->siggen_sigver_test ?
-			      /* Run asymmetric signature verification */
-			      crypto_akcipher_verify(req) :
-			      /* Run asymmetric encrypt */
-			      crypto_akcipher_encrypt(req), &wait);
+	err = crypto_wait_req(crypto_akcipher_encrypt(req), &wait);
 	if (err) {
-		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
+		pr_err("alg: akcipher: encrypt test failed. err %d\n", err);
 		goto free_all;
 	}
-	if (!vecs->siggen_sigver_test && c) {
+	if (c) {
 		if (req->dst_len != c_size) {
-			pr_err("alg: akcipher: %s test failed. Invalid output len\n",
-			       op);
+			pr_err("alg: akcipher: encrypt test failed. Invalid output len\n");
 			err = -EINVAL;
 			goto free_all;
 		}
 		/* verify that encrypted message is equal to expected */
 		if (memcmp(c, outbuf_enc, c_size) != 0) {
-			pr_err("alg: akcipher: %s test failed. Invalid output\n",
-			       op);
+			pr_err("alg: akcipher: encrypt test failed. Invalid output\n");
 			hexdump(outbuf_enc, c_size);
 			err = -EINVAL;
 			goto free_all;
@@ -4220,7 +4179,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
 	}
 
 	/*
-	 * Don't invoke (decrypt or sign) test which require a private key
+	 * Don't invoke decrypt test which requires a private key
 	 * for vectors with only a public key.
 	 */
 	if (vecs->public_key_vec) {
@@ -4233,13 +4192,12 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
 		goto free_all;
 	}
 
-	if (!vecs->siggen_sigver_test && !c) {
+	if (!c) {
 		c = outbuf_enc;
 		c_size = req->dst_len;
 	}
 
 	err = -E2BIG;
-	op = vecs->siggen_sigver_test ? "sign" : "decrypt";
 	if (WARN_ON(c_size > PAGE_SIZE))
 		goto free_all;
 	memcpy(xbuf[0], c, c_size);
@@ -4249,34 +4207,29 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
 	crypto_init_wait(&wait);
 	akcipher_request_set_crypt(req, &src, &dst, c_size, out_len_max);
 
-	err = crypto_wait_req(vecs->siggen_sigver_test ?
-			      /* Run asymmetric signature generation */
-			      crypto_akcipher_sign(req) :
-			      /* Run asymmetric decrypt */
-			      crypto_akcipher_decrypt(req), &wait);
+	err = crypto_wait_req(crypto_akcipher_decrypt(req), &wait);
 	if (err) {
-		pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
+		pr_err("alg: akcipher: decrypt test failed. err %d\n", err);
 		goto free_all;
 	}
 	out_len = req->dst_len;
-	if (out_len < m_size) {
-		pr_err("alg: akcipher: %s test failed. Invalid output len %u\n",
-		       op, out_len);
+	if (out_len < vecs->m_size) {
+		pr_err("alg: akcipher: decrypt test failed. Invalid output len %u\n",
+		       out_len);
 		err = -EINVAL;
 		goto free_all;
 	}
 	/* verify that decrypted message is equal to the original msg */
-	if (memchr_inv(outbuf_dec, 0, out_len - m_size) ||
-	    memcmp(m, outbuf_dec + out_len - m_size, m_size)) {
-		pr_err("alg: akcipher: %s test failed. Invalid output\n", op);
+	if (memchr_inv(outbuf_dec, 0, out_len - vecs->m_size) ||
+	    memcmp(vecs->m, outbuf_dec + out_len - vecs->m_size,
+		   vecs->m_size)) {
+		pr_err("alg: akcipher: decrypt test failed. Invalid output\n");
 		hexdump(outbuf_dec, out_len);
 		err = -EINVAL;
 	}
 free_all:
 	kfree(outbuf_dec);
 	kfree(outbuf_enc);
-free_key:
-	kfree(key);
 free_req:
 	akcipher_request_free(req);
 free_xbuf:
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index d29d03fec852..e10b6d7f2cd9 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -150,16 +150,12 @@ struct drbg_testvec {
 
 struct akcipher_testvec {
 	const unsigned char *key;
-	const unsigned char *params;
 	const unsigned char *m;
 	const unsigned char *c;
 	unsigned int key_len;
-	unsigned int param_len;
 	unsigned int m_size;
 	unsigned int c_size;
 	bool public_key_vec;
-	bool siggen_sigver_test;
-	enum OID algo;
 };
 
 struct sig_testvec {
diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index 18a10cad07aa..cdf7da74bf2f 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -12,24 +12,19 @@
 #include <linux/crypto.h>
 
 /**
- * struct akcipher_request - public key request
+ * struct akcipher_request - public key cipher request
  *
  * @base:	Common attributes for async crypto requests
  * @src:	Source data
- *		For verify op this is signature + digest, in that case
- *		total size of @src is @src_len + @dst_len.
- * @dst:	Destination data (Should be NULL for verify op)
+ * @dst:	Destination data
  * @src_len:	Size of the input buffer
- *		For verify op it's size of signature part of @src, this part
- *		is supposed to be operated by cipher.
- * @dst_len:	Size of @dst buffer (for all ops except verify).
+ * @dst_len:	Size of @dst buffer
  *		It needs to be at least	as big as the expected result
  *		depending on the operation.
  *		After operation it will be updated with the actual size of the
  *		result.
  *		In case of error where the dst sgl size was insufficient,
  *		it will be updated to the size required for the operation.
- *		For verify op this is size of digest part in @src.
  * @__ctx:	Start of private context data
  */
 struct akcipher_request {
@@ -55,15 +50,8 @@ struct crypto_akcipher {
 };
 
 /**
- * struct akcipher_alg - generic public key algorithm
+ * struct akcipher_alg - generic public key cipher algorithm
  *
- * @sign:	Function performs a sign operation as defined by public key
- *		algorithm. In case of error, where the dst_len was insufficient,
- *		the req->dst_len will be updated to the size required for the
- *		operation
- * @verify:	Function performs a complete verify operation as defined by
- *		public key algorithm, returning verification status. Requires
- *		digest value as input parameter.
  * @encrypt:	Function performs an encrypt operation as defined by public key
  *		algorithm. In case of error, where the dst_len was insufficient,
  *		the req->dst_len will be updated to the size required for the
@@ -94,8 +82,6 @@ struct crypto_akcipher {
  * @base:	Common crypto API algorithm data structure
  */
 struct akcipher_alg {
-	int (*sign)(struct akcipher_request *req);
-	int (*verify)(struct akcipher_request *req);
 	int (*encrypt)(struct akcipher_request *req);
 	int (*decrypt)(struct akcipher_request *req);
 	int (*set_pub_key)(struct crypto_akcipher *tfm, const void *key,
@@ -110,9 +96,9 @@ struct akcipher_alg {
 };
 
 /**
- * DOC: Generic Public Key API
+ * DOC: Generic Public Key Cipher API
  *
- * The Public Key API is used with the algorithms of type
+ * The Public Key Cipher API is used with the algorithms of type
  * CRYPTO_ALG_TYPE_AKCIPHER (listed as type "akcipher" in /proc/crypto)
  */
 
@@ -243,10 +229,9 @@ static inline void akcipher_request_set_callback(struct akcipher_request *req,
  *
  * @req:	public key request
  * @src:	ptr to input scatter list
- * @dst:	ptr to output scatter list or NULL for verify op
+ * @dst:	ptr to output scatter list
  * @src_len:	size of the src input scatter list to be processed
- * @dst_len:	size of the dst output scatter list or size of signature
- *		portion in @src for verify op
+ * @dst_len:	size of the dst output scatter list
  */
 static inline void akcipher_request_set_crypt(struct akcipher_request *req,
 					      struct scatterlist *src,
@@ -347,44 +332,6 @@ int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm,
 				 const void *src, unsigned int slen,
 				 void *dst, unsigned int dlen);
 
-/**
- * crypto_akcipher_sign() - Invoke public key sign operation
- *
- * Function invokes the specific public key sign operation for a given
- * public key algorithm
- *
- * @req:	asymmetric key request
- *
- * Return: zero on success; error code in case of error
- */
-static inline int crypto_akcipher_sign(struct akcipher_request *req)
-{
-	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
-
-	return crypto_akcipher_alg(tfm)->sign(req);
-}
-
-/**
- * crypto_akcipher_verify() - Invoke public key signature verification
- *
- * Function invokes the specific public key signature verification operation
- * for a given public key algorithm.
- *
- * @req:	asymmetric key request
- *
- * Note: req->dst should be NULL, req->src should point to SG of size
- * (req->src_size + req->dst_size), containing signature (of req->src_size
- * length) with appended digest (of req->dst_size length).
- *
- * Return: zero on verification success; error code in case of error.
- */
-static inline int crypto_akcipher_verify(struct akcipher_request *req)
-{
-	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
-
-	return crypto_akcipher_alg(tfm)->verify(req);
-}
-
 /**
  * crypto_akcipher_set_pub_key() - Invoke set public key operation
  *
diff --git a/include/crypto/internal/akcipher.h b/include/crypto/internal/akcipher.h
index a0fba4b2eccf..14ee62bc52b6 100644
--- a/include/crypto/internal/akcipher.h
+++ b/include/crypto/internal/akcipher.h
@@ -124,7 +124,7 @@ static inline struct akcipher_alg *crypto_spawn_akcipher_alg(
 /**
  * crypto_register_akcipher() -- Register public key algorithm
  *
- * Function registers an implementation of a public key verify algorithm
+ * Function registers an implementation of a public key cipher algorithm
  *
  * @alg:	algorithm definition
  *
@@ -135,7 +135,7 @@ int crypto_register_akcipher(struct akcipher_alg *alg);
 /**
  * crypto_unregister_akcipher() -- Unregister public key algorithm
  *
- * Function unregisters an implementation of a public key verify algorithm
+ * Function unregisters an implementation of a public key cipher algorithm
  *
  * @alg:	algorithm definition
  */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 12/19] crypto: sig - Move crypto_sig_*() API calls to include file
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (10 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 11/19] crypto: akcipher " Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 19:24   ` Stefan Berger
  2024-09-10 14:30 ` [PATCH v2 13/19] ASN.1: Clean up include statements in public headers Lukas Wunner
                   ` (8 subsequent siblings)
  20 siblings, 1 reply; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

The crypto_sig_*() API calls lived in sig.c so far because they needed
access to struct crypto_sig_type:  This was necessary to differentiate
between signature algorithms that had already been migrated from
crypto_akcipher to crypto_sig and those that hadn't yet.

Now that all algorithms have been migrated, the API calls can become
static inlines in <crypto/sig.h> to mimic what <crypto/akcipher.h> is
doing.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 crypto/sig.c         | 46 -------------------------------------------
 include/crypto/sig.h | 47 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 36 insertions(+), 57 deletions(-)

diff --git a/crypto/sig.c b/crypto/sig.c
index 1e6b0d677472..84d0ea9fd73b 100644
--- a/crypto/sig.c
+++ b/crypto/sig.c
@@ -84,52 +84,6 @@ struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask)
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_sig);
 
-int crypto_sig_maxsize(struct crypto_sig *tfm)
-{
-	struct sig_alg *alg = crypto_sig_alg(tfm);
-
-	return alg->max_size(tfm);
-}
-EXPORT_SYMBOL_GPL(crypto_sig_maxsize);
-
-int crypto_sig_sign(struct crypto_sig *tfm,
-		    const void *src, unsigned int slen,
-		    void *dst, unsigned int dlen)
-{
-	struct sig_alg *alg = crypto_sig_alg(tfm);
-
-	return alg->sign(tfm, src, slen, dst, dlen);
-}
-EXPORT_SYMBOL_GPL(crypto_sig_sign);
-
-int crypto_sig_verify(struct crypto_sig *tfm,
-		      const void *src, unsigned int slen,
-		      const void *digest, unsigned int dlen)
-{
-	struct sig_alg *alg = crypto_sig_alg(tfm);
-
-	return alg->verify(tfm, src, slen, digest, dlen);
-}
-EXPORT_SYMBOL_GPL(crypto_sig_verify);
-
-int crypto_sig_set_pubkey(struct crypto_sig *tfm,
-			  const void *key, unsigned int keylen)
-{
-	struct sig_alg *alg = crypto_sig_alg(tfm);
-
-	return alg->set_pub_key(tfm, key, keylen);
-}
-EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);
-
-int crypto_sig_set_privkey(struct crypto_sig *tfm,
-			  const void *key, unsigned int keylen)
-{
-	struct sig_alg *alg = crypto_sig_alg(tfm);
-
-	return alg->set_priv_key(tfm, key, keylen);
-}
-EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);
-
 static void sig_prepare_alg(struct sig_alg *alg)
 {
 	struct crypto_alg *base = &alg->base;
diff --git a/include/crypto/sig.h b/include/crypto/sig.h
index f0f52a7c5ae7..bbc902642bf5 100644
--- a/include/crypto/sig.h
+++ b/include/crypto/sig.h
@@ -130,7 +130,12 @@ static inline void crypto_free_sig(struct crypto_sig *tfm)
  *
  * @tfm:	signature tfm handle allocated with crypto_alloc_sig()
  */
-int crypto_sig_maxsize(struct crypto_sig *tfm);
+static inline int crypto_sig_maxsize(struct crypto_sig *tfm)
+{
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->max_size(tfm);
+}
 
 /**
  * crypto_sig_sign() - Invoke signing operation
@@ -145,9 +150,14 @@ int crypto_sig_maxsize(struct crypto_sig *tfm);
  *
  * Return: zero on success; error code in case of error
  */
-int crypto_sig_sign(struct crypto_sig *tfm,
-		    const void *src, unsigned int slen,
-		    void *dst, unsigned int dlen);
+static inline int crypto_sig_sign(struct crypto_sig *tfm,
+				  const void *src, unsigned int slen,
+				  void *dst, unsigned int dlen)
+{
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->sign(tfm, src, slen, dst, dlen);
+}
 
 /**
  * crypto_sig_verify() - Invoke signature verification
@@ -163,9 +173,14 @@ int crypto_sig_sign(struct crypto_sig *tfm,
  *
  * Return: zero on verification success; error code in case of error.
  */
-int crypto_sig_verify(struct crypto_sig *tfm,
-		      const void *src, unsigned int slen,
-		      const void *digest, unsigned int dlen);
+static inline int crypto_sig_verify(struct crypto_sig *tfm,
+				    const void *src, unsigned int slen,
+				    const void *digest, unsigned int dlen)
+{
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->verify(tfm, src, slen, digest, dlen);
+}
 
 /**
  * crypto_sig_set_pubkey() - Invoke set public key operation
@@ -180,8 +195,13 @@ int crypto_sig_verify(struct crypto_sig *tfm,
  *
  * Return: zero on success; error code in case of error
  */
-int crypto_sig_set_pubkey(struct crypto_sig *tfm,
-			  const void *key, unsigned int keylen);
+static inline int crypto_sig_set_pubkey(struct crypto_sig *tfm,
+					const void *key, unsigned int keylen)
+{
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->set_pub_key(tfm, key, keylen);
+}
 
 /**
  * crypto_sig_set_privkey() - Invoke set private key operation
@@ -196,6 +216,11 @@ int crypto_sig_set_pubkey(struct crypto_sig *tfm,
  *
  * Return: zero on success; error code in case of error
  */
-int crypto_sig_set_privkey(struct crypto_sig *tfm,
-			   const void *key, unsigned int keylen);
+static inline int crypto_sig_set_privkey(struct crypto_sig *tfm,
+					 const void *key, unsigned int keylen)
+{
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->set_priv_key(tfm, key, keylen);
+}
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 13/19] ASN.1: Clean up include statements in public headers
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (11 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 12/19] crypto: sig - Move crypto_sig_*() API calls to include file Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 14/19] crypto: ecdsa - Avoid signed integer overflow on signature decoding Lukas Wunner
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

If <linux/asn1_decoder.h> is the first header included from a .c file
(due to headers being sorted alphabetically), the compiler complains:

  include/linux/asn1_decoder.h:18:29: error: unknown type name 'size_t'

Avoid by including <linux/types.h>.

Jonathan notes that the counterpart <linux/asn1_encoder.h> already
includes <linux/types.h>, but additionally includes the unnecessary
<linux/bug.h>.  Drop it.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
Changes v1 -> v2:
  * Drop "#include <linux/bug.h>" from <linux/asn1_encoder.h> (Jonathan)

 include/linux/asn1_decoder.h | 1 +
 include/linux/asn1_encoder.h | 1 -
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/asn1_decoder.h b/include/linux/asn1_decoder.h
index 83f9c6e1e5e9..b41bce82a191 100644
--- a/include/linux/asn1_decoder.h
+++ b/include/linux/asn1_decoder.h
@@ -9,6 +9,7 @@
 #define _LINUX_ASN1_DECODER_H
 
 #include <linux/asn1.h>
+#include <linux/types.h>
 
 struct asn1_decoder;
 
diff --git a/include/linux/asn1_encoder.h b/include/linux/asn1_encoder.h
index 08cd0c2ad34f..d17484dffb74 100644
--- a/include/linux/asn1_encoder.h
+++ b/include/linux/asn1_encoder.h
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 #include <linux/asn1.h>
 #include <linux/asn1_ber_bytecode.h>
-#include <linux/bug.h>
 
 #define asn1_oid_len(oid) (sizeof(oid)/sizeof(u32))
 unsigned char *
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 14/19] crypto: ecdsa - Avoid signed integer overflow on signature decoding
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (12 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 13/19] ASN.1: Clean up include statements in public headers Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 15/19] crypto: ecdsa - Move X9.62 signature decoding into template Lukas Wunner
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

When extracting a signature component r or s from an ASN.1-encoded
integer, ecdsa_get_signature_rs() subtracts the expected length
"bufsize" from the ASN.1 length "vlen" (both of unsigned type size_t)
and stores the result in "diff" (of signed type ssize_t).

This results in a signed integer overflow if vlen > SSIZE_MAX + bufsize.

The kernel is compiled with -fno-strict-overflow, which implies -fwrapv,
meaning signed integer overflow is not undefined behavior.  And the
function does check for overflow:

       if (-diff >= bufsize)
               return -EINVAL;

So the code is fine in principle but not very obvious.  In the future it
might trigger a false-positive with CONFIG_UBSAN_SIGNED_WRAP=y.

Avoid by comparing the two unsigned variables directly and erroring out
if "vlen" is too large.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
Changes v1 -> v2:
  * Add code comment explaining why vlen may be larger than bufsize (Stefan)

 crypto/ecdsa.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index 3b9873f56b0a..4a0ca93c99ea 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -35,29 +35,24 @@ static int ecdsa_get_signature_rs(u64 *dest, size_t hdrlen, unsigned char tag,
 				  const void *value, size_t vlen, unsigned int ndigits)
 {
 	size_t bufsize = ndigits * sizeof(u64);
-	ssize_t diff = vlen - bufsize;
 	const char *d = value;
 
-	if (!value || !vlen)
+	if (!value || !vlen || vlen > bufsize + 1)
 		return -EINVAL;
 
-	/* diff = 0: 'value' has exacly the right size
-	 * diff > 0: 'value' has too many bytes; one leading zero is allowed that
-	 *           makes the value a positive integer; error on more
-	 * diff < 0: 'value' is missing leading zeros
+	/*
+	 * vlen may be 1 byte larger than bufsize due to a leading zero byte
+	 * (necessary if the most significant bit of the integer is set).
 	 */
-	if (diff > 0) {
+	if (vlen > bufsize) {
 		/* skip over leading zeros that make 'value' a positive int */
 		if (*d == 0) {
 			vlen -= 1;
-			diff--;
 			d++;
-		}
-		if (diff)
+		} else {
 			return -EINVAL;
+		}
 	}
-	if (-diff >= bufsize)
-		return -EINVAL;
 
 	ecc_digits_from_bytes(d, vlen, dest, ndigits);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 15/19] crypto: ecdsa - Move X9.62 signature decoding into template
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (13 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 14/19] crypto: ecdsa - Avoid signed integer overflow on signature decoding Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 20:46   ` Stefan Berger
  2024-09-10 14:30 ` [PATCH v2 16/19] crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize() Lukas Wunner
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

Unlike the rsa driver, which separates signature decoding and
signature verification into two steps, the ecdsa driver does both in one.

This restricts users to the one signature format currently supported
(X9.62) and prevents addition of others such as P1363, which is needed
by the forthcoming SPDM library (Security Protocol and Data Model) for
PCI device authentication.

Per Herbert's suggestion, change ecdsa to use a "raw" signature encoding
and then implement X9.62 and P1363 as templates which convert their
respective encodings to the raw one.  One may then specify
"x962(ecdsa-nist-XXX)" or "p1363(ecdsa-nist-XXX)" to pick the encoding.

The present commit moves X9.62 decoding to a template.  A separate
commit is going to introduce another template for P1363 decoding.

The ecdsa driver internally represents a signature as two u64 arrays of
size ECC_MAX_BYTES.  This appears to be the most natural choice for the
raw format as it can directly be used for verification without having to
further decode signature data or copy it around.

Repurpose all the existing test vectors for "x962(ecdsa-nist-XXX)" and
create a duplicate of them to test the raw encoding.

Link: https://lore.kernel.org/all/ZoHXyGwRzVvYkcTP@gondor.apana.org.au/
Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
Changes v1 -> v2:
  * Drop unnecessary "params", "param_len" and "algo" definitions from
    ecdsa_nist_p{192,256,384,521}_tv_template[].
  * Introduce and use struct ecdsa_raw_sig in <crypto/internal/ecc.h>.

 crypto/Makefile                     |   3 +-
 crypto/asymmetric_keys/public_key.c |   3 +
 crypto/ecdsa-x962.c                 | 201 ++++++++
 crypto/ecdsa.c                      |  79 +---
 crypto/testmgr.c                    |  27 ++
 crypto/testmgr.h                    | 699 +++++++++++++++++++++++++++-
 include/crypto/internal/ecc.h       |  13 +
 7 files changed, 955 insertions(+), 70 deletions(-)
 create mode 100644 crypto/ecdsa-x962.c

diff --git a/crypto/Makefile b/crypto/Makefile
index 7de29bf843e9..af43a1bd1cfa 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -52,8 +52,9 @@ rsa_generic-y += rsassa-pkcs1.o
 obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
 
 $(obj)/ecdsasignature.asn1.o: $(obj)/ecdsasignature.asn1.c $(obj)/ecdsasignature.asn1.h
-$(obj)/ecdsa.o: $(obj)/ecdsasignature.asn1.h
+$(obj)/ecdsa-x962.o: $(obj)/ecdsasignature.asn1.h
 ecdsa_generic-y += ecdsa.o
+ecdsa_generic-y += ecdsa-x962.o
 ecdsa_generic-y += ecdsasignature.asn1.o
 obj-$(CONFIG_CRYPTO_ECDSA) += ecdsa_generic.o
 
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 3fb27ecd65f6..cc6d48cafa2b 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -130,6 +130,9 @@ software_key_determine_akcipher(const struct public_key *pkey,
 		    strcmp(hash_algo, "sha3-384") != 0 &&
 		    strcmp(hash_algo, "sha3-512") != 0)
 			return -EINVAL;
+		n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
+			     encoding, pkey->pkey_algo);
+		return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
 	} else if (strcmp(pkey->pkey_algo, "ecrdsa") == 0) {
 		if (strcmp(encoding, "raw") != 0)
 			return -EINVAL;
diff --git a/crypto/ecdsa-x962.c b/crypto/ecdsa-x962.c
new file mode 100644
index 000000000000..022e654c075d
--- /dev/null
+++ b/crypto/ecdsa-x962.c
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ECDSA X9.62 signature encoding
+ *
+ * Copyright (c) 2021 IBM Corporation
+ * Copyright (c) 2024 Intel Corporation
+ */
+
+#include <linux/asn1_decoder.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <crypto/algapi.h>
+#include <crypto/sig.h>
+#include <crypto/internal/ecc.h>
+#include <crypto/internal/sig.h>
+
+#include "ecdsasignature.asn1.h"
+
+struct ecdsa_x962_ctx {
+	struct crypto_sig *child;
+};
+
+struct ecdsa_x962_signature_ctx {
+	struct ecdsa_raw_sig sig;
+	unsigned int ndigits;
+};
+
+/* Get the r and s components of a signature from the X.509 certificate. */
+static int ecdsa_get_signature_rs(u64 *dest, size_t hdrlen, unsigned char tag,
+				  const void *value, size_t vlen,
+				  unsigned int ndigits)
+{
+	size_t bufsize = ndigits * sizeof(u64);
+	const char *d = value;
+
+	if (!value || !vlen || vlen > bufsize + 1)
+		return -EINVAL;
+
+	/*
+	 * vlen may be 1 byte larger than bufsize due to a leading zero byte
+	 * (necessary if the most significant bit of the integer is set).
+	 */
+	if (vlen > bufsize) {
+		/* skip over leading zeros that make 'value' a positive int */
+		if (*d == 0) {
+			vlen -= 1;
+			d++;
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	ecc_digits_from_bytes(d, vlen, dest, ndigits);
+
+	return 0;
+}
+
+int ecdsa_get_signature_r(void *context, size_t hdrlen, unsigned char tag,
+			  const void *value, size_t vlen)
+{
+	struct ecdsa_x962_signature_ctx *sig_ctx = context;
+
+	return ecdsa_get_signature_rs(sig_ctx->sig.r, hdrlen, tag, value, vlen,
+				      sig_ctx->ndigits);
+}
+
+int ecdsa_get_signature_s(void *context, size_t hdrlen, unsigned char tag,
+			  const void *value, size_t vlen)
+{
+	struct ecdsa_x962_signature_ctx *sig_ctx = context;
+
+	return ecdsa_get_signature_rs(sig_ctx->sig.s, hdrlen, tag, value, vlen,
+				      sig_ctx->ndigits);
+}
+
+static int ecdsa_x962_verify(struct crypto_sig *tfm,
+			     const void *src, unsigned int slen,
+			     const void *digest, unsigned int dlen)
+{
+	struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+	struct ecdsa_x962_signature_ctx sig_ctx;
+	int err;
+
+	sig_ctx.ndigits = DIV_ROUND_UP(crypto_sig_maxsize(ctx->child),
+				       sizeof(u64));
+
+	err = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx, src, slen);
+	if (err < 0)
+		return err;
+
+	return crypto_sig_verify(ctx->child, &sig_ctx.sig, sizeof(sig_ctx.sig),
+				 digest, dlen);
+}
+
+static unsigned int ecdsa_x962_max_size(struct crypto_sig *tfm)
+{
+	struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return crypto_sig_maxsize(ctx->child);
+}
+
+static int ecdsa_x962_set_pub_key(struct crypto_sig *tfm,
+				  const void *key, unsigned int keylen)
+{
+	struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return crypto_sig_set_pubkey(ctx->child, key, keylen);
+}
+
+static int ecdsa_x962_init_tfm(struct crypto_sig *tfm)
+{
+	struct sig_instance *inst = sig_alg_instance(tfm);
+	struct crypto_sig_spawn *spawn = sig_instance_ctx(inst);
+	struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+	struct crypto_sig *child_tfm;
+
+	child_tfm = crypto_spawn_sig(spawn);
+	if (IS_ERR(child_tfm))
+		return PTR_ERR(child_tfm);
+
+	ctx->child = child_tfm;
+
+	return 0;
+}
+
+static void ecdsa_x962_exit_tfm(struct crypto_sig *tfm)
+{
+	struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+
+	crypto_free_sig(ctx->child);
+}
+
+static void ecdsa_x962_free(struct sig_instance *inst)
+{
+	struct crypto_sig_spawn *spawn = sig_instance_ctx(inst);
+
+	crypto_drop_sig(spawn);
+	kfree(inst);
+}
+
+static int ecdsa_x962_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	struct crypto_sig_spawn *spawn;
+	struct sig_instance *inst;
+	struct sig_alg *ecdsa_alg;
+	u32 mask;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SIG, &mask);
+	if (err)
+		return err;
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	spawn = sig_instance_ctx(inst);
+
+	err = crypto_grab_sig(spawn, sig_crypto_instance(inst),
+			      crypto_attr_alg_name(tb[1]), 0, mask);
+	if (err)
+		goto err_free_inst;
+
+	ecdsa_alg = crypto_spawn_sig_alg(spawn);
+
+	err = -EINVAL;
+	if (strncmp(ecdsa_alg->base.cra_name, "ecdsa", 5) != 0)
+		goto err_free_inst;
+
+	err = crypto_inst_setname(sig_crypto_instance(inst), tmpl->name,
+				  &ecdsa_alg->base);
+	if (err)
+		goto err_free_inst;
+
+	inst->alg.base.cra_priority = ecdsa_alg->base.cra_priority;
+	inst->alg.base.cra_ctxsize = sizeof(struct ecdsa_x962_ctx);
+
+	inst->alg.init = ecdsa_x962_init_tfm;
+	inst->alg.exit = ecdsa_x962_exit_tfm;
+
+	inst->alg.verify = ecdsa_x962_verify;
+	inst->alg.max_size = ecdsa_x962_max_size;
+	inst->alg.set_pub_key = ecdsa_x962_set_pub_key;
+
+	inst->free = ecdsa_x962_free;
+
+	err = sig_register_instance(tmpl, inst);
+	if (err) {
+err_free_inst:
+		ecdsa_x962_free(inst);
+	}
+	return err;
+}
+
+struct crypto_template ecdsa_x962_tmpl = {
+	.name = "x962",
+	.create = ecdsa_x962_create,
+	.module = THIS_MODULE,
+};
+
+MODULE_ALIAS_CRYPTO("x962");
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index 4a0ca93c99ea..1f7c29468a86 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -8,9 +8,6 @@
 #include <crypto/internal/sig.h>
 #include <crypto/ecdh.h>
 #include <crypto/sig.h>
-#include <linux/asn1_decoder.h>
-
-#include "ecdsasignature.asn1.h"
 
 struct ecc_ctx {
 	unsigned int curve_id;
@@ -22,61 +19,6 @@ struct ecc_ctx {
 	struct ecc_point pub_key;
 };
 
-struct ecdsa_signature_ctx {
-	const struct ecc_curve *curve;
-	u64 r[ECC_MAX_DIGITS];
-	u64 s[ECC_MAX_DIGITS];
-};
-
-/*
- * Get the r and s components of a signature from the X509 certificate.
- */
-static int ecdsa_get_signature_rs(u64 *dest, size_t hdrlen, unsigned char tag,
-				  const void *value, size_t vlen, unsigned int ndigits)
-{
-	size_t bufsize = ndigits * sizeof(u64);
-	const char *d = value;
-
-	if (!value || !vlen || vlen > bufsize + 1)
-		return -EINVAL;
-
-	/*
-	 * vlen may be 1 byte larger than bufsize due to a leading zero byte
-	 * (necessary if the most significant bit of the integer is set).
-	 */
-	if (vlen > bufsize) {
-		/* skip over leading zeros that make 'value' a positive int */
-		if (*d == 0) {
-			vlen -= 1;
-			d++;
-		} else {
-			return -EINVAL;
-		}
-	}
-
-	ecc_digits_from_bytes(d, vlen, dest, ndigits);
-
-	return 0;
-}
-
-int ecdsa_get_signature_r(void *context, size_t hdrlen, unsigned char tag,
-			  const void *value, size_t vlen)
-{
-	struct ecdsa_signature_ctx *sig = context;
-
-	return ecdsa_get_signature_rs(sig->r, hdrlen, tag, value, vlen,
-				      sig->curve->g.ndigits);
-}
-
-int ecdsa_get_signature_s(void *context, size_t hdrlen, unsigned char tag,
-			  const void *value, size_t vlen)
-{
-	struct ecdsa_signature_ctx *sig = context;
-
-	return ecdsa_get_signature_rs(sig->s, hdrlen, tag, value, vlen,
-				      sig->curve->g.ndigits);
-}
-
 static int _ecdsa_verify(struct ecc_ctx *ctx, const u64 *hash, const u64 *r, const u64 *s)
 {
 	const struct ecc_curve *curve = ctx->curve;
@@ -126,25 +68,21 @@ static int ecdsa_verify(struct crypto_sig *tfm,
 {
 	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 	size_t bufsize = ctx->curve->g.ndigits * sizeof(u64);
-	struct ecdsa_signature_ctx sig_ctx = {
-		.curve = ctx->curve,
-	};
+	const struct ecdsa_raw_sig *sig = src;
 	u64 hash[ECC_MAX_DIGITS];
-	int ret;
 
 	if (unlikely(!ctx->pub_key_set))
 		return -EINVAL;
 
-	ret = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx, src, slen);
-	if (ret < 0)
-		return ret;
+	if (slen != sizeof(*sig))
+		return -EINVAL;
 
 	if (bufsize > dlen)
 		bufsize = dlen;
 
 	ecc_digits_from_bytes(digest, bufsize, hash, ctx->curve->g.ndigits);
 
-	return _ecdsa_verify(ctx, hash, sig_ctx.r, sig_ctx.s);
+	return _ecdsa_verify(ctx, hash, sig->r, sig->s);
 }
 
 static int ecdsa_ecc_ctx_init(struct ecc_ctx *ctx, unsigned int curve_id)
@@ -340,8 +278,15 @@ static int __init ecdsa_init(void)
 	if (ret)
 		goto nist_p521_error;
 
+	ret = crypto_register_template(&ecdsa_x962_tmpl);
+	if (ret)
+		goto x962_tmpl_error;
+
 	return 0;
 
+x962_tmpl_error:
+	crypto_unregister_sig(&ecdsa_nist_p521);
+
 nist_p521_error:
 	crypto_unregister_sig(&ecdsa_nist_p384);
 
@@ -356,6 +301,8 @@ static int __init ecdsa_init(void)
 
 static void __exit ecdsa_exit(void)
 {
+	crypto_unregister_template(&ecdsa_x962_tmpl);
+
 	if (ecdsa_nist_p192_registered)
 		crypto_unregister_sig(&ecdsa_nist_p192);
 	crypto_unregister_sig(&ecdsa_nist_p256);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index fdebdafdf027..19c1d01a064f 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5729,6 +5729,33 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.suite = {
 			.hash = __VECS(wp512_tv_template)
 		}
+	}, {
+		.alg = "x962(ecdsa-nist-p192)",
+		.test = alg_test_sig,
+		.suite = {
+			.sig = __VECS(x962_ecdsa_nist_p192_tv_template)
+		}
+	}, {
+		.alg = "x962(ecdsa-nist-p256)",
+		.test = alg_test_sig,
+		.fips_allowed = 1,
+		.suite = {
+			.sig = __VECS(x962_ecdsa_nist_p256_tv_template)
+		}
+	}, {
+		.alg = "x962(ecdsa-nist-p384)",
+		.test = alg_test_sig,
+		.fips_allowed = 1,
+		.suite = {
+			.sig = __VECS(x962_ecdsa_nist_p384_tv_template)
+		}
+	}, {
+		.alg = "x962(ecdsa-nist-p521)",
+		.test = alg_test_sig,
+		.fips_allowed = 1,
+		.suite = {
+			.sig = __VECS(x962_ecdsa_nist_p521_tv_template)
+		}
 	}, {
 		.alg = "xcbc(aes)",
 		.test = alg_test_hash,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index e10b6d7f2cd9..2bd77eaafdf6 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -21,6 +21,7 @@
 #define _CRYPTO_TESTMGR_H
 
 #include <linux/oid_registry.h>
+#include <crypto/internal/ecc.h>
 
 #define MAX_IVLEN		32
 
@@ -656,10 +657,702 @@ static const struct akcipher_testvec rsa_tv_template[] = {
 	}
 };
 
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define be64_to_cpua(b1, b2, b3, b4, b5, b6, b7, b8)			\
+	0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8
+#else
+#define be64_to_cpua(b1, b2, b3, b4, b5, b6, b7, b8)			\
+	0x##b8, 0x##b7, 0x##b6, 0x##b5, 0x##b4, 0x##b3, 0x##b2, 0x##b1
+#endif
+
 /*
  * ECDSA test vectors.
  */
 static const struct sig_testvec ecdsa_nist_p192_tv_template[] = {
+	{
+	.key = /* secp192r1(sha1) */
+	"\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1"
+	"\xd4\x09\x73\xcf\xea\xd0\x15\x07\x3d\xa5\x8a\x8a\x95\x43\xe4\x68"
+	"\xea\xc6\x25\xc1\xc1\x01\x25\x4c\x7e\xc3\x3c\xa6\x04\x0a\xe7\x08"
+	"\x98",
+	.key_len = 49,
+	.m =
+	"\xcd\xb9\xd2\x1c\xb7\x6f\xcd\x44\xb3\xfd\x63\xea\xa3\x66\x7f\xae"
+	"\x63\x85\xe7\x82",
+	.m_size = 20,
+	.c = (const unsigned char[]){
+	be64_to_cpua(ad, 59, ad, 88, 27, d6, 92, 6b),
+	be64_to_cpua(a0, 27, 91, c6, f6, 7f, c3, 09),
+	be64_to_cpua(ba, e5, 93, 83, 6e, b6, 3b, 63),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(86, 80, 6f, a5, 79, 77, da, d0),
+	be64_to_cpua(ef, 95, 52, 7b, a0, 0f, e4, 18),
+	be64_to_cpua(10, 68, 01, 9d, ba, ce, 83, 08),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp192r1(sha224) */
+	"\x04\xb6\x4b\xb1\xd1\xac\xba\x24\x8f\x65\xb2\x60\x00\x90\xbf\xbd"
+	"\x78\x05\x73\xe9\x79\x1d\x6f\x7c\x0b\xd2\xc3\x93\xa7\x28\xe1\x75"
+	"\xf7\xd5\x95\x1d\x28\x10\xc0\x75\x50\x5c\x1a\x4f\x3f\x8f\xa5\xee"
+	"\xa3",
+	.key_len = 49,
+	.m =
+	"\x8d\xd6\xb8\x3e\xe5\xff\x23\xf6\x25\xa2\x43\x42\x74\x45\xa7\x40"
+	"\x3a\xff\x2f\xe1\xd3\xf6\x9f\xe8\x33\xcb\x12\x11",
+	.m_size = 28,
+	.c = (const unsigned char[]){
+	be64_to_cpua(83, 7b, 12, e6, b6, 5b, cb, d4),
+	be64_to_cpua(14, f8, 11, 2b, 55, dc, ae, 37),
+	be64_to_cpua(5a, 8b, 82, 69, 7e, 8a, 0a, 09),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(a3, e3, 5c, 99, db, 92, 5b, 36),
+	be64_to_cpua(eb, c3, 92, 0f, 1e, 72, ee, c4),
+	be64_to_cpua(6a, 14, 4f, 53, 75, c8, 02, 48),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp192r1(sha256) */
+	"\x04\xe2\x51\x24\x9b\xf7\xb6\x32\x82\x39\x66\x3d\x5b\xec\x3b\xae"
+	"\x0c\xd5\xf2\x67\xd1\xc7\xe1\x02\xe4\xbf\x90\x62\xb8\x55\x75\x56"
+	"\x69\x20\x5e\xcb\x4e\xca\x33\xd6\xcb\x62\x6b\x94\xa9\xa2\xe9\x58"
+	"\x91",
+	.key_len = 49,
+	.m =
+	"\x35\xec\xa1\xa0\x9e\x14\xde\x33\x03\xb6\xf6\xbd\x0c\x2f\xb2\xfd"
+	"\x1f\x27\x82\xa5\xd7\x70\x3f\xef\xa0\x82\x69\x8e\x73\x31\x8e\xd7",
+	.m_size = 32,
+	.c = (const unsigned char[]){
+	be64_to_cpua(01, 48, fb, 5f, 72, 2a, d4, 8f),
+	be64_to_cpua(6b, 1a, 58, 56, f1, 8f, f7, fd),
+	be64_to_cpua(3f, 72, 3f, 1f, 42, d2, 3f, 1d),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(7d, 3a, 97, d9, cd, 1a, 6a, 49),
+	be64_to_cpua(32, dd, 41, 74, 6a, 51, c7, d9),
+	be64_to_cpua(b3, 69, 43, fd, 48, 19, 86, cf),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp192r1(sha384) */
+	"\x04\x5a\x13\xfe\x68\x86\x4d\xf4\x17\xc7\xa4\xe5\x8c\x65\x57\xb7"
+	"\x03\x73\x26\x57\xfb\xe5\x58\x40\xd8\xfd\x49\x05\xab\xf1\x66\x1f"
+	"\xe2\x9d\x93\x9e\xc2\x22\x5a\x8b\x4f\xf3\x77\x22\x59\x7e\xa6\x4e"
+	"\x8b",
+	.key_len = 49,
+	.m =
+	"\x9d\x2e\x1a\x8f\xed\x6c\x4b\x61\xae\xac\xd5\x19\x79\xce\x67\xf9"
+	"\xa0\x34\xeb\xb0\x81\xf9\xd9\xdc\x6e\xb3\x5c\xa8\x69\xfc\x8a\x61"
+	"\x39\x81\xfb\xfd\x5c\x30\x6b\xa8\xee\xed\x89\xaf\xa3\x05\xe4\x78",
+	.m_size = 48,
+	.c = (const unsigned char[]){
+	be64_to_cpua(dd, 15, bb, d6, 8c, a7, 03, 78),
+	be64_to_cpua(cf, 7f, 34, b4, b4, e5, c5, 00),
+	be64_to_cpua(f0, a3, 38, ce, 2b, f8, 9d, 1a),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(93, 12, 3b, 3b, 28, fb, 6d, e1),
+	be64_to_cpua(d1, 01, 77, 44, 5d, 53, a4, 7c),
+	be64_to_cpua(64, bc, 5a, 1f, 82, 96, 61, d7),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp192r1(sha512) */
+	"\x04\xd5\xf2\x6e\xc3\x94\x5c\x52\xbc\xdf\x86\x6c\x14\xd1\xca\xea"
+	"\xcc\x72\x3a\x8a\xf6\x7a\x3a\x56\x36\x3b\xca\xc6\x94\x0e\x17\x1d"
+	"\x9e\xa0\x58\x28\xf9\x4b\xe6\xd1\xa5\x44\x91\x35\x0d\xe7\xf5\x11"
+	"\x57",
+	.key_len = 49,
+	.m =
+	"\xd5\x4b\xe9\x36\xda\xd8\x6e\xc0\x50\x03\xbe\x00\x43\xff\xf0\x23"
+	"\xac\xa2\x42\xe7\x37\x77\x79\x52\x8f\x3e\xc0\x16\xc1\xfc\x8c\x67"
+	"\x16\xbc\x8a\x5d\x3b\xd3\x13\xbb\xb6\xc0\x26\x1b\xeb\x33\xcc\x70"
+	"\x4a\xf2\x11\x37\xe8\x1b\xba\x55\xac\x69\xe1\x74\x62\x7c\x6e\xb5",
+	.m_size = 64,
+	.c = (const unsigned char[]){
+	be64_to_cpua(2b, 11, 2d, 1c, b6, 06, c9, 6c),
+	be64_to_cpua(dd, 3f, 07, 87, 12, a0, d4, ac),
+	be64_to_cpua(88, 5b, 8f, 59, 43, bf, cf, c6),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(28, 6a, df, 97, fd, 82, 76, 24),
+	be64_to_cpua(a9, 14, 2a, 5e, f5, e5, fb, 72),
+	be64_to_cpua(73, b4, 22, 9a, 98, 73, 3c, 83),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	},
+};
+
+static const struct sig_testvec ecdsa_nist_p256_tv_template[] = {
+	{
+	.key = /* secp256r1(sha1) */
+	"\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41"
+	"\x22\xd6\x9a\xaa\x87\x17\xec\x4f\x63\x55\x2f\x94\xba\xdd\x83\xe9"
+	"\x34\x4b\xf3\xe9\x91\x13\x50\xb6\xcb\xca\x62\x08\xe7\x3b\x09\xdc"
+	"\xc3\x63\x4b\x2d\xb9\x73\x53\xe4\x45\xe6\x7c\xad\xe7\x6b\xb0\xe8"
+	"\xaf",
+	.key_len = 65,
+	.m =
+	"\xc2\x2b\x5f\x91\x78\x34\x26\x09\x42\x8d\x6f\x51\xb2\xc5\xaf\x4c"
+	"\x0b\xde\x6a\x42",
+	.m_size = 20,
+	.c = (const unsigned char[]){
+	be64_to_cpua(ee, ca, 6a, 52, 0e, 48, 4d, cc),
+	be64_to_cpua(f7, d4, ad, 8d, 94, 5a, 69, 89),
+	be64_to_cpua(cf, d4, e7, b7, f0, 82, 56, 41),
+	be64_to_cpua(f9, 25, ce, 9f, 3a, a6, 35, 81),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(fb, 9d, 8b, de, d4, 8d, 6f, ad),
+	be64_to_cpua(f1, 03, 03, f3, 3b, e2, 73, f7),
+	be64_to_cpua(8a, fa, 54, 93, 29, a7, 70, 86),
+	be64_to_cpua(d7, e4, ef, 52, 66, d3, 5b, 9d),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp256r1(sha224) */
+	"\x04\x8b\x6d\xc0\x33\x8e\x2d\x8b\x67\xf5\xeb\xc4\x7f\xa0\xf5\xd9"
+	"\x7b\x03\xa5\x78\x9a\xb5\xea\x14\xe4\x23\xd0\xaf\xd7\x0e\x2e\xa0"
+	"\xc9\x8b\xdb\x95\xf8\xb3\xaf\xac\x00\x2c\x2c\x1f\x7a\xfd\x95\x88"
+	"\x43\x13\xbf\xf3\x1c\x05\x1a\x14\x18\x09\x3f\xd6\x28\x3e\xc5\xa0"
+	"\xd4",
+	.key_len = 65,
+	.m =
+	"\x1a\x15\xbc\xa3\xe4\xed\x3a\xb8\x23\x67\xc6\xc4\x34\xf8\x6c\x41"
+	"\x04\x0b\xda\xc5\x77\xfa\x1c\x2d\xe6\x2c\x3b\xe0",
+	.m_size = 28,
+	.c = (const unsigned char[]){
+	be64_to_cpua(7d, 25, d8, 25, f5, 81, d2, 1e),
+	be64_to_cpua(34, 62, 79, cb, 6a, 91, 67, 2e),
+	be64_to_cpua(ae, ce, 77, 59, 1a, db, 59, d5),
+	be64_to_cpua(20, 43, fa, c0, 9f, 9d, 7b, e7),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(ce, d5, 2e, 8b, de, 5a, 04, 0e),
+	be64_to_cpua(bf, 50, 05, 58, 39, 0e, 26, 92),
+	be64_to_cpua(76, 20, 4a, 77, 22, ec, c8, 66),
+	be64_to_cpua(5f, f8, 74, f8, 57, d0, 5e, 54),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp256r1(sha256) */
+	"\x04\xf1\xea\xc4\x53\xf3\xb9\x0e\x9f\x7e\xad\xe3\xea\xd7\x0e\x0f"
+	"\xd6\x98\x9a\xca\x92\x4d\x0a\x80\xdb\x2d\x45\xc7\xec\x4b\x97\x00"
+	"\x2f\xe9\x42\x6c\x29\xdc\x55\x0e\x0b\x53\x12\x9b\x2b\xad\x2c\xe9"
+	"\x80\xe6\xc5\x43\xc2\x1d\x5e\xbb\x65\x21\x50\xb6\x37\xb0\x03\x8e"
+	"\xb8",
+	.key_len = 65,
+	.m =
+	"\x8f\x43\x43\x46\x64\x8f\x6b\x96\xdf\x89\xdd\xa9\x01\xc5\x17\x6b"
+	"\x10\xa6\xd8\x39\x61\xdd\x3c\x1a\xc8\x8b\x59\xb2\xdc\x32\x7a\xa4",
+	.m_size = 32,
+	.c = (const unsigned char[]){
+	be64_to_cpua(91, dc, 02, 67, dc, 0c, d0, 82),
+	be64_to_cpua(ac, 44, c3, e8, 24, 11, 2d, a4),
+	be64_to_cpua(09, dc, 29, 63, a8, 1a, ad, fc),
+	be64_to_cpua(08, 31, fa, 74, 0d, 1d, 21, 5d),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(4f, 2a, 65, 35, 23, e3, 1d, fa),
+	be64_to_cpua(0a, 6e, 1b, c4, af, e1, 83, c3),
+	be64_to_cpua(f9, a9, 81, ac, 4a, 50, d0, 91),
+	be64_to_cpua(bd, ff, ce, ee, 42, c3, 97, ff),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp256r1(sha384) */
+	"\x04\xc5\xc6\xea\x60\xc9\xce\xad\x02\x8d\xf5\x3e\x24\xe3\x52\x1d"
+	"\x28\x47\x3b\xc3\x6b\xa4\x99\x35\x99\x11\x88\x88\xc8\xf4\xee\x7e"
+	"\x8c\x33\x8f\x41\x03\x24\x46\x2b\x1a\x82\xf9\x9f\xe1\x97\x1b\x00"
+	"\xda\x3b\x24\x41\xf7\x66\x33\x58\x3d\x3a\x81\xad\xcf\x16\xe9\xe2"
+	"\x7c",
+	.key_len = 65,
+	.m =
+	"\x3e\x78\x70\xfb\xcd\x66\xba\x91\xa1\x79\xff\x1e\x1c\x6b\x78\xe6"
+	"\xc0\x81\x3a\x65\x97\x14\x84\x36\x14\x1a\x9a\xb7\xc5\xab\x84\x94"
+	"\x5e\xbb\x1b\x34\x71\xcb\x41\xe1\xf6\xfc\x92\x7b\x34\xbb\x86\xbb",
+	.m_size = 48,
+	.c = (const unsigned char[]){
+	be64_to_cpua(f2, e4, 6c, c7, 94, b1, d5, fe),
+	be64_to_cpua(08, b2, 6b, 24, 94, 48, 46, 5e),
+	be64_to_cpua(d0, 2e, 95, 54, d1, 95, 64, 93),
+	be64_to_cpua(8e, f3, 6f, dc, f8, 69, a6, 2e),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(c0, 60, 11, 92, dc, 17, 89, 12),
+	be64_to_cpua(69, f4, 3b, 4f, 47, cf, 9b, 16),
+	be64_to_cpua(19, fb, 5f, 92, f4, c9, 23, 37),
+	be64_to_cpua(eb, a7, 80, 26, dc, f9, 3a, 44),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp256r1(sha512) */
+	"\x04\xd7\x27\x46\x49\xf6\x26\x85\x12\x40\x76\x8e\xe2\xe6\x2a\x7a"
+	"\x83\xb1\x4e\x7a\xeb\x3b\x5c\x67\x4a\xb5\xa4\x92\x8c\x69\xff\x38"
+	"\xee\xd9\x4e\x13\x29\x59\xad\xde\x6b\xbb\x45\x31\xee\xfd\xd1\x1b"
+	"\x64\xd3\xb5\xfc\xaf\x9b\x4b\x88\x3b\x0e\xb7\xd6\xdf\xf1\xd5\x92"
+	"\xbf",
+	.key_len = 65,
+	.m =
+	"\x57\xb7\x9e\xe9\x05\x0a\x8c\x1b\xc9\x13\xe5\x4a\x24\xc7\xe2\xe9"
+	"\x43\xc3\xd1\x76\x62\xf4\x98\x1a\x9c\x13\xb0\x20\x1b\xe5\x39\xca"
+	"\x4f\xd9\x85\x34\x95\xa2\x31\xbc\xbb\xde\xdd\x76\xbb\x61\xe3\xcf"
+	"\x9d\xc0\x49\x7a\xf3\x7a\xc4\x7d\xa8\x04\x4b\x8d\xb4\x4d\x5b\xd6",
+	.m_size = 64,
+	.c = (const unsigned char[]){
+	be64_to_cpua(76, f6, 04, 99, 09, 37, 4d, fa),
+	be64_to_cpua(ed, 8c, 73, 30, 6c, 22, b3, 97),
+	be64_to_cpua(40, ea, 44, 81, 00, 4e, 29, 08),
+	be64_to_cpua(b8, 6d, 87, 81, 43, df, fb, 9f),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(76, 31, 79, 4a, e9, 81, 6a, ee),
+	be64_to_cpua(5c, ad, c3, 78, 1c, c2, c1, 19),
+	be64_to_cpua(f8, 00, dd, ab, d4, c0, 2b, e6),
+	be64_to_cpua(1e, b9, 75, 31, f6, 04, a5, 4d),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	},
+};
+
+static const struct sig_testvec ecdsa_nist_p384_tv_template[] = {
+	{
+	.key = /* secp384r1(sha1) */
+	"\x04\x89\x25\xf3\x97\x88\xcb\xb0\x78\xc5\x72\x9a\x14\x6e\x7a\xb1"
+	"\x5a\xa5\x24\xf1\x95\x06\x9e\x28\xfb\xc4\xb9\xbe\x5a\x0d\xd9\x9f"
+	"\xf3\xd1\x4d\x2d\x07\x99\xbd\xda\xa7\x66\xec\xbb\xea\xba\x79\x42"
+	"\xc9\x34\x89\x6a\xe7\x0b\xc3\xf2\xfe\x32\x30\xbe\xba\xf9\xdf\x7e"
+	"\x4b\x6a\x07\x8e\x26\x66\x3f\x1d\xec\xa2\x57\x91\x51\xdd\x17\x0e"
+	"\x0b\x25\xd6\x80\x5c\x3b\xe6\x1a\x98\x48\x91\x45\x7a\x73\xb0\xc3"
+	"\xf1",
+	.key_len = 97,
+	.m =
+	"\x12\x55\x28\xf0\x77\xd5\xb6\x21\x71\x32\x48\xcd\x28\xa8\x25\x22"
+	"\x3a\x69\xc1\x93",
+	.m_size = 20,
+	.c = (const unsigned char[]){
+	be64_to_cpua(ec, 7c, 7e, d0, 87, d7, d7, 6e),
+	be64_to_cpua(78, f1, 4c, 26, e6, 5b, 86, cf),
+	be64_to_cpua(3a, c6, f1, 32, 3c, ce, 70, 2b),
+	be64_to_cpua(8d, 26, 8e, ae, 63, 3f, bc, 20),
+	be64_to_cpua(57, 55, 07, 20, 43, 30, de, a0),
+	be64_to_cpua(f5, 0f, 24, 4c, 07, 93, 6f, 21),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(79, 12, 2a, b7, c5, 15, 92, c5),
+	be64_to_cpua(4a, a1, 59, f1, 1c, a4, 58, 26),
+	be64_to_cpua(74, a0, 0f, bf, af, c3, 36, 76),
+	be64_to_cpua(df, 28, 8c, 1b, fa, f9, 95, 88),
+	be64_to_cpua(5f, 63, b1, be, 5e, 4c, 0e, a1),
+	be64_to_cpua(cd, bb, 7e, 81, 5d, 8f, 63, c0),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp384r1(sha224) */
+	"\x04\x69\x6c\xcf\x62\xee\xd0\x0d\xe5\xb5\x2f\x70\x54\xcf\x26\xa0"
+	"\xd9\x98\x8d\x92\x2a\xab\x9b\x11\xcb\x48\x18\xa1\xa9\x0d\xd5\x18"
+	"\x3e\xe8\x29\x6e\xf6\xe4\xb5\x8e\xc7\x4a\xc2\x5f\x37\x13\x99\x05"
+	"\xb6\xa4\x9d\xf9\xfb\x79\x41\xe7\xd7\x96\x9f\x73\x3b\x39\x43\xdc"
+	"\xda\xf4\x06\xb9\xa5\x29\x01\x9d\x3b\xe1\xd8\x68\x77\x2a\xf4\x50"
+	"\x6b\x93\x99\x6c\x66\x4c\x42\x3f\x65\x60\x6c\x1c\x0b\x93\x9b\x9d"
+	"\xe0",
+	.key_len = 97,
+	.m =
+	"\x12\x80\xb6\xeb\x25\xe2\x3d\xf0\x21\x32\x96\x17\x3a\x38\x39\xfd"
+	"\x1f\x05\x34\x7b\xb8\xf9\x71\x66\x03\x4f\xd5\xe5",
+	.m_size = 28,
+	.c = (const unsigned char[]){
+	be64_to_cpua(3f, dd, 15, 1b, 68, 2b, 9d, 8b),
+	be64_to_cpua(c9, 9c, 11, b8, 10, 01, c5, 41),
+	be64_to_cpua(c5, da, b4, e3, 93, 07, e0, 99),
+	be64_to_cpua(97, f1, c8, 72, 26, cf, 5a, 5e),
+	be64_to_cpua(ec, cb, e4, 89, 47, b2, f7, bc),
+	be64_to_cpua(8a, 51, 84, ce, 13, 1e, d2, dc),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(88, 2b, 82, 26, 5e, 1c, da, fb),
+	be64_to_cpua(9f, 19, d0, 42, 8b, 93, c2, 11),
+	be64_to_cpua(4d, d0, c6, 6e, b0, e9, fc, 14),
+	be64_to_cpua(df, d8, 68, a2, 64, 42, 65, f3),
+	be64_to_cpua(4b, 00, 08, 31, 6c, f5, d5, f6),
+	be64_to_cpua(8b, 03, 2c, fc, 1f, d1, a9, a4),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp384r1(sha256) */
+	"\x04\xee\xd6\xda\x3e\x94\x90\x00\x27\xed\xf8\x64\x55\xd6\x51\x9a"
+	"\x1f\x52\x00\x63\x78\xf1\xa9\xfd\x75\x4c\x9e\xb2\x20\x1a\x91\x5a"
+	"\xba\x7a\xa3\xe5\x6c\xb6\x25\x68\x4b\xe8\x13\xa6\x54\x87\x2c\x0e"
+	"\xd0\x83\x95\xbc\xbf\xc5\x28\x4f\x77\x1c\x46\xa6\xf0\xbc\xd4\xa4"
+	"\x8d\xc2\x8f\xb3\x32\x37\x40\xd6\xca\xf8\xae\x07\x34\x52\x39\x52"
+	"\x17\xc3\x34\x29\xd6\x40\xea\x5c\xb9\x3f\xfb\x32\x2e\x12\x33\xbc"
+	"\xab",
+	.key_len = 97,
+	.m =
+	"\xaa\xe7\xfd\x03\x26\xcb\x94\x71\xe4\xce\x0f\xc5\xff\xa6\x29\xa3"
+	"\xe1\xcc\x4c\x35\x4e\xde\xca\x80\xab\x26\x0c\x25\xe6\x68\x11\xc2",
+	.m_size = 32,
+	.c = (const unsigned char[]){
+	be64_to_cpua(c8, 8d, 2c, 79, 3a, 8e, 32, c4),
+	be64_to_cpua(b6, c6, fc, 70, 2e, 66, 3c, 77),
+	be64_to_cpua(af, 06, 3f, 84, 04, e2, f9, 67),
+	be64_to_cpua(cc, 47, 53, 87, bc, bd, 83, 3f),
+	be64_to_cpua(8e, 3f, 7e, ce, 0a, 9b, aa, 59),
+	be64_to_cpua(08, 09, 12, 9d, 6e, 96, 64, a6),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(10, 0e, f4, 1f, 39, ca, 4d, 43),
+	be64_to_cpua(4f, 8d, de, 1e, 93, 8d, 95, bb),
+	be64_to_cpua(15, 68, c0, 75, 3e, 23, 5e, 36),
+	be64_to_cpua(dd, ce, bc, b2, 97, f4, 9c, f3),
+	be64_to_cpua(26, a2, b0, 89, 42, 0a, da, d9),
+	be64_to_cpua(40, 34, b8, 90, a9, 80, ab, 47),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp384r1(sha384) */
+	"\x04\x3a\x2f\x62\xe7\x1a\xcf\x24\xd0\x0b\x7c\xe0\xed\x46\x0a\x4f"
+	"\x74\x16\x43\xe9\x1a\x25\x7c\x55\xff\xf0\x29\x68\x66\x20\x91\xf9"
+	"\xdb\x2b\xf6\xb3\x6c\x54\x01\xca\xc7\x6a\x5c\x0d\xeb\x68\xd9\x3c"
+	"\xf1\x01\x74\x1f\xf9\x6c\xe5\x5b\x60\xe9\x7f\x5d\xb3\x12\x80\x2a"
+	"\xd8\x67\x92\xc9\x0e\x4c\x4c\x6b\xa1\xb2\xa8\x1e\xac\x1c\x97\xd9"
+	"\x21\x67\xe5\x1b\x5a\x52\x31\x68\xd6\xee\xf0\x19\xb0\x55\xed\x89"
+	"\x9e",
+	.key_len = 97,
+	.m =
+	"\x8d\xf2\xc0\xe9\xa8\xf3\x8e\x44\xc4\x8c\x1a\xa0\xb8\xd7\x17\xdf"
+	"\xf2\x37\x1b\xc6\xe3\xf5\x62\xcc\x68\xf5\xd5\x0b\xbf\x73\x2b\xb1"
+	"\xb0\x4c\x04\x00\x31\xab\xfe\xc8\xd6\x09\xc8\xf2\xea\xd3\x28\xff",
+	.m_size = 48,
+	.c = (const unsigned char[]){
+	be64_to_cpua(a2, a4, c8, f2, ea, 9d, 11, 1f),
+	be64_to_cpua(3b, 1f, 07, 8f, 15, 02, fe, 1d),
+	be64_to_cpua(29, e6, fb, ca, 8c, d6, b6, b4),
+	be64_to_cpua(2d, 7a, 91, 5f, 49, 2d, 22, 08),
+	be64_to_cpua(ee, 2e, 62, 35, 46, fa, 00, d8),
+	be64_to_cpua(9b, 28, 68, c0, a1, ea, 8c, 50),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(ab, 8d, 4e, de, e6, 6d, 9b, 66),
+	be64_to_cpua(96, 17, 04, c9, 05, 77, f1, 8e),
+	be64_to_cpua(44, 92, 8c, 86, 99, 65, b3, 97),
+	be64_to_cpua(71, cd, 8f, 18, 99, f0, 0f, 13),
+	be64_to_cpua(bf, e3, 75, 24, 49, ac, fb, c8),
+	be64_to_cpua(fc, 50, f6, 43, bd, 50, 82, 0e),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	}, {
+	.key = /* secp384r1(sha512) */
+	"\x04\xb4\xe7\xc1\xeb\x64\x25\x22\x46\xc3\x86\x61\x80\xbe\x1e\x46"
+	"\xcb\xf6\x05\xc2\xee\x73\x83\xbc\xea\x30\x61\x4d\x40\x05\x41\xf4"
+	"\x8c\xe3\x0e\x5c\xf0\x50\xf2\x07\x19\xe8\x4f\x25\xbe\xee\x0c\x95"
+	"\x54\x36\x86\xec\xc2\x20\x75\xf3\x89\xb5\x11\xa1\xb7\xf5\xaf\xbe"
+	"\x81\xe4\xc3\x39\x06\xbd\xe4\xfe\x68\x1c\x6d\x99\x2b\x1b\x63\xfa"
+	"\xdf\x42\x5c\xc2\x5a\xc7\x0c\xf4\x15\xf7\x1b\xa3\x2e\xd7\x00\xac"
+	"\xa3",
+	.key_len = 97,
+	.m =
+	"\xe8\xb7\x52\x7d\x1a\x44\x20\x05\x53\x6b\x3a\x68\xf2\xe7\x6c\xa1"
+	"\xae\x9d\x84\xbb\xba\x52\x43\x3e\x2c\x42\x78\x49\xbf\x78\xb2\x71"
+	"\xeb\xe1\xe0\xe8\x42\x7b\x11\xad\x2b\x99\x05\x1d\x36\xe6\xac\xfc"
+	"\x55\x73\xf0\x15\x63\x39\xb8\x6a\x6a\xc5\x91\x5b\xca\x6a\xa8\x0e",
+	.m_size = 64,
+	.c = (const unsigned char[]){
+	be64_to_cpua(3e, b3, c7, a8, b3, 17, 77, d1),
+	be64_to_cpua(dc, 2b, 43, 0e, 6a, b3, 53, 6f),
+	be64_to_cpua(4c, fc, 6f, 80, e3, af, b3, d9),
+	be64_to_cpua(9a, 02, de, 93, e8, 83, e4, 84),
+	be64_to_cpua(4d, c6, ef, da, 02, e7, 0f, 52),
+	be64_to_cpua(00, 1d, 20, 94, 77, fe, 31, fa),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(4e, 45, cf, 3c, 93, ff, 50, 5d),
+	be64_to_cpua(34, e4, 8b, 80, a5, b6, da, 2c),
+	be64_to_cpua(c4, 6a, 03, 5f, 8d, 7a, f9, fb),
+	be64_to_cpua(ec, 63, e3, 0c, ec, 50, dc, cc),
+	be64_to_cpua(de, 3a, 3d, 16, af, b4, 52, 6a),
+	be64_to_cpua(63, f6, f0, 3d, 5f, 5f, 99, 3f),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 00) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	},
+};
+
+static const struct sig_testvec ecdsa_nist_p521_tv_template[] = {
+	{
+	.key = /* secp521r1(sha224) */
+	"\x04\x01\x4f\x43\x18\xb6\xa9\xc9\x5d\x68\xd3\xa9\x42\xf8\x98\xc0"
+	"\xd2\xd1\xa9\x50\x3b\xe8\xc4\x40\xe6\x11\x78\x88\x4b\xbd\x76\xa7"
+	"\x9a\xe0\xdd\x31\xa4\x67\x78\x45\x33\x9e\x8c\xd1\xc7\x44\xac\x61"
+	"\x68\xc8\x04\xe7\x5c\x79\xb1\xf1\x41\x0c\x71\xc0\x53\xa8\xbc\xfb"
+	"\xf5\xca\xd4\x01\x40\xfd\xa3\x45\xda\x08\xe0\xb4\xcb\x28\x3b\x0a"
+	"\x02\x35\x5f\x02\x9f\x3f\xcd\xef\x08\x22\x40\x97\x74\x65\xb7\x76"
+	"\x85\xc7\xc0\x5c\xfb\x81\xe1\xa5\xde\x0c\x4e\x8b\x12\x31\xb6\x47"
+	"\xed\x37\x0f\x99\x3f\x26\xba\xa3\x8e\xff\x79\x34\x7c\x3a\xfe\x1f"
+	"\x3b\x83\x82\x2f\x14",
+	.key_len = 133,
+	.m =
+	"\xa2\x3a\x6a\x8c\x7b\x3c\xf2\x51\xf8\xbe\x5f\x4f\x3b\x15\x05\xc4"
+	"\xb5\xbc\x19\xe7\x21\x85\xe9\x23\x06\x33\x62\xfb",
+	.m_size = 28,
+	.c = (const unsigned char[]){
+	be64_to_cpua(46, 6b, c7, af, 7a, b9, 19, 0a),
+	be64_to_cpua(6c, a6, 9b, 89, 8b, 1e, fd, 09),
+	be64_to_cpua(98, 85, 29, 88, ff, 0b, 94, 94),
+	be64_to_cpua(18, c6, 37, 8a, cb, a7, d8, 7d),
+	be64_to_cpua(f8, 3f, 59, 0f, 74, f0, 3f, d8),
+	be64_to_cpua(e2, ef, 07, 92, ee, 60, 94, 06),
+	be64_to_cpua(35, f6, dc, 6d, 02, 7b, 22, ac),
+	be64_to_cpua(d6, 43, e7, ff, 42, b2, ba, 74),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 01),
+	be64_to_cpua(50, b1, a5, 98, 92, 2a, a5, 52),
+	be64_to_cpua(1c, ad, 22, da, 82, 00, 35, a3),
+	be64_to_cpua(0e, 64, cc, c4, e8, 43, d9, 0e),
+	be64_to_cpua(30, 90, 0f, 1c, 8f, 78, d3, 9f),
+	be64_to_cpua(26, 0b, 5f, 49, 32, 6b, 91, 99),
+	be64_to_cpua(0f, f8, 65, 97, 6b, 09, 4d, 22),
+	be64_to_cpua(5e, f9, 88, f3, d2, 32, 90, 57),
+	be64_to_cpua(26, 0d, 55, cd, 23, 1e, 7d, a0),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 3a) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	},
+	{
+	.key = /* secp521r1(sha256) */
+	"\x04\x01\x05\x3a\x6b\x3b\x5a\x0f\xa7\xb9\xb7\x32\x53\x4e\xe2\xae"
+	"\x0a\x52\xc5\xda\xdd\x5a\x79\x1c\x30\x2d\x33\x07\x79\xd5\x70\x14"
+	"\x61\x0c\xec\x26\x4d\xd8\x35\x57\x04\x1d\x88\x33\x4d\xce\x05\x36"
+	"\xa5\xaf\x56\x84\xfa\x0b\x9e\xff\x7b\x30\x4b\x92\x1d\x06\xf8\x81"
+	"\x24\x1e\x51\x00\x09\x21\x51\xf7\x46\x0a\x77\xdb\xb5\x0c\xe7\x9c"
+	"\xff\x27\x3c\x02\x71\xd7\x85\x36\xf1\xaa\x11\x59\xd8\xb8\xdc\x09"
+	"\xdc\x6d\x5a\x6f\x63\x07\x6c\xe1\xe5\x4d\x6e\x0f\x6e\xfb\x7c\x05"
+	"\x8a\xe9\x53\xa8\xcf\xce\x43\x0e\x82\x20\x86\xbc\x88\x9c\xb7\xe3"
+	"\xe6\x77\x1e\x1f\x8a",
+	.key_len = 133,
+	.m =
+	"\xcc\x97\x73\x0c\x73\xa2\x53\x2b\xfa\xd7\x83\x1d\x0c\x72\x1b\x39"
+	"\x80\x71\x8d\xdd\xc5\x9b\xff\x55\x32\x98\x25\xa2\x58\x2e\xb7\x73",
+	.m_size = 32,
+	.c = (const unsigned char[]){
+	be64_to_cpua(de, 7e, d7, 59, 10, e9, d9, d5),
+	be64_to_cpua(38, 1f, 46, 0b, 04, 64, 34, 79),
+	be64_to_cpua(ae, ce, 54, 76, 9a, c2, 8f, b8),
+	be64_to_cpua(95, 35, 6f, 02, 0e, af, e1, 4c),
+	be64_to_cpua(56, 3c, f6, f0, d8, e1, b7, 5d),
+	be64_to_cpua(50, 9f, 7d, 1f, ca, 8b, a8, 2d),
+	be64_to_cpua(06, 0f, fd, 83, fc, 0e, d9, ce),
+	be64_to_cpua(a5, 5f, 57, 52, 27, 78, 3a, b5),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, cd),
+	be64_to_cpua(55, 38, b6, f6, 34, 65, c7, bd),
+	be64_to_cpua(1c, 57, 56, 8f, 12, b7, 1d, 91),
+	be64_to_cpua(03, 42, 02, 5f, 50, f0, a2, 0d),
+	be64_to_cpua(fa, 10, dd, 9b, fb, 36, 1a, 31),
+	be64_to_cpua(e0, 87, 2c, 44, 4b, 5a, ee, af),
+	be64_to_cpua(a9, 79, 24, b9, 37, 35, dd, a0),
+	be64_to_cpua(6b, 35, ae, 65, b5, 99, 12, 0a),
+	be64_to_cpua(50, 85, 38, f9, 15, 83, 18, 04),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 01, cf) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	},
+	{
+	.key = /* secp521r1(sha384) */
+	"\x04\x00\x2e\xd6\x21\x04\x75\xc3\xdc\x7d\xff\x0e\xf3\x70\x25\x2b"
+	"\xad\x72\xfc\x5a\x91\xf1\xd5\x9c\x64\xf3\x1f\x47\x11\x10\x62\x33"
+	"\xfd\x2e\xe8\x32\xca\x9e\x6f\x0a\x4c\x5b\x35\x9a\x46\xc5\xe7\xd4"
+	"\x38\xda\xb2\xf0\xf4\x87\xf3\x86\xf4\xea\x70\xad\x1e\xd4\x78\x8c"
+	"\x36\x18\x17\x00\xa2\xa0\x34\x1b\x2e\x6a\xdf\x06\xd6\x99\x2d\x47"
+	"\x50\x92\x1a\x8a\x72\x9c\x23\x44\xfa\xa7\xa9\xed\xa6\xef\x26\x14"
+	"\xb3\x9d\xfe\x5e\xa3\x8c\xd8\x29\xf8\xdf\xad\xa6\xab\xfc\xdd\x46"
+	"\x22\x6e\xd7\x35\xc7\x23\xb7\x13\xae\xb6\x34\xff\xd7\x80\xe5\x39"
+	"\xb3\x3b\x5b\x1b\x94",
+	.key_len = 133,
+	.m =
+	"\x36\x98\xd6\x82\xfa\xad\xed\x3c\xb9\x40\xb6\x4d\x9e\xb7\x04\x26"
+	"\xad\x72\x34\x44\xd2\x81\xb4\x9b\xbe\x01\x04\x7a\xd8\x50\xf8\x59"
+	"\xba\xad\x23\x85\x6b\x59\xbe\xfb\xf6\x86\xd4\x67\xa8\x43\x28\x76",
+	.m_size = 48,
+	.c = (const unsigned char[]){
+	be64_to_cpua(b8, 6a, dd, fb, e6, 63, 4e, 28),
+	be64_to_cpua(84, 59, fd, 1a, c4, 40, dd, 43),
+	be64_to_cpua(32, 76, 06, d0, f9, c0, e4, e6),
+	be64_to_cpua(e4, df, 9b, 7d, 9e, 47, ca, 33),
+	be64_to_cpua(7e, 42, 71, 86, 57, 2d, f1, 7d),
+	be64_to_cpua(f2, 4b, 64, 98, f7, ec, da, c7),
+	be64_to_cpua(ec, 51, dc, e8, 35, 5e, ae, 16),
+	be64_to_cpua(96, 76, 3c, 27, ea, aa, 9c, 26),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, 93),
+	be64_to_cpua(c6, 4f, ab, 2b, 62, c1, 42, b1),
+	be64_to_cpua(e5, 5a, 94, 56, cf, 8f, b4, 22),
+	be64_to_cpua(6a, c3, f3, 7a, d1, fa, e7, a7),
+	be64_to_cpua(df, c4, c0, db, 54, db, 8a, 0d),
+	be64_to_cpua(da, a7, cd, 26, 28, 76, 3b, 52),
+	be64_to_cpua(e4, 3c, bc, 93, 65, 57, 1c, 30),
+	be64_to_cpua(55, ce, 37, 97, c9, 05, 51, e5),
+	be64_to_cpua(c3, 6a, 87, 6e, b5, 13, 1f, 20),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 00, ff) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	},
+	{
+	.key = /* secp521r1(sha512) */
+	"\x04\x00\xc7\x65\xee\x0b\x86\x7d\x8f\x02\xf1\x74\x5b\xb0\x4c\x3f"
+	"\xa6\x35\x60\x9f\x55\x23\x11\xcc\xdf\xb8\x42\x99\xee\x6c\x96\x6a"
+	"\x27\xa2\x56\xb2\x2b\x03\xad\x0f\xe7\x97\xde\x09\x5d\xb4\xc5\x5f"
+	"\xbd\x87\x37\xbf\x5a\x16\x35\x56\x08\xfd\x6f\x06\x1a\x1c\x84\xee"
+	"\xc3\x64\xb3\x00\x9e\xbd\x6e\x60\x76\xee\x69\xfd\x3a\xb8\xcd\x7e"
+	"\x91\x68\x53\x57\x44\x13\x2e\x77\x09\x2a\xbe\x48\xbd\x91\xd8\xf6"
+	"\x21\x16\x53\x99\xd5\xf0\x40\xad\xa6\xf8\x58\x26\xb6\x9a\xf8\x77"
+	"\xfe\x3a\x05\x1a\xdb\xa9\x0f\xc0\x6c\x76\x30\x8c\xd8\xde\x44\xae"
+	"\xd0\x17\xdf\x49\x6a",
+	.key_len = 133,
+	.m =
+	"\x5c\xa6\xbc\x79\xb8\xa0\x1e\x11\x83\xf7\xe9\x05\xdf\xba\xf7\x69"
+	"\x97\x22\x32\xe4\x94\x7c\x65\xbd\x74\xc6\x9a\x8b\xbd\x0d\xdc\xed"
+	"\xf5\x9c\xeb\xe1\xc5\x68\x40\xf2\xc7\x04\xde\x9e\x0d\x76\xc5\xa3"
+	"\xf9\x3c\x6c\x98\x08\x31\xbd\x39\xe8\x42\x7f\x80\x39\x6f\xfe\x68",
+	.m_size = 64,
+	.c = (const unsigned char[]){
+	be64_to_cpua(28, b5, 04, b0, b6, 33, 1c, 7e),
+	be64_to_cpua(80, a6, 13, fc, b6, 90, f7, bb),
+	be64_to_cpua(27, 93, e8, 6c, 49, 7d, 28, fc),
+	be64_to_cpua(1f, 12, 3e, b7, 7e, 51, ff, 7f),
+	be64_to_cpua(fb, 62, 1e, 42, 03, 6c, 74, 8a),
+	be64_to_cpua(63, 0e, 02, cc, 94, a9, 05, b9),
+	be64_to_cpua(aa, 86, ec, a8, 05, 03, 52, 56),
+	be64_to_cpua(71, 86, 96, ac, 21, 33, 7e, 4e),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 01, 5c),
+	be64_to_cpua(46, 1e, 77, 44, 78, e0, d1, 04),
+	be64_to_cpua(72, 74, 13, 63, 39, a6, e5, 25),
+	be64_to_cpua(00, 55, bb, 6a, b4, 73, 00, d2),
+	be64_to_cpua(71, d0, e9, ca, a7, c0, cb, aa),
+	be64_to_cpua(7a, 76, 37, 51, 47, 49, 98, 12),
+	be64_to_cpua(88, 05, 3e, 43, 39, 01, bd, b7),
+	be64_to_cpua(95, 35, 89, 4f, 41, 5f, 9e, 19),
+	be64_to_cpua(43, 52, 1d, e3, c6, bd, 5a, 40),
+	be64_to_cpua(00, 00, 00, 00, 00, 00, 01, 70) },
+	.c_size = ECC_MAX_BYTES * 2,
+	.public_key_vec = true,
+	},
+};
+
+/*
+ * ECDSA X9.62 test vectors.
+ *
+ * Identical to ECDSA test vectors, except signature in "c" is X9.62 encoded.
+ */
+static const struct sig_testvec x962_ecdsa_nist_p192_tv_template[] = {
 	{
 	.key = /* secp192r1(sha1) */
 	"\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1"
@@ -756,7 +1449,7 @@ static const struct sig_testvec ecdsa_nist_p192_tv_template[] = {
 	},
 };
 
-static const struct sig_testvec ecdsa_nist_p256_tv_template[] = {
+static const struct sig_testvec x962_ecdsa_nist_p256_tv_template[] = {
 	{
 	.key = /* secp256r1(sha1) */
 	"\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41"
@@ -863,7 +1556,7 @@ static const struct sig_testvec ecdsa_nist_p256_tv_template[] = {
 	},
 };
 
-static const struct sig_testvec ecdsa_nist_p384_tv_template[] = {
+static const struct sig_testvec x962_ecdsa_nist_p384_tv_template[] = {
 	{
 	.key = /* secp384r1(sha1) */
 	"\x04\x89\x25\xf3\x97\x88\xcb\xb0\x78\xc5\x72\x9a\x14\x6e\x7a\xb1"
@@ -990,7 +1683,7 @@ static const struct sig_testvec ecdsa_nist_p384_tv_template[] = {
 	},
 };
 
-static const struct sig_testvec ecdsa_nist_p521_tv_template[] = {
+static const struct sig_testvec x962_ecdsa_nist_p521_tv_template[] = {
 	{
 	.key = /* secp521r1(sha224) */
 	"\x04\x01\x4f\x43\x18\xb6\xa9\xc9\x5d\x68\xd3\xa9\x42\xf8\x98\xc0"
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index 0717a53ae732..68db975e0963 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -42,6 +42,18 @@
 
 #define ECC_POINT_INIT(x, y, ndigits)	(struct ecc_point) { x, y, ndigits }
 
+/*
+ * The integers r and s making up the signature are expected to be
+ * formatted as two consecutive u64 arrays of size ECC_MAX_BYTES.
+ * The bytes within each u64 digit are in native endianness,
+ * but the order of the u64 digits themselves is little endian.
+ * This format allows direct use by internal vli_*() functions.
+ */
+struct ecdsa_raw_sig {
+	u64 r[ECC_MAX_DIGITS];
+	u64 s[ECC_MAX_DIGITS];
+};
+
 /**
  * ecc_swap_digits() - Copy ndigits from big endian array to native array
  * @in:       Input array
@@ -293,4 +305,5 @@ void ecc_point_mult_shamir(const struct ecc_point *result,
 			   const u64 *y, const struct ecc_point *q,
 			   const struct ecc_curve *curve);
 
+extern struct crypto_template ecdsa_x962_tmpl;
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 16/19] crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize()
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (14 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 15/19] crypto: ecdsa - Move X9.62 signature decoding into template Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-11 13:02   ` Jarkko Sakkinen
  2024-09-10 14:30 ` [PATCH v2 17/19] crypto: ecdsa - Move X9.62 signature size calculation into template Lukas Wunner
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

crypto_sig_maxsize() is a bit of a misnomer as it doesn't return the
maximum signature size, but rather the key size.

Rename it as well as all implementations of the ->max_size callback.
A subsequent commit introduces a crypto_sig_maxsize() function which
returns the actual maximum signature size.

While at it, change the return type of crypto_sig_keysize() from int to
unsigned int for consistency with crypto_akcipher_maxsize().  None of
the callers checks for a negative return value and an error condition
can always be indicated by returning zero.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 Documentation/crypto/api-sig.rst    |  2 +-
 crypto/asymmetric_keys/public_key.c |  4 ++--
 crypto/ecdsa-x962.c                 |  8 ++++----
 crypto/ecdsa.c                      | 10 +++++-----
 crypto/ecrdsa.c                     |  4 ++--
 crypto/rsassa-pkcs1.c               |  4 ++--
 crypto/sig.c                        |  2 +-
 crypto/testmgr.c                    |  2 +-
 include/crypto/sig.h                | 14 +++++++-------
 9 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/Documentation/crypto/api-sig.rst b/Documentation/crypto/api-sig.rst
index e5e87e106884..10dabc87df02 100644
--- a/Documentation/crypto/api-sig.rst
+++ b/Documentation/crypto/api-sig.rst
@@ -11,5 +11,5 @@ Asymmetric Signature API
    :doc: Generic Public Key Signature API
 
 .. kernel-doc:: include/crypto/sig.h
-   :functions: crypto_alloc_sig crypto_free_sig crypto_sig_set_pubkey crypto_sig_set_privkey crypto_sig_maxsize crypto_sig_sign crypto_sig_verify
+   :functions: crypto_alloc_sig crypto_free_sig crypto_sig_set_pubkey crypto_sig_set_privkey crypto_sig_keysize crypto_sig_sign crypto_sig_verify
 
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index cc6d48cafa2b..8bf5aa329c26 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -201,7 +201,7 @@ static int software_key_query(const struct kernel_pkey_params *params,
 		if (ret < 0)
 			goto error_free_tfm;
 
-		len = crypto_sig_maxsize(sig);
+		len = crypto_sig_keysize(sig);
 
 		info->supported_ops = KEYCTL_SUPPORTS_VERIFY;
 		if (pkey->key_is_private)
@@ -332,7 +332,7 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
 		if (ret)
 			goto error_free_tfm;
 
-		ksz = crypto_sig_maxsize(sig);
+		ksz = crypto_sig_keysize(sig);
 	} else {
 		tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 		if (IS_ERR(tfm)) {
diff --git a/crypto/ecdsa-x962.c b/crypto/ecdsa-x962.c
index 022e654c075d..8a15232dfa77 100644
--- a/crypto/ecdsa-x962.c
+++ b/crypto/ecdsa-x962.c
@@ -81,7 +81,7 @@ static int ecdsa_x962_verify(struct crypto_sig *tfm,
 	struct ecdsa_x962_signature_ctx sig_ctx;
 	int err;
 
-	sig_ctx.ndigits = DIV_ROUND_UP(crypto_sig_maxsize(ctx->child),
+	sig_ctx.ndigits = DIV_ROUND_UP(crypto_sig_keysize(ctx->child),
 				       sizeof(u64));
 
 	err = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx, src, slen);
@@ -92,11 +92,11 @@ static int ecdsa_x962_verify(struct crypto_sig *tfm,
 				 digest, dlen);
 }
 
-static unsigned int ecdsa_x962_max_size(struct crypto_sig *tfm)
+static unsigned int ecdsa_x962_key_size(struct crypto_sig *tfm)
 {
 	struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
 
-	return crypto_sig_maxsize(ctx->child);
+	return crypto_sig_keysize(ctx->child);
 }
 
 static int ecdsa_x962_set_pub_key(struct crypto_sig *tfm,
@@ -179,7 +179,7 @@ static int ecdsa_x962_create(struct crypto_template *tmpl, struct rtattr **tb)
 	inst->alg.exit = ecdsa_x962_exit_tfm;
 
 	inst->alg.verify = ecdsa_x962_verify;
-	inst->alg.max_size = ecdsa_x962_max_size;
+	inst->alg.key_size = ecdsa_x962_key_size;
 	inst->alg.set_pub_key = ecdsa_x962_set_pub_key;
 
 	inst->free = ecdsa_x962_free;
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index 1f7c29468a86..6cb0a6ce9de1 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -162,7 +162,7 @@ static void ecdsa_exit_tfm(struct crypto_sig *tfm)
 	ecdsa_ecc_ctx_deinit(ctx);
 }
 
-static unsigned int ecdsa_max_size(struct crypto_sig *tfm)
+static unsigned int ecdsa_key_size(struct crypto_sig *tfm)
 {
 	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
 
@@ -179,7 +179,7 @@ static int ecdsa_nist_p521_init_tfm(struct crypto_sig *tfm)
 static struct sig_alg ecdsa_nist_p521 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
-	.max_size = ecdsa_max_size,
+	.key_size = ecdsa_key_size,
 	.init = ecdsa_nist_p521_init_tfm,
 	.exit = ecdsa_exit_tfm,
 	.base = {
@@ -201,7 +201,7 @@ static int ecdsa_nist_p384_init_tfm(struct crypto_sig *tfm)
 static struct sig_alg ecdsa_nist_p384 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
-	.max_size = ecdsa_max_size,
+	.key_size = ecdsa_key_size,
 	.init = ecdsa_nist_p384_init_tfm,
 	.exit = ecdsa_exit_tfm,
 	.base = {
@@ -223,7 +223,7 @@ static int ecdsa_nist_p256_init_tfm(struct crypto_sig *tfm)
 static struct sig_alg ecdsa_nist_p256 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
-	.max_size = ecdsa_max_size,
+	.key_size = ecdsa_key_size,
 	.init = ecdsa_nist_p256_init_tfm,
 	.exit = ecdsa_exit_tfm,
 	.base = {
@@ -245,7 +245,7 @@ static int ecdsa_nist_p192_init_tfm(struct crypto_sig *tfm)
 static struct sig_alg ecdsa_nist_p192 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
-	.max_size = ecdsa_max_size,
+	.key_size = ecdsa_key_size,
 	.init = ecdsa_nist_p192_init_tfm,
 	.exit = ecdsa_exit_tfm,
 	.base = {
diff --git a/crypto/ecrdsa.c b/crypto/ecrdsa.c
index 7383dd11089b..f981b31f4249 100644
--- a/crypto/ecrdsa.c
+++ b/crypto/ecrdsa.c
@@ -241,7 +241,7 @@ static int ecrdsa_set_pub_key(struct crypto_sig *tfm, const void *key,
 	return 0;
 }
 
-static unsigned int ecrdsa_max_size(struct crypto_sig *tfm)
+static unsigned int ecrdsa_key_size(struct crypto_sig *tfm)
 {
 	struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
 
@@ -259,7 +259,7 @@ static void ecrdsa_exit_tfm(struct crypto_sig *tfm)
 static struct sig_alg ecrdsa_alg = {
 	.verify		= ecrdsa_verify,
 	.set_pub_key	= ecrdsa_set_pub_key,
-	.max_size	= ecrdsa_max_size,
+	.key_size	= ecrdsa_key_size,
 	.exit		= ecrdsa_exit_tfm,
 	.base = {
 		.cra_name	 = "ecrdsa",
diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
index b291ec0944a2..9c28f1c62826 100644
--- a/crypto/rsassa-pkcs1.c
+++ b/crypto/rsassa-pkcs1.c
@@ -302,7 +302,7 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
 	return 0;
 }
 
-static unsigned int rsassa_pkcs1_max_size(struct crypto_sig *tfm)
+static unsigned int rsassa_pkcs1_key_size(struct crypto_sig *tfm)
 {
 	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
 
@@ -419,7 +419,7 @@ static int rsassa_pkcs1_create(struct crypto_template *tmpl, struct rtattr **tb)
 
 	inst->alg.sign = rsassa_pkcs1_sign;
 	inst->alg.verify = rsassa_pkcs1_verify;
-	inst->alg.max_size = rsassa_pkcs1_max_size;
+	inst->alg.key_size = rsassa_pkcs1_key_size;
 	inst->alg.set_pub_key = rsassa_pkcs1_set_pub_key;
 	inst->alg.set_priv_key = rsassa_pkcs1_set_priv_key;
 
diff --git a/crypto/sig.c b/crypto/sig.c
index 84d0ea9fd73b..7a3521bee29a 100644
--- a/crypto/sig.c
+++ b/crypto/sig.c
@@ -125,7 +125,7 @@ int crypto_register_sig(struct sig_alg *alg)
 		alg->set_priv_key = sig_default_set_key;
 	if (!alg->set_pub_key)
 		return -EINVAL;
-	if (!alg->max_size)
+	if (!alg->key_size)
 		return -EINVAL;
 
 	sig_prepare_alg(alg);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 19c1d01a064f..287ed2daadf4 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4319,7 +4319,7 @@ static int test_sig_one(struct crypto_sig *tfm, const struct sig_testvec *vecs)
 	if (vecs->public_key_vec)
 		return 0;
 
-	sig_size = crypto_sig_maxsize(tfm);
+	sig_size = crypto_sig_keysize(tfm);
 	if (sig_size < vecs->c_size) {
 		pr_err("alg: sig: invalid maxsize %u\n", sig_size);
 		return -EINVAL;
diff --git a/include/crypto/sig.h b/include/crypto/sig.h
index bbc902642bf5..a3ef17c5f72f 100644
--- a/include/crypto/sig.h
+++ b/include/crypto/sig.h
@@ -32,7 +32,7 @@ struct crypto_sig {
  * @set_priv_key: Function invokes the algorithm specific set private key
  *		function, which knows how to decode and interpret
  *		the BER encoded private key and parameters. Optional.
- * @max_size:	Function returns key size. Mandatory.
+ * @key_size:	Function returns key size. Mandatory.
  * @init:	Initialize the cryptographic transformation object.
  *		This function is used to initialize the cryptographic
  *		transformation object. This function is called only once at
@@ -58,7 +58,7 @@ struct sig_alg {
 			   const void *key, unsigned int keylen);
 	int (*set_priv_key)(struct crypto_sig *tfm,
 			    const void *key, unsigned int keylen);
-	unsigned int (*max_size)(struct crypto_sig *tfm);
+	unsigned int (*key_size)(struct crypto_sig *tfm);
 	int (*init)(struct crypto_sig *tfm);
 	void (*exit)(struct crypto_sig *tfm);
 
@@ -121,20 +121,20 @@ static inline void crypto_free_sig(struct crypto_sig *tfm)
 }
 
 /**
- * crypto_sig_maxsize() - Get len for output buffer
+ * crypto_sig_keysize() - Get key size
  *
- * Function returns the dest buffer size required for a given key.
+ * Function returns the key size in bytes.
  * Function assumes that the key is already set in the transformation. If this
- * function is called without a setkey or with a failed setkey, you will end up
+ * function is called without a setkey or with a failed setkey, you may end up
  * in a NULL dereference.
  *
  * @tfm:	signature tfm handle allocated with crypto_alloc_sig()
  */
-static inline int crypto_sig_maxsize(struct crypto_sig *tfm)
+static inline unsigned int crypto_sig_keysize(struct crypto_sig *tfm)
 {
 	struct sig_alg *alg = crypto_sig_alg(tfm);
 
-	return alg->max_size(tfm);
+	return alg->key_size(tfm);
 }
 
 /**
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 17/19] crypto: ecdsa - Move X9.62 signature size calculation into template
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (15 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 16/19] crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize() Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 14:30 ` [PATCH v2 18/19] crypto: ecdsa - Support P1363 signature decoding Lukas Wunner
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

software_key_query() returns the maximum signature and digest size for a
given key to user space.  When it only supported RSA keys, calculating
those sizes was trivial as they were always equivalent to the key size.

However when ECDSA was added, the function grew somewhat complicated
calculations which take the ASN.1 encoding and curve into account.
This doesn't scale well and adjusting the calculations is easily
forgotten when adding support for new encodings or curves.  In fact,
when NIST P521 support was recently added, the function was initially
not amended:

https://lore.kernel.org/all/b749d5ee-c3b8-4cbd-b252-7773e4536e07@linux.ibm.com/

Introduce a ->max_size() callback to struct sig_alg and take advantage
of it to move the signature size calculations to ecdsa-x962.c.

Introduce a ->digest_size() callback to struct sig_alg and move the
maximum ECDSA digest size to ecdsa.c.  It is common across ecdsa-x962.c
and the upcoming ecdsa-p1363.c and thus inherited by both of them.

For all other algorithms, continue using the key size as maximum
signature and digest size.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 Documentation/crypto/api-sig.rst    |  2 +-
 crypto/asymmetric_keys/public_key.c | 38 +++--------------------------
 crypto/ecdsa-x962.c                 | 36 +++++++++++++++++++++++++++
 crypto/ecdsa.c                      | 16 ++++++++++++
 crypto/sig.c                        |  4 +++
 include/crypto/sig.h                | 38 +++++++++++++++++++++++++++++
 6 files changed, 99 insertions(+), 35 deletions(-)

diff --git a/Documentation/crypto/api-sig.rst b/Documentation/crypto/api-sig.rst
index 10dabc87df02..aaec18e26d54 100644
--- a/Documentation/crypto/api-sig.rst
+++ b/Documentation/crypto/api-sig.rst
@@ -11,5 +11,5 @@ Asymmetric Signature API
    :doc: Generic Public Key Signature API
 
 .. kernel-doc:: include/crypto/sig.h
-   :functions: crypto_alloc_sig crypto_free_sig crypto_sig_set_pubkey crypto_sig_set_privkey crypto_sig_keysize crypto_sig_sign crypto_sig_verify
+   :functions: crypto_alloc_sig crypto_free_sig crypto_sig_set_pubkey crypto_sig_set_privkey crypto_sig_keysize crypto_sig_maxsize crypto_sig_digestsize crypto_sig_sign crypto_sig_verify
 
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 8bf5aa329c26..ec2c0e009b49 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -202,6 +202,8 @@ static int software_key_query(const struct kernel_pkey_params *params,
 			goto error_free_tfm;
 
 		len = crypto_sig_keysize(sig);
+		info->max_sig_size = crypto_sig_maxsize(sig);
+		info->max_data_size = crypto_sig_digestsize(sig);
 
 		info->supported_ops = KEYCTL_SUPPORTS_VERIFY;
 		if (pkey->key_is_private)
@@ -227,6 +229,8 @@ static int software_key_query(const struct kernel_pkey_params *params,
 			goto error_free_tfm;
 
 		len = crypto_akcipher_maxsize(tfm);
+		info->max_sig_size = len;
+		info->max_data_size = len;
 
 		info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT;
 		if (pkey->key_is_private)
@@ -234,40 +238,6 @@ static int software_key_query(const struct kernel_pkey_params *params,
 	}
 
 	info->key_size = len * 8;
-
-	if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
-		int slen = len;
-		/*
-		 * ECDSA key sizes are much smaller than RSA, and thus could
-		 * operate on (hashed) inputs that are larger than key size.
-		 * For example SHA384-hashed input used with secp256r1
-		 * based keys.  Set max_data_size to be at least as large as
-		 * the largest supported hash size (SHA512)
-		 */
-		info->max_data_size = 64;
-
-		/*
-		 * Verify takes ECDSA-Sig (described in RFC 5480) as input,
-		 * which is actually 2 'key_size'-bit integers encoded in
-		 * ASN.1.  Account for the ASN.1 encoding overhead here.
-		 *
-		 * NIST P192/256/384 may prepend a '0' to a coordinate to
-		 * indicate a positive integer. NIST P521 never needs it.
-		 */
-		if (strcmp(pkey->pkey_algo, "ecdsa-nist-p521") != 0)
-			slen += 1;
-		/* Length of encoding the x & y coordinates */
-		slen = 2 * (slen + 2);
-		/*
-		 * If coordinate encoding takes at least 128 bytes then an
-		 * additional byte for length encoding is needed.
-		 */
-		info->max_sig_size = 1 + (slen >= 128) + 1 + slen;
-	} else {
-		info->max_data_size = len;
-		info->max_sig_size = len;
-	}
-
 	info->max_enc_size = len;
 	info->max_dec_size = len;
 
diff --git a/crypto/ecdsa-x962.c b/crypto/ecdsa-x962.c
index 8a15232dfa77..6a77c13e192b 100644
--- a/crypto/ecdsa-x962.c
+++ b/crypto/ecdsa-x962.c
@@ -99,6 +99,40 @@ static unsigned int ecdsa_x962_key_size(struct crypto_sig *tfm)
 	return crypto_sig_keysize(ctx->child);
 }
 
+static unsigned int ecdsa_x962_max_size(struct crypto_sig *tfm)
+{
+	struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+	struct sig_alg *alg = crypto_sig_alg(ctx->child);
+	int slen = crypto_sig_keysize(ctx->child);
+
+	/*
+	 * Verify takes ECDSA-Sig-Value (described in RFC 5480) as input,
+	 * which is actually 2 'key_size'-bit integers encoded in ASN.1.
+	 * Account for the ASN.1 encoding overhead here.
+	 *
+	 * NIST P192/256/384 may prepend a '0' to a coordinate to indicate
+	 * a positive integer. NIST P521 never needs it.
+	 */
+	if (strcmp(alg->base.cra_name, "ecdsa-nist-p521") != 0)
+		slen += 1;
+
+	/* Length of encoding the x & y coordinates */
+	slen = 2 * (slen + 2);
+
+	/*
+	 * If coordinate encoding takes at least 128 bytes then an
+	 * additional byte for length encoding is needed.
+	 */
+	return 1 + (slen >= 128) + 1 + slen;
+}
+
+static unsigned int ecdsa_x962_digest_size(struct crypto_sig *tfm)
+{
+	struct ecdsa_x962_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return crypto_sig_digestsize(ctx->child);
+}
+
 static int ecdsa_x962_set_pub_key(struct crypto_sig *tfm,
 				  const void *key, unsigned int keylen)
 {
@@ -180,6 +214,8 @@ static int ecdsa_x962_create(struct crypto_template *tmpl, struct rtattr **tb)
 
 	inst->alg.verify = ecdsa_x962_verify;
 	inst->alg.key_size = ecdsa_x962_key_size;
+	inst->alg.max_size = ecdsa_x962_max_size;
+	inst->alg.digest_size = ecdsa_x962_digest_size;
 	inst->alg.set_pub_key = ecdsa_x962_set_pub_key;
 
 	inst->free = ecdsa_x962_free;
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index 6cb0a6ce9de1..cf8e0c5d1dd8 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -7,6 +7,7 @@
 #include <crypto/internal/ecc.h>
 #include <crypto/internal/sig.h>
 #include <crypto/ecdh.h>
+#include <crypto/sha2.h>
 #include <crypto/sig.h>
 
 struct ecc_ctx {
@@ -169,6 +170,17 @@ static unsigned int ecdsa_key_size(struct crypto_sig *tfm)
 	return DIV_ROUND_UP(ctx->curve->nbits, 8);
 }
 
+static unsigned int ecdsa_digest_size(struct crypto_sig *tfm)
+{
+	/*
+	 * ECDSA key sizes are much smaller than RSA, and thus could
+	 * operate on (hashed) inputs that are larger than the key size.
+	 * E.g. SHA384-hashed input used with secp256r1 based keys.
+	 * Return the largest supported hash size (SHA512).
+	 */
+	return SHA512_DIGEST_SIZE;
+}
+
 static int ecdsa_nist_p521_init_tfm(struct crypto_sig *tfm)
 {
 	struct ecc_ctx *ctx = crypto_sig_ctx(tfm);
@@ -180,6 +192,7 @@ static struct sig_alg ecdsa_nist_p521 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
 	.key_size = ecdsa_key_size,
+	.digest_size = ecdsa_digest_size,
 	.init = ecdsa_nist_p521_init_tfm,
 	.exit = ecdsa_exit_tfm,
 	.base = {
@@ -202,6 +215,7 @@ static struct sig_alg ecdsa_nist_p384 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
 	.key_size = ecdsa_key_size,
+	.digest_size = ecdsa_digest_size,
 	.init = ecdsa_nist_p384_init_tfm,
 	.exit = ecdsa_exit_tfm,
 	.base = {
@@ -224,6 +238,7 @@ static struct sig_alg ecdsa_nist_p256 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
 	.key_size = ecdsa_key_size,
+	.digest_size = ecdsa_digest_size,
 	.init = ecdsa_nist_p256_init_tfm,
 	.exit = ecdsa_exit_tfm,
 	.base = {
@@ -246,6 +261,7 @@ static struct sig_alg ecdsa_nist_p192 = {
 	.verify = ecdsa_verify,
 	.set_pub_key = ecdsa_set_pub_key,
 	.key_size = ecdsa_key_size,
+	.digest_size = ecdsa_digest_size,
 	.init = ecdsa_nist_p192_init_tfm,
 	.exit = ecdsa_exit_tfm,
 	.base = {
diff --git a/crypto/sig.c b/crypto/sig.c
index 7a3521bee29a..be5ac0e59384 100644
--- a/crypto/sig.c
+++ b/crypto/sig.c
@@ -127,6 +127,10 @@ int crypto_register_sig(struct sig_alg *alg)
 		return -EINVAL;
 	if (!alg->key_size)
 		return -EINVAL;
+	if (!alg->max_size)
+		alg->max_size = alg->key_size;
+	if (!alg->digest_size)
+		alg->digest_size = alg->key_size;
 
 	sig_prepare_alg(alg);
 	return crypto_register_alg(base);
diff --git a/include/crypto/sig.h b/include/crypto/sig.h
index a3ef17c5f72f..cff41ad93824 100644
--- a/include/crypto/sig.h
+++ b/include/crypto/sig.h
@@ -33,6 +33,8 @@ struct crypto_sig {
  *		function, which knows how to decode and interpret
  *		the BER encoded private key and parameters. Optional.
  * @key_size:	Function returns key size. Mandatory.
+ * @digest_size: Function returns maximum digest size. Optional.
+ * @max_size:	Function returns maximum signature size. Optional.
  * @init:	Initialize the cryptographic transformation object.
  *		This function is used to initialize the cryptographic
  *		transformation object. This function is called only once at
@@ -59,6 +61,8 @@ struct sig_alg {
 	int (*set_priv_key)(struct crypto_sig *tfm,
 			    const void *key, unsigned int keylen);
 	unsigned int (*key_size)(struct crypto_sig *tfm);
+	unsigned int (*digest_size)(struct crypto_sig *tfm);
+	unsigned int (*max_size)(struct crypto_sig *tfm);
 	int (*init)(struct crypto_sig *tfm);
 	void (*exit)(struct crypto_sig *tfm);
 
@@ -137,6 +141,40 @@ static inline unsigned int crypto_sig_keysize(struct crypto_sig *tfm)
 	return alg->key_size(tfm);
 }
 
+/**
+ * crypto_sig_digestsize() - Get maximum digest size
+ *
+ * Function returns the maximum digest size in bytes.
+ * Function assumes that the key is already set in the transformation. If this
+ * function is called without a setkey or with a failed setkey, you may end up
+ * in a NULL dereference.
+ *
+ * @tfm:	signature tfm handle allocated with crypto_alloc_sig()
+ */
+static inline unsigned int crypto_sig_digestsize(struct crypto_sig *tfm)
+{
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->digest_size(tfm);
+}
+
+/**
+ * crypto_sig_maxsize() - Get maximum signature size
+ *
+ * Function returns the maximum signature size in bytes.
+ * Function assumes that the key is already set in the transformation. If this
+ * function is called without a setkey or with a failed setkey, you may end up
+ * in a NULL dereference.
+ *
+ * @tfm:	signature tfm handle allocated with crypto_alloc_sig()
+ */
+static inline unsigned int crypto_sig_maxsize(struct crypto_sig *tfm)
+{
+	struct sig_alg *alg = crypto_sig_alg(tfm);
+
+	return alg->max_size(tfm);
+}
+
 /**
  * crypto_sig_sign() - Invoke signing operation
  *
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 18/19] crypto: ecdsa - Support P1363 signature decoding
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (16 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 17/19] crypto: ecdsa - Move X9.62 signature size calculation into template Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-09-10 21:46   ` Stefan Berger
  2024-09-10 14:30 ` [PATCH v2 19/19] crypto: ecrdsa - Fix signature size calculation Lukas Wunner
                   ` (2 subsequent siblings)
  20 siblings, 1 reply; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

Alternatively to the X9.62 encoding of ecdsa signatures, which uses
ASN.1 and is already supported by the kernel, there's another common
encoding called P1363.  It stores r and s as the concatenation of two
big endian, unsigned integers.  The name originates from IEEE P1363.

Add a P1363 template in support of the forthcoming SPDM library
(Security Protocol and Data Model) for PCI device authentication.

P1363 is prescribed by SPDM 1.2.1 margin no 44:

   "For ECDSA signatures, excluding SM2, in SPDM, the signature shall be
    the concatenation of r and s.  The size of r shall be the size of
    the selected curve.  Likewise, the size of s shall be the size of
    the selected curve.  See BaseAsymAlgo in NEGOTIATE_ALGORITHMS for
    the size of r and s.  The byte order for r and s shall be in big
    endian order.  When placing ECDSA signatures into an SPDM signature
    field, r shall come first followed by s."

Link: https://www.dmtf.org/sites/default/files/standards/documents/DSP0274_1.2.1.pdf
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
Changes v1 -> v2:
  * Drop unnecessary "params", "param_len" and "algo" definitions from
    p1363_ecdsa_nist_p256_tv_template[].

 crypto/Makefile                     |   1 +
 crypto/asymmetric_keys/public_key.c |   3 +-
 crypto/ecdsa-p1363.c                | 159 ++++++++++++++++++++++++++++
 crypto/ecdsa.c                      |   8 ++
 crypto/testmgr.c                    |  18 ++++
 crypto/testmgr.h                    |  28 +++++
 include/crypto/internal/ecc.h       |   1 +
 7 files changed, 217 insertions(+), 1 deletion(-)
 create mode 100644 crypto/ecdsa-p1363.c

diff --git a/crypto/Makefile b/crypto/Makefile
index af43a1bd1cfa..81be78d39c2d 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -55,6 +55,7 @@ $(obj)/ecdsasignature.asn1.o: $(obj)/ecdsasignature.asn1.c $(obj)/ecdsasignature
 $(obj)/ecdsa-x962.o: $(obj)/ecdsasignature.asn1.h
 ecdsa_generic-y += ecdsa.o
 ecdsa_generic-y += ecdsa-x962.o
+ecdsa_generic-y += ecdsa-p1363.o
 ecdsa_generic-y += ecdsasignature.asn1.o
 obj-$(CONFIG_CRYPTO_ECDSA) += ecdsa_generic.o
 
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index ec2c0e009b49..c98c1588802b 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -110,7 +110,8 @@ software_key_determine_akcipher(const struct public_key *pkey,
 			return -EINVAL;
 		*sig = false;
 	} else if (strncmp(pkey->pkey_algo, "ecdsa", 5) == 0) {
-		if (strcmp(encoding, "x962") != 0)
+		if (strcmp(encoding, "x962") != 0 &&
+		    strcmp(encoding, "p1363") != 0)
 			return -EINVAL;
 		/*
 		 * ECDSA signatures are taken over a raw hash, so they don't
diff --git a/crypto/ecdsa-p1363.c b/crypto/ecdsa-p1363.c
new file mode 100644
index 000000000000..eaae7214d69b
--- /dev/null
+++ b/crypto/ecdsa-p1363.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ECDSA P1363 signature encoding
+ *
+ * Copyright (c) 2024 Intel Corporation
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <crypto/algapi.h>
+#include <crypto/sig.h>
+#include <crypto/internal/ecc.h>
+#include <crypto/internal/sig.h>
+
+struct ecdsa_p1363_ctx {
+	struct crypto_sig *child;
+};
+
+static int ecdsa_p1363_verify(struct crypto_sig *tfm,
+			      const void *src, unsigned int slen,
+			      const void *digest, unsigned int dlen)
+{
+	struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+	unsigned int keylen = crypto_sig_keysize(ctx->child);
+	unsigned int ndigits = DIV_ROUND_UP(keylen, sizeof(u64));
+	struct ecdsa_raw_sig sig;
+
+	if (slen != 2 * keylen)
+		return -EINVAL;
+
+	ecc_digits_from_bytes(src, keylen, sig.r, ndigits);
+	ecc_digits_from_bytes(src + keylen, keylen, sig.s, ndigits);
+
+	return crypto_sig_verify(ctx->child, &sig, sizeof(sig), digest, dlen);
+}
+
+static unsigned int ecdsa_p1363_key_size(struct crypto_sig *tfm)
+{
+	struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return crypto_sig_keysize(ctx->child);
+}
+
+static unsigned int ecdsa_p1363_max_size(struct crypto_sig *tfm)
+{
+	struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return 2 * crypto_sig_keysize(ctx->child);
+}
+
+static unsigned int ecdsa_p1363_digest_size(struct crypto_sig *tfm)
+{
+	struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return crypto_sig_digestsize(ctx->child);
+}
+
+static int ecdsa_p1363_set_pub_key(struct crypto_sig *tfm,
+				   const void *key, unsigned int keylen)
+{
+	struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return crypto_sig_set_pubkey(ctx->child, key, keylen);
+}
+
+static int ecdsa_p1363_init_tfm(struct crypto_sig *tfm)
+{
+	struct sig_instance *inst = sig_alg_instance(tfm);
+	struct crypto_sig_spawn *spawn = sig_instance_ctx(inst);
+	struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+	struct crypto_sig *child_tfm;
+
+	child_tfm = crypto_spawn_sig(spawn);
+	if (IS_ERR(child_tfm))
+		return PTR_ERR(child_tfm);
+
+	ctx->child = child_tfm;
+
+	return 0;
+}
+
+static void ecdsa_p1363_exit_tfm(struct crypto_sig *tfm)
+{
+	struct ecdsa_p1363_ctx *ctx = crypto_sig_ctx(tfm);
+
+	crypto_free_sig(ctx->child);
+}
+
+static void ecdsa_p1363_free(struct sig_instance *inst)
+{
+	struct crypto_sig_spawn *spawn = sig_instance_ctx(inst);
+
+	crypto_drop_sig(spawn);
+	kfree(inst);
+}
+
+static int ecdsa_p1363_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	struct crypto_sig_spawn *spawn;
+	struct sig_instance *inst;
+	struct sig_alg *ecdsa_alg;
+	u32 mask;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SIG, &mask);
+	if (err)
+		return err;
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	spawn = sig_instance_ctx(inst);
+
+	err = crypto_grab_sig(spawn, sig_crypto_instance(inst),
+			      crypto_attr_alg_name(tb[1]), 0, mask);
+	if (err)
+		goto err_free_inst;
+
+	ecdsa_alg = crypto_spawn_sig_alg(spawn);
+
+	err = -EINVAL;
+	if (strncmp(ecdsa_alg->base.cra_name, "ecdsa", 5) != 0)
+		goto err_free_inst;
+
+	err = crypto_inst_setname(sig_crypto_instance(inst), tmpl->name,
+				  &ecdsa_alg->base);
+	if (err)
+		goto err_free_inst;
+
+	inst->alg.base.cra_priority = ecdsa_alg->base.cra_priority;
+	inst->alg.base.cra_ctxsize = sizeof(struct ecdsa_p1363_ctx);
+
+	inst->alg.init = ecdsa_p1363_init_tfm;
+	inst->alg.exit = ecdsa_p1363_exit_tfm;
+
+	inst->alg.verify = ecdsa_p1363_verify;
+	inst->alg.key_size = ecdsa_p1363_key_size;
+	inst->alg.max_size = ecdsa_p1363_max_size;
+	inst->alg.digest_size = ecdsa_p1363_digest_size;
+	inst->alg.set_pub_key = ecdsa_p1363_set_pub_key;
+
+	inst->free = ecdsa_p1363_free;
+
+	err = sig_register_instance(tmpl, inst);
+	if (err) {
+err_free_inst:
+		ecdsa_p1363_free(inst);
+	}
+	return err;
+}
+
+struct crypto_template ecdsa_p1363_tmpl = {
+	.name = "p1363",
+	.create = ecdsa_p1363_create,
+	.module = THIS_MODULE,
+};
+
+MODULE_ALIAS_CRYPTO("p1363");
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index cf8e0c5d1dd8..117526d15dde 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -298,8 +298,15 @@ static int __init ecdsa_init(void)
 	if (ret)
 		goto x962_tmpl_error;
 
+	ret = crypto_register_template(&ecdsa_p1363_tmpl);
+	if (ret)
+		goto p1363_tmpl_error;
+
 	return 0;
 
+p1363_tmpl_error:
+	crypto_unregister_template(&ecdsa_x962_tmpl);
+
 x962_tmpl_error:
 	crypto_unregister_sig(&ecdsa_nist_p521);
 
@@ -318,6 +325,7 @@ static int __init ecdsa_init(void)
 static void __exit ecdsa_exit(void)
 {
 	crypto_unregister_template(&ecdsa_x962_tmpl);
+	crypto_unregister_template(&ecdsa_p1363_tmpl);
 
 	if (ecdsa_nist_p192_registered)
 		crypto_unregister_sig(&ecdsa_nist_p192);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 287ed2daadf4..bf266dedd07f 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5494,6 +5494,24 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.suite = {
 			.hash = __VECS(nhpoly1305_tv_template)
 		}
+	}, {
+		.alg = "p1363(ecdsa-nist-p192)",
+		.test = alg_test_null,
+	}, {
+		.alg = "p1363(ecdsa-nist-p256)",
+		.test = alg_test_sig,
+		.fips_allowed = 1,
+		.suite = {
+			.sig = __VECS(p1363_ecdsa_nist_p256_tv_template)
+		}
+	}, {
+		.alg = "p1363(ecdsa-nist-p384)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
+	}, {
+		.alg = "p1363(ecdsa-nist-p521)",
+		.test = alg_test_null,
+		.fips_allowed = 1,
 	}, {
 		.alg = "pcbc(fcrypt)",
 		.test = alg_test_skcipher,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 2bd77eaafdf6..55aae1859d2c 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -1805,6 +1805,34 @@ static const struct sig_testvec x962_ecdsa_nist_p521_tv_template[] = {
 	},
 };
 
+/*
+ * ECDSA P1363 test vectors.
+ *
+ * Identical to ECDSA test vectors, except signature in "c" is P1363 encoded.
+ */
+static const struct sig_testvec p1363_ecdsa_nist_p256_tv_template[] = {
+	{
+	.key = /* secp256r1(sha256) */
+	"\x04\xf1\xea\xc4\x53\xf3\xb9\x0e\x9f\x7e\xad\xe3\xea\xd7\x0e\x0f"
+	"\xd6\x98\x9a\xca\x92\x4d\x0a\x80\xdb\x2d\x45\xc7\xec\x4b\x97\x00"
+	"\x2f\xe9\x42\x6c\x29\xdc\x55\x0e\x0b\x53\x12\x9b\x2b\xad\x2c\xe9"
+	"\x80\xe6\xc5\x43\xc2\x1d\x5e\xbb\x65\x21\x50\xb6\x37\xb0\x03\x8e"
+	"\xb8",
+	.key_len = 65,
+	.m =
+	"\x8f\x43\x43\x46\x64\x8f\x6b\x96\xdf\x89\xdd\xa9\x01\xc5\x17\x6b"
+	"\x10\xa6\xd8\x39\x61\xdd\x3c\x1a\xc8\x8b\x59\xb2\xdc\x32\x7a\xa4",
+	.m_size = 32,
+	.c =
+	"\x08\x31\xfa\x74\x0d\x1d\x21\x5d\x09\xdc\x29\x63\xa8\x1a\xad\xfc"
+	"\xac\x44\xc3\xe8\x24\x11\x2d\xa4\x91\xdc\x02\x67\xdc\x0c\xd0\x82"
+	"\xbd\xff\xce\xee\x42\xc3\x97\xff\xf9\xa9\x81\xac\x4a\x50\xd0\x91"
+	"\x0a\x6e\x1b\xc4\xaf\xe1\x83\xc3\x4f\x2a\x65\x35\x23\xe3\x1d\xfa",
+	.c_size = 64,
+	.public_key_vec = true,
+	},
+};
+
 /*
  * EC-RDSA test vectors are generated by gost-engine.
  */
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index 68db975e0963..71483e5305e1 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -306,4 +306,5 @@ void ecc_point_mult_shamir(const struct ecc_point *result,
 			   const struct ecc_curve *curve);
 
 extern struct crypto_template ecdsa_x962_tmpl;
+extern struct crypto_template ecdsa_p1363_tmpl;
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH v2 19/19] crypto: ecrdsa - Fix signature size calculation
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (17 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 18/19] crypto: ecdsa - Support P1363 signature decoding Lukas Wunner
@ 2024-09-10 14:30 ` Lukas Wunner
  2024-10-01  9:17 ` [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
  2024-10-05  5:27 ` Herbert Xu
  20 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-10 14:30 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

software_key_query() returns the curve size as maximum signature size
for ecrdsa.  However it should return twice as much.

It's only the maximum signature size that seems to be off.  The maximum
digest size is likewise set to the curve size, but that's correct as it
matches the checks in ecrdsa_set_pub_key() and ecrdsa_verify().

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 crypto/ecrdsa.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/crypto/ecrdsa.c b/crypto/ecrdsa.c
index f981b31f4249..b3dd8a3ddeb7 100644
--- a/crypto/ecrdsa.c
+++ b/crypto/ecrdsa.c
@@ -252,6 +252,13 @@ static unsigned int ecrdsa_key_size(struct crypto_sig *tfm)
 	return ctx->pub_key.ndigits * sizeof(u64);
 }
 
+static unsigned int ecrdsa_max_size(struct crypto_sig *tfm)
+{
+	struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
+
+	return 2 * ctx->pub_key.ndigits * sizeof(u64);
+}
+
 static void ecrdsa_exit_tfm(struct crypto_sig *tfm)
 {
 }
@@ -260,6 +267,7 @@ static struct sig_alg ecrdsa_alg = {
 	.verify		= ecrdsa_verify,
 	.set_pub_key	= ecrdsa_set_pub_key,
 	.key_size	= ecrdsa_key_size,
+	.max_size	= ecrdsa_max_size,
 	.exit		= ecrdsa_exit_tfm,
 	.base = {
 		.cra_name	 = "ecrdsa",
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements
  2024-09-10 14:30 ` [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements Lukas Wunner
@ 2024-09-10 18:49   ` Stefan Berger
  2024-09-11 11:52   ` Jarkko Sakkinen
  1 sibling, 0 replies; 53+ messages in thread
From: Stefan Berger @ 2024-09-10 18:49 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings



On 9/10/24 10:30 AM, Lukas Wunner wrote:
> The ECDSA test vectors contain "params", "param_len" and "algo" elements
> even though ecdsa.c doesn't make any use of them.  The only algorithm
> implementation using those elements is ecrdsa.c.
> 
> Drop the unused test vector elements.
> 
> For the curious, "params" is an ASN.1 SEQUENCE of OID_id_ecPublicKey
> and a second OID identifying the curve.  For example:
> 
>      "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
>      "\xce\x3d\x03\x01\x01"
> 
> ... decodes to:
> 
>      SEQUENCE (OID_id_ecPublicKey, OID_id_prime192v1)
> 
> The curve OIDs used in those "params" elements are unsurprisingly:
> 
>      OID_id_prime192v1 (2a8648ce3d030101)
>      OID_id_prime256v1 (2a8648ce3d030107)
>      OID_id_ansip384r1 (2b81040022)
>      OID_id_ansip521r1 (2b81040023)
> 
> Those are just different names for secp192r1, secp256r1, secp384r1 and
> secp521r1, respectively, per RFC 8422 appendix A:
> https://www.rfc-editor.org/rfc/rfc8422#appendix-A
> 
> The entries for secp384r1 and secp521r1 curves contain a useful code
> comment calling out the curve and hash.  Add analogous code comments
> to secp192r1 and secp256r1 curve entries.
> 
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>   crypto/testmgr.h | 115 +++++------------------------------------------
>   1 file changed, 10 insertions(+), 105 deletions(-)
> 
> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index 9b38501a17b2..ed1640f3e352 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -652,21 +652,16 @@ static const struct akcipher_testvec rsa_tv_template[] = {
>    */
>   static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
>   	{
> -	.key =
> +	.key = /* secp192r1(sha1) */
>   	"\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1"
>   	"\xd4\x09\x73\xcf\xea\xd0\x15\x07\x3d\xa5\x8a\x8a\x95\x43\xe4\x68"
>   	"\xea\xc6\x25\xc1\xc1\x01\x25\x4c\x7e\xc3\x3c\xa6\x04\x0a\xe7\x08"
>   	"\x98",
>   	.key_len = 49,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x01",
> -	.param_len = 21,
>   	.m =
>   	"\xcd\xb9\xd2\x1c\xb7\x6f\xcd\x44\xb3\xfd\x63\xea\xa3\x66\x7f\xae"
>   	"\x63\x85\xe7\x82",
>   	.m_size = 20,
> -	.algo = OID_id_ecdsa_with_sha1,
>   	.c =
>   	"\x30\x35\x02\x19\x00\xba\xe5\x93\x83\x6e\xb6\x3b\x63\xa0\x27\x91"
>   	"\xc6\xf6\x7f\xc3\x09\xad\x59\xad\x88\x27\xd6\x92\x6b\x02\x18\x10"
> @@ -676,21 +671,16 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
>   	.public_key_vec = true,
>   	.siggen_sigver_test = true,
>   	}, {
> -	.key =
> +	.key = /* secp192r1(sha224) */
>   	"\x04\xb6\x4b\xb1\xd1\xac\xba\x24\x8f\x65\xb2\x60\x00\x90\xbf\xbd"
>   	"\x78\x05\x73\xe9\x79\x1d\x6f\x7c\x0b\xd2\xc3\x93\xa7\x28\xe1\x75"
>   	"\xf7\xd5\x95\x1d\x28\x10\xc0\x75\x50\x5c\x1a\x4f\x3f\x8f\xa5\xee"
>   	"\xa3",
>   	.key_len = 49,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x01",
> -	.param_len = 21,
>   	.m =
>   	"\x8d\xd6\xb8\x3e\xe5\xff\x23\xf6\x25\xa2\x43\x42\x74\x45\xa7\x40"
>   	"\x3a\xff\x2f\xe1\xd3\xf6\x9f\xe8\x33\xcb\x12\x11",
>   	.m_size = 28,
> -	.algo = OID_id_ecdsa_with_sha224,
>   	.c =
>   	"\x30\x34\x02\x18\x5a\x8b\x82\x69\x7e\x8a\x0a\x09\x14\xf8\x11\x2b"
>   	"\x55\xdc\xae\x37\x83\x7b\x12\xe6\xb6\x5b\xcb\xd4\x02\x18\x6a\x14"
> @@ -700,21 +690,16 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
>   	.public_key_vec = true,
>   	.siggen_sigver_test = true,
>   	}, {
> -	.key =
> +	.key = /* secp192r1(sha256) */
>   	"\x04\xe2\x51\x24\x9b\xf7\xb6\x32\x82\x39\x66\x3d\x5b\xec\x3b\xae"
>   	"\x0c\xd5\xf2\x67\xd1\xc7\xe1\x02\xe4\xbf\x90\x62\xb8\x55\x75\x56"
>   	"\x69\x20\x5e\xcb\x4e\xca\x33\xd6\xcb\x62\x6b\x94\xa9\xa2\xe9\x58"
>   	"\x91",
>   	.key_len = 49,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x01",
> -	.param_len = 21,
>   	.m =
>   	"\x35\xec\xa1\xa0\x9e\x14\xde\x33\x03\xb6\xf6\xbd\x0c\x2f\xb2\xfd"
>   	"\x1f\x27\x82\xa5\xd7\x70\x3f\xef\xa0\x82\x69\x8e\x73\x31\x8e\xd7",
>   	.m_size = 32,
> -	.algo = OID_id_ecdsa_with_sha256,
>   	.c =
>   	"\x30\x35\x02\x18\x3f\x72\x3f\x1f\x42\xd2\x3f\x1d\x6b\x1a\x58\x56"
>   	"\xf1\x8f\xf7\xfd\x01\x48\xfb\x5f\x72\x2a\xd4\x8f\x02\x19\x00\xb3"
> @@ -724,22 +709,17 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
>   	.public_key_vec = true,
>   	.siggen_sigver_test = true,
>   	}, {
> -	.key =
> +	.key = /* secp192r1(sha384) */
>   	"\x04\x5a\x13\xfe\x68\x86\x4d\xf4\x17\xc7\xa4\xe5\x8c\x65\x57\xb7"
>   	"\x03\x73\x26\x57\xfb\xe5\x58\x40\xd8\xfd\x49\x05\xab\xf1\x66\x1f"
>   	"\xe2\x9d\x93\x9e\xc2\x22\x5a\x8b\x4f\xf3\x77\x22\x59\x7e\xa6\x4e"
>   	"\x8b",
>   	.key_len = 49,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x01",
> -	.param_len = 21,
>   	.m =
>   	"\x9d\x2e\x1a\x8f\xed\x6c\x4b\x61\xae\xac\xd5\x19\x79\xce\x67\xf9"
>   	"\xa0\x34\xeb\xb0\x81\xf9\xd9\xdc\x6e\xb3\x5c\xa8\x69\xfc\x8a\x61"
>   	"\x39\x81\xfb\xfd\x5c\x30\x6b\xa8\xee\xed\x89\xaf\xa3\x05\xe4\x78",
>   	.m_size = 48,
> -	.algo = OID_id_ecdsa_with_sha384,
>   	.c =
>   	"\x30\x35\x02\x19\x00\xf0\xa3\x38\xce\x2b\xf8\x9d\x1a\xcf\x7f\x34"
>   	"\xb4\xb4\xe5\xc5\x00\xdd\x15\xbb\xd6\x8c\xa7\x03\x78\x02\x18\x64"
> @@ -749,23 +729,18 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
>   	.public_key_vec = true,
>   	.siggen_sigver_test = true,
>   	}, {
> -	.key =
> +	.key = /* secp192r1(sha512) */
>   	"\x04\xd5\xf2\x6e\xc3\x94\x5c\x52\xbc\xdf\x86\x6c\x14\xd1\xca\xea"
>   	"\xcc\x72\x3a\x8a\xf6\x7a\x3a\x56\x36\x3b\xca\xc6\x94\x0e\x17\x1d"
>   	"\x9e\xa0\x58\x28\xf9\x4b\xe6\xd1\xa5\x44\x91\x35\x0d\xe7\xf5\x11"
>   	"\x57",
>   	.key_len = 49,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x01",
> -	.param_len = 21,
>   	.m =
>   	"\xd5\x4b\xe9\x36\xda\xd8\x6e\xc0\x50\x03\xbe\x00\x43\xff\xf0\x23"
>   	"\xac\xa2\x42\xe7\x37\x77\x79\x52\x8f\x3e\xc0\x16\xc1\xfc\x8c\x67"
>   	"\x16\xbc\x8a\x5d\x3b\xd3\x13\xbb\xb6\xc0\x26\x1b\xeb\x33\xcc\x70"
>   	"\x4a\xf2\x11\x37\xe8\x1b\xba\x55\xac\x69\xe1\x74\x62\x7c\x6e\xb5",
>   	.m_size = 64,
> -	.algo = OID_id_ecdsa_with_sha512,
>   	.c =
>   	"\x30\x35\x02\x19\x00\x88\x5b\x8f\x59\x43\xbf\xcf\xc6\xdd\x3f\x07"
>   	"\x87\x12\xa0\xd4\xac\x2b\x11\x2d\x1c\xb6\x06\xc9\x6c\x02\x18\x73"
> @@ -779,22 +754,17 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
>   
>   static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
>   	{
> -	.key =
> +	.key = /* secp256r1(sha1) */
>   	"\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41"
>   	"\x22\xd6\x9a\xaa\x87\x17\xec\x4f\x63\x55\x2f\x94\xba\xdd\x83\xe9"
>   	"\x34\x4b\xf3\xe9\x91\x13\x50\xb6\xcb\xca\x62\x08\xe7\x3b\x09\xdc"
>   	"\xc3\x63\x4b\x2d\xb9\x73\x53\xe4\x45\xe6\x7c\xad\xe7\x6b\xb0\xe8"
>   	"\xaf",
>   	.key_len = 65,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x07",
> -	.param_len = 21,
>   	.m =
>   	"\xc2\x2b\x5f\x91\x78\x34\x26\x09\x42\x8d\x6f\x51\xb2\xc5\xaf\x4c"
>   	"\x0b\xde\x6a\x42",
>   	.m_size = 20,
> -	.algo = OID_id_ecdsa_with_sha1,
>   	.c =
>   	"\x30\x46\x02\x21\x00\xf9\x25\xce\x9f\x3a\xa6\x35\x81\xcf\xd4\xe7"
>   	"\xb7\xf0\x82\x56\x41\xf7\xd4\xad\x8d\x94\x5a\x69\x89\xee\xca\x6a"
> @@ -805,22 +775,17 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
>   	.public_key_vec = true,
>   	.siggen_sigver_test = true,
>   	}, {
> -	.key =
> +	.key = /* secp256r1(sha224) */
>   	"\x04\x8b\x6d\xc0\x33\x8e\x2d\x8b\x67\xf5\xeb\xc4\x7f\xa0\xf5\xd9"
>   	"\x7b\x03\xa5\x78\x9a\xb5\xea\x14\xe4\x23\xd0\xaf\xd7\x0e\x2e\xa0"
>   	"\xc9\x8b\xdb\x95\xf8\xb3\xaf\xac\x00\x2c\x2c\x1f\x7a\xfd\x95\x88"
>   	"\x43\x13\xbf\xf3\x1c\x05\x1a\x14\x18\x09\x3f\xd6\x28\x3e\xc5\xa0"
>   	"\xd4",
>   	.key_len = 65,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x07",
> -	.param_len = 21,
>   	.m =
>   	"\x1a\x15\xbc\xa3\xe4\xed\x3a\xb8\x23\x67\xc6\xc4\x34\xf8\x6c\x41"
>   	"\x04\x0b\xda\xc5\x77\xfa\x1c\x2d\xe6\x2c\x3b\xe0",
>   	.m_size = 28,
> -	.algo = OID_id_ecdsa_with_sha224,
>   	.c =
>   	"\x30\x44\x02\x20\x20\x43\xfa\xc0\x9f\x9d\x7b\xe7\xae\xce\x77\x59"
>   	"\x1a\xdb\x59\xd5\x34\x62\x79\xcb\x6a\x91\x67\x2e\x7d\x25\xd8\x25"
> @@ -831,22 +796,17 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
>   	.public_key_vec = true,
>   	.siggen_sigver_test = true,
>   	}, {
> -	.key =
> +	.key = /* secp256r1(sha256) */
>   	"\x04\xf1\xea\xc4\x53\xf3\xb9\x0e\x9f\x7e\xad\xe3\xea\xd7\x0e\x0f"
>   	"\xd6\x98\x9a\xca\x92\x4d\x0a\x80\xdb\x2d\x45\xc7\xec\x4b\x97\x00"
>   	"\x2f\xe9\x42\x6c\x29\xdc\x55\x0e\x0b\x53\x12\x9b\x2b\xad\x2c\xe9"
>   	"\x80\xe6\xc5\x43\xc2\x1d\x5e\xbb\x65\x21\x50\xb6\x37\xb0\x03\x8e"
>   	"\xb8",
>   	.key_len = 65,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x07",
> -	.param_len = 21,
>   	.m =
>   	"\x8f\x43\x43\x46\x64\x8f\x6b\x96\xdf\x89\xdd\xa9\x01\xc5\x17\x6b"
>   	"\x10\xa6\xd8\x39\x61\xdd\x3c\x1a\xc8\x8b\x59\xb2\xdc\x32\x7a\xa4",
>   	.m_size = 32,
> -	.algo = OID_id_ecdsa_with_sha256,
>   	.c =
>   	"\x30\x45\x02\x20\x08\x31\xfa\x74\x0d\x1d\x21\x5d\x09\xdc\x29\x63"
>   	"\xa8\x1a\xad\xfc\xac\x44\xc3\xe8\x24\x11\x2d\xa4\x91\xdc\x02\x67"
> @@ -857,23 +817,18 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
>   	.public_key_vec = true,
>   	.siggen_sigver_test = true,
>   	}, {
> -	.key =
> +	.key = /* secp256r1(sha384) */
>   	"\x04\xc5\xc6\xea\x60\xc9\xce\xad\x02\x8d\xf5\x3e\x24\xe3\x52\x1d"
>   	"\x28\x47\x3b\xc3\x6b\xa4\x99\x35\x99\x11\x88\x88\xc8\xf4\xee\x7e"
>   	"\x8c\x33\x8f\x41\x03\x24\x46\x2b\x1a\x82\xf9\x9f\xe1\x97\x1b\x00"
>   	"\xda\x3b\x24\x41\xf7\x66\x33\x58\x3d\x3a\x81\xad\xcf\x16\xe9\xe2"
>   	"\x7c",
>   	.key_len = 65,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x07",
> -	.param_len = 21,
>   	.m =
>   	"\x3e\x78\x70\xfb\xcd\x66\xba\x91\xa1\x79\xff\x1e\x1c\x6b\x78\xe6"
>   	"\xc0\x81\x3a\x65\x97\x14\x84\x36\x14\x1a\x9a\xb7\xc5\xab\x84\x94"
>   	"\x5e\xbb\x1b\x34\x71\xcb\x41\xe1\xf6\xfc\x92\x7b\x34\xbb\x86\xbb",
>   	.m_size = 48,
> -	.algo = OID_id_ecdsa_with_sha384,
>   	.c =
>   	"\x30\x46\x02\x21\x00\x8e\xf3\x6f\xdc\xf8\x69\xa6\x2e\xd0\x2e\x95"
>   	"\x54\xd1\x95\x64\x93\x08\xb2\x6b\x24\x94\x48\x46\x5e\xf2\xe4\x6c"
> @@ -884,24 +839,19 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
>   	.public_key_vec = true,
>   	.siggen_sigver_test = true,
>   	}, {
> -	.key =
> +	.key = /* secp256r1(sha512) */
>   	"\x04\xd7\x27\x46\x49\xf6\x26\x85\x12\x40\x76\x8e\xe2\xe6\x2a\x7a"
>   	"\x83\xb1\x4e\x7a\xeb\x3b\x5c\x67\x4a\xb5\xa4\x92\x8c\x69\xff\x38"
>   	"\xee\xd9\x4e\x13\x29\x59\xad\xde\x6b\xbb\x45\x31\xee\xfd\xd1\x1b"
>   	"\x64\xd3\xb5\xfc\xaf\x9b\x4b\x88\x3b\x0e\xb7\xd6\xdf\xf1\xd5\x92"
>   	"\xbf",
>   	.key_len = 65,
> -	.params =
> -	"\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
> -	"\xce\x3d\x03\x01\x07",
> -	.param_len = 21,
>   	.m =
>   	"\x57\xb7\x9e\xe9\x05\x0a\x8c\x1b\xc9\x13\xe5\x4a\x24\xc7\xe2\xe9"
>   	"\x43\xc3\xd1\x76\x62\xf4\x98\x1a\x9c\x13\xb0\x20\x1b\xe5\x39\xca"
>   	"\x4f\xd9\x85\x34\x95\xa2\x31\xbc\xbb\xde\xdd\x76\xbb\x61\xe3\xcf"
>   	"\x9d\xc0\x49\x7a\xf3\x7a\xc4\x7d\xa8\x04\x4b\x8d\xb4\x4d\x5b\xd6",
>   	.m_size = 64,
> -	.algo = OID_id_ecdsa_with_sha512,
>   	.c =
>   	"\x30\x45\x02\x21\x00\xb8\x6d\x87\x81\x43\xdf\xfb\x9f\x40\xea\x44"
>   	"\x81\x00\x4e\x29\x08\xed\x8c\x73\x30\x6c\x22\xb3\x97\x76\xf6\x04"
> @@ -925,15 +875,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
>   	"\x0b\x25\xd6\x80\x5c\x3b\xe6\x1a\x98\x48\x91\x45\x7a\x73\xb0\xc3"
>   	"\xf1",
>   	.key_len = 97,
> -	.params =
> -	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
> -	"\x00\x22",
> -	.param_len = 18,
>   	.m =
>   	"\x12\x55\x28\xf0\x77\xd5\xb6\x21\x71\x32\x48\xcd\x28\xa8\x25\x22"
>   	"\x3a\x69\xc1\x93",
>   	.m_size = 20,
> -	.algo = OID_id_ecdsa_with_sha1,
>   	.c =
>   	"\x30\x66\x02\x31\x00\xf5\x0f\x24\x4c\x07\x93\x6f\x21\x57\x55\x07"
>   	"\x20\x43\x30\xde\xa0\x8d\x26\x8e\xae\x63\x3f\xbc\x20\x3a\xc6\xf1"
> @@ -955,15 +900,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
>   	"\x6b\x93\x99\x6c\x66\x4c\x42\x3f\x65\x60\x6c\x1c\x0b\x93\x9b\x9d"
>   	"\xe0",
>   	.key_len = 97,
> -	.params =
> -	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
> -	"\x00\x22",
> -	.param_len = 18,
>   	.m =
>   	"\x12\x80\xb6\xeb\x25\xe2\x3d\xf0\x21\x32\x96\x17\x3a\x38\x39\xfd"
>   	"\x1f\x05\x34\x7b\xb8\xf9\x71\x66\x03\x4f\xd5\xe5",
>   	.m_size = 28,
> -	.algo = OID_id_ecdsa_with_sha224,
>   	.c =
>   	"\x30\x66\x02\x31\x00\x8a\x51\x84\xce\x13\x1e\xd2\xdc\xec\xcb\xe4"
>   	"\x89\x47\xb2\xf7\xbc\x97\xf1\xc8\x72\x26\xcf\x5a\x5e\xc5\xda\xb4"
> @@ -985,15 +925,10 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
>   	"\x17\xc3\x34\x29\xd6\x40\xea\x5c\xb9\x3f\xfb\x32\x2e\x12\x33\xbc"
>   	"\xab",
>   	.key_len = 97,
> -	.params =
> -	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
> -	"\x00\x22",
> -	.param_len = 18,
>   	.m =
>   	"\xaa\xe7\xfd\x03\x26\xcb\x94\x71\xe4\xce\x0f\xc5\xff\xa6\x29\xa3"
>   	"\xe1\xcc\x4c\x35\x4e\xde\xca\x80\xab\x26\x0c\x25\xe6\x68\x11\xc2",
>   	.m_size = 32,
> -	.algo = OID_id_ecdsa_with_sha256,
>   	.c =
>   	"\x30\x64\x02\x30\x08\x09\x12\x9d\x6e\x96\x64\xa6\x8e\x3f\x7e\xce"
>   	"\x0a\x9b\xaa\x59\xcc\x47\x53\x87\xbc\xbd\x83\x3f\xaf\x06\x3f\x84"
> @@ -1015,16 +950,11 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
>   	"\x21\x67\xe5\x1b\x5a\x52\x31\x68\xd6\xee\xf0\x19\xb0\x55\xed\x89"
>   	"\x9e",
>   	.key_len = 97,
> -	.params =
> -	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
> -	"\x00\x22",
> -	.param_len = 18,
>   	.m =
>   	"\x8d\xf2\xc0\xe9\xa8\xf3\x8e\x44\xc4\x8c\x1a\xa0\xb8\xd7\x17\xdf"
>   	"\xf2\x37\x1b\xc6\xe3\xf5\x62\xcc\x68\xf5\xd5\x0b\xbf\x73\x2b\xb1"
>   	"\xb0\x4c\x04\x00\x31\xab\xfe\xc8\xd6\x09\xc8\xf2\xea\xd3\x28\xff",
>   	.m_size = 48,
> -	.algo = OID_id_ecdsa_with_sha384,
>   	.c =
>   	"\x30\x66\x02\x31\x00\x9b\x28\x68\xc0\xa1\xea\x8c\x50\xee\x2e\x62"
>   	"\x35\x46\xfa\x00\xd8\x2d\x7a\x91\x5f\x49\x2d\x22\x08\x29\xe6\xfb"
> @@ -1046,17 +976,12 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
>   	"\xdf\x42\x5c\xc2\x5a\xc7\x0c\xf4\x15\xf7\x1b\xa3\x2e\xd7\x00\xac"
>   	"\xa3",
>   	.key_len = 97,
> -	.params =
> -	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
> -	"\x00\x22",
> -	.param_len = 18,
>   	.m =
>   	"\xe8\xb7\x52\x7d\x1a\x44\x20\x05\x53\x6b\x3a\x68\xf2\xe7\x6c\xa1"
>   	"\xae\x9d\x84\xbb\xba\x52\x43\x3e\x2c\x42\x78\x49\xbf\x78\xb2\x71"
>   	"\xeb\xe1\xe0\xe8\x42\x7b\x11\xad\x2b\x99\x05\x1d\x36\xe6\xac\xfc"
>   	"\x55\x73\xf0\x15\x63\x39\xb8\x6a\x6a\xc5\x91\x5b\xca\x6a\xa8\x0e",
>   	.m_size = 64,
> -	.algo = OID_id_ecdsa_with_sha512,
>   	.c =
>   	"\x30\x63\x02\x2f\x1d\x20\x94\x77\xfe\x31\xfa\x4d\xc6\xef\xda\x02"
>   	"\xe7\x0f\x52\x9a\x02\xde\x93\xe8\x83\xe4\x84\x4c\xfc\x6f\x80\xe3"
> @@ -1084,15 +1009,10 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
>   	"\xed\x37\x0f\x99\x3f\x26\xba\xa3\x8e\xff\x79\x34\x7c\x3a\xfe\x1f"
>   	"\x3b\x83\x82\x2f\x14",
>   	.key_len = 133,
> -	.params =
> -	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
> -	"\x00\x23",
> -	.param_len = 18,
>   	.m =
>   	"\xa2\x3a\x6a\x8c\x7b\x3c\xf2\x51\xf8\xbe\x5f\x4f\x3b\x15\x05\xc4"
>   	"\xb5\xbc\x19\xe7\x21\x85\xe9\x23\x06\x33\x62\xfb",
>   	.m_size = 28,
> -	.algo = OID_id_ecdsa_with_sha224,
>   	.c =
>   	"\x30\x81\x86\x02\x41\x01\xd6\x43\xe7\xff\x42\xb2\xba\x74\x35\xf6"
>   	"\xdc\x6d\x02\x7b\x22\xac\xe2\xef\x07\x92\xee\x60\x94\x06\xf8\x3f"
> @@ -1119,15 +1039,10 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
>   	"\x8a\xe9\x53\xa8\xcf\xce\x43\x0e\x82\x20\x86\xbc\x88\x9c\xb7\xe3"
>   	"\xe6\x77\x1e\x1f\x8a",
>   	.key_len = 133,
> -	.params =
> -	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
> -	"\x00\x23",
> -	.param_len = 18,
>   	.m =
>   	"\xcc\x97\x73\x0c\x73\xa2\x53\x2b\xfa\xd7\x83\x1d\x0c\x72\x1b\x39"
>   	"\x80\x71\x8d\xdd\xc5\x9b\xff\x55\x32\x98\x25\xa2\x58\x2e\xb7\x73",
>   	.m_size = 32,
> -	.algo = OID_id_ecdsa_with_sha256,
>   	.c =
>   	"\x30\x81\x88\x02\x42\x00\xcd\xa5\x5f\x57\x52\x27\x78\x3a\xb5\x06"
>   	"\x0f\xfd\x83\xfc\x0e\xd9\xce\x50\x9f\x7d\x1f\xca\x8b\xa8\x2d\x56"
> @@ -1154,16 +1069,11 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
>   	"\x22\x6e\xd7\x35\xc7\x23\xb7\x13\xae\xb6\x34\xff\xd7\x80\xe5\x39"
>   	"\xb3\x3b\x5b\x1b\x94",
>   	.key_len = 133,
> -	.params =
> -	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
> -	"\x00\x23",
> -	.param_len = 18,
>   	.m =
>   	"\x36\x98\xd6\x82\xfa\xad\xed\x3c\xb9\x40\xb6\x4d\x9e\xb7\x04\x26"
>   	"\xad\x72\x34\x44\xd2\x81\xb4\x9b\xbe\x01\x04\x7a\xd8\x50\xf8\x59"
>   	"\xba\xad\x23\x85\x6b\x59\xbe\xfb\xf6\x86\xd4\x67\xa8\x43\x28\x76",
>   	.m_size = 48,
> -	.algo = OID_id_ecdsa_with_sha384,
>   	.c =
>   	"\x30\x81\x88\x02\x42\x00\x93\x96\x76\x3c\x27\xea\xaa\x9c\x26\xec"
>   	"\x51\xdc\xe8\x35\x5e\xae\x16\xf2\x4b\x64\x98\xf7\xec\xda\xc7\x7e"
> @@ -1190,17 +1100,12 @@ static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
>   	"\xfe\x3a\x05\x1a\xdb\xa9\x0f\xc0\x6c\x76\x30\x8c\xd8\xde\x44\xae"
>   	"\xd0\x17\xdf\x49\x6a",
>   	.key_len = 133,
> -	.params =
> -	"\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
> -	"\x00\x23",
> -	.param_len = 18,
>   	.m =
>   	"\x5c\xa6\xbc\x79\xb8\xa0\x1e\x11\x83\xf7\xe9\x05\xdf\xba\xf7\x69"
>   	"\x97\x22\x32\xe4\x94\x7c\x65\xbd\x74\xc6\x9a\x8b\xbd\x0d\xdc\xed"
>   	"\xf5\x9c\xeb\xe1\xc5\x68\x40\xf2\xc7\x04\xde\x9e\x0d\x76\xc5\xa3"
>   	"\xf9\x3c\x6c\x98\x08\x31\xbd\x39\xe8\x42\x7f\x80\x39\x6f\xfe\x68",
>   	.m_size = 64,
> -	.algo = OID_id_ecdsa_with_sha512,
>   	.c =
>   	"\x30\x81\x88\x02\x42\x01\x5c\x71\x86\x96\xac\x21\x33\x7e\x4e\xaa"
>   	"\x86\xec\xa8\x05\x03\x52\x56\x63\x0e\x02\xcc\x94\xa9\x05\xb9\xfb"


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

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks
  2024-09-10 14:30 ` [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks Lukas Wunner
@ 2024-09-10 19:03   ` Stefan Berger
  2024-09-11 12:54   ` Jarkko Sakkinen
  1 sibling, 0 replies; 53+ messages in thread
From: Stefan Berger @ 2024-09-10 19:03 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings



On 9/10/24 10:30 AM, Lukas Wunner wrote:
> pkcs1pad_set_pub_key() and pkcs1pad_set_priv_key() are almost identical.
> 
> The upcoming migration of sign/verify operations from rsa-pkcs1pad.c
> into a separate crypto_template will require another copy of the exact
> same functions.  When RSASSA-PSS and RSAES-OAEP are introduced, each
> will need yet another copy.
> 
> Deduplicate the functions into a single one which lives in a common
> header file for reuse by RSASSA-PKCS1-v1_5, RSASSA-PSS and RSAES-OAEP.
> 
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>   crypto/rsa-pkcs1pad.c         | 30 ++----------------------------
>   include/crypto/internal/rsa.h | 28 ++++++++++++++++++++++++++++
>   2 files changed, 30 insertions(+), 28 deletions(-)
> 
> diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
> index cd501195f34a..3c5fe8c93938 100644
> --- a/crypto/rsa-pkcs1pad.c
> +++ b/crypto/rsa-pkcs1pad.c
> @@ -131,42 +131,16 @@ static int pkcs1pad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
>   		unsigned int keylen)
>   {
>   	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
> -	int err;
> -
> -	ctx->key_size = 0;
>   
> -	err = crypto_akcipher_set_pub_key(ctx->child, key, keylen);
> -	if (err)
> -		return err;
> -
> -	/* Find out new modulus size from rsa implementation */
> -	err = crypto_akcipher_maxsize(ctx->child);
> -	if (err > PAGE_SIZE)
> -		return -ENOTSUPP;
> -
> -	ctx->key_size = err;
> -	return 0;
> +	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PUB, key, keylen);
>   }
>   
>   static int pkcs1pad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
>   		unsigned int keylen)
>   {
>   	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
> -	int err;
> -
> -	ctx->key_size = 0;
>   
> -	err = crypto_akcipher_set_priv_key(ctx->child, key, keylen);
> -	if (err)
> -		return err;
> -
> -	/* Find out new modulus size from rsa implementation */
> -	err = crypto_akcipher_maxsize(ctx->child);
> -	if (err > PAGE_SIZE)
> -		return -ENOTSUPP;
> -
> -	ctx->key_size = err;
> -	return 0;
> +	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PRIV, key, keylen);
>   }
>   
>   static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
> diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
> index e870133f4b77..754f687134df 100644
> --- a/include/crypto/internal/rsa.h
> +++ b/include/crypto/internal/rsa.h
> @@ -8,6 +8,7 @@
>   #ifndef _RSA_HELPER_
>   #define _RSA_HELPER_
>   #include <linux/types.h>
> +#include <crypto/akcipher.h>
>   
>   /**
>    * rsa_key - RSA key structure
> @@ -53,5 +54,32 @@ int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
>   int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
>   		       unsigned int key_len);
>   
> +#define RSA_PUB (true)
> +#define RSA_PRIV (false)
> +
> +static inline int rsa_set_key(struct crypto_akcipher *child,
> +			      unsigned int *key_size, bool is_pubkey,
> +			      const void *key, unsigned int keylen)
> +{
> +	int err;
> +
> +	*key_size = 0;
> +
> +	if (is_pubkey)
> +		err = crypto_akcipher_set_pub_key(child, key, keylen);
> +	else
> +		err = crypto_akcipher_set_priv_key(child, key, keylen);
> +	if (err)
> +		return err;
> +
> +	/* Find out new modulus size from rsa implementation */
> +	err = crypto_akcipher_maxsize(child);
> +	if (err > PAGE_SIZE)
> +		return -ENOTSUPP;
> +
> +	*key_size = err;
> +	return 0;
> +}
> +
>   extern struct crypto_template rsa_pkcs1pad_tmpl;
>   #endif

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

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 12/19] crypto: sig - Move crypto_sig_*() API calls to include file
  2024-09-10 14:30 ` [PATCH v2 12/19] crypto: sig - Move crypto_sig_*() API calls to include file Lukas Wunner
@ 2024-09-10 19:24   ` Stefan Berger
  0 siblings, 0 replies; 53+ messages in thread
From: Stefan Berger @ 2024-09-10 19:24 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings



On 9/10/24 10:30 AM, Lukas Wunner wrote:
> The crypto_sig_*() API calls lived in sig.c so far because they needed
> access to struct crypto_sig_type:  This was necessary to differentiate
> between signature algorithms that had already been migrated from
> crypto_akcipher to crypto_sig and those that hadn't yet.
> 
> Now that all algorithms have been migrated, the API calls can become
> static inlines in <crypto/sig.h> to mimic what <crypto/akcipher.h> is
> doing.
> 
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>   crypto/sig.c         | 46 -------------------------------------------
>   include/crypto/sig.h | 47 +++++++++++++++++++++++++++++++++-----------
>   2 files changed, 36 insertions(+), 57 deletions(-)
> 
> diff --git a/crypto/sig.c b/crypto/sig.c
> index 1e6b0d677472..84d0ea9fd73b 100644
> --- a/crypto/sig.c
> +++ b/crypto/sig.c
> @@ -84,52 +84,6 @@ struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask)
>   }
>   EXPORT_SYMBOL_GPL(crypto_alloc_sig);
>   
> -int crypto_sig_maxsize(struct crypto_sig *tfm)
> -{
> -	struct sig_alg *alg = crypto_sig_alg(tfm);
> -
> -	return alg->max_size(tfm);
> -}
> -EXPORT_SYMBOL_GPL(crypto_sig_maxsize);
> -
> -int crypto_sig_sign(struct crypto_sig *tfm,
> -		    const void *src, unsigned int slen,
> -		    void *dst, unsigned int dlen)
> -{
> -	struct sig_alg *alg = crypto_sig_alg(tfm);
> -
> -	return alg->sign(tfm, src, slen, dst, dlen);
> -}
> -EXPORT_SYMBOL_GPL(crypto_sig_sign);
> -
> -int crypto_sig_verify(struct crypto_sig *tfm,
> -		      const void *src, unsigned int slen,
> -		      const void *digest, unsigned int dlen)
> -{
> -	struct sig_alg *alg = crypto_sig_alg(tfm);
> -
> -	return alg->verify(tfm, src, slen, digest, dlen);
> -}
> -EXPORT_SYMBOL_GPL(crypto_sig_verify);
> -
> -int crypto_sig_set_pubkey(struct crypto_sig *tfm,
> -			  const void *key, unsigned int keylen)
> -{
> -	struct sig_alg *alg = crypto_sig_alg(tfm);
> -
> -	return alg->set_pub_key(tfm, key, keylen);
> -}
> -EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);
> -
> -int crypto_sig_set_privkey(struct crypto_sig *tfm,
> -			  const void *key, unsigned int keylen)
> -{
> -	struct sig_alg *alg = crypto_sig_alg(tfm);
> -
> -	return alg->set_priv_key(tfm, key, keylen);
> -}
> -EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);
> -
>   static void sig_prepare_alg(struct sig_alg *alg)
>   {
>   	struct crypto_alg *base = &alg->base;
> diff --git a/include/crypto/sig.h b/include/crypto/sig.h
> index f0f52a7c5ae7..bbc902642bf5 100644
> --- a/include/crypto/sig.h
> +++ b/include/crypto/sig.h
> @@ -130,7 +130,12 @@ static inline void crypto_free_sig(struct crypto_sig *tfm)
>    *
>    * @tfm:	signature tfm handle allocated with crypto_alloc_sig()
>    */
> -int crypto_sig_maxsize(struct crypto_sig *tfm);
> +static inline int crypto_sig_maxsize(struct crypto_sig *tfm)
> +{
> +	struct sig_alg *alg = crypto_sig_alg(tfm);
> +
> +	return alg->max_size(tfm);
> +}
>   
>   /**
>    * crypto_sig_sign() - Invoke signing operation
> @@ -145,9 +150,14 @@ int crypto_sig_maxsize(struct crypto_sig *tfm);
>    *
>    * Return: zero on success; error code in case of error
>    */
> -int crypto_sig_sign(struct crypto_sig *tfm,
> -		    const void *src, unsigned int slen,
> -		    void *dst, unsigned int dlen);
> +static inline int crypto_sig_sign(struct crypto_sig *tfm,
> +				  const void *src, unsigned int slen,
> +				  void *dst, unsigned int dlen)
> +{
> +	struct sig_alg *alg = crypto_sig_alg(tfm);
> +
> +	return alg->sign(tfm, src, slen, dst, dlen);
> +}
>   
>   /**
>    * crypto_sig_verify() - Invoke signature verification
> @@ -163,9 +173,14 @@ int crypto_sig_sign(struct crypto_sig *tfm,
>    *
>    * Return: zero on verification success; error code in case of error.
>    */
> -int crypto_sig_verify(struct crypto_sig *tfm,
> -		      const void *src, unsigned int slen,
> -		      const void *digest, unsigned int dlen);
> +static inline int crypto_sig_verify(struct crypto_sig *tfm,
> +				    const void *src, unsigned int slen,
> +				    const void *digest, unsigned int dlen)
> +{
> +	struct sig_alg *alg = crypto_sig_alg(tfm);
> +
> +	return alg->verify(tfm, src, slen, digest, dlen);
> +}
>   
>   /**
>    * crypto_sig_set_pubkey() - Invoke set public key operation
> @@ -180,8 +195,13 @@ int crypto_sig_verify(struct crypto_sig *tfm,
>    *
>    * Return: zero on success; error code in case of error
>    */
> -int crypto_sig_set_pubkey(struct crypto_sig *tfm,
> -			  const void *key, unsigned int keylen);
> +static inline int crypto_sig_set_pubkey(struct crypto_sig *tfm,
> +					const void *key, unsigned int keylen)
> +{
> +	struct sig_alg *alg = crypto_sig_alg(tfm);
> +
> +	return alg->set_pub_key(tfm, key, keylen);
> +}
>   
>   /**
>    * crypto_sig_set_privkey() - Invoke set private key operation
> @@ -196,6 +216,11 @@ int crypto_sig_set_pubkey(struct crypto_sig *tfm,
>    *
>    * Return: zero on success; error code in case of error
>    */
> -int crypto_sig_set_privkey(struct crypto_sig *tfm,
> -			   const void *key, unsigned int keylen);
> +static inline int crypto_sig_set_privkey(struct crypto_sig *tfm,
> +					 const void *key, unsigned int keylen)
> +{
> +	struct sig_alg *alg = crypto_sig_alg(tfm);
> +
> +	return alg->set_priv_key(tfm, key, keylen);
> +}
>   #endif

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

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 15/19] crypto: ecdsa - Move X9.62 signature decoding into template
  2024-09-10 14:30 ` [PATCH v2 15/19] crypto: ecdsa - Move X9.62 signature decoding into template Lukas Wunner
@ 2024-09-10 20:46   ` Stefan Berger
  0 siblings, 0 replies; 53+ messages in thread
From: Stefan Berger @ 2024-09-10 20:46 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings



On 9/10/24 10:30 AM, Lukas Wunner wrote:
> Unlike the rsa driver, which separates signature decoding and
> signature verification into two steps, the ecdsa driver does both in one.
> 
> This restricts users to the one signature format currently supported
> (X9.62) and prevents addition of others such as P1363, which is needed
> by the forthcoming SPDM library (Security Protocol and Data Model) for
> PCI device authentication.
> 
> Per Herbert's suggestion, change ecdsa to use a "raw" signature encoding
> and then implement X9.62 and P1363 as templates which convert their
> respective encodings to the raw one.  One may then specify
> "x962(ecdsa-nist-XXX)" or "p1363(ecdsa-nist-XXX)" to pick the encoding.
> 
> The present commit moves X9.62 decoding to a template.  A separate
> commit is going to introduce another template for P1363 decoding.
> 
> The ecdsa driver internally represents a signature as two u64 arrays of
> size ECC_MAX_BYTES.  This appears to be the most natural choice for the
> raw format as it can directly be used for verification without having to
> further decode signature data or copy it around.
> 
> Repurpose all the existing test vectors for "x962(ecdsa-nist-XXX)" and
> create a duplicate of them to test the raw encoding.
> 
> Link: https://lore.kernel.org/all/ZoHXyGwRzVvYkcTP@gondor.apana.org.au/
> Signed-off-by: Lukas Wunner <lukas@wunner.de>

I ran my signature verification test cases over this:

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

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 18/19] crypto: ecdsa - Support P1363 signature decoding
  2024-09-10 14:30 ` [PATCH v2 18/19] crypto: ecdsa - Support P1363 signature decoding Lukas Wunner
@ 2024-09-10 21:46   ` Stefan Berger
  0 siblings, 0 replies; 53+ messages in thread
From: Stefan Berger @ 2024-09-10 21:46 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings



On 9/10/24 10:30 AM, Lukas Wunner wrote:
> Alternatively to the X9.62 encoding of ecdsa signatures, which uses
> ASN.1 and is already supported by the kernel, there's another common
> encoding called P1363.  It stores r and s as the concatenation of two
> big endian, unsigned integers.  The name originates from IEEE P1363.
> 
> Add a P1363 template in support of the forthcoming SPDM library
> (Security Protocol and Data Model) for PCI device authentication.
> 
> P1363 is prescribed by SPDM 1.2.1 margin no 44:
> 
>     "For ECDSA signatures, excluding SM2, in SPDM, the signature shall be
>      the concatenation of r and s.  The size of r shall be the size of
>      the selected curve.  Likewise, the size of s shall be the size of
>      the selected curve.  See BaseAsymAlgo in NEGOTIATE_ALGORITHMS for
>      the size of r and s.  The byte order for r and s shall be in big
>      endian order.  When placing ECDSA signatures into an SPDM signature
>      field, r shall come first followed by s."
> 
> Link: https://www.dmtf.org/sites/default/files/standards/documents/DSP0274_1.2.1.pdf
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

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


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements
  2024-09-10 14:30 ` [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements Lukas Wunner
  2024-09-10 18:49   ` Stefan Berger
@ 2024-09-11 11:52   ` Jarkko Sakkinen
  2024-09-12  7:59     ` Lukas Wunner
  1 sibling, 1 reply; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-11 11:52 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Stefan Berger, Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> The ECDSA test vectors contain "params", "param_len" and "algo" elements
> even though ecdsa.c doesn't make any use of them.  The only algorithm
> implementation using those elements is ecrdsa.c.

I'm missing these pieces of information here at least:

- akcipher.h tells that tail contains OID, parameter blob length and the
  blob itself.
- akcipher.h leaves the size of those fields completely *undefined*.
- According to call sites OID and blob length are 32-bit fields.
- According to call sites that I bumped into they are always set to
  zero.
- There's no information in the kernel source code that I could fine
  for any other rules how the should be set.
  
Putting random words (of which params_len is not even a word) to quotes
does not really make this whole story obvious. You could just as well
delete the paragraph, because that only makes you look for a struct
that does not even exist.

BR, Jarkko


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend
  2024-09-10 14:30 ` [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend Lukas Wunner
@ 2024-09-11 12:12   ` Jarkko Sakkinen
  2024-09-12  7:54     ` Lukas Wunner
  2024-09-13 18:40   ` Jonathan Cameron
  1 sibling, 1 reply; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-11 12:12 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Stefan Berger, Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> Commit 6cb8815f41a9 ("crypto: sig - Add interface for sign/verify")
> began a transition of asymmetric sign/verify operations from
> crypto_akcipher to a new crypto_sig frontend.
>
> Internally, the crypto_sig frontend still uses akcipher_alg as backend,
> however:
>
>    "The link between sig and akcipher is meant to be temporary.  The
>     plan is to create a new low-level API for sig and then migrate
>     the signature code over to that from akcipher."
>     https://lore.kernel.org/r/ZrG6w9wsb-iiLZIF@gondor.apana.org.au/
>
>    "having a separate alg for sig is definitely where we want to
>     be since there is very little that the two types actually share."
>     https://lore.kernel.org/r/ZrHlpz4qnre0zWJO@gondor.apana.org.au/
>
> Take the next step of that migration and augment the crypto_sig frontend
> with a sig_alg backend to which all algorithms can be moved.
>
> During the migration, there will briefly be signature algorithms that
> are still based on crypto_akcipher, whilst others are already based on
> crypto_sig.  Allow for that by building a fork into crypto_sig_*() API
> calls (i.e. crypto_sig_maxsize() and friends) such that one of the two
> backends is selected based on the transform's cra_type.
>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>  Documentation/crypto/api-sig.rst      |  15 +++
>  Documentation/crypto/api.rst          |   1 +
>  Documentation/crypto/architecture.rst |   2 +
>  crypto/sig.c                          | 143 +++++++++++++++++++++++++-
>  crypto/testmgr.c                      | 115 +++++++++++++++++++++
>  crypto/testmgr.h                      |  13 +++
>  include/crypto/internal/sig.h         |  80 ++++++++++++++
>  include/crypto/sig.h                  |  61 +++++++++++
>  include/uapi/linux/cryptouser.h       |   5 +
>  9 files changed, 433 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/crypto/api-sig.rst
>
> diff --git a/Documentation/crypto/api-sig.rst b/Documentation/crypto/api-sig.rst
> new file mode 100644
> index 000000000000..e5e87e106884
> --- /dev/null
> +++ b/Documentation/crypto/api-sig.rst
> @@ -0,0 +1,15 @@
> +Asymmetric Signature Algorithm Definitions
> +------------------------------------------
> +
> +.. kernel-doc:: include/crypto/sig.h
> +   :functions: sig_alg
> +
> +Asymmetric Signature API
> +------------------------
> +
> +.. kernel-doc:: include/crypto/sig.h
> +   :doc: Generic Public Key Signature API
> +
> +.. kernel-doc:: include/crypto/sig.h
> +   :functions: crypto_alloc_sig crypto_free_sig crypto_sig_set_pubkey crypto_sig_set_privkey crypto_sig_maxsize crypto_sig_sign crypto_sig_verify
> +
> diff --git a/Documentation/crypto/api.rst b/Documentation/crypto/api.rst
> index ff31c30561d4..8b2a90521886 100644
> --- a/Documentation/crypto/api.rst
> +++ b/Documentation/crypto/api.rst
> @@ -10,4 +10,5 @@ Programming Interface
>     api-digest
>     api-rng
>     api-akcipher
> +   api-sig
>     api-kpp
> diff --git a/Documentation/crypto/architecture.rst b/Documentation/crypto/architecture.rst
> index 646c3380a7ed..15dcd62fd22f 100644
> --- a/Documentation/crypto/architecture.rst
> +++ b/Documentation/crypto/architecture.rst
> @@ -214,6 +214,8 @@ the aforementioned cipher types:
>  
>  -  CRYPTO_ALG_TYPE_AKCIPHER Asymmetric cipher
>  
> +-  CRYPTO_ALG_TYPE_SIG Asymmetric signature
> +
>  -  CRYPTO_ALG_TYPE_PCOMPRESS Enhanced version of
>     CRYPTO_ALG_TYPE_COMPRESS allowing for segmented compression /
>     decompression instead of performing the operation on one segment

I'd split the documentation update. It's not strictly necessary as it is
still part of crypto (e.g. not kernel-parameters.txt) but they are still
too disjoint logical artifacts that you need to review separately.

> diff --git a/crypto/sig.c b/crypto/sig.c
> index 7645bedf3a1f..4f36ceb7a90b 100644
> --- a/crypto/sig.c
> +++ b/crypto/sig.c
> @@ -21,14 +21,38 @@
>  
>  static const struct crypto_type crypto_sig_type;
>  
> +static void crypto_sig_exit_tfm(struct crypto_tfm *tfm)
> +{
> +	struct crypto_sig *sig = __crypto_sig_tfm(tfm);
> +	struct sig_alg *alg = crypto_sig_alg(sig);
> +
> +	alg->exit(sig);
> +}
> +
>  static int crypto_sig_init_tfm(struct crypto_tfm *tfm)
>  {
>  	if (tfm->__crt_alg->cra_type != &crypto_sig_type)
>  		return crypto_init_akcipher_ops_sig(tfm);
>  
> +	struct crypto_sig *sig = __crypto_sig_tfm(tfm);
> +	struct sig_alg *alg = crypto_sig_alg(sig);
> +
> +	if (alg->exit)
> +		sig->base.exit = crypto_sig_exit_tfm;
> +
> +	if (alg->init)
> +		return alg->init(sig);

1. alg->exit == NULL, alg->init == NULL
2. alg->exit != NULL, alg->init == NULL
3. alg->exit == NULL, alg->init != NULL

Which of the three are legit use of the API and which are not?

BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 04/19] crypto: ecrdsa - Migrate to sig_alg backend
  2024-09-10 14:30 ` [PATCH v2 04/19] crypto: ecrdsa " Lukas Wunner
@ 2024-09-11 12:49   ` Jarkko Sakkinen
  2024-09-12  8:05     ` Lukas Wunner
  0 siblings, 1 reply; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-11 12:49 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Stefan Berger, Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> A sig_alg backend has just been introduced with the intent of moving all
> asymmetric sign/verify algorithms to it one by one.
>
> Migrate ecrdsa.c to the new backend.
>
> One benefit of the new API is the use of kernel buffers instead of
> sglists, which avoids the overhead of copying signature and digest
> sglists back into kernel buffers.  ecrdsa.c is thus simplified quite
> a bit.
>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>  crypto/Kconfig   |  2 +-
>  crypto/ecrdsa.c  | 56 +++++++++++++++++++++---------------------------
>  crypto/testmgr.c |  4 ++--
>  crypto/testmgr.h |  7 +-----
>  4 files changed, 28 insertions(+), 41 deletions(-)
>
> diff --git a/crypto/Kconfig b/crypto/Kconfig
> index 89b728c72f07..e8488b8c45e3 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -302,7 +302,7 @@ config CRYPTO_ECDSA
>  config CRYPTO_ECRDSA
>  	tristate "EC-RDSA (Elliptic Curve Russian Digital Signature Algorithm)"
>  	select CRYPTO_ECC
> -	select CRYPTO_AKCIPHER
> +	select CRYPTO_SIG
>  	select CRYPTO_STREEBOG
>  	select OID_REGISTRY
>  	select ASN1
> diff --git a/crypto/ecrdsa.c b/crypto/ecrdsa.c
> index 3811f3805b5d..7383dd11089b 100644
> --- a/crypto/ecrdsa.c
> +++ b/crypto/ecrdsa.c
> @@ -18,12 +18,11 @@
>  
>  #include <linux/module.h>
>  #include <linux/crypto.h>
> +#include <crypto/sig.h>
>  #include <crypto/streebog.h>
> -#include <crypto/internal/akcipher.h>
>  #include <crypto/internal/ecc.h>
> -#include <crypto/akcipher.h>
> +#include <crypto/internal/sig.h>
>  #include <linux/oid_registry.h>
> -#include <linux/scatterlist.h>
>  #include "ecrdsa_params.asn1.h"
>  #include "ecrdsa_pub_key.asn1.h"
>  #include "ecrdsa_defs.h"
> @@ -68,13 +67,12 @@ static const struct ecc_curve *get_curve_by_oid(enum OID oid)
>  	}
>  }
>  
> -static int ecrdsa_verify(struct akcipher_request *req)
> +static int ecrdsa_verify(struct crypto_sig *tfm,
> +			 const void *src, unsigned int slen,
> +			 const void *digest, unsigned int dlen)
>  {
> -	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> -	struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> -	unsigned char sig[ECRDSA_MAX_SIG_SIZE];
> -	unsigned char digest[STREEBOG512_DIGEST_SIZE];
> -	unsigned int ndigits = req->dst_len / sizeof(u64);
> +	struct ecrdsa_ctx *ctx = crypto_sig_ctx(tfm);
> +	unsigned int ndigits = dlen / sizeof(u64);
>  	u64 r[ECRDSA_MAX_DIGITS]; /* witness (r) */
>  	u64 _r[ECRDSA_MAX_DIGITS]; /* -r */
>  	u64 s[ECRDSA_MAX_DIGITS]; /* second part of sig (s) */
> @@ -91,25 +89,19 @@ static int ecrdsa_verify(struct akcipher_request *req)
>  	 */
>  	if (!ctx->curve ||
>  	    !ctx->digest ||
> -	    !req->src ||
> +	    !src ||
> +	    !digest ||
>  	    !ctx->pub_key.x ||
> -	    req->dst_len != ctx->digest_len ||
> -	    req->dst_len != ctx->curve->g.ndigits * sizeof(u64) ||
> +	    dlen != ctx->digest_len ||
> +	    dlen != ctx->curve->g.ndigits * sizeof(u64) ||
>  	    ctx->pub_key.ndigits != ctx->curve->g.ndigits ||
> -	    req->dst_len * 2 != req->src_len ||
> -	    WARN_ON(req->src_len > sizeof(sig)) ||
> -	    WARN_ON(req->dst_len > sizeof(digest)))
> +	    dlen * 2 != slen ||
> +	    WARN_ON(slen > ECRDSA_MAX_SIG_SIZE) ||
> +	    WARN_ON(dlen > STREEBOG512_DIGEST_SIZE))

Despite being migration I don't see no point recycling use of WARN_ON()
here, given panic_on_warn kernel command-line flag.

If you want to print to something, please do separate checks and use
pr_warn() instead at most.

BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks
  2024-09-10 14:30 ` [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks Lukas Wunner
  2024-09-10 19:03   ` Stefan Berger
@ 2024-09-11 12:54   ` Jarkko Sakkinen
  1 sibling, 0 replies; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-11 12:54 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Stefan Berger, Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> pkcs1pad_set_pub_key() and pkcs1pad_set_priv_key() are almost identical.
>
> The upcoming migration of sign/verify operations from rsa-pkcs1pad.c
> into a separate crypto_template will require another copy of the exact
> same functions.  When RSASSA-PSS and RSAES-OAEP are introduced, each
> will need yet another copy.
>
> Deduplicate the functions into a single one which lives in a common
> header file for reuse by RSASSA-PKCS1-v1_5, RSASSA-PSS and RSAES-OAEP.

Nit: I'd simply swap the order of the two last paragraphs. I.e. I get
the question and then I have energy to read the answer ;-) For longer
feature patch starting with motivation makes more sense but here I
think opposite order would serve better...

>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>  crypto/rsa-pkcs1pad.c         | 30 ++----------------------------
>  include/crypto/internal/rsa.h | 28 ++++++++++++++++++++++++++++
>  2 files changed, 30 insertions(+), 28 deletions(-)
>
> diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
> index cd501195f34a..3c5fe8c93938 100644
> --- a/crypto/rsa-pkcs1pad.c
> +++ b/crypto/rsa-pkcs1pad.c
> @@ -131,42 +131,16 @@ static int pkcs1pad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
>  		unsigned int keylen)
>  {
>  	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
> -	int err;
> -
> -	ctx->key_size = 0;
>  
> -	err = crypto_akcipher_set_pub_key(ctx->child, key, keylen);
> -	if (err)
> -		return err;
> -
> -	/* Find out new modulus size from rsa implementation */
> -	err = crypto_akcipher_maxsize(ctx->child);
> -	if (err > PAGE_SIZE)
> -		return -ENOTSUPP;
> -
> -	ctx->key_size = err;
> -	return 0;
> +	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PUB, key, keylen);
>  }
>  
>  static int pkcs1pad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
>  		unsigned int keylen)
>  {
>  	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
> -	int err;
> -
> -	ctx->key_size = 0;
>  
> -	err = crypto_akcipher_set_priv_key(ctx->child, key, keylen);
> -	if (err)
> -		return err;
> -
> -	/* Find out new modulus size from rsa implementation */
> -	err = crypto_akcipher_maxsize(ctx->child);
> -	if (err > PAGE_SIZE)
> -		return -ENOTSUPP;
> -
> -	ctx->key_size = err;
> -	return 0;
> +	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PRIV, key, keylen);
>  }
>  
>  static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
> diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
> index e870133f4b77..754f687134df 100644
> --- a/include/crypto/internal/rsa.h
> +++ b/include/crypto/internal/rsa.h
> @@ -8,6 +8,7 @@
>  #ifndef _RSA_HELPER_
>  #define _RSA_HELPER_
>  #include <linux/types.h>
> +#include <crypto/akcipher.h>
>  
>  /**
>   * rsa_key - RSA key structure
> @@ -53,5 +54,32 @@ int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
>  int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
>  		       unsigned int key_len);
>  
> +#define RSA_PUB (true)
> +#define RSA_PRIV (false)
> +

/**
 * rsa_set_key() - <summary>
 * <params>
 *
 * <description>
 */
> +static inline int rsa_set_key(struct crypto_akcipher *child,
> +			      unsigned int *key_size, bool is_pubkey,
> +			      const void *key, unsigned int keylen)
> +{
> +	int err;
> +
> +	*key_size = 0;
> +
> +	if (is_pubkey)
> +		err = crypto_akcipher_set_pub_key(child, key, keylen);
> +	else
> +		err = crypto_akcipher_set_priv_key(child, key, keylen);
> +	if (err)
> +		return err;
> +
> +	/* Find out new modulus size from rsa implementation */
> +	err = crypto_akcipher_maxsize(child);
> +	if (err > PAGE_SIZE)
> +		return -ENOTSUPP;
> +
> +	*key_size = err;
> +	return 0;
> +}
> +
>  extern struct crypto_template rsa_pkcs1pad_tmpl;
>  #endif

BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-09-10 14:30 ` [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend Lukas Wunner
@ 2024-09-11 12:56   ` Jarkko Sakkinen
  2024-10-21 16:08   ` Klara Modin
  1 sibling, 0 replies; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-11 12:56 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Stefan Berger, Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings,
	Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
	linux-security-module

On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> A sig_alg backend has just been introduced with the intent of moving all
> asymmetric sign/verify algorithms to it one by one.
>
> Migrate the sign/verify operations from rsa-pkcs1pad.c to a separate
> rsassa-pkcs1.c which uses the new backend.
>
> Consequently there are now two templates which build on the "rsa"
> akcipher_alg:
>
> * The existing "pkcs1pad" template, which is instantiated as an
>   akcipher_instance and retains the encrypt/decrypt operations of
>   RSAES-PKCS1-v1_5 (RFC 8017 sec 7.2).
>
> * The new "pkcs1" template, which is instantiated as a sig_instance
>   and contains the sign/verify operations of RSASSA-PKCS1-v1_5
>   (RFC 8017 sec 8.2).
>
> In a separate step, rsa-pkcs1pad.c could optionally be renamed to
> rsaes-pkcs1.c for clarity.  Additional "oaep" and "pss" templates
> could be added for RSAES-OAEP and RSASSA-PSS.
>
> Note that it's currently allowed to allocate a "pkcs1pad(rsa)" transform
> without specifying a hash algorithm.  That makes sense if the transform
> is only used for encrypt/decrypt and continues to be supported.  But for
> sign/verify, such transforms previously did not insert the Full Hash
> Prefix into the padding.  The resulting message encoding was incompliant
> with EMSA-PKCS1-v1_5 (RFC 8017 sec 9.2) and therefore nonsensical.
>
> From here on in, it is no longer allowed to allocate a transform without
> specifying a hash algorithm if the transform is used for sign/verify
> operations.  This simplifies the code because the insertion of the Full
> Hash Prefix is no longer optional, so various "if (digest_info)" clauses
> can be removed.
>
> There has been a previous attempt to forbid transform allocation without
> specifying a hash algorithm, namely by commit c0d20d22e0ad ("crypto:
> rsa-pkcs1pad - Require hash to be present").  It had to be rolled back
> with commit b3a8c8a5ebb5 ("crypto: rsa-pkcs1pad: Allow hash to be
> optional [ver #2]"), presumably because it broke allocation of a
> transform which was solely used for encrypt/decrypt, not sign/verify.
> Avoid such breakage by allowing transform allocation for encrypt/decrypt
> with and without specifying a hash algorithm (and simply ignoring the
> hash algorithm in the former case).
>
> So again, specifying a hash algorithm is now mandatory for sign/verify,
> but optional and ignored for encrypt/decrypt.
>
> The new sig_alg API uses kernel buffers instead of sglists, which
> avoids the overhead of copying signature and digest from sglists back
> into kernel buffers.  rsassa-pkcs1.c is thus simplified quite a bit.
>
> sig_alg is always synchronous, whereas the underlying "rsa" akcipher_alg
> may be asynchronous.  So await the result of the akcipher_alg, similar
> to crypto_akcipher_sync_{en,de}crypt().
>
> As part of the migration, rename "rsa_digest_info" to "hash_prefix" to
> adhere to the spec language in RFC 9580.  Otherwise keep the code
> unmodified wherever possible to ease reviewing and bisecting.  Leave
> several simplification and hardening opportunities to separate commits.
>
> rsassa-pkcs1.c uses modern __free() syntax for allocation of buffers
> which need to be freed by kfree_sensitive(), hence a DEFINE_FREE()
> clause for kfree_sensitive() is introduced herein as a byproduct.

Just a generic comment without micro managing: I'd put focus on this
commit message and edit it a few rounds to make it easier to follow.
Now it is somewhat convoluted, which is not in balance with +480
SLOC.

>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>  crypto/Kconfig                      |   1 +
>  crypto/Makefile                     |   1 +
>  crypto/asymmetric_keys/public_key.c |  10 +-
>  crypto/rsa-pkcs1pad.c               | 341 ++--------------------
>  crypto/rsa.c                        |  17 +-
>  crypto/rsassa-pkcs1.c               | 422 ++++++++++++++++++++++++++++
>  crypto/testmgr.c                    |  22 +-
>  crypto/testmgr.h                    |   3 +-
>  include/crypto/internal/rsa.h       |   1 +
>  include/linux/slab.h                |   1 +
>  security/integrity/ima/ima_main.c   |   6 +-
>  11 files changed, 480 insertions(+), 345 deletions(-)
>  create mode 100644 crypto/rsassa-pkcs1.c
>
> diff --git a/crypto/Kconfig b/crypto/Kconfig
> index e8488b8c45e3..94ef57c9e936 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -250,6 +250,7 @@ config CRYPTO_RSA
>  	tristate "RSA (Rivest-Shamir-Adleman)"
>  	select CRYPTO_AKCIPHER
>  	select CRYPTO_MANAGER
> +	select CRYPTO_SIG
>  	select MPILIB
>  	select ASN1
>  	help
> diff --git a/crypto/Makefile b/crypto/Makefile
> index 4c99e5d376f6..7de29bf843e9 100644
> --- a/crypto/Makefile
> +++ b/crypto/Makefile
> @@ -48,6 +48,7 @@ rsa_generic-y += rsaprivkey.asn1.o
>  rsa_generic-y += rsa.o
>  rsa_generic-y += rsa_helper.o
>  rsa_generic-y += rsa-pkcs1pad.o
> +rsa_generic-y += rsassa-pkcs1.o
>  obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
>  
>  $(obj)/ecdsasignature.asn1.o: $(obj)/ecdsasignature.asn1.c $(obj)/ecdsasignature.asn1.h
> diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
> index 422940a6706a..3fb27ecd65f6 100644
> --- a/crypto/asymmetric_keys/public_key.c
> +++ b/crypto/asymmetric_keys/public_key.c
> @@ -83,13 +83,19 @@ software_key_determine_akcipher(const struct public_key *pkey,
>  		if (strcmp(encoding, "pkcs1") == 0) {
>  			*sig = op == kernel_pkey_sign ||
>  			       op == kernel_pkey_verify;
> -			if (!hash_algo) {
> +			if (!*sig) {
> +				/*
> +				 * For encrypt/decrypt, hash_algo is not used
> +				 * but allowed to be set for historic reasons.
> +				 */
>  				n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
>  					     "pkcs1pad(%s)",
>  					     pkey->pkey_algo);
>  			} else {
> +				if (!hash_algo)
> +					return -EINVAL;
>  				n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
> -					     "pkcs1pad(%s,%s)",
> +					     "pkcs1(%s,%s)",
>  					     pkey->pkey_algo, hash_algo);
>  			}
>  			return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
> diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
> index 3c5fe8c93938..50bdb18e7b48 100644
> --- a/crypto/rsa-pkcs1pad.c
> +++ b/crypto/rsa-pkcs1pad.c
> @@ -16,101 +16,6 @@
>  #include <linux/random.h>
>  #include <linux/scatterlist.h>
>  
> -/*
> - * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
> - */
> -static const u8 rsa_digest_info_md5[] = {
> -	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
> -	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
> -	0x05, 0x00, 0x04, 0x10
> -};
> -
> -static const u8 rsa_digest_info_sha1[] = {
> -	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> -	0x2b, 0x0e, 0x03, 0x02, 0x1a,
> -	0x05, 0x00, 0x04, 0x14
> -};
> -
> -static const u8 rsa_digest_info_rmd160[] = {
> -	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> -	0x2b, 0x24, 0x03, 0x02, 0x01,
> -	0x05, 0x00, 0x04, 0x14
> -};
> -
> -static const u8 rsa_digest_info_sha224[] = {
> -	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
> -	0x05, 0x00, 0x04, 0x1c
> -};
> -
> -static const u8 rsa_digest_info_sha256[] = {
> -	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
> -	0x05, 0x00, 0x04, 0x20
> -};
> -
> -static const u8 rsa_digest_info_sha384[] = {
> -	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
> -	0x05, 0x00, 0x04, 0x30
> -};
> -
> -static const u8 rsa_digest_info_sha512[] = {
> -	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
> -	0x05, 0x00, 0x04, 0x40
> -};
> -
> -static const u8 rsa_digest_info_sha3_256[] = {
> -	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08,
> -	0x05, 0x00, 0x04, 0x20
> -};
> -
> -static const u8 rsa_digest_info_sha3_384[] = {
> -	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09,
> -	0x05, 0x00, 0x04, 0x30
> -};
> -
> -static const u8 rsa_digest_info_sha3_512[] = {
> -	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
> -	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0A,
> -	0x05, 0x00, 0x04, 0x40
> -};
> -
> -static const struct rsa_asn1_template {
> -	const char	*name;
> -	const u8	*data;
> -	size_t		size;
> -} rsa_asn1_templates[] = {
> -#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
> -	_(md5),
> -	_(sha1),
> -	_(rmd160),
> -	_(sha256),
> -	_(sha384),
> -	_(sha512),
> -	_(sha224),
> -#undef _
> -#define _(X) { "sha3-" #X, rsa_digest_info_sha3_##X, sizeof(rsa_digest_info_sha3_##X) }
> -	_(256),
> -	_(384),
> -	_(512),
> -#undef _
> -	{ NULL }
> -};
> -
> -static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
> -{
> -	const struct rsa_asn1_template *p;
> -
> -	for (p = rsa_asn1_templates; p->name; p++)
> -		if (strcmp(name, p->name) == 0)
> -			return p;
> -	return NULL;
> -}
> -
>  struct pkcs1pad_ctx {
>  	struct crypto_akcipher *child;
>  	unsigned int key_size;
> @@ -118,7 +23,6 @@ struct pkcs1pad_ctx {
>  
>  struct pkcs1pad_inst_ctx {
>  	struct crypto_akcipher_spawn spawn;
> -	const struct rsa_asn1_template *digest_info;
>  };
>  
>  struct pkcs1pad_request {
> @@ -148,9 +52,9 @@ static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
>  	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
>  
>  	/*
> -	 * The maximum destination buffer size for the encrypt/sign operations
> +	 * The maximum destination buffer size for the encrypt operation
>  	 * will be the same as for RSA, even though it's smaller for
> -	 * decrypt/verify.
> +	 * decrypt.
>  	 */
>  
>  	return ctx->key_size;
> @@ -168,7 +72,7 @@ static void pkcs1pad_sg_set_buf(struct scatterlist *sg, void *buf, size_t len,
>  		sg_chain(sg, nsegs, next);
>  }
>  
> -static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
> +static int pkcs1pad_encrypt_complete(struct akcipher_request *req, int err)
>  {
>  	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
>  	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
> @@ -207,14 +111,14 @@ static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
>  	return err;
>  }
>  
> -static void pkcs1pad_encrypt_sign_complete_cb(void *data, int err)
> +static void pkcs1pad_encrypt_complete_cb(void *data, int err)
>  {
>  	struct akcipher_request *req = data;
>  
>  	if (err == -EINPROGRESS)
>  		goto out;
>  
> -	err = pkcs1pad_encrypt_sign_complete(req, err);
> +	err = pkcs1pad_encrypt_complete(req, err);
>  
>  out:
>  	akcipher_request_complete(req, err);
> @@ -255,7 +159,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
>  
>  	akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
>  	akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
> -			pkcs1pad_encrypt_sign_complete_cb, req);
> +			pkcs1pad_encrypt_complete_cb, req);
>  
>  	/* Reuse output buffer */
>  	akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
> @@ -263,7 +167,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
>  
>  	err = crypto_akcipher_encrypt(&req_ctx->child_req);
>  	if (err != -EINPROGRESS && err != -EBUSY)
> -		return pkcs1pad_encrypt_sign_complete(req, err);
> +		return pkcs1pad_encrypt_complete(req, err);
>  
>  	return err;
>  }
> @@ -368,195 +272,6 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
>  	return err;
>  }
>  
> -static int pkcs1pad_sign(struct akcipher_request *req)
> -{
> -	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> -	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
> -	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
> -	struct akcipher_instance *inst = akcipher_alg_instance(tfm);
> -	struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
> -	const struct rsa_asn1_template *digest_info = ictx->digest_info;
> -	int err;
> -	unsigned int ps_end, digest_info_size = 0;
> -
> -	if (!ctx->key_size)
> -		return -EINVAL;
> -
> -	if (digest_info)
> -		digest_info_size = digest_info->size;
> -
> -	if (req->src_len + digest_info_size > ctx->key_size - 11)
> -		return -EOVERFLOW;
> -
> -	if (req->dst_len < ctx->key_size) {
> -		req->dst_len = ctx->key_size;
> -		return -EOVERFLOW;
> -	}
> -
> -	req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
> -				  GFP_KERNEL);
> -	if (!req_ctx->in_buf)
> -		return -ENOMEM;
> -
> -	ps_end = ctx->key_size - digest_info_size - req->src_len - 2;
> -	req_ctx->in_buf[0] = 0x01;
> -	memset(req_ctx->in_buf + 1, 0xff, ps_end - 1);
> -	req_ctx->in_buf[ps_end] = 0x00;
> -
> -	if (digest_info)
> -		memcpy(req_ctx->in_buf + ps_end + 1, digest_info->data,
> -		       digest_info->size);
> -
> -	pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
> -			ctx->key_size - 1 - req->src_len, req->src);
> -
> -	akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
> -	akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
> -			pkcs1pad_encrypt_sign_complete_cb, req);
> -
> -	/* Reuse output buffer */
> -	akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
> -				   req->dst, ctx->key_size - 1, req->dst_len);
> -
> -	err = crypto_akcipher_decrypt(&req_ctx->child_req);
> -	if (err != -EINPROGRESS && err != -EBUSY)
> -		return pkcs1pad_encrypt_sign_complete(req, err);
> -
> -	return err;
> -}
> -
> -static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
> -{
> -	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> -	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
> -	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
> -	struct akcipher_instance *inst = akcipher_alg_instance(tfm);
> -	struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
> -	const struct rsa_asn1_template *digest_info = ictx->digest_info;
> -	const unsigned int sig_size = req->src_len;
> -	const unsigned int digest_size = req->dst_len;
> -	unsigned int dst_len;
> -	unsigned int pos;
> -	u8 *out_buf;
> -
> -	if (err)
> -		goto done;
> -
> -	err = -EINVAL;
> -	dst_len = req_ctx->child_req.dst_len;
> -	if (dst_len < ctx->key_size - 1)
> -		goto done;
> -
> -	out_buf = req_ctx->out_buf;
> -	if (dst_len == ctx->key_size) {
> -		if (out_buf[0] != 0x00)
> -			/* Decrypted value had no leading 0 byte */
> -			goto done;
> -
> -		dst_len--;
> -		out_buf++;
> -	}
> -
> -	err = -EBADMSG;
> -	if (out_buf[0] != 0x01)
> -		goto done;
> -
> -	for (pos = 1; pos < dst_len; pos++)
> -		if (out_buf[pos] != 0xff)
> -			break;
> -
> -	if (pos < 9 || pos == dst_len || out_buf[pos] != 0x00)
> -		goto done;
> -	pos++;
> -
> -	if (digest_info) {
> -		if (digest_info->size > dst_len - pos)
> -			goto done;
> -		if (crypto_memneq(out_buf + pos, digest_info->data,
> -				  digest_info->size))
> -			goto done;
> -
> -		pos += digest_info->size;
> -	}
> -
> -	err = 0;
> -
> -	if (digest_size != dst_len - pos) {
> -		err = -EKEYREJECTED;
> -		req->dst_len = dst_len - pos;
> -		goto done;
> -	}
> -	/* Extract appended digest. */
> -	sg_pcopy_to_buffer(req->src,
> -			   sg_nents_for_len(req->src, sig_size + digest_size),
> -			   req_ctx->out_buf + ctx->key_size,
> -			   digest_size, sig_size);
> -	/* Do the actual verification step. */
> -	if (memcmp(req_ctx->out_buf + ctx->key_size, out_buf + pos,
> -		   digest_size) != 0)
> -		err = -EKEYREJECTED;
> -done:
> -	kfree_sensitive(req_ctx->out_buf);
> -
> -	return err;
> -}
> -
> -static void pkcs1pad_verify_complete_cb(void *data, int err)
> -{
> -	struct akcipher_request *req = data;
> -
> -	if (err == -EINPROGRESS)
> -		goto out;
> -
> -	err = pkcs1pad_verify_complete(req, err);
> -
> -out:
> -	akcipher_request_complete(req, err);
> -}
> -
> -/*
> - * The verify operation is here for completeness similar to the verification
> - * defined in RFC2313 section 10.2 except that block type 0 is not accepted,
> - * as in RFC2437.  RFC2437 section 9.2 doesn't define any operation to
> - * retrieve the DigestInfo from a signature, instead the user is expected
> - * to call the sign operation to generate the expected signature and compare
> - * signatures instead of the message-digests.
> - */
> -static int pkcs1pad_verify(struct akcipher_request *req)
> -{
> -	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> -	struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
> -	struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
> -	const unsigned int sig_size = req->src_len;
> -	const unsigned int digest_size = req->dst_len;
> -	int err;
> -
> -	if (WARN_ON(req->dst) || WARN_ON(!digest_size) ||
> -	    !ctx->key_size || sig_size != ctx->key_size)
> -		return -EINVAL;
> -
> -	req_ctx->out_buf = kmalloc(ctx->key_size + digest_size, GFP_KERNEL);
> -	if (!req_ctx->out_buf)
> -		return -ENOMEM;
> -
> -	pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf,
> -			    ctx->key_size, NULL);
> -
> -	akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
> -	akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
> -			pkcs1pad_verify_complete_cb, req);
> -
> -	/* Reuse input buffer, output to a new buffer */
> -	akcipher_request_set_crypt(&req_ctx->child_req, req->src,
> -				   req_ctx->out_sg, sig_size, ctx->key_size);
> -
> -	err = crypto_akcipher_encrypt(&req_ctx->child_req);
> -	if (err != -EINPROGRESS && err != -EBUSY)
> -		return pkcs1pad_verify_complete(req, err);
> -
> -	return err;
> -}
> -
>  static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
>  {
>  	struct akcipher_instance *inst = akcipher_alg_instance(tfm);
> @@ -598,7 +313,6 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
>  	struct akcipher_instance *inst;
>  	struct pkcs1pad_inst_ctx *ctx;
>  	struct akcipher_alg *rsa_alg;
> -	const char *hash_name;
>  	int err;
>  
>  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AKCIPHER, &mask);
> @@ -624,36 +338,15 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
>  	}
>  
>  	err = -ENAMETOOLONG;
> -	hash_name = crypto_attr_alg_name(tb[2]);
> -	if (IS_ERR(hash_name)) {
> -		if (snprintf(inst->alg.base.cra_name,
> -			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
> -			     rsa_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
> -			goto err_free_inst;
> -
> -		if (snprintf(inst->alg.base.cra_driver_name,
> -			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
> -			     rsa_alg->base.cra_driver_name) >=
> -			     CRYPTO_MAX_ALG_NAME)
> -			goto err_free_inst;
> -	} else {
> -		ctx->digest_info = rsa_lookup_asn1(hash_name);
> -		if (!ctx->digest_info) {
> -			err = -EINVAL;
> -			goto err_free_inst;
> -		}
> -
> -		if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
> -			     "pkcs1pad(%s,%s)", rsa_alg->base.cra_name,
> -			     hash_name) >= CRYPTO_MAX_ALG_NAME)
> -			goto err_free_inst;
> -
> -		if (snprintf(inst->alg.base.cra_driver_name,
> -			     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
> -			     rsa_alg->base.cra_driver_name,
> -			     hash_name) >= CRYPTO_MAX_ALG_NAME)
> -			goto err_free_inst;
> -	}
> +	if (snprintf(inst->alg.base.cra_name,
> +		     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
> +		     rsa_alg->base.cra_name) >= CRYPTO_MAX_ALG_NAME)
> +		goto err_free_inst;
> +
> +	if (snprintf(inst->alg.base.cra_driver_name,
> +		     CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
> +		     rsa_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
> +		goto err_free_inst;
>  
>  	inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
>  	inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx);
> @@ -663,8 +356,6 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
>  
>  	inst->alg.encrypt = pkcs1pad_encrypt;
>  	inst->alg.decrypt = pkcs1pad_decrypt;
> -	inst->alg.sign = pkcs1pad_sign;
> -	inst->alg.verify = pkcs1pad_verify;
>  	inst->alg.set_pub_key = pkcs1pad_set_pub_key;
>  	inst->alg.set_priv_key = pkcs1pad_set_priv_key;
>  	inst->alg.max_size = pkcs1pad_get_max_size;
> diff --git a/crypto/rsa.c b/crypto/rsa.c
> index d9be9e86097e..89e9fd9f6d7f 100644
> --- a/crypto/rsa.c
> +++ b/crypto/rsa.c
> @@ -402,16 +402,25 @@ static int __init rsa_init(void)
>  		return err;
>  
>  	err = crypto_register_template(&rsa_pkcs1pad_tmpl);
> -	if (err) {
> -		crypto_unregister_akcipher(&rsa);
> -		return err;
> -	}
> +	if (err)
> +		goto err_unregister_rsa;
> +
> +	err = crypto_register_template(&rsassa_pkcs1_tmpl);
> +	if (err)
> +		goto err_unregister_rsa_pkcs1pad;
>  
>  	return 0;
> +
> +err_unregister_rsa_pkcs1pad:
> +	crypto_unregister_template(&rsa_pkcs1pad_tmpl);
> +err_unregister_rsa:
> +	crypto_unregister_akcipher(&rsa);
> +	return err;
>  }
>  
>  static void __exit rsa_exit(void)
>  {
> +	crypto_unregister_template(&rsassa_pkcs1_tmpl);
>  	crypto_unregister_template(&rsa_pkcs1pad_tmpl);
>  	crypto_unregister_akcipher(&rsa);
>  }
> diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
> new file mode 100644
> index 000000000000..779c080fc013
> --- /dev/null
> +++ b/crypto/rsassa-pkcs1.c
> @@ -0,0 +1,422 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * RSA Signature Scheme with Appendix - PKCS #1 v1.5 (RFC 8017 sec 8.2)
> + *
> + * https://www.rfc-editor.org/rfc/rfc8017#section-8.2
> + *
> + * Copyright (c) 2015 - 2024 Intel Corporation
> + */
> +
> +#include <linux/module.h>
> +#include <linux/scatterlist.h>
> +#include <crypto/akcipher.h>
> +#include <crypto/algapi.h>
> +#include <crypto/sig.h>
> +#include <crypto/internal/akcipher.h>
> +#include <crypto/internal/rsa.h>
> +#include <crypto/internal/sig.h>
> +
> +/*
> + * Full Hash Prefix for EMSA-PKCS1-v1_5 encoding method (RFC 9580 table 24)
> + *
> + * RSA keys are usually much larger than the hash of the message to be signed.
> + * The hash is therefore prepended by the Full Hash Prefix and a 0xff padding.
> + * The Full Hash Prefix is an ASN.1 SEQUENCE containing the hash algorithm OID.
> + *
> + * https://www.rfc-editor.org/rfc/rfc9580#table-24
> + */
> +
> +static const u8 hash_prefix_md5[] = {
> +	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,	  /* SEQUENCE (SEQUENCE (OID */
> +	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05,	/*	<algorithm>, */
> +	0x05, 0x00, 0x04, 0x10		      /* NULL), OCTET STRING <hash>) */
> +};
> +
> +static const u8 hash_prefix_sha1[] = {
> +	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> +	0x2b, 0x0e, 0x03, 0x02, 0x1a,
> +	0x05, 0x00, 0x04, 0x14
> +};
> +
> +static const u8 hash_prefix_rmd160[] = {
> +	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
> +	0x2b, 0x24, 0x03, 0x02, 0x01,
> +	0x05, 0x00, 0x04, 0x14
> +};
> +
> +static const u8 hash_prefix_sha224[] = {
> +	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
> +	0x05, 0x00, 0x04, 0x1c
> +};
> +
> +static const u8 hash_prefix_sha256[] = {
> +	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
> +	0x05, 0x00, 0x04, 0x20
> +};
> +
> +static const u8 hash_prefix_sha384[] = {
> +	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
> +	0x05, 0x00, 0x04, 0x30
> +};
> +
> +static const u8 hash_prefix_sha512[] = {
> +	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
> +	0x05, 0x00, 0x04, 0x40
> +};
> +
> +static const u8 hash_prefix_sha3_256[] = {
> +	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08,
> +	0x05, 0x00, 0x04, 0x20
> +};
> +
> +static const u8 hash_prefix_sha3_384[] = {
> +	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09,
> +	0x05, 0x00, 0x04, 0x30
> +};
> +
> +static const u8 hash_prefix_sha3_512[] = {
> +	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
> +	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a,
> +	0x05, 0x00, 0x04, 0x40
> +};
> +
> +static const struct hash_prefix {
> +	const char	*name;
> +	const u8	*data;
> +	size_t		size;
> +} hash_prefixes[] = {
> +#define _(X) { #X, hash_prefix_##X, sizeof(hash_prefix_##X) }
> +	_(md5),
> +	_(sha1),
> +	_(rmd160),
> +	_(sha256),
> +	_(sha384),
> +	_(sha512),
> +	_(sha224),
> +#undef _
> +#define _(X) { "sha3-" #X, hash_prefix_sha3_##X, sizeof(hash_prefix_sha3_##X) }
> +	_(256),
> +	_(384),
> +	_(512),
> +#undef _
> +	{ NULL }
> +};
> +
> +static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name)
> +{
> +	const struct hash_prefix *p;
> +
> +	for (p = hash_prefixes; p->name; p++)
> +		if (strcmp(name, p->name) == 0)
> +			return p;
> +	return NULL;
> +}
> +
> +struct rsassa_pkcs1_ctx {
> +	struct crypto_akcipher *child;
> +	unsigned int key_size;
> +};
> +
> +struct rsassa_pkcs1_inst_ctx {
> +	struct crypto_akcipher_spawn spawn;
> +	const struct hash_prefix *hash_prefix;
> +};
> +
> +static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
> +			     const void *src, unsigned int slen,
> +			     void *dst, unsigned int dlen)
> +{
> +	struct sig_instance *inst = sig_alg_instance(tfm);
> +	struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
> +	const struct hash_prefix *hash_prefix = ictx->hash_prefix;
> +	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
> +	unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
> +	struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
> +	struct scatterlist in_sg[2], out_sg;
> +	struct crypto_wait cwait;
> +	unsigned int pad_len;
> +	unsigned int ps_end;
> +	unsigned int len;
> +	u8 *in_buf;
> +	int err;
> +
> +	if (!ctx->key_size)
> +		return -EINVAL;
> +
> +	if (dlen < ctx->key_size)
> +		return -EOVERFLOW;
> +
> +	if (slen + hash_prefix->size > ctx->key_size - 11)
> +		return -EOVERFLOW;
> +
> +	child_req = kmalloc(sizeof(*child_req) + child_reqsize +
> +			    ctx->key_size - 1 - slen, GFP_KERNEL);
> +	if (!child_req)
> +		return -ENOMEM;
> +
> +	/* RFC 8017 sec 8.2.1 step 1 - EMSA-PKCS1-v1_5 encoding generation */
> +	in_buf = (u8 *)(child_req + 1) + child_reqsize;
> +	ps_end = ctx->key_size - hash_prefix->size - slen - 2;
> +	in_buf[0] = 0x01;
> +	memset(in_buf + 1, 0xff, ps_end - 1);
> +	in_buf[ps_end] = 0x00;
> +	memcpy(in_buf + ps_end + 1, hash_prefix->data, hash_prefix->size);
> +
> +	/* RFC 8017 sec 8.2.1 step 2 - RSA signature */
> +	crypto_init_wait(&cwait);
> +	sg_init_table(in_sg, 2);
> +	sg_set_buf(&in_sg[0], in_buf, ctx->key_size - 1 - slen);
> +	sg_set_buf(&in_sg[1], src, slen);
> +	sg_init_one(&out_sg, dst, dlen);
> +	akcipher_request_set_tfm(child_req, ctx->child);
> +	akcipher_request_set_crypt(child_req, in_sg, &out_sg,
> +				   ctx->key_size - 1, dlen);
> +	akcipher_request_set_callback(child_req, CRYPTO_TFM_REQ_MAY_SLEEP,
> +				      crypto_req_done, &cwait);
> +
> +	err = crypto_akcipher_decrypt(child_req);
> +	err = crypto_wait_req(err, &cwait);
> +	if (err)
> +		return err;
> +
> +	len = child_req->dst_len;
> +	pad_len = ctx->key_size - len;
> +
> +	/* Four billion to one */
> +	if (unlikely(pad_len)) {
> +		memmove(dst + pad_len, dst, len);
> +		memset(dst, 0, pad_len);
> +	}
> +
> +	return 0;
> +}
> +
> +static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
> +			       const void *src, unsigned int slen,
> +			       const void *digest, unsigned int dlen)
> +{
> +	struct sig_instance *inst = sig_alg_instance(tfm);
> +	struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
> +	const struct hash_prefix *hash_prefix = ictx->hash_prefix;
> +	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
> +	unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
> +	struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
> +	struct scatterlist in_sg, out_sg;
> +	struct crypto_wait cwait;
> +	unsigned int dst_len;
> +	unsigned int pos;
> +	u8 *out_buf;
> +	int err;
> +
> +	/* RFC 8017 sec 8.2.2 step 1 - length checking */
> +	if (!ctx->key_size ||
> +	    slen != ctx->key_size ||
> +	    !dlen)
> +		return -EINVAL;
> +
> +	/* RFC 8017 sec 8.2.2 step 2 - RSA verification */
> +	child_req = kmalloc(sizeof(*child_req) + child_reqsize + ctx->key_size,
> +			    GFP_KERNEL);
> +	if (!child_req)
> +		return -ENOMEM;
> +
> +	out_buf = (u8 *)(child_req + 1) + child_reqsize;
> +
> +	crypto_init_wait(&cwait);
> +	sg_init_one(&in_sg, src, slen);
> +	sg_init_one(&out_sg, out_buf, ctx->key_size);
> +	akcipher_request_set_tfm(child_req, ctx->child);
> +	akcipher_request_set_crypt(child_req, &in_sg, &out_sg,
> +				   slen, ctx->key_size);
> +	akcipher_request_set_callback(child_req, CRYPTO_TFM_REQ_MAY_SLEEP,
> +				      crypto_req_done, &cwait);
> +
> +	err = crypto_akcipher_encrypt(child_req);
> +	err = crypto_wait_req(err, &cwait);
> +	if (err)
> +		return err;
> +
> +	/* RFC 8017 sec 8.2.2 step 3 - EMSA-PKCS1-v1_5 encoding verification */
> +	dst_len = child_req->dst_len;
> +	if (dst_len < ctx->key_size - 1)
> +		return -EINVAL;
> +
> +	if (dst_len == ctx->key_size) {
> +		if (out_buf[0] != 0x00)
> +			/* Encrypted value had no leading 0 byte */
> +			return -EINVAL;
> +
> +		dst_len--;
> +		out_buf++;
> +	}
> +
> +	if (out_buf[0] != 0x01)
> +		return -EBADMSG;
> +
> +	for (pos = 1; pos < dst_len; pos++)
> +		if (out_buf[pos] != 0xff)
> +			break;
> +
> +	if (pos < 9 || pos == dst_len || out_buf[pos] != 0x00)
> +		return -EBADMSG;
> +	pos++;
> +
> +	if (hash_prefix->size > dst_len - pos)
> +		return -EBADMSG;
> +	if (crypto_memneq(out_buf + pos, hash_prefix->data, hash_prefix->size))
> +		return -EBADMSG;
> +	pos += hash_prefix->size;
> +
> +	/* RFC 8017 sec 8.2.2 step 4 - comparison of digest with out_buf */
> +	if (dlen != dst_len - pos)
> +		return -EKEYREJECTED;
> +	if (memcmp(digest, out_buf + pos, dlen) != 0)
> +		return -EKEYREJECTED;
> +
> +	return 0;
> +}
> +
> +static unsigned int rsassa_pkcs1_max_size(struct crypto_sig *tfm)
> +{
> +	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
> +
> +	return ctx->key_size;
> +}
> +
> +static int rsassa_pkcs1_set_pub_key(struct crypto_sig *tfm,
> +				    const void *key, unsigned int keylen)
> +{
> +	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
> +
> +	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PUB, key, keylen);
> +}
> +
> +static int rsassa_pkcs1_set_priv_key(struct crypto_sig *tfm,
> +				     const void *key, unsigned int keylen)
> +{
> +	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
> +
> +	return rsa_set_key(ctx->child, &ctx->key_size, RSA_PRIV, key, keylen);
> +}
> +
> +static int rsassa_pkcs1_init_tfm(struct crypto_sig *tfm)
> +{
> +	struct sig_instance *inst = sig_alg_instance(tfm);
> +	struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
> +	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
> +	struct crypto_akcipher *child_tfm;
> +
> +	child_tfm = crypto_spawn_akcipher(&ictx->spawn);
> +	if (IS_ERR(child_tfm))
> +		return PTR_ERR(child_tfm);
> +
> +	ctx->child = child_tfm;
> +
> +	return 0;
> +}
> +
> +static void rsassa_pkcs1_exit_tfm(struct crypto_sig *tfm)
> +{
> +	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
> +
> +	crypto_free_akcipher(ctx->child);
> +}
> +
> +static void rsassa_pkcs1_free(struct sig_instance *inst)
> +{
> +	struct rsassa_pkcs1_inst_ctx *ctx = sig_instance_ctx(inst);
> +	struct crypto_akcipher_spawn *spawn = &ctx->spawn;
> +
> +	crypto_drop_akcipher(spawn);
> +	kfree(inst);
> +}
> +
> +static int rsassa_pkcs1_create(struct crypto_template *tmpl, struct rtattr **tb)
> +{
> +	struct rsassa_pkcs1_inst_ctx *ctx;
> +	struct akcipher_alg *rsa_alg;
> +	struct sig_instance *inst;
> +	const char *hash_name;
> +	u32 mask;
> +	int err;
> +
> +	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SIG, &mask);
> +	if (err)
> +		return err;
> +
> +	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
> +	if (!inst)
> +		return -ENOMEM;
> +
> +	ctx = sig_instance_ctx(inst);
> +
> +	err = crypto_grab_akcipher(&ctx->spawn, sig_crypto_instance(inst),
> +				   crypto_attr_alg_name(tb[1]), 0, mask);
> +	if (err)
> +		goto err_free_inst;
> +
> +	rsa_alg = crypto_spawn_akcipher_alg(&ctx->spawn);
> +
> +	if (strcmp(rsa_alg->base.cra_name, "rsa") != 0) {
> +		err = -EINVAL;
> +		goto err_free_inst;
> +	}
> +
> +	hash_name = crypto_attr_alg_name(tb[2]);
> +	if (IS_ERR(hash_name)) {
> +		err = PTR_ERR(hash_name);
> +		goto err_free_inst;
> +	}
> +
> +	ctx->hash_prefix = rsassa_pkcs1_find_hash_prefix(hash_name);
> +	if (!ctx->hash_prefix) {
> +		err = -EINVAL;
> +		goto err_free_inst;
> +	}
> +
> +	err = -ENAMETOOLONG;
> +	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
> +		     "pkcs1(%s,%s)", rsa_alg->base.cra_name,
> +		     hash_name) >= CRYPTO_MAX_ALG_NAME)
> +		goto err_free_inst;
> +
> +	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
> +		     "pkcs1(%s,%s)", rsa_alg->base.cra_driver_name,
> +		     hash_name) >= CRYPTO_MAX_ALG_NAME)
> +		goto err_free_inst;
> +
> +	inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
> +	inst->alg.base.cra_ctxsize = sizeof(struct rsassa_pkcs1_ctx);
> +
> +	inst->alg.init = rsassa_pkcs1_init_tfm;
> +	inst->alg.exit = rsassa_pkcs1_exit_tfm;
> +
> +	inst->alg.sign = rsassa_pkcs1_sign;
> +	inst->alg.verify = rsassa_pkcs1_verify;
> +	inst->alg.max_size = rsassa_pkcs1_max_size;
> +	inst->alg.set_pub_key = rsassa_pkcs1_set_pub_key;
> +	inst->alg.set_priv_key = rsassa_pkcs1_set_priv_key;
> +
> +	inst->free = rsassa_pkcs1_free;
> +
> +	err = sig_register_instance(tmpl, inst);
> +	if (err) {
> +err_free_inst:
> +		rsassa_pkcs1_free(inst);
> +	}
> +	return err;
> +}
> +
> +struct crypto_template rsassa_pkcs1_tmpl = {
> +	.name = "pkcs1",
> +	.create = rsassa_pkcs1_create,
> +	.module = THIS_MODULE,
> +};
> +
> +MODULE_ALIAS_CRYPTO("pkcs1");
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index 0542817a9456..91dc29e79dd6 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -5548,34 +5548,38 @@ static const struct alg_test_desc alg_test_descs[] = {
>  			.cipher = __VECS(fcrypt_pcbc_tv_template)
>  		}
>  	}, {
> -		.alg = "pkcs1pad(rsa,sha224)",
> +		.alg = "pkcs1(rsa,sha224)",
>  		.test = alg_test_null,
>  		.fips_allowed = 1,
>  	}, {
> -		.alg = "pkcs1pad(rsa,sha256)",
> -		.test = alg_test_akcipher,
> +		.alg = "pkcs1(rsa,sha256)",
> +		.test = alg_test_sig,
>  		.fips_allowed = 1,
>  		.suite = {
> -			.akcipher = __VECS(pkcs1pad_rsa_tv_template)
> +			.sig = __VECS(pkcs1_rsa_tv_template)
>  		}
>  	}, {
> -		.alg = "pkcs1pad(rsa,sha3-256)",
> +		.alg = "pkcs1(rsa,sha3-256)",
> +		.test = alg_test_null,
> +		.fips_allowed = 1,
> +	}, {
> +		.alg = "pkcs1(rsa,sha3-384)",
>  		.test = alg_test_null,
>  		.fips_allowed = 1,
>  	}, {
> -		.alg = "pkcs1pad(rsa,sha3-384)",
> +		.alg = "pkcs1(rsa,sha3-512)",
>  		.test = alg_test_null,
>  		.fips_allowed = 1,
>  	}, {
> -		.alg = "pkcs1pad(rsa,sha3-512)",
> +		.alg = "pkcs1(rsa,sha384)",
>  		.test = alg_test_null,
>  		.fips_allowed = 1,
>  	}, {
> -		.alg = "pkcs1pad(rsa,sha384)",
> +		.alg = "pkcs1(rsa,sha512)",
>  		.test = alg_test_null,
>  		.fips_allowed = 1,
>  	}, {
> -		.alg = "pkcs1pad(rsa,sha512)",
> +		.alg = "pkcs1pad(rsa)",
>  		.test = alg_test_null,
>  		.fips_allowed = 1,
>  	}, {
> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index fd4823c26d93..d29d03fec852 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -1268,7 +1268,7 @@ static const struct sig_testvec ecrdsa_tv_template[] = {
>  /*
>   * PKCS#1 RSA test vectors. Obtained from CAVS testing.
>   */
> -static const struct akcipher_testvec pkcs1pad_rsa_tv_template[] = {
> +static const struct sig_testvec pkcs1_rsa_tv_template[] = {
>  	{
>  	.key =
>  	"\x30\x82\x04\xa5\x02\x01\x00\x02\x82\x01\x01\x00\xd7\x1e\x77\x82"
> @@ -1380,7 +1380,6 @@ static const struct akcipher_testvec pkcs1pad_rsa_tv_template[] = {
>  	"\xda\x62\x8d\xe1\x2a\x71\x91\x43\x40\x61\x3c\x5a\xbe\x86\xfc\x5b"
>  	"\xe6\xf9\xa9\x16\x31\x1f\xaf\x25\x6d\xc2\x4a\x23\x6e\x63\x02\xa2",
>  	.c_size = 256,
> -	.siggen_sigver_test = true,
>  	}
>  };
>  
> diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
> index 754f687134df..071a1951b992 100644
> --- a/include/crypto/internal/rsa.h
> +++ b/include/crypto/internal/rsa.h
> @@ -82,4 +82,5 @@ static inline int rsa_set_key(struct crypto_akcipher *child,
>  }
>  
>  extern struct crypto_template rsa_pkcs1pad_tmpl;
> +extern struct crypto_template rsassa_pkcs1_tmpl;
>  #endif
> diff --git a/include/linux/slab.h b/include/linux/slab.h
> index eb2bf4629157..11b620b0ba1d 100644
> --- a/include/linux/slab.h
> +++ b/include/linux/slab.h
> @@ -280,6 +280,7 @@ void kfree_sensitive(const void *objp);
>  size_t __ksize(const void *objp);
>  
>  DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T))
> +DEFINE_FREE(kfree_sensitive, void *, if (_T) kfree_sensitive(_T))
>  
>  /**
>   * ksize - Report actual allocation size of associated object
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index f04f43af651c..280a3feeba45 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -1114,7 +1114,7 @@ EXPORT_SYMBOL_GPL(ima_measure_critical_data);
>  #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
>  
>  /**
> - * ima_kernel_module_request - Prevent crypto-pkcs1pad(rsa,*) requests
> + * ima_kernel_module_request - Prevent crypto-pkcs1(rsa,*) requests
>   * @kmod_name: kernel module name
>   *
>   * Avoid a verification loop where verifying the signature of the modprobe
> @@ -1128,7 +1128,7 @@ EXPORT_SYMBOL_GPL(ima_measure_critical_data);
>   * algorithm on the fly, but crypto_larval_lookup() will try to use alg_name
>   * in order to load a kernel module with same name.
>   *
> - * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
> + * Since we don't have any real "crypto-pkcs1(rsa,*)" kernel modules,
>   * we are safe to fail such module request from crypto_larval_lookup(), and
>   * avoid the verification loop.
>   *
> @@ -1136,7 +1136,7 @@ EXPORT_SYMBOL_GPL(ima_measure_critical_data);
>   */
>  static int ima_kernel_module_request(char *kmod_name)
>  {
> -	if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
> +	if (strncmp(kmod_name, "crypto-pkcs1(rsa,", 17) == 0)
>  		return -EINVAL;
>  
>  	return 0;


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 07/19] crypto: rsassa-pkcs1 - Harden digest length verification
  2024-09-10 14:30 ` [PATCH v2 07/19] crypto: rsassa-pkcs1 - Harden digest length verification Lukas Wunner
@ 2024-09-11 12:58   ` Jarkko Sakkinen
  0 siblings, 0 replies; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-11 12:58 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Stefan Berger, Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> The RSASSA-PKCS1-v1_5 sign operation currently only checks that the
> digest length is less than "key_size - hash_prefix->size - 11".
> The verify operation merely checks that it's more than zero.
>
> Actually the precise digest length is known because the hash algorithm
> is specified upon instance creation and the digest length is encoded
> into the final byte of the hash algorithm's Full Hash Prefix.
>
> So check for the exact digest length rather than solely relying on
> imprecise maximum/minimum checks.
>
> Keep the maximum length check for the sign operation as a safety net,
> but drop the now unnecessary minimum check for the verify operation.
>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>  crypto/rsassa-pkcs1.c | 20 +++++++++++++++++++-
>  1 file changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
> index 779c080fc013..8f42a5712806 100644
> --- a/crypto/rsassa-pkcs1.c
> +++ b/crypto/rsassa-pkcs1.c
> @@ -11,6 +11,7 @@
>  #include <linux/scatterlist.h>
>  #include <crypto/akcipher.h>
>  #include <crypto/algapi.h>
> +#include <crypto/hash.h>
>  #include <crypto/sig.h>
>  #include <crypto/internal/akcipher.h>
>  #include <crypto/internal/rsa.h>
> @@ -118,6 +119,20 @@ static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name)
>  	return NULL;
>  }
>  
> +static unsigned int rsassa_pkcs1_hash_len(const struct hash_prefix *p)
> +{
> +	/*
> +	 * The final byte of the Full Hash Prefix encodes the hash length.
> +	 *
> +	 * This needs to be revisited should hash algorithms with more than
> +	 * 1016 bits (127 bytes * 8) ever be added.  The length would then
> +	 * be encoded into more than one byte by ASN.1.
> +	 */

Maybe this could be moved outside the function.

> +	static_assert(HASH_MAX_DIGESTSIZE <= 127);
> +
> +	return p->data[p->size - 1];
> +}
> +
>  struct rsassa_pkcs1_ctx {
>  	struct crypto_akcipher *child;
>  	unsigned int key_size;
> @@ -152,6 +167,9 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
>  	if (dlen < ctx->key_size)
>  		return -EOVERFLOW;
>  
> +	if (slen != rsassa_pkcs1_hash_len(hash_prefix))
> +		return -EINVAL;
> +
>  	if (slen + hash_prefix->size > ctx->key_size - 11)
>  		return -EOVERFLOW;
>  
> @@ -217,7 +235,7 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
>  	/* RFC 8017 sec 8.2.2 step 1 - length checking */
>  	if (!ctx->key_size ||
>  	    slen != ctx->key_size ||
> -	    !dlen)
> +	    dlen != rsassa_pkcs1_hash_len(hash_prefix))
>  		return -EINVAL;
>  
>  	/* RFC 8017 sec 8.2.2 step 2 - RSA verification */


BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 08/19] crypto: rsassa-pkcs1 - Avoid copying hash prefix
  2024-09-10 14:30 ` [PATCH v2 08/19] crypto: rsassa-pkcs1 - Avoid copying hash prefix Lukas Wunner
@ 2024-09-11 13:00   ` Jarkko Sakkinen
  0 siblings, 0 replies; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-11 13:00 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Stefan Berger, Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> When constructing the EMSA-PKCS1-v1_5 padding for the sign operation,
> a buffer for the padding is allocated and the Full Hash Prefix is copied
> into it.  The padding is then passed to the RSA decrypt operation as an
> sglist entry which is succeeded by a second sglist entry for the hash.
>
> Actually copying the hash prefix around is completely unnecessary.
> It can simply be referenced from a third sglist entry which sits
> in-between the padding and the digest.
>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>  crypto/rsassa-pkcs1.c | 18 ++++++++++--------
>  1 file changed, 10 insertions(+), 8 deletions(-)
>
> diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
> index 8f42a5712806..b291ec0944a2 100644
> --- a/crypto/rsassa-pkcs1.c
> +++ b/crypto/rsassa-pkcs1.c
> @@ -153,7 +153,7 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
>  	struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
>  	unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
>  	struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
> -	struct scatterlist in_sg[2], out_sg;
> +	struct scatterlist in_sg[3], out_sg;
>  	struct crypto_wait cwait;
>  	unsigned int pad_len;
>  	unsigned int ps_end;
> @@ -173,24 +173,26 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
>  	if (slen + hash_prefix->size > ctx->key_size - 11)
>  		return -EOVERFLOW;
>  
> -	child_req = kmalloc(sizeof(*child_req) + child_reqsize +
> -			    ctx->key_size - 1 - slen, GFP_KERNEL);
> +	pad_len = ctx->key_size - slen - hash_prefix->size - 1;
> +
> +	child_req = kmalloc(sizeof(*child_req) + child_reqsize + pad_len,
> +			    GFP_KERNEL);
>  	if (!child_req)
>  		return -ENOMEM;
>  
>  	/* RFC 8017 sec 8.2.1 step 1 - EMSA-PKCS1-v1_5 encoding generation */
>  	in_buf = (u8 *)(child_req + 1) + child_reqsize;
> -	ps_end = ctx->key_size - hash_prefix->size - slen - 2;
> +	ps_end = pad_len - 1;
>  	in_buf[0] = 0x01;
>  	memset(in_buf + 1, 0xff, ps_end - 1);
>  	in_buf[ps_end] = 0x00;
> -	memcpy(in_buf + ps_end + 1, hash_prefix->data, hash_prefix->size);
>  
>  	/* RFC 8017 sec 8.2.1 step 2 - RSA signature */
>  	crypto_init_wait(&cwait);
> -	sg_init_table(in_sg, 2);
> -	sg_set_buf(&in_sg[0], in_buf, ctx->key_size - 1 - slen);
> -	sg_set_buf(&in_sg[1], src, slen);
> +	sg_init_table(in_sg, 3);
> +	sg_set_buf(&in_sg[0], in_buf, pad_len);
> +	sg_set_buf(&in_sg[1], hash_prefix->data, hash_prefix->size);
> +	sg_set_buf(&in_sg[2], src, slen);
>  	sg_init_one(&out_sg, dst, dlen);
>  	akcipher_request_set_tfm(child_req, ctx->child);
>  	akcipher_request_set_crypt(child_req, in_sg, &out_sg,

LGTM. Not giving any tags because given the size of the patch set this
could change in content and/or order (in the series). Wondering if this
could be as a clean up like more in the head of the series?

BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 16/19] crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize()
  2024-09-10 14:30 ` [PATCH v2 16/19] crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize() Lukas Wunner
@ 2024-09-11 13:02   ` Jarkko Sakkinen
  2024-09-12  8:12     ` Lukas Wunner
  0 siblings, 1 reply; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-11 13:02 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Stefan Berger, Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings

On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> crypto_sig_maxsize() is a bit of a misnomer as it doesn't return the
> maximum signature size, but rather the key size.
>
> Rename it as well as all implementations of the ->max_size callback.
> A subsequent commit introduces a crypto_sig_maxsize() function which
> returns the actual maximum signature size.
>
> While at it, change the return type of crypto_sig_keysize() from int to
> unsigned int for consistency with crypto_akcipher_maxsize().  None of
> the callers checks for a negative return value and an error condition
> can always be indicated by returning zero.
>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>

Why this is so late in the series?

BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend
  2024-09-11 12:12   ` Jarkko Sakkinen
@ 2024-09-12  7:54     ` Lukas Wunner
  2024-09-12 14:19       ` Jarkko Sakkinen
  0 siblings, 1 reply; 53+ messages in thread
From: Lukas Wunner @ 2024-09-12  7:54 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings

On Wed, Sep 11, 2024 at 03:12:33PM +0300, Jarkko Sakkinen wrote:
> >  static int crypto_sig_init_tfm(struct crypto_tfm *tfm)
> >  {
> >  	if (tfm->__crt_alg->cra_type != &crypto_sig_type)
> >  		return crypto_init_akcipher_ops_sig(tfm);
> >  
> > +	struct crypto_sig *sig = __crypto_sig_tfm(tfm);
> > +	struct sig_alg *alg = crypto_sig_alg(sig);
> > +
> > +	if (alg->exit)
> > +		sig->base.exit = crypto_sig_exit_tfm;
> > +
> > +	if (alg->init)
> > +		return alg->init(sig);
> 
> 1. alg->exit == NULL, alg->init == NULL
> 2. alg->exit != NULL, alg->init == NULL
> 3. alg->exit == NULL, alg->init != NULL
> 
> Which of the three are legit use of the API and which are not?

All three are possible.  Same as crypto_akcipher_init_tfm().

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements
  2024-09-11 11:52   ` Jarkko Sakkinen
@ 2024-09-12  7:59     ` Lukas Wunner
  0 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-12  7:59 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings

On Wed, Sep 11, 2024 at 02:52:27PM +0300, Jarkko Sakkinen wrote:
> On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> > The ECDSA test vectors contain "params", "param_len" and "algo" elements
> > even though ecdsa.c doesn't make any use of them.  The only algorithm
> > implementation using those elements is ecrdsa.c.
> 
> I'm missing these pieces of information here at least:
> 
> - akcipher.h tells that tail contains OID, parameter blob length and the
>   blob itself.
> - akcipher.h leaves the size of those fields completely *undefined*.
> - According to call sites OID and blob length are 32-bit fields.
> - According to call sites that I bumped into they are always set to
>   zero.
> - There's no information in the kernel source code that I could fine
>   for any other rules how the should be set.
>   
> Putting random words (of which params_len is not even a word) to quotes
> does not really make this whole story obvious. You could just as well
> delete the paragraph, because that only makes you look for a struct
> that does not even exist.

As explained above, "The only algorithm implementation using those elements
is ecrdsa.c."

So if you're interested in understanding how the elements are used,
you need to look at crypto/ecrdsa.c.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 04/19] crypto: ecrdsa - Migrate to sig_alg backend
  2024-09-11 12:49   ` Jarkko Sakkinen
@ 2024-09-12  8:05     ` Lukas Wunner
  2024-09-12 14:20       ` Jarkko Sakkinen
  0 siblings, 1 reply; 53+ messages in thread
From: Lukas Wunner @ 2024-09-12  8:05 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings

On Wed, Sep 11, 2024 at 03:49:07PM +0300, Jarkko Sakkinen wrote:
> On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> > A sig_alg backend has just been introduced with the intent of moving all
> > asymmetric sign/verify algorithms to it one by one.
> >
> > Migrate ecrdsa.c to the new backend.
[...]
> >  	if (!ctx->curve ||
> >  	    !ctx->digest ||
> > -	    !req->src ||
> > +	    !src ||
> > +	    !digest ||
> >  	    !ctx->pub_key.x ||
> > -	    req->dst_len != ctx->digest_len ||
> > -	    req->dst_len != ctx->curve->g.ndigits * sizeof(u64) ||
> > +	    dlen != ctx->digest_len ||
> > +	    dlen != ctx->curve->g.ndigits * sizeof(u64) ||
> >  	    ctx->pub_key.ndigits != ctx->curve->g.ndigits ||
> > -	    req->dst_len * 2 != req->src_len ||
> > -	    WARN_ON(req->src_len > sizeof(sig)) ||
> > -	    WARN_ON(req->dst_len > sizeof(digest)))
> > +	    dlen * 2 != slen ||
> > +	    WARN_ON(slen > ECRDSA_MAX_SIG_SIZE) ||
> > +	    WARN_ON(dlen > STREEBOG512_DIGEST_SIZE))
> 
> Despite being migration I don't see no point recycling use of WARN_ON()
> here, given panic_on_warn kernel command-line flag.
> 
> If you want to print to something, please do separate checks and use
> pr_warn() instead at most.

The object of the patch is to migrate ecrdsa.c to sig_alg with no
behavioral change.

If you feel the WARN_ON() is uncalled for, please submit a cleanup
patch.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 16/19] crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize()
  2024-09-11 13:02   ` Jarkko Sakkinen
@ 2024-09-12  8:12     ` Lukas Wunner
  0 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-12  8:12 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings

On Wed, Sep 11, 2024 at 04:02:03PM +0300, Jarkko Sakkinen wrote:
> On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> > crypto_sig_maxsize() is a bit of a misnomer as it doesn't return the
> > maximum signature size, but rather the key size.
> >
> > Rename it as well as all implementations of the ->max_size callback.
> > A subsequent commit introduces a crypto_sig_maxsize() function which
> > returns the actual maximum signature size.
> >
> > While at it, change the return type of crypto_sig_keysize() from int to
> > unsigned int for consistency with crypto_akcipher_maxsize().  None of
> > the callers checks for a negative return value and an error condition
> > can always be indicated by returning zero.
> 
> Why this is so late in the series?

Because it's a prerequisite for the subsequent patch.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend
  2024-09-12  7:54     ` Lukas Wunner
@ 2024-09-12 14:19       ` Jarkko Sakkinen
  2024-09-12 15:27         ` Lukas Wunner
  0 siblings, 1 reply; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-12 14:19 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings

On Thu Sep 12, 2024 at 10:54 AM EEST, Lukas Wunner wrote:
> On Wed, Sep 11, 2024 at 03:12:33PM +0300, Jarkko Sakkinen wrote:
> > >  static int crypto_sig_init_tfm(struct crypto_tfm *tfm)
> > >  {
> > >  	if (tfm->__crt_alg->cra_type != &crypto_sig_type)
> > >  		return crypto_init_akcipher_ops_sig(tfm);
> > >  
> > > +	struct crypto_sig *sig = __crypto_sig_tfm(tfm);
> > > +	struct sig_alg *alg = crypto_sig_alg(sig);
> > > +
> > > +	if (alg->exit)
> > > +		sig->base.exit = crypto_sig_exit_tfm;
> > > +
> > > +	if (alg->init)
> > > +		return alg->init(sig);
> > 
> > 1. alg->exit == NULL, alg->init == NULL
> > 2. alg->exit != NULL, alg->init == NULL
> > 3. alg->exit == NULL, alg->init != NULL
> > 
> > Which of the three are legit use of the API and which are not?
>
> All three are possible.  Same as crypto_akcipher_init_tfm().

Lot's of nitpicks but...

I try to understand these in detail because I rebase later on my TPM2
ECDSA patches (series last updated in April) on top of this. I'll hold
with that for the sake of less possible conflicts with this larger
series.

Many of the questions rised during the Spring about akcipher so now is
my chance to fill the dots by asking them here.

BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 04/19] crypto: ecrdsa - Migrate to sig_alg backend
  2024-09-12  8:05     ` Lukas Wunner
@ 2024-09-12 14:20       ` Jarkko Sakkinen
  0 siblings, 0 replies; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-12 14:20 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings

On Thu Sep 12, 2024 at 11:05 AM EEST, Lukas Wunner wrote:
> On Wed, Sep 11, 2024 at 03:49:07PM +0300, Jarkko Sakkinen wrote:
> > On Tue Sep 10, 2024 at 5:30 PM EEST, Lukas Wunner wrote:
> > > A sig_alg backend has just been introduced with the intent of moving all
> > > asymmetric sign/verify algorithms to it one by one.
> > >
> > > Migrate ecrdsa.c to the new backend.
> [...]
> > >  	if (!ctx->curve ||
> > >  	    !ctx->digest ||
> > > -	    !req->src ||
> > > +	    !src ||
> > > +	    !digest ||
> > >  	    !ctx->pub_key.x ||
> > > -	    req->dst_len != ctx->digest_len ||
> > > -	    req->dst_len != ctx->curve->g.ndigits * sizeof(u64) ||
> > > +	    dlen != ctx->digest_len ||
> > > +	    dlen != ctx->curve->g.ndigits * sizeof(u64) ||
> > >  	    ctx->pub_key.ndigits != ctx->curve->g.ndigits ||
> > > -	    req->dst_len * 2 != req->src_len ||
> > > -	    WARN_ON(req->src_len > sizeof(sig)) ||
> > > -	    WARN_ON(req->dst_len > sizeof(digest)))
> > > +	    dlen * 2 != slen ||
> > > +	    WARN_ON(slen > ECRDSA_MAX_SIG_SIZE) ||
> > > +	    WARN_ON(dlen > STREEBOG512_DIGEST_SIZE))
> > 
> > Despite being migration I don't see no point recycling use of WARN_ON()
> > here, given panic_on_warn kernel command-line flag.
> > 
> > If you want to print to something, please do separate checks and use
> > pr_warn() instead at most.
>
> The object of the patch is to migrate ecrdsa.c to sig_alg with no
> behavioral change.
>
> If you feel the WARN_ON() is uncalled for, please submit a cleanup
> patch.

OK, put on consideration since I have a related series.

BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend
  2024-09-12 14:19       ` Jarkko Sakkinen
@ 2024-09-12 15:27         ` Lukas Wunner
  2024-09-12 17:14           ` Jarkko Sakkinen
  2024-11-18  7:56           ` Jarkko Sakkinen
  0 siblings, 2 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-09-12 15:27 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings

On Thu, Sep 12, 2024 at 05:19:15PM +0300, Jarkko Sakkinen wrote:
> I try to understand these in detail because I rebase later on my TPM2
> ECDSA patches (series last updated in April) on top of this. I'll hold
> with that for the sake of less possible conflicts with this larger
> series.
> 
> Many of the questions rised during the Spring about akcipher so now is
> my chance to fill the dots by asking them here.

I assume you're referring to:
https://lore.kernel.org/all/20240528210823.28798-1-jarkko@kernel.org/

Help me understand this:
Once you import a private key to a TPM, can you get it out again?
Can you generate private keys on the TPM which cannot be retrieved?

It would be good if the cover letter or one of the commits in your
series explained this.  Some of the commit messages are overly terse
and consist of just two or three bullet points.

The reason I'm asking is, there are security chips such as ATECC508A
which allow generating private ECDSA keys on the chip that cannot
be retrieved.  One can send a message digest to the chip and get
a signature back.  One can also use the chip for signature verification,
but that's less interesting because it's attached via i2c, which is
usually slower than verifying on the CPU:

https://cdn.sparkfun.com/assets/learn_tutorials/1/0/0/3/Microchip_ATECC508A_Datasheet.pdf

If TPMs support unretrievable, maybe even on-device created
private keys, they would offer comparable functionality to the
ATECC508A and that would suggest adding an asymmetric_key_subtype
which uses some kind of abstraction that works for both kinds of
devices.

I note there are ASN.1 modules in your series.  Please provide a
spec reference in the .asn1 file so that one knows where it's
originating from.  If it's originating from an RFC, please add
an SPDX identifier as in commit 201c0da4d029.

Thanks,

Lukas

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend
  2024-09-12 15:27         ` Lukas Wunner
@ 2024-09-12 17:14           ` Jarkko Sakkinen
  2024-11-18  7:56           ` Jarkko Sakkinen
  1 sibling, 0 replies; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-09-12 17:14 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings

On Thu, 2024-09-12 at 17:27 +0200, Lukas Wunner wrote:
> On Thu, Sep 12, 2024 at 05:19:15PM +0300, Jarkko Sakkinen wrote:
> > I try to understand these in detail because I rebase later on my TPM2
> > ECDSA patches (series last updated in April) on top of this. I'll hold
> > with that for the sake of less possible conflicts with this larger
> > series.
> > 
> > Many of the questions rised during the Spring about akcipher so now is
> > my chance to fill the dots by asking them here.
> 
> I assume you're referring to:
> https://lore.kernel.org/all/20240528210823.28798-1-jarkko@kernel.org/
> 
> Help me understand this:
> Once you import a private key to a TPM, can you get it out again?
> Can you generate private keys on the TPM which cannot be retrieved?

It is for implementing TPM2 bits of

https://www.ietf.org/archive/id/draft-woodhouse-cert-best-practice-00.html

The main use case is to protect signing key coming from outside CA
infrastructure.

> It would be good if the cover letter or one of the commits in your
> series explained this.  Some of the commit messages are overly terse
> and consist of just two or three bullet points.

I keep this in mind for the next version. Thanks!

> 
> The reason I'm asking is, there are security chips such as ATECC508A
> which allow generating private ECDSA keys on the chip that cannot
> be retrieved.  One can send a message digest to the chip and get
> a signature back.  One can also use the chip for signature verification,
> but that's less interesting because it's attached via i2c, which is
> usually slower than verifying on the CPU:
> 
> https://cdn.sparkfun.com/assets/learn_tutorials/1/0/0/3/Microchip_ATECC508A_Datasheet.pdf
> 
> If TPMs support unretrievable, maybe even on-device created
> private keys, they would offer comparable functionality to the
> ATECC508A and that would suggest adding an asymmetric_key_subtype
> which uses some kind of abstraction that works for both kinds of
> devices.
> 
> I note there are ASN.1 modules in your series.  Please provide a
> spec reference in the .asn1 file so that one knows where it's
> originating from.  If it's originating from an RFC, please add
> an SPDX identifier as in commit 201c0da4d029.

OK this is good to know and I can address this as follows:

1. I explicitly state that the feature that in the scope of the patch set
   it supports the original use case (or at least how I understood
   David's specification).
2. It is probably then better make sure that the implementation
   does not set any possible roadblocks for the possible use cases
   you described.

Also one thing I'm going to do in order to have better focus is to cut
out RSA part because they don't have to be in the same patch set and it
is way more important to have ECDSA. OFC I'll work on RSA right after
that but I think this is the right order :-)

> 
> Thanks,
> 
> Lukas

BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend
  2024-09-10 14:30 ` [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend Lukas Wunner
  2024-09-11 12:12   ` Jarkko Sakkinen
@ 2024-09-13 18:40   ` Jonathan Cameron
  1 sibling, 0 replies; 53+ messages in thread
From: Jonathan Cameron @ 2024-09-13 18:40 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Ignat Korchagin, Marek Behun, Varad Gautam,
	Denis Kenzior, linux-crypto, keyrings

On Tue, 10 Sep 2024 16:30:12 +0200
Lukas Wunner <lukas@wunner.de> wrote:

> Commit 6cb8815f41a9 ("crypto: sig - Add interface for sign/verify")
> began a transition of asymmetric sign/verify operations from
> crypto_akcipher to a new crypto_sig frontend.
> 
> Internally, the crypto_sig frontend still uses akcipher_alg as backend,
> however:
> 
>    "The link between sig and akcipher is meant to be temporary.  The
>     plan is to create a new low-level API for sig and then migrate
>     the signature code over to that from akcipher."
>     https://lore.kernel.org/r/ZrG6w9wsb-iiLZIF@gondor.apana.org.au/
> 
>    "having a separate alg for sig is definitely where we want to
>     be since there is very little that the two types actually share."
>     https://lore.kernel.org/r/ZrHlpz4qnre0zWJO@gondor.apana.org.au/
> 
> Take the next step of that migration and augment the crypto_sig frontend
> with a sig_alg backend to which all algorithms can be moved.
> 
> During the migration, there will briefly be signature algorithms that
> are still based on crypto_akcipher, whilst others are already based on
> crypto_sig.  Allow for that by building a fork into crypto_sig_*() API
> calls (i.e. crypto_sig_maxsize() and friends) such that one of the two
> backends is selected based on the transform's cra_type.
> 
> Signed-off-by: Lukas Wunner <lukas@wunner.de>

Hi Lukas,

A few trivial comments.

Jonathan

> diff --git a/crypto/sig.c b/crypto/sig.c
> index 7645bedf3a1f..4f36ceb7a90b 100644
> --- a/crypto/sig.c
> +++ b/crypto/sig.c

> @@ -68,6 +93,14 @@ EXPORT_SYMBOL_GPL(crypto_alloc_sig);
>  
>  int crypto_sig_maxsize(struct crypto_sig *tfm)
>  {
> +	if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
> +		goto akcipher;
> +
> +	struct sig_alg *alg = crypto_sig_alg(tfm);
> +
> +	return alg->max_size(tfm);
> +
> +akcipher:

Neat trick for temporary retention of the code.
Hideous code in the meantime ;) Not that I have a better idea.

>  	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
>  
>  	return crypto_akcipher_maxsize(*ctx);

> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index f02cb075bd68..bb21378aa510 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
...

> @@ -4317,6 +4324,114 @@ static int alg_test_akcipher(const struct alg_test_desc *desc,
>  	return err;
>  }
>  
> +static int test_sig_one(struct crypto_sig *tfm, const struct sig_testvec *vecs)
> +{
> +	u8 *ptr, *key __free(kfree);
I would move definition of key down to where the constructor is.
Current pattern is fine until some extra code sneaks inbetween with
an error return.

> +	int err, sig_size;
> +
> +	key = kmalloc(vecs->key_len + 2 * sizeof(u32) + vecs->param_len,
> +		      GFP_KERNEL);
> +	if (!key)
> +		return -ENOMEM;

git a/include/crypto/internal/sig.h b/include/crypto/internal/sig.h
> index 97cb26ef8115..b16648c1a986 100644
> --- a/include/crypto/internal/sig.h
> +++ b/include/crypto/internal/sig.h

> +static inline struct crypto_sig *crypto_spawn_sig(struct crypto_sig_spawn
> +								   *spawn)

That's an odd wrap. I'd just go long where this happens and slightly past 80 chars.


> +{
> +	return crypto_spawn_tfm2(&spawn->base);
> +}


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (18 preceding siblings ...)
  2024-09-10 14:30 ` [PATCH v2 19/19] crypto: ecrdsa - Fix signature size calculation Lukas Wunner
@ 2024-10-01  9:17 ` Lukas Wunner
  2024-10-05  5:27 ` Herbert Xu
  20 siblings, 0 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-10-01  9:17 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, Dimitri John Ledkov
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings,
	Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
	linux-security-module, Gonglei, Michael S. Tsirkin, Jason Wang,
	Xuan Zhuo, Eugenio Perez, virtualization, zhenwei pi, lei he,
	Neal Liu, Joel Stanley, Andrew Jeff ery, linux-aspeed, Zhiqi Song,
	Longfang Liu, Jia Jie Ho, William Qiu

Hi Herbert,

On Tue, Sep 10, 2024 at 04:30:10PM +0200, Lukas Wunner wrote:
> The original impetus of this series is to introduce P1363 signature
> decoding for ecdsa (patch [18/19]), which is needed by the upcoming
> SPDM library (Security Protocol and Data Model) for PCI device
> authentication.
> 
> To facilitate that, move X9.62 signature decoding out of ecdsa.c and
> into a template (patch [15/19]).
> 
> New in v2:  Move the maximum signature size calculations for ecdsa
> out of software_key_query() and into the X9.62 template so that
> corresponding calculations can be added for P1363 without further
> cluttering up software_key_query() (patch [16/19] - [17/19]).
> 
> New in v2:  Avoid inefficient copying from kernel buffers to sglists
> in the new templates by introducing a sig_alg backend and migrating
> all algorithms to it, per Herbert's advice (patch [02/19] - [12/19]).
> 
> Clean up various smaller issues that caught my eye in ecdsa
> (patch [01/19] and [14/19]), ecrdsa (patch [19/19]) and
> ASN.1 headers (patch [13/19]).

This series was submitted at the tail end of the v6.11 cycle.
It still applies cleanly to v6.12-rc1 though, so I'm not sure
whether to resubmit.

Is there anything you want me to change?

Thanks!

Lukas

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa
  2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
                   ` (19 preceding siblings ...)
  2024-10-01  9:17 ` [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
@ 2024-10-05  5:27 ` Herbert Xu
  20 siblings, 0 replies; 53+ messages in thread
From: Herbert Xu @ 2024-10-05  5:27 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: David S. Miller, Eric Biggers, Stefan Berger, Vitaly Chikunov,
	Tadeusz Struk, Dimitri John Ledkov, David Howells,
	Andrew Zaborowski, Saulo Alessandre, Jonathan Cameron,
	Ignat Korchagin, Marek Behun, Varad Gautam, Stephan Mueller,
	Denis Kenzior, linux-crypto, keyrings, Mimi Zohar, Roberto Sassu,
	Dmitry Kasatkin, Eric Snowberg, linux-security-module, Gonglei,
	Michael S. Tsirkin, Jason Wang, Xuan Zhuo, Eugenio Perez,
	virtualization, zhenwei pi, lei he, Neal Liu, Joel Stanley,
	Andrew Jeff ery, linux-aspeed, Zhiqi Song, Longfang Liu,
	Jia Jie Ho, William Qiu

On Tue, Sep 10, 2024 at 04:30:10PM +0200, Lukas Wunner wrote:
> The original impetus of this series is to introduce P1363 signature
> decoding for ecdsa (patch [18/19]), which is needed by the upcoming
> SPDM library (Security Protocol and Data Model) for PCI device
> authentication.
> 
> To facilitate that, move X9.62 signature decoding out of ecdsa.c and
> into a template (patch [15/19]).
> 
> New in v2:  Move the maximum signature size calculations for ecdsa
> out of software_key_query() and into the X9.62 template so that
> corresponding calculations can be added for P1363 without further
> cluttering up software_key_query() (patch [16/19] - [17/19]).
> 
> New in v2:  Avoid inefficient copying from kernel buffers to sglists
> in the new templates by introducing a sig_alg backend and migrating
> all algorithms to it, per Herbert's advice (patch [02/19] - [12/19]).
> 
> Clean up various smaller issues that caught my eye in ecdsa
> (patch [01/19] and [14/19]), ecrdsa (patch [19/19]) and
> ASN.1 headers (patch [13/19]).
> 
> I've also accumulated various cleanups for crypto virtio on my
> development branch but will leave them for another day as this
> series is already nearing the "too big to review" threshold. ;)
> 
> I've run selftests on every single commit, but further testing
> would be appreciated to raise the confidence.
> 
> 
> Link to v1:
> 
> https://lore.kernel.org/all/cover.1722260176.git.lukas@wunner.de/
> 
> Changes v1 -> v2:
> 
> * [PATCH 13/19] ASN.1: Clean up include statements in public headers
>   * Drop "#include <linux/bug.h>" from <linux/asn1_encoder.h> (Jonathan)
> 
> * [PATCH 14/19] crypto: ecdsa - Avoid signed integer overflow on signature
>   decoding
>   * Add code comment explaining why vlen may be larger than bufsize (Stefan)
> 
> * [PATCH 15/19] crypto: ecdsa - Move X9.62 signature decoding into template
>   * Drop unnecessary "params", "param_len" and "algo" definitions from
>     ecdsa_nist_p{192,256,384,521}_tv_template[].
>   * Introduce and use struct ecdsa_raw_sig in <crypto/internal/ecc.h>.
> 
> * [PATCH 18/19] crypto: ecdsa - Support P1363 signature decoding
>   * Drop unnecessary "params", "param_len" and "algo" definitions from
>     p1363_ecdsa_nist_p256_tv_template[].
> 
> 
> Lukas Wunner (19):
>   crypto: ecdsa - Drop unused test vector elements
>   crypto: sig - Introduce sig_alg backend
>   crypto: ecdsa - Migrate to sig_alg backend
>   crypto: ecrdsa - Migrate to sig_alg backend
>   crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks
>   crypto: rsassa-pkcs1 - Migrate to sig_alg backend
>   crypto: rsassa-pkcs1 - Harden digest length verification
>   crypto: rsassa-pkcs1 - Avoid copying hash prefix
>   crypto: virtio - Drop sign/verify operations
>   crypto: drivers - Drop sign/verify operations
>   crypto: akcipher - Drop sign/verify operations
>   crypto: sig - Move crypto_sig_*() API calls to include file
>   ASN.1: Clean up include statements in public headers
>   crypto: ecdsa - Avoid signed integer overflow on signature decoding
>   crypto: ecdsa - Move X9.62 signature decoding into template
>   crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize()
>   crypto: ecdsa - Move X9.62 signature size calculation into template
>   crypto: ecdsa - Support P1363 signature decoding
>   crypto: ecrdsa - Fix signature size calculation
> 
>  Documentation/crypto/api-akcipher.rst         |   2 +-
>  Documentation/crypto/api-sig.rst              |  15 +
>  Documentation/crypto/api.rst                  |   1 +
>  Documentation/crypto/architecture.rst         |   2 +
>  crypto/Kconfig                                |   5 +-
>  crypto/Makefile                               |   5 +-
>  crypto/akcipher.c                             |  64 +-
>  crypto/asymmetric_keys/public_key.c           |  58 +-
>  crypto/ecdsa-p1363.c                          | 159 ++++
>  crypto/ecdsa-x962.c                           | 237 +++++
>  crypto/ecdsa.c                                | 209 ++---
>  crypto/ecrdsa.c                               |  64 +-
>  crypto/internal.h                             |  19 -
>  crypto/rsa-pkcs1pad.c                         | 371 +-------
>  crypto/rsa.c                                  |  17 +-
>  crypto/rsassa-pkcs1.c                         | 442 +++++++++
>  crypto/sig.c                                  | 143 +--
>  crypto/testmgr.c                              | 320 +++++--
>  crypto/testmgr.h                              | 884 +++++++++++++++---
>  drivers/crypto/aspeed/aspeed-acry.c           |   2 -
>  drivers/crypto/hisilicon/hpre/hpre_crypto.c   |   2 -
>  drivers/crypto/starfive/jh7110-rsa.c          |   2 -
>  .../virtio/virtio_crypto_akcipher_algs.c      |  65 +-
>  include/crypto/akcipher.h                     |  69 +-
>  include/crypto/internal/akcipher.h            |   4 +-
>  include/crypto/internal/ecc.h                 |  14 +
>  include/crypto/internal/rsa.h                 |  29 +
>  include/crypto/internal/sig.h                 |  80 ++
>  include/crypto/sig.h                          | 152 ++-
>  include/linux/asn1_decoder.h                  |   1 +
>  include/linux/asn1_encoder.h                  |   1 -
>  include/linux/slab.h                          |   1 +
>  include/uapi/linux/cryptouser.h               |   5 +
>  include/uapi/linux/virtio_crypto.h            |   1 +
>  security/integrity/ima/ima_main.c             |   6 +-
>  35 files changed, 2398 insertions(+), 1053 deletions(-)
>  create mode 100644 Documentation/crypto/api-sig.rst
>  create mode 100644 crypto/ecdsa-p1363.c
>  create mode 100644 crypto/ecdsa-x962.c
>  create mode 100644 crypto/rsassa-pkcs1.c
> 
> -- 
> 2.43.0

All applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-09-10 14:30 ` [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend Lukas Wunner
  2024-09-11 12:56   ` Jarkko Sakkinen
@ 2024-10-21 16:08   ` Klara Modin
  2024-10-21 19:02     ` Lukas Wunner
  1 sibling, 1 reply; 53+ messages in thread
From: Klara Modin @ 2024-10-21 16:08 UTC (permalink / raw)
  To: Lukas Wunner, Herbert Xu, David S. Miller, Eric Biggers,
	Stefan Berger, Vitaly Chikunov, Tadeusz Struk
  Cc: David Howells, Andrew Zaborowski, Saulo Alessandre,
	Jonathan Cameron, Ignat Korchagin, Marek Behun, Varad Gautam,
	Stephan Mueller, Denis Kenzior, linux-crypto, keyrings,
	Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
	linux-security-module

[-- Attachment #1: Type: text/plain, Size: 4687 bytes --]

Hi,

On 2024-09-10 16:30, Lukas Wunner wrote:
> A sig_alg backend has just been introduced with the intent of moving all
> asymmetric sign/verify algorithms to it one by one.
> 
> Migrate the sign/verify operations from rsa-pkcs1pad.c to a separate
> rsassa-pkcs1.c which uses the new backend.
> 
> Consequently there are now two templates which build on the "rsa"
> akcipher_alg:
> 
> * The existing "pkcs1pad" template, which is instantiated as an
>    akcipher_instance and retains the encrypt/decrypt operations of
>    RSAES-PKCS1-v1_5 (RFC 8017 sec 7.2).
> 
> * The new "pkcs1" template, which is instantiated as a sig_instance
>    and contains the sign/verify operations of RSASSA-PKCS1-v1_5
>    (RFC 8017 sec 8.2).
> 
> In a separate step, rsa-pkcs1pad.c could optionally be renamed to
> rsaes-pkcs1.c for clarity.  Additional "oaep" and "pss" templates
> could be added for RSAES-OAEP and RSASSA-PSS.
> 
> Note that it's currently allowed to allocate a "pkcs1pad(rsa)" transform
> without specifying a hash algorithm.  That makes sense if the transform
> is only used for encrypt/decrypt and continues to be supported.  But for
> sign/verify, such transforms previously did not insert the Full Hash
> Prefix into the padding.  The resulting message encoding was incompliant
> with EMSA-PKCS1-v1_5 (RFC 8017 sec 9.2) and therefore nonsensical.
> 
>>From here on in, it is no longer allowed to allocate a transform without
> specifying a hash algorithm if the transform is used for sign/verify
> operations.  This simplifies the code because the insertion of the Full
> Hash Prefix is no longer optional, so various "if (digest_info)" clauses
> can be removed.
> 
> There has been a previous attempt to forbid transform allocation without
> specifying a hash algorithm, namely by commit c0d20d22e0ad ("crypto:
> rsa-pkcs1pad - Require hash to be present").  It had to be rolled back
> with commit b3a8c8a5ebb5 ("crypto: rsa-pkcs1pad: Allow hash to be
> optional [ver #2]"), presumably because it broke allocation of a
> transform which was solely used for encrypt/decrypt, not sign/verify.
> Avoid such breakage by allowing transform allocation for encrypt/decrypt
> with and without specifying a hash algorithm (and simply ignoring the
> hash algorithm in the former case).
> 
> So again, specifying a hash algorithm is now mandatory for sign/verify,
> but optional and ignored for encrypt/decrypt.
> 
> The new sig_alg API uses kernel buffers instead of sglists, which
> avoids the overhead of copying signature and digest from sglists back
> into kernel buffers.  rsassa-pkcs1.c is thus simplified quite a bit.
> 
> sig_alg is always synchronous, whereas the underlying "rsa" akcipher_alg
> may be asynchronous.  So await the result of the akcipher_alg, similar
> to crypto_akcipher_sync_{en,de}crypt().
> 
> As part of the migration, rename "rsa_digest_info" to "hash_prefix" to
> adhere to the spec language in RFC 9580.  Otherwise keep the code
> unmodified wherever possible to ease reviewing and bisecting.  Leave
> several simplification and hardening opportunities to separate commits.
> 
> rsassa-pkcs1.c uses modern __free() syntax for allocation of buffers
> which need to be freed by kfree_sensitive(), hence a DEFINE_FREE()
> clause for kfree_sensitive() is introduced herein as a byproduct.
> 
> Signed-off-by: Lukas Wunner <lukas@wunner.de>

This commit (1e562deacecca1f1bec7d23da526904a1e87525e in next-20241021) 
seems to break connecting to wpa2-enterprise with iwd.

I've only tested with one such network (eduroam, EAP-PEAP MSCHAPv2) and 
not yet with wpa_supplicant.

This appears in the kernel log repeatedly:

[  123.714646] wlan0: authenticate with b4:de:31:fa:2d:cc (local 
address=78:46:5c:01:28:85)
[  123.737991] wlan0: send auth to b4:de:31:fa:2d:cc (try 1/3)
[  123.763621] wlan0: authenticated
[  123.767600] wlan0: associate with b4:de:31:fa:2d:cc (try 1/3)
[  123.780873] wlan0: RX AssocResp from b4:de:31:fa:2d:cc (capab=0x1111 
status=0 aid=1)
[  123.809668] wlan0: associated
[  123.882344] wlan0: Limiting TX power to 30 (30 - 0) dBm as advertised 
by b4:de:31:fa:2d:cc
[  126.895233] wlan0: deauthenticating from b4:de:31:fa:2d:cc by local 
choice (Reason: 23=IEEE8021X_FAILED)

followed by this for a while:

[  127.214582] wlan0: authenticate with b4:de:31:fa:2d:cc (local 
address=78:46:5c:01:28:85)
[  127.237431] wlan0: send auth to b4:de:31:fa:2d:cc (try 1/3)
[  127.363430] wlan0: send auth to b4:de:31:fa:2d:cc (try 2/3)
[  127.467526] wlan0: send auth to b4:de:31:fa:2d:cc (try 3/3)
[  127.571506] wlan0: authentication with b4:de:31:fa:2d:cc timed out

Please let me know if there's anything else you need.

Regards,
Klara Modin

[-- Attachment #2: eduroam_8021x_auth_failure_bisect --]
[-- Type: text/plain, Size: 2951 bytes --]

git bisect start
# status: waiting for both good and bad commits
# bad: [d49518711f816af793de9d4a1a0e13ad10b5ce91] i2c: spacemit: add support for SpacemiT K1 SoC
git bisect bad d49518711f816af793de9d4a1a0e13ad10b5ce91
# status: waiting for good commit(s), bad commit known
# good: [c55228220dd33e7627ad9736b6fce4df5e7eac98] Merge tag 'char-misc-6.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
git bisect good c55228220dd33e7627ad9736b6fce4df5e7eac98
# bad: [092d750e6edc08fdf25e858ac5aed09cfe4685be] Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
git bisect bad 092d750e6edc08fdf25e858ac5aed09cfe4685be
# good: [e0c1b92a36f6e500684f5e47d95eeb0719bad2ca] Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux.git
git bisect good e0c1b92a36f6e500684f5e47d95eeb0719bad2ca
# good: [a8a3d62d6fa4c374c9b1fc669ca1bc73f5370650] Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git
git bisect good a8a3d62d6fa4c374c9b1fc669ca1bc73f5370650
# good: [39ab20647d7b8516fcad91950d8491369ebd5ea3] Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
git bisect good 39ab20647d7b8516fcad91950d8491369ebd5ea3
# good: [2fe3f43cbfb72a5dd053663933542d190311210c] Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
git bisect good 2fe3f43cbfb72a5dd053663933542d190311210c
# good: [582173a1dcc0a38c210b20450a615d724026d18f] Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git
git bisect good 582173a1dcc0a38c210b20450a615d724026d18f
# good: [07375e61c414d70a7332443e710e24f8dc5d6705] Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git
git bisect good 07375e61c414d70a7332443e710e24f8dc5d6705
# bad: [98091a826873bc5c114455f474121b67907e98ab] crypto: drivers - Correct multiple typos in comments
git bisect bad 98091a826873bc5c114455f474121b67907e98ab
# bad: [d6793ff974e07e4eea151d1f0805e92d042825a1] crypto: ecdsa - Move X9.62 signature decoding into template
git bisect bad d6793ff974e07e4eea151d1f0805e92d042825a1
# bad: [5e00481bf0a8b4dbd1588ae08f1ff82492011987] crypto: rsassa-pkcs1 - Harden digest length verification
git bisect bad 5e00481bf0a8b4dbd1588ae08f1ff82492011987
# good: [ef132350a3c2ae15349b7f748ce0859f0c2861be] crypto: ecdsa - Migrate to sig_alg backend
git bisect good ef132350a3c2ae15349b7f748ce0859f0c2861be
# good: [7964b0d4bd1271f82d6b455366a200d320f7dbf8] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks
git bisect good 7964b0d4bd1271f82d6b455366a200d320f7dbf8
# bad: [1e562deacecca1f1bec7d23da526904a1e87525e] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
git bisect bad 1e562deacecca1f1bec7d23da526904a1e87525e
# first bad commit: [1e562deacecca1f1bec7d23da526904a1e87525e] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

[-- Attachment #3: dmesg_eduroam_8021x_auth_failure.gz --]
[-- Type: application/gzip, Size: 26127 bytes --]

[-- Attachment #4: config.gz --]
[-- Type: application/gzip, Size: 48087 bytes --]

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-10-21 16:08   ` Klara Modin
@ 2024-10-21 19:02     ` Lukas Wunner
  2024-10-22 10:15       ` Klara Modin
  2024-10-23 10:19       ` Klara Modin
  0 siblings, 2 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-10-21 19:02 UTC (permalink / raw)
  To: Klara Modin
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
	Eric Snowberg, linux-security-module

On Mon, Oct 21, 2024 at 06:08:03PM +0200, Klara Modin wrote:
> On 2024-09-10 16:30, Lukas Wunner wrote:
> > A sig_alg backend has just been introduced with the intent of moving all
> > asymmetric sign/verify algorithms to it one by one.
> > 
> > Migrate the sign/verify operations from rsa-pkcs1pad.c to a separate
> > rsassa-pkcs1.c which uses the new backend.
[...]
> This commit (1e562deacecca1f1bec7d23da526904a1e87525e in next-20241021)
> seems to break connecting to wpa2-enterprise with iwd.

Thanks for the report and sorry for the breakage.

There is one pending fix for an issue I inadvertently introduced
with my sig_alg rework:

https://lore.kernel.org/r/ff7a28cddfc28e7a3fb8292c680510f35ec54391.1728898147.git.lukas@wunner.de/

However it fixes a different commit than the one you found through
bisection, so I suspect it won't fix the problem, though it would
still be good if you could test it.

There is a *second* issue I discovered last week.  I cooked up
a fix this morning, but haven't written a commit message yet.
The patch is included below and it could indeed solve the
problem because it fixes an issue introduced by the commit you
identified as culprit.  So if you could test the patch below as well
I'd be grateful.

I'll now look at the config and dmesg output you've provided.
Just wanted to get this e-mail out the door quickly to point you
to potential fixes.

Thanks!

Lukas

-- >8 --

diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index c98c158..af19f9c 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -165,14 +165,22 @@ static int software_key_query(const struct kernel_pkey_params *params,
 {
 	struct crypto_akcipher *tfm;
 	struct public_key *pkey = params->key->payload.data[asym_crypto];
+	const char *hash_algo = params->hash_algo;
 	char alg_name[CRYPTO_MAX_ALG_NAME];
 	struct crypto_sig *sig;
 	u8 *key, *ptr;
 	int ret, len;
 	bool issig;
 
+	/*
+	 * Specifying hash_algo has historically been optional for pkcs1,
+	 * so use an arbitrary algorithm for backward compatibility.
+	 */
+	if (strcmp(params->encoding, "pkcs1") == 0 && !hash_algo)
+		hash_algo = "sha256";
+
 	ret = software_key_determine_akcipher(pkey, params->encoding,
-					      params->hash_algo, alg_name,
+					      hash_algo, alg_name,
 					      &issig, kernel_pkey_sign);
 	if (ret < 0)
 		return ret;

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-10-21 19:02     ` Lukas Wunner
@ 2024-10-22 10:15       ` Klara Modin
  2024-10-23 10:19       ` Klara Modin
  1 sibling, 0 replies; 53+ messages in thread
From: Klara Modin @ 2024-10-22 10:15 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
	Eric Snowberg, linux-security-module

On 2024-10-21 21:02, Lukas Wunner wrote:
> On Mon, Oct 21, 2024 at 06:08:03PM +0200, Klara Modin wrote:
>> On 2024-09-10 16:30, Lukas Wunner wrote:
>>> A sig_alg backend has just been introduced with the intent of moving all
>>> asymmetric sign/verify algorithms to it one by one.
>>>
>>> Migrate the sign/verify operations from rsa-pkcs1pad.c to a separate
>>> rsassa-pkcs1.c which uses the new backend.
> [...]
>> This commit (1e562deacecca1f1bec7d23da526904a1e87525e in next-20241021)
>> seems to break connecting to wpa2-enterprise with iwd.
> 
> Thanks for the report and sorry for the breakage.
> 
> There is one pending fix for an issue I inadvertently introduced
> with my sig_alg rework:
> 
> https://lore.kernel.org/r/ff7a28cddfc28e7a3fb8292c680510f35ec54391.1728898147.git.lukas@wunner.de/
> 
> However it fixes a different commit than the one you found through
> bisection, so I suspect it won't fix the problem, though it would
> still be good if you could test it.
> 
> There is a *second* issue I discovered last week.  I cooked up
> a fix this morning, but haven't written a commit message yet.
> The patch is included below and it could indeed solve the
> problem because it fixes an issue introduced by the commit you
> identified as culprit.  So if you could test the patch below as well
> I'd be grateful.
> 
> I'll now look at the config and dmesg output you've provided.
> Just wanted to get this e-mail out the door quickly to point you
> to potential fixes.
> 
> Thanks!
> 
> Lukas
> 
> -- >8 --
> 
> diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
> index c98c158..af19f9c 100644
> --- a/crypto/asymmetric_keys/public_key.c
> +++ b/crypto/asymmetric_keys/public_key.c
> @@ -165,14 +165,22 @@ static int software_key_query(const struct kernel_pkey_params *params,
>   {
>   	struct crypto_akcipher *tfm;
>   	struct public_key *pkey = params->key->payload.data[asym_crypto];
> +	const char *hash_algo = params->hash_algo;
>   	char alg_name[CRYPTO_MAX_ALG_NAME];
>   	struct crypto_sig *sig;
>   	u8 *key, *ptr;
>   	int ret, len;
>   	bool issig;
>   
> +	/*
> +	 * Specifying hash_algo has historically been optional for pkcs1,
> +	 * so use an arbitrary algorithm for backward compatibility.
> +	 */
> +	if (strcmp(params->encoding, "pkcs1") == 0 && !hash_algo)
> +		hash_algo = "sha256";
> +
>   	ret = software_key_determine_akcipher(pkey, params->encoding,
> -					      params->hash_algo, alg_name,
> +					      hash_algo, alg_name,
>   					      &issig, kernel_pkey_sign);
>   	if (ret < 0)
>   		return ret;
> 

I don't think I have hit the first issue you mention but I'll apply the 
fix and see if it changes anything. I'll probably be able to test these 
two sometime tomorrow.

Thanks,
Klara Modin

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-10-21 19:02     ` Lukas Wunner
  2024-10-22 10:15       ` Klara Modin
@ 2024-10-23 10:19       ` Klara Modin
  2024-10-25  7:17         ` Lukas Wunner
  1 sibling, 1 reply; 53+ messages in thread
From: Klara Modin @ 2024-10-23 10:19 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
	Eric Snowberg, linux-security-module

[-- Attachment #1: Type: text/plain, Size: 2929 bytes --]

On 2024-10-21 21:02, Lukas Wunner wrote:
> On Mon, Oct 21, 2024 at 06:08:03PM +0200, Klara Modin wrote:
>> On 2024-09-10 16:30, Lukas Wunner wrote:
>>> A sig_alg backend has just been introduced with the intent of moving all
>>> asymmetric sign/verify algorithms to it one by one.
>>>
>>> Migrate the sign/verify operations from rsa-pkcs1pad.c to a separate
>>> rsassa-pkcs1.c which uses the new backend.
> [...]
>> This commit (1e562deacecca1f1bec7d23da526904a1e87525e in next-20241021)
>> seems to break connecting to wpa2-enterprise with iwd.
> 
> Thanks for the report and sorry for the breakage.
> 
> There is one pending fix for an issue I inadvertently introduced
> with my sig_alg rework:
> 
> https://lore.kernel.org/r/ff7a28cddfc28e7a3fb8292c680510f35ec54391.1728898147.git.lukas@wunner.de/
> 
> However it fixes a different commit than the one you found through
> bisection, so I suspect it won't fix the problem, though it would
> still be good if you could test it.
> 
> There is a *second* issue I discovered last week.  I cooked up
> a fix this morning, but haven't written a commit message yet.
> The patch is included below and it could indeed solve the
> problem because it fixes an issue introduced by the commit you
> identified as culprit.  So if you could test the patch below as well
> I'd be grateful.
> 
> I'll now look at the config and dmesg output you've provided.
> Just wanted to get this e-mail out the door quickly to point you
> to potential fixes.
> 
> Thanks!
> 
> Lukas
> 
> -- >8 --
> 
> diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
> index c98c158..af19f9c 100644
> --- a/crypto/asymmetric_keys/public_key.c
> +++ b/crypto/asymmetric_keys/public_key.c
> @@ -165,14 +165,22 @@ static int software_key_query(const struct kernel_pkey_params *params,
>   {
>   	struct crypto_akcipher *tfm;
>   	struct public_key *pkey = params->key->payload.data[asym_crypto];
> +	const char *hash_algo = params->hash_algo;
>   	char alg_name[CRYPTO_MAX_ALG_NAME];
>   	struct crypto_sig *sig;
>   	u8 *key, *ptr;
>   	int ret, len;
>   	bool issig;
>   
> +	/*
> +	 * Specifying hash_algo has historically been optional for pkcs1,
> +	 * so use an arbitrary algorithm for backward compatibility.
> +	 */
> +	if (strcmp(params->encoding, "pkcs1") == 0 && !hash_algo)
> +		hash_algo = "sha256";
> +
>   	ret = software_key_determine_akcipher(pkey, params->encoding,
> -					      params->hash_algo, alg_name,
> +					      hash_algo, alg_name,
>   					      &issig, kernel_pkey_sign);
>   	if (ret < 0)
>   		return ret;
> 

Tested on top of yesterday's next-20241022.

With the first patch only there is no change, same behavior as previously.

With the second patch only I get an oops, similar as the one you 
mentioned in the first fix

With both patches everything seems to work as expected. Thanks!

(for both fixes)
Tested-by: Klara Modin <klarasmodin@gmail.com>

[-- Attachment #2: iwd_oops_decoded.gz --]
[-- Type: application/gzip, Size: 25234 bytes --]

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-10-23 10:19       ` Klara Modin
@ 2024-10-25  7:17         ` Lukas Wunner
  2024-10-25 16:50           ` Eric Biggers
                             ` (2 more replies)
  0 siblings, 3 replies; 53+ messages in thread
From: Lukas Wunner @ 2024-10-25  7:17 UTC (permalink / raw)
  To: Klara Modin
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
	Eric Snowberg, linux-security-module

On Wed, Oct 23, 2024 at 12:19:45PM +0200, Klara Modin wrote:
> On 2024-10-21 21:02, Lukas Wunner wrote:
> > On Mon, Oct 21, 2024 at 06:08:03PM +0200, Klara Modin wrote:
> > > This commit (1e562deacecca1f1bec7d23da526904a1e87525e in next-20241021)
> > > seems to break connecting to wpa2-enterprise with iwd.
[...]
> > There is a *second* issue I discovered last week.  I cooked up
> > a fix this morning, but haven't written a commit message yet.
> > The patch is included below and it could indeed solve the
> > problem because it fixes an issue introduced by the commit you
> > identified as culprit.
[...]
> Tested on top of yesterday's next-20241022.
> 
> With the first patch only there is no change, same behavior as previously.
> 
> With the second patch only I get an oops, similar as the one you mentioned
> in the first fix
> 
> With both patches everything seems to work as expected. Thanks!

Thanks a lot for your testing efforts, this helps greatly!

I've dug into the source code of iwd (Intel Wireless Daemon) and
the ell library it uses (Embedded Linux Library).

It turns out that the patch I sent you is sufficient when using
TLS 1.2 or newer for EAP (which I assume is true in your case).
But the patch is *not* sufficient for TLS 1.1 or earlier.

Normally RSA PKCS#1 encoding requires that the hash is prepended
by a Full Hash Prefix (an ASN.1 sequence which identifies the
hash algorithm used).  But it turns out there are legacy protocols
such as TLS 1.1 or earlier as well as IKEv1 which omit the
Full Hash Prefix.

The kernel supported this prior to 1e562deacecc.  Although TLS 1.1
was deprecated in 2021 by RFC 8996, I think we cannot just remove
support without advance notice.

So below is a new patch which reinstates support for these legacy
protocols.  It should also fix the issue you're seeing with TLS 1.2
or newer (which is caused by invoking KEYCTL_PKEY_QUERY without
specifying a hash algorithm).

The patch below replaces the one I sent on Monday.  You'll still
need the other pending fix:

https://lore.kernel.org/r/ff7a28cddfc28e7a3fb8292c680510f35ec54391.1728898147.git.lukas@wunner.de/

Would you mind testing this combination?  It did work in my own
testing, but if you could test it as well that would raise the
confidence.

I've looked at the source code of wpa_supplicant as well as
various IKEv1 daemons (strongswan, libreswan, isakmpd, raccoon)
and none of them seems to use the kernel's Key Retention Service,
so iwd is the only known user space application affected so far.

Thanks,

Lukas

-- >8 --

diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index c98c158..bbd07a9 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -93,7 +93,7 @@ static void public_key_destroy(void *payload0, void *payload3)
 					     pkey->pkey_algo);
 			} else {
 				if (!hash_algo)
-					return -EINVAL;
+					hash_algo = "none";
 				n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
 					     "pkcs1(%s,%s)",
 					     pkey->pkey_algo, hash_algo);
diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
index 9c28f1c..4d077fc9 100644
--- a/crypto/rsassa-pkcs1.c
+++ b/crypto/rsassa-pkcs1.c
@@ -27,6 +27,8 @@
  * https://www.rfc-editor.org/rfc/rfc9580#table-24
  */
 
+static const u8 hash_prefix_none[] = { };
+
 static const u8 hash_prefix_md5[] = {
 	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,	  /* SEQUENCE (SEQUENCE (OID */
 	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05,	/*	<algorithm>, */
@@ -93,6 +95,7 @@
 	size_t		size;
 } hash_prefixes[] = {
 #define _(X) { #X, hash_prefix_##X, sizeof(hash_prefix_##X) }
+	_(none),
 	_(md5),
 	_(sha1),
 	_(rmd160),
@@ -119,9 +122,18 @@ static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name)
 	return NULL;
 }
 
-static unsigned int rsassa_pkcs1_hash_len(const struct hash_prefix *p)
+static bool rsassa_pkcs1_invalid_hash_len(unsigned int len,
+					  const struct hash_prefix *p)
 {
 	/*
+	 * Legacy protocols such as TLS 1.1 or earlier and IKE version 1
+	 * do not prepend a Full Hash Prefix to the hash.  In that case,
+	 * the size of the Full Hash Prefix is zero.
+	 */
+	if (p->data == hash_prefix_none)
+		return false;
+
+	/*
 	 * The final byte of the Full Hash Prefix encodes the hash length.
 	 *
 	 * This needs to be revisited should hash algorithms with more than
@@ -130,7 +142,7 @@ static unsigned int rsassa_pkcs1_hash_len(const struct hash_prefix *p)
 	 */
 	static_assert(HASH_MAX_DIGESTSIZE <= 127);
 
-	return p->data[p->size - 1];
+	return len != p->data[p->size - 1];
 }
 
 struct rsassa_pkcs1_ctx {
@@ -167,7 +179,7 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
 	if (dlen < ctx->key_size)
 		return -EOVERFLOW;
 
-	if (slen != rsassa_pkcs1_hash_len(hash_prefix))
+	if (rsassa_pkcs1_invalid_hash_len(slen, hash_prefix))
 		return -EINVAL;
 
 	if (slen + hash_prefix->size > ctx->key_size - 11)
@@ -237,7 +249,7 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
 	/* RFC 8017 sec 8.2.2 step 1 - length checking */
 	if (!ctx->key_size ||
 	    slen != ctx->key_size ||
-	    dlen != rsassa_pkcs1_hash_len(hash_prefix))
+	    rsassa_pkcs1_invalid_hash_len(dlen, hash_prefix))
 		return -EINVAL;
 
 	/* RFC 8017 sec 8.2.2 step 2 - RSA verification */
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 7d768f0..86126be 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5540,6 +5540,12 @@ static int alg_test_null(const struct alg_test_desc *desc,
 			.cipher = __VECS(fcrypt_pcbc_tv_template)
 		}
 	}, {
+		.alg = "pkcs1(rsa,none)",
+		.test = alg_test_sig,
+		.suite = {
+			.sig = __VECS(pkcs1_rsa_none_tv_template)
+		}
+	}, {
 		.alg = "pkcs1(rsa,sha224)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 55aae18..d4c232a 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -1983,6 +1983,61 @@ struct kpp_testvec {
 };
 
 /*
+ * PKCS#1 RSA test vectors for hash algorithm "none"
+ * (i.e. the hash in "m" is not prepended by a Full Hash Prefix)
+ *
+ * Obtained from:
+ * https://vcsjones.dev/sometimes-valid-rsa-dotnet/
+ * https://gist.github.com/vcsjones/ab4c2327b53ed018eada76b75ef4fd99
+ */
+static const struct sig_testvec pkcs1_rsa_none_tv_template[] = {
+	{
+	.key =
+	"\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa2\x63\x0b\x39\x44\xb8\xbb"
+	"\x23\xa7\x44\x49\xbb\x0e\xff\xa1\xf0\x61\x0a\x53\x93\xb0\x98\xdb"
+	"\xad\x2c\x0f\x4a\xc5\x6e\xff\x86\x3c\x53\x55\x0f\x15\xce\x04\x3f"
+	"\x2b\xfd\xa9\x96\x96\xd9\xbe\x61\x79\x0b\x5b\xc9\x4c\x86\x76\xe5"
+	"\xe0\x43\x4b\x22\x95\xee\xc2\x2b\x43\xc1\x9f\xd8\x68\xb4\x8e\x40"
+	"\x4f\xee\x85\x38\xb9\x11\xc5\x23\xf2\x64\x58\xf0\x15\x32\x6f\x4e"
+	"\x57\xa1\xae\x88\xa4\x02\xd7\x2a\x1e\xcd\x4b\xe1\xdd\x63\xd5\x17"
+	"\x89\x32\x5b\xb0\x5e\x99\x5a\xa8\x9d\x28\x50\x0e\x17\xee\x96\xdb"
+	"\x61\x3b\x45\x51\x1d\xcf\x12\x56\x0b\x92\x47\xfc\xab\xae\xf6\x66"
+	"\x3d\x47\xac\x70\x72\xe7\x92\xe7\x5f\xcd\x10\xb9\xc4\x83\x64\x94"
+	"\x19\xbd\x25\x80\xe1\xe8\xd2\x22\xa5\xd0\xba\x02\x7a\xa1\x77\x93"
+	"\x5b\x65\xc3\xee\x17\x74\xbc\x41\x86\x2a\xdc\x08\x4c\x8c\x92\x8c"
+	"\x91\x2d\x9e\x77\x44\x1f\x68\xd6\xa8\x74\x77\xdb\x0e\x5b\x32\x8b"
+	"\x56\x8b\x33\xbd\xd9\x63\xc8\x49\x9d\x3a\xc5\xc5\xea\x33\x0b\xd2"
+	"\xf1\xa3\x1b\xf4\x8b\xbe\xd9\xb3\x57\x8b\x3b\xde\x04\xa7\x7a\x22"
+	"\xb2\x24\xae\x2e\xc7\x70\xc5\xbe\x4e\x83\x26\x08\xfb\x0b\xbd\xa9"
+	"\x4f\x99\x08\xe1\x10\x28\x72\xaa\xcd\x02\x03\x01\x00\x01",
+	.key_len = 294,
+	.m =
+	"\x68\xb4\xf9\x26\x34\x31\x25\xdd\x26\x50\x13\x68\xc1\x99\x26\x71"
+	"\x19\xa2\xde\x81",
+	.m_size = 20,
+	.c =
+	"\x6a\xdb\x39\xe5\x63\xb3\x25\xde\x58\xca\xc3\xf1\x36\x9c\x0b\x36"
+	"\xb7\xd6\x69\xf9\xba\xa6\x68\x14\x8c\x24\x52\xd3\x25\xa5\xf3\xad"
+	"\xc9\x47\x44\xde\x06\xd8\x0f\x56\xca\x2d\xfb\x0f\xe9\x99\xe2\x9d"
+	"\x8a\xe8\x7f\xfb\x9a\x99\x96\xf1\x2c\x4a\xe4\xc0\xae\x4d\x29\x47"
+	"\x38\x96\x51\x2f\x6d\x8e\xb8\x88\xbd\x1a\x0a\x70\xbc\x23\x38\x67"
+	"\x62\x22\x01\x23\x71\xe5\xbb\x95\xea\x6b\x8d\x31\x62\xbf\xf0\xc4"
+	"\xb9\x46\xd6\x67\xfc\x4c\xe6\x1f\xd6\x5d\xf7\xa9\xad\x3a\xf1\xbf"
+	"\xa2\xf9\x66\xde\xb6\x8e\xec\x8f\x81\x8d\x1e\x3a\x12\x27\x6a\xfc"
+	"\xae\x92\x9f\xc3\x87\xc3\xba\x8d\x04\xb8\x8f\x0f\x61\x68\x9a\x96"
+	"\x2c\x80\x2c\x32\x40\xde\x9d\xb9\x9b\xe2\xe4\x45\x2e\x91\x47\x5c"
+	"\x47\xa4\x9d\x02\x57\x59\xf7\x75\x5d\x5f\x32\x82\x75\x5d\xe5\x78"
+	"\xc9\x19\x61\x46\x06\x9d\xa5\x1d\xd6\x32\x48\x9a\xdb\x09\x29\x81"
+	"\x14\x2e\xf0\x27\xe9\x37\x13\x74\xec\xa5\xcd\x67\x6b\x19\xf6\x88"
+	"\xf0\xc2\x8b\xa8\x7f\x2f\x76\x5a\x3e\x0c\x47\x5d\xe8\x82\x50\x27"
+	"\x40\xce\x27\x41\x45\xa0\xcf\xaa\x2f\xd3\xad\x3c\xbf\x73\xff\x93"
+	"\xe3\x78\x49\xd9\xa9\x78\x22\x81\x9a\xe5\xe2\x94\xe9\x40\xab\xf1",
+	.c_size = 256,
+	.public_key_vec = true,
+	},
+};
+
+/*
  * PKCS#1 RSA test vectors. Obtained from CAVS testing.
  */
 static const struct sig_testvec pkcs1_rsa_tv_template[] = {

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-10-25  7:17         ` Lukas Wunner
@ 2024-10-25 16:50           ` Eric Biggers
  2024-10-26  9:40           ` Klara Modin
  2024-10-28 11:45           ` Klara Modin
  2 siblings, 0 replies; 53+ messages in thread
From: Eric Biggers @ 2024-10-25 16:50 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Klara Modin, Herbert Xu, David S. Miller, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
	Eric Snowberg, linux-security-module

On Fri, Oct 25, 2024 at 09:17:02AM +0200, Lukas Wunner wrote:
> So below is a new patch which reinstates support for these legacy
> protocols.  It should also fix the issue you're seeing with TLS 1.2
> or newer (which is caused by invoking KEYCTL_PKEY_QUERY without
> specifying a hash algorithm).
[...]
> I've looked at the source code of wpa_supplicant as well as
> various IKEv1 daemons (strongswan, libreswan, isakmpd, raccoon)
> and none of them seems to use the kernel's Key Retention Service,
> so iwd is the only known user space application affected so far.

Yes, based on historical mailing list discussions it appears that KEYCTL_PKEY_*
were added to the kernel for iwd, and iwd is their only user.  This design is a
huge mistake both on the part of iwd and the kernel community, for a variety of
reasons that have already been covered extensively in the discussions that occur
each time iwd breaks.  iwd should be using a real crypto library, like all the
other wireless daemons.

- Eric

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-10-25  7:17         ` Lukas Wunner
  2024-10-25 16:50           ` Eric Biggers
@ 2024-10-26  9:40           ` Klara Modin
  2024-10-28 11:45           ` Klara Modin
  2 siblings, 0 replies; 53+ messages in thread
From: Klara Modin @ 2024-10-26  9:40 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
	Eric Snowberg, linux-security-module, klara

On 2024-10-25 09:17, Lukas Wunner wrote:
> On Wed, Oct 23, 2024 at 12:19:45PM +0200, Klara Modin wrote:
>> On 2024-10-21 21:02, Lukas Wunner wrote:
>>> On Mon, Oct 21, 2024 at 06:08:03PM +0200, Klara Modin wrote:
>>>> This commit (1e562deacecca1f1bec7d23da526904a1e87525e in next-20241021)
>>>> seems to break connecting to wpa2-enterprise with iwd.
> [...]
>>> There is a *second* issue I discovered last week.  I cooked up
>>> a fix this morning, but haven't written a commit message yet.
>>> The patch is included below and it could indeed solve the
>>> problem because it fixes an issue introduced by the commit you
>>> identified as culprit.
> [...]
>> Tested on top of yesterday's next-20241022.
>>
>> With the first patch only there is no change, same behavior as previously.
>>
>> With the second patch only I get an oops, similar as the one you mentioned
>> in the first fix
>>
>> With both patches everything seems to work as expected. Thanks!
> 
> Thanks a lot for your testing efforts, this helps greatly!
> 
> I've dug into the source code of iwd (Intel Wireless Daemon) and
> the ell library it uses (Embedded Linux Library).
> 
> It turns out that the patch I sent you is sufficient when using
> TLS 1.2 or newer for EAP (which I assume is true in your case).
> But the patch is *not* sufficient for TLS 1.1 or earlier.
> 
> Normally RSA PKCS#1 encoding requires that the hash is prepended
> by a Full Hash Prefix (an ASN.1 sequence which identifies the
> hash algorithm used).  But it turns out there are legacy protocols
> such as TLS 1.1 or earlier as well as IKEv1 which omit the
> Full Hash Prefix.
> 
> The kernel supported this prior to 1e562deacecc.  Although TLS 1.1
> was deprecated in 2021 by RFC 8996, I think we cannot just remove
> support without advance notice.
> 
> So below is a new patch which reinstates support for these legacy
> protocols.  It should also fix the issue you're seeing with TLS 1.2
> or newer (which is caused by invoking KEYCTL_PKEY_QUERY without
> specifying a hash algorithm).
> 
> The patch below replaces the one I sent on Monday.  You'll still
> need the other pending fix:
> 
> https://lore.kernel.org/r/ff7a28cddfc28e7a3fb8292c680510f35ec54391.1728898147.git.lukas@wunner.de/
> 
> Would you mind testing this combination?  It did work in my own
> testing, but if you could test it as well that would raise the
> confidence.
> 
> I've looked at the source code of wpa_supplicant as well as
> various IKEv1 daemons (strongswan, libreswan, isakmpd, raccoon)
> and none of them seems to use the kernel's Key Retention Service,
> so iwd is the only known user space application affected so far.
> 
> Thanks,
> 
> Lukas
> 

Thanks for the explanation. I'll probably be able to test this on Monday.

(by the way, I don't seem to be receiving your emails. It could perhaps 
be something on the gmail side. I'll add klara@kasm.eu to the CC which 
is on my own server, maybe that'll work better)

Regards,
Klara Modin

> -- >8 --
> 
> diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
> index c98c158..bbd07a9 100644
> --- a/crypto/asymmetric_keys/public_key.c
> +++ b/crypto/asymmetric_keys/public_key.c
> @@ -93,7 +93,7 @@ static void public_key_destroy(void *payload0, void *payload3)
>   					     pkey->pkey_algo);
>   			} else {
>   				if (!hash_algo)
> -					return -EINVAL;
> +					hash_algo = "none";
>   				n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
>   					     "pkcs1(%s,%s)",
>   					     pkey->pkey_algo, hash_algo);
> diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
> index 9c28f1c..4d077fc9 100644
> --- a/crypto/rsassa-pkcs1.c
> +++ b/crypto/rsassa-pkcs1.c
> @@ -27,6 +27,8 @@
>    * https://www.rfc-editor.org/rfc/rfc9580#table-24
>    */
>   
> +static const u8 hash_prefix_none[] = { };
> +
>   static const u8 hash_prefix_md5[] = {
>   	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,	  /* SEQUENCE (SEQUENCE (OID */
>   	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05,	/*	<algorithm>, */
> @@ -93,6 +95,7 @@
>   	size_t		size;
>   } hash_prefixes[] = {
>   #define _(X) { #X, hash_prefix_##X, sizeof(hash_prefix_##X) }
> +	_(none),
>   	_(md5),
>   	_(sha1),
>   	_(rmd160),
> @@ -119,9 +122,18 @@ static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name)
>   	return NULL;
>   }
>   
> -static unsigned int rsassa_pkcs1_hash_len(const struct hash_prefix *p)
> +static bool rsassa_pkcs1_invalid_hash_len(unsigned int len,
> +					  const struct hash_prefix *p)
>   {
>   	/*
> +	 * Legacy protocols such as TLS 1.1 or earlier and IKE version 1
> +	 * do not prepend a Full Hash Prefix to the hash.  In that case,
> +	 * the size of the Full Hash Prefix is zero.
> +	 */
> +	if (p->data == hash_prefix_none)
> +		return false;
> +
> +	/*
>   	 * The final byte of the Full Hash Prefix encodes the hash length.
>   	 *
>   	 * This needs to be revisited should hash algorithms with more than
> @@ -130,7 +142,7 @@ static unsigned int rsassa_pkcs1_hash_len(const struct hash_prefix *p)
>   	 */
>   	static_assert(HASH_MAX_DIGESTSIZE <= 127);
>   
> -	return p->data[p->size - 1];
> +	return len != p->data[p->size - 1];
>   }
>   
>   struct rsassa_pkcs1_ctx {
> @@ -167,7 +179,7 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
>   	if (dlen < ctx->key_size)
>   		return -EOVERFLOW;
>   
> -	if (slen != rsassa_pkcs1_hash_len(hash_prefix))
> +	if (rsassa_pkcs1_invalid_hash_len(slen, hash_prefix))
>   		return -EINVAL;
>   
>   	if (slen + hash_prefix->size > ctx->key_size - 11)
> @@ -237,7 +249,7 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
>   	/* RFC 8017 sec 8.2.2 step 1 - length checking */
>   	if (!ctx->key_size ||
>   	    slen != ctx->key_size ||
> -	    dlen != rsassa_pkcs1_hash_len(hash_prefix))
> +	    rsassa_pkcs1_invalid_hash_len(dlen, hash_prefix))
>   		return -EINVAL;
>   
>   	/* RFC 8017 sec 8.2.2 step 2 - RSA verification */
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index 7d768f0..86126be 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -5540,6 +5540,12 @@ static int alg_test_null(const struct alg_test_desc *desc,
>   			.cipher = __VECS(fcrypt_pcbc_tv_template)
>   		}
>   	}, {
> +		.alg = "pkcs1(rsa,none)",
> +		.test = alg_test_sig,
> +		.suite = {
> +			.sig = __VECS(pkcs1_rsa_none_tv_template)
> +		}
> +	}, {
>   		.alg = "pkcs1(rsa,sha224)",
>   		.test = alg_test_null,
>   		.fips_allowed = 1,
> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index 55aae18..d4c232a 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -1983,6 +1983,61 @@ struct kpp_testvec {
>   };
>   
>   /*
> + * PKCS#1 RSA test vectors for hash algorithm "none"
> + * (i.e. the hash in "m" is not prepended by a Full Hash Prefix)
> + *
> + * Obtained from:
> + * https://vcsjones.dev/sometimes-valid-rsa-dotnet/
> + * https://gist.github.com/vcsjones/ab4c2327b53ed018eada76b75ef4fd99
> + */
> +static const struct sig_testvec pkcs1_rsa_none_tv_template[] = {
> +	{
> +	.key =
> +	"\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa2\x63\x0b\x39\x44\xb8\xbb"
> +	"\x23\xa7\x44\x49\xbb\x0e\xff\xa1\xf0\x61\x0a\x53\x93\xb0\x98\xdb"
> +	"\xad\x2c\x0f\x4a\xc5\x6e\xff\x86\x3c\x53\x55\x0f\x15\xce\x04\x3f"
> +	"\x2b\xfd\xa9\x96\x96\xd9\xbe\x61\x79\x0b\x5b\xc9\x4c\x86\x76\xe5"
> +	"\xe0\x43\x4b\x22\x95\xee\xc2\x2b\x43\xc1\x9f\xd8\x68\xb4\x8e\x40"
> +	"\x4f\xee\x85\x38\xb9\x11\xc5\x23\xf2\x64\x58\xf0\x15\x32\x6f\x4e"
> +	"\x57\xa1\xae\x88\xa4\x02\xd7\x2a\x1e\xcd\x4b\xe1\xdd\x63\xd5\x17"
> +	"\x89\x32\x5b\xb0\x5e\x99\x5a\xa8\x9d\x28\x50\x0e\x17\xee\x96\xdb"
> +	"\x61\x3b\x45\x51\x1d\xcf\x12\x56\x0b\x92\x47\xfc\xab\xae\xf6\x66"
> +	"\x3d\x47\xac\x70\x72\xe7\x92\xe7\x5f\xcd\x10\xb9\xc4\x83\x64\x94"
> +	"\x19\xbd\x25\x80\xe1\xe8\xd2\x22\xa5\xd0\xba\x02\x7a\xa1\x77\x93"
> +	"\x5b\x65\xc3\xee\x17\x74\xbc\x41\x86\x2a\xdc\x08\x4c\x8c\x92\x8c"
> +	"\x91\x2d\x9e\x77\x44\x1f\x68\xd6\xa8\x74\x77\xdb\x0e\x5b\x32\x8b"
> +	"\x56\x8b\x33\xbd\xd9\x63\xc8\x49\x9d\x3a\xc5\xc5\xea\x33\x0b\xd2"
> +	"\xf1\xa3\x1b\xf4\x8b\xbe\xd9\xb3\x57\x8b\x3b\xde\x04\xa7\x7a\x22"
> +	"\xb2\x24\xae\x2e\xc7\x70\xc5\xbe\x4e\x83\x26\x08\xfb\x0b\xbd\xa9"
> +	"\x4f\x99\x08\xe1\x10\x28\x72\xaa\xcd\x02\x03\x01\x00\x01",
> +	.key_len = 294,
> +	.m =
> +	"\x68\xb4\xf9\x26\x34\x31\x25\xdd\x26\x50\x13\x68\xc1\x99\x26\x71"
> +	"\x19\xa2\xde\x81",
> +	.m_size = 20,
> +	.c =
> +	"\x6a\xdb\x39\xe5\x63\xb3\x25\xde\x58\xca\xc3\xf1\x36\x9c\x0b\x36"
> +	"\xb7\xd6\x69\xf9\xba\xa6\x68\x14\x8c\x24\x52\xd3\x25\xa5\xf3\xad"
> +	"\xc9\x47\x44\xde\x06\xd8\x0f\x56\xca\x2d\xfb\x0f\xe9\x99\xe2\x9d"
> +	"\x8a\xe8\x7f\xfb\x9a\x99\x96\xf1\x2c\x4a\xe4\xc0\xae\x4d\x29\x47"
> +	"\x38\x96\x51\x2f\x6d\x8e\xb8\x88\xbd\x1a\x0a\x70\xbc\x23\x38\x67"
> +	"\x62\x22\x01\x23\x71\xe5\xbb\x95\xea\x6b\x8d\x31\x62\xbf\xf0\xc4"
> +	"\xb9\x46\xd6\x67\xfc\x4c\xe6\x1f\xd6\x5d\xf7\xa9\xad\x3a\xf1\xbf"
> +	"\xa2\xf9\x66\xde\xb6\x8e\xec\x8f\x81\x8d\x1e\x3a\x12\x27\x6a\xfc"
> +	"\xae\x92\x9f\xc3\x87\xc3\xba\x8d\x04\xb8\x8f\x0f\x61\x68\x9a\x96"
> +	"\x2c\x80\x2c\x32\x40\xde\x9d\xb9\x9b\xe2\xe4\x45\x2e\x91\x47\x5c"
> +	"\x47\xa4\x9d\x02\x57\x59\xf7\x75\x5d\x5f\x32\x82\x75\x5d\xe5\x78"
> +	"\xc9\x19\x61\x46\x06\x9d\xa5\x1d\xd6\x32\x48\x9a\xdb\x09\x29\x81"
> +	"\x14\x2e\xf0\x27\xe9\x37\x13\x74\xec\xa5\xcd\x67\x6b\x19\xf6\x88"
> +	"\xf0\xc2\x8b\xa8\x7f\x2f\x76\x5a\x3e\x0c\x47\x5d\xe8\x82\x50\x27"
> +	"\x40\xce\x27\x41\x45\xa0\xcf\xaa\x2f\xd3\xad\x3c\xbf\x73\xff\x93"
> +	"\xe3\x78\x49\xd9\xa9\x78\x22\x81\x9a\xe5\xe2\x94\xe9\x40\xab\xf1",
> +	.c_size = 256,
> +	.public_key_vec = true,
> +	},
> +};
> +
> +/*
>    * PKCS#1 RSA test vectors. Obtained from CAVS testing.
>    */
>   static const struct sig_testvec pkcs1_rsa_tv_template[] = {
> 


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend
  2024-10-25  7:17         ` Lukas Wunner
  2024-10-25 16:50           ` Eric Biggers
  2024-10-26  9:40           ` Klara Modin
@ 2024-10-28 11:45           ` Klara Modin
  2 siblings, 0 replies; 53+ messages in thread
From: Klara Modin @ 2024-10-28 11:45 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
	Eric Snowberg, linux-security-module, klara

On 2024-10-25 09:17, Lukas Wunner wrote:
> On Wed, Oct 23, 2024 at 12:19:45PM +0200, Klara Modin wrote:
>> On 2024-10-21 21:02, Lukas Wunner wrote:
>>> On Mon, Oct 21, 2024 at 06:08:03PM +0200, Klara Modin wrote:
>>>> This commit (1e562deacecca1f1bec7d23da526904a1e87525e in next-20241021)
>>>> seems to break connecting to wpa2-enterprise with iwd.
> [...]
>>> There is a *second* issue I discovered last week.  I cooked up
>>> a fix this morning, but haven't written a commit message yet.
>>> The patch is included below and it could indeed solve the
>>> problem because it fixes an issue introduced by the commit you
>>> identified as culprit.
> [...]
>> Tested on top of yesterday's next-20241022.
>>
>> With the first patch only there is no change, same behavior as previously.
>>
>> With the second patch only I get an oops, similar as the one you mentioned
>> in the first fix
>>
>> With both patches everything seems to work as expected. Thanks!
> 
> Thanks a lot for your testing efforts, this helps greatly!
> 
> I've dug into the source code of iwd (Intel Wireless Daemon) and
> the ell library it uses (Embedded Linux Library).
> 
> It turns out that the patch I sent you is sufficient when using
> TLS 1.2 or newer for EAP (which I assume is true in your case).
> But the patch is *not* sufficient for TLS 1.1 or earlier.
> 
> Normally RSA PKCS#1 encoding requires that the hash is prepended
> by a Full Hash Prefix (an ASN.1 sequence which identifies the
> hash algorithm used).  But it turns out there are legacy protocols
> such as TLS 1.1 or earlier as well as IKEv1 which omit the
> Full Hash Prefix.
> 
> The kernel supported this prior to 1e562deacecc.  Although TLS 1.1
> was deprecated in 2021 by RFC 8996, I think we cannot just remove
> support without advance notice.
> 
> So below is a new patch which reinstates support for these legacy
> protocols.  It should also fix the issue you're seeing with TLS 1.2
> or newer (which is caused by invoking KEYCTL_PKEY_QUERY without
> specifying a hash algorithm).
> 
> The patch below replaces the one I sent on Monday.  You'll still
> need the other pending fix:
> 
> https://lore.kernel.org/r/ff7a28cddfc28e7a3fb8292c680510f35ec54391.1728898147.git.lukas@wunner.de/
> 
> Would you mind testing this combination?  It did work in my own
> testing, but if you could test it as well that would raise the
> confidence.
> 
> I've looked at the source code of wpa_supplicant as well as
> various IKEv1 daemons (strongswan, libreswan, isakmpd, raccoon)
> and none of them seems to use the kernel's Key Retention Service,
> so iwd is the only known user space application affected so far.
> 
> Thanks,
> 
> Lukas

This patch also fixes the issue for me (on top of next-20241028).

Thanks,
Tested-by: Klara Modin <klarasmodin@gmail.com>

> 
> -- >8 --
> 
> diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
> index c98c158..bbd07a9 100644
> --- a/crypto/asymmetric_keys/public_key.c
> +++ b/crypto/asymmetric_keys/public_key.c
> @@ -93,7 +93,7 @@ static void public_key_destroy(void *payload0, void *payload3)
>   					     pkey->pkey_algo);
>   			} else {
>   				if (!hash_algo)
> -					return -EINVAL;
> +					hash_algo = "none";
>   				n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
>   					     "pkcs1(%s,%s)",
>   					     pkey->pkey_algo, hash_algo);
> diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
> index 9c28f1c..4d077fc9 100644
> --- a/crypto/rsassa-pkcs1.c
> +++ b/crypto/rsassa-pkcs1.c
> @@ -27,6 +27,8 @@
>    * https://www.rfc-editor.org/rfc/rfc9580#table-24
>    */
>   
> +static const u8 hash_prefix_none[] = { };
> +
>   static const u8 hash_prefix_md5[] = {
>   	0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,	  /* SEQUENCE (SEQUENCE (OID */
>   	0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05,	/*	<algorithm>, */
> @@ -93,6 +95,7 @@
>   	size_t		size;
>   } hash_prefixes[] = {
>   #define _(X) { #X, hash_prefix_##X, sizeof(hash_prefix_##X) }
> +	_(none),
>   	_(md5),
>   	_(sha1),
>   	_(rmd160),
> @@ -119,9 +122,18 @@ static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name)
>   	return NULL;
>   }
>   
> -static unsigned int rsassa_pkcs1_hash_len(const struct hash_prefix *p)
> +static bool rsassa_pkcs1_invalid_hash_len(unsigned int len,
> +					  const struct hash_prefix *p)
>   {
>   	/*
> +	 * Legacy protocols such as TLS 1.1 or earlier and IKE version 1
> +	 * do not prepend a Full Hash Prefix to the hash.  In that case,
> +	 * the size of the Full Hash Prefix is zero.
> +	 */
> +	if (p->data == hash_prefix_none)
> +		return false;
> +
> +	/*
>   	 * The final byte of the Full Hash Prefix encodes the hash length.
>   	 *
>   	 * This needs to be revisited should hash algorithms with more than
> @@ -130,7 +142,7 @@ static unsigned int rsassa_pkcs1_hash_len(const struct hash_prefix *p)
>   	 */
>   	static_assert(HASH_MAX_DIGESTSIZE <= 127);
>   
> -	return p->data[p->size - 1];
> +	return len != p->data[p->size - 1];
>   }
>   
>   struct rsassa_pkcs1_ctx {
> @@ -167,7 +179,7 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
>   	if (dlen < ctx->key_size)
>   		return -EOVERFLOW;
>   
> -	if (slen != rsassa_pkcs1_hash_len(hash_prefix))
> +	if (rsassa_pkcs1_invalid_hash_len(slen, hash_prefix))
>   		return -EINVAL;
>   
>   	if (slen + hash_prefix->size > ctx->key_size - 11)
> @@ -237,7 +249,7 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
>   	/* RFC 8017 sec 8.2.2 step 1 - length checking */
>   	if (!ctx->key_size ||
>   	    slen != ctx->key_size ||
> -	    dlen != rsassa_pkcs1_hash_len(hash_prefix))
> +	    rsassa_pkcs1_invalid_hash_len(dlen, hash_prefix))
>   		return -EINVAL;
>   
>   	/* RFC 8017 sec 8.2.2 step 2 - RSA verification */
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index 7d768f0..86126be 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -5540,6 +5540,12 @@ static int alg_test_null(const struct alg_test_desc *desc,
>   			.cipher = __VECS(fcrypt_pcbc_tv_template)
>   		}
>   	}, {
> +		.alg = "pkcs1(rsa,none)",
> +		.test = alg_test_sig,
> +		.suite = {
> +			.sig = __VECS(pkcs1_rsa_none_tv_template)
> +		}
> +	}, {
>   		.alg = "pkcs1(rsa,sha224)",
>   		.test = alg_test_null,
>   		.fips_allowed = 1,
> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index 55aae18..d4c232a 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -1983,6 +1983,61 @@ struct kpp_testvec {
>   };
>   
>   /*
> + * PKCS#1 RSA test vectors for hash algorithm "none"
> + * (i.e. the hash in "m" is not prepended by a Full Hash Prefix)
> + *
> + * Obtained from:
> + * https://vcsjones.dev/sometimes-valid-rsa-dotnet/
> + * https://gist.github.com/vcsjones/ab4c2327b53ed018eada76b75ef4fd99
> + */
> +static const struct sig_testvec pkcs1_rsa_none_tv_template[] = {
> +	{
> +	.key =
> +	"\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa2\x63\x0b\x39\x44\xb8\xbb"
> +	"\x23\xa7\x44\x49\xbb\x0e\xff\xa1\xf0\x61\x0a\x53\x93\xb0\x98\xdb"
> +	"\xad\x2c\x0f\x4a\xc5\x6e\xff\x86\x3c\x53\x55\x0f\x15\xce\x04\x3f"
> +	"\x2b\xfd\xa9\x96\x96\xd9\xbe\x61\x79\x0b\x5b\xc9\x4c\x86\x76\xe5"
> +	"\xe0\x43\x4b\x22\x95\xee\xc2\x2b\x43\xc1\x9f\xd8\x68\xb4\x8e\x40"
> +	"\x4f\xee\x85\x38\xb9\x11\xc5\x23\xf2\x64\x58\xf0\x15\x32\x6f\x4e"
> +	"\x57\xa1\xae\x88\xa4\x02\xd7\x2a\x1e\xcd\x4b\xe1\xdd\x63\xd5\x17"
> +	"\x89\x32\x5b\xb0\x5e\x99\x5a\xa8\x9d\x28\x50\x0e\x17\xee\x96\xdb"
> +	"\x61\x3b\x45\x51\x1d\xcf\x12\x56\x0b\x92\x47\xfc\xab\xae\xf6\x66"
> +	"\x3d\x47\xac\x70\x72\xe7\x92\xe7\x5f\xcd\x10\xb9\xc4\x83\x64\x94"
> +	"\x19\xbd\x25\x80\xe1\xe8\xd2\x22\xa5\xd0\xba\x02\x7a\xa1\x77\x93"
> +	"\x5b\x65\xc3\xee\x17\x74\xbc\x41\x86\x2a\xdc\x08\x4c\x8c\x92\x8c"
> +	"\x91\x2d\x9e\x77\x44\x1f\x68\xd6\xa8\x74\x77\xdb\x0e\x5b\x32\x8b"
> +	"\x56\x8b\x33\xbd\xd9\x63\xc8\x49\x9d\x3a\xc5\xc5\xea\x33\x0b\xd2"
> +	"\xf1\xa3\x1b\xf4\x8b\xbe\xd9\xb3\x57\x8b\x3b\xde\x04\xa7\x7a\x22"
> +	"\xb2\x24\xae\x2e\xc7\x70\xc5\xbe\x4e\x83\x26\x08\xfb\x0b\xbd\xa9"
> +	"\x4f\x99\x08\xe1\x10\x28\x72\xaa\xcd\x02\x03\x01\x00\x01",
> +	.key_len = 294,
> +	.m =
> +	"\x68\xb4\xf9\x26\x34\x31\x25\xdd\x26\x50\x13\x68\xc1\x99\x26\x71"
> +	"\x19\xa2\xde\x81",
> +	.m_size = 20,
> +	.c =
> +	"\x6a\xdb\x39\xe5\x63\xb3\x25\xde\x58\xca\xc3\xf1\x36\x9c\x0b\x36"
> +	"\xb7\xd6\x69\xf9\xba\xa6\x68\x14\x8c\x24\x52\xd3\x25\xa5\xf3\xad"
> +	"\xc9\x47\x44\xde\x06\xd8\x0f\x56\xca\x2d\xfb\x0f\xe9\x99\xe2\x9d"
> +	"\x8a\xe8\x7f\xfb\x9a\x99\x96\xf1\x2c\x4a\xe4\xc0\xae\x4d\x29\x47"
> +	"\x38\x96\x51\x2f\x6d\x8e\xb8\x88\xbd\x1a\x0a\x70\xbc\x23\x38\x67"
> +	"\x62\x22\x01\x23\x71\xe5\xbb\x95\xea\x6b\x8d\x31\x62\xbf\xf0\xc4"
> +	"\xb9\x46\xd6\x67\xfc\x4c\xe6\x1f\xd6\x5d\xf7\xa9\xad\x3a\xf1\xbf"
> +	"\xa2\xf9\x66\xde\xb6\x8e\xec\x8f\x81\x8d\x1e\x3a\x12\x27\x6a\xfc"
> +	"\xae\x92\x9f\xc3\x87\xc3\xba\x8d\x04\xb8\x8f\x0f\x61\x68\x9a\x96"
> +	"\x2c\x80\x2c\x32\x40\xde\x9d\xb9\x9b\xe2\xe4\x45\x2e\x91\x47\x5c"
> +	"\x47\xa4\x9d\x02\x57\x59\xf7\x75\x5d\x5f\x32\x82\x75\x5d\xe5\x78"
> +	"\xc9\x19\x61\x46\x06\x9d\xa5\x1d\xd6\x32\x48\x9a\xdb\x09\x29\x81"
> +	"\x14\x2e\xf0\x27\xe9\x37\x13\x74\xec\xa5\xcd\x67\x6b\x19\xf6\x88"
> +	"\xf0\xc2\x8b\xa8\x7f\x2f\x76\x5a\x3e\x0c\x47\x5d\xe8\x82\x50\x27"
> +	"\x40\xce\x27\x41\x45\xa0\xcf\xaa\x2f\xd3\xad\x3c\xbf\x73\xff\x93"
> +	"\xe3\x78\x49\xd9\xa9\x78\x22\x81\x9a\xe5\xe2\x94\xe9\x40\xab\xf1",
> +	.c_size = 256,
> +	.public_key_vec = true,
> +	},
> +};
> +
> +/*
>    * PKCS#1 RSA test vectors. Obtained from CAVS testing.
>    */
>   static const struct sig_testvec pkcs1_rsa_tv_template[] = {
> 


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend
  2024-09-12 15:27         ` Lukas Wunner
  2024-09-12 17:14           ` Jarkko Sakkinen
@ 2024-11-18  7:56           ` Jarkko Sakkinen
  1 sibling, 0 replies; 53+ messages in thread
From: Jarkko Sakkinen @ 2024-11-18  7:56 UTC (permalink / raw)
  To: Lukas Wunner
  Cc: Herbert Xu, David S. Miller, Eric Biggers, Stefan Berger,
	Vitaly Chikunov, Tadeusz Struk, David Howells, Andrew Zaborowski,
	Saulo Alessandre, Jonathan Cameron, Ignat Korchagin, Marek Behun,
	Varad Gautam, Stephan Mueller, Denis Kenzior, linux-crypto,
	keyrings

On Thu Sep 12, 2024 at 6:27 PM EEST, Lukas Wunner wrote:
> On Thu, Sep 12, 2024 at 05:19:15PM +0300, Jarkko Sakkinen wrote:
> > I try to understand these in detail because I rebase later on my TPM2
> > ECDSA patches (series last updated in April) on top of this. I'll hold
> > with that for the sake of less possible conflicts with this larger
> > series.
> > 
> > Many of the questions rised during the Spring about akcipher so now is
> > my chance to fill the dots by asking them here.
>
> I assume you're referring to:
> https://lore.kernel.org/all/20240528210823.28798-1-jarkko@kernel.org/

Returning to this as I started to update the series. Sorry if for
possible duplicates with my earelier response.

> Help me understand this:
> Once you import a private key to a TPM, can you get it out again?

No.

> Can you generate private keys on the TPM which cannot be retrieved?

Yes.

>
> It would be good if the cover letter or one of the commits in your
> series explained this.  Some of the commit messages are overly terse
> and consist of just two or three bullet points.

Yes.

I'm picking right now the use case where key is uploaded to the TPM
because:

1. The creation part is more complex as data flow starts from user
   space so it pretty much tests the edges also for a generated
   private key.
2. I can drop the code related to public key and add only signing
   operation, not signature verification.

My test script will along the lines of [1]. The new version of the
series is not yet fully working so also the test is due to change.
The idea is to get flow working where a normal public key can verify
a signature made by the TPM chip.

One area what I know probably might not be correct, is what I put
in the 'describe' callbacks:

static void tpm2_key_ecc_describe(const struct key *asymmetric_key,
				    struct seq_file *m)
{
	struct tpm2_key *key = asymmetric_key->payload.data[asym_crypto];

	if (!key) {
		pr_err("key missing");
		return;
	}

	seq_puts(m, "TPM2/ECDSA");
}

So any ideas what to put here are welcome (obviously).

[1]
#!/usr/bin/env bash

set -e

PRIMARY=0x81000001

function egress {
  keyctl clear @u
  tpm2_evictcontrol -C o -c $PRIMARY 2> /dev/null
  tpm2_getcap handles-transient
  tpm2_getcap handles-persistent
}
trap egress EXIT

openssl ecparam -name prime256v1 -genkey -noout -out ecc.pem
openssl pkcs8 -topk8 -inform PEM -outform DER -nocrypt -in ecc.pem -out ecc_pkcs8.der

tpm2_createprimary --hierarchy o -G ecc -c owner.txt
tpm2_evictcontrol -c owner.txt $PRIMARY

# EC parameters to TPM2 blob:
tpm2_import -C $PRIMARY -G ecc -i ecc.pem -u tpm2.pub -r tpm2.priv

# TPM2 blob to ASN.1:
tpm2_encodeobject -C $PRIMARY -u tpm2.pub -r tpm2.priv -o tpm2.pem
openssl asn1parse -inform pem -in tpm2.pem -noout -out tpm2.der

# Populate asymmetric keys:
tpm2_ecc_key=$(keyctl padd asymmetric "tpm_ecc" @u < tpm2.der)
kernel_ecc_key=$(keyctl padd asymmetric "kernel_ecc" @u < ecc_pkcs8.der)

echo "SECRET" > doc.txt

echo TPM2 ECC SIGN
keyctl pkey_sign "$tpm2_ecc_key" 0 doc.txt hash=sha256 > doc.txt.sig

echo TPM2 VERIFY
keyctl pkey_verify "$kernel_ecc_key" 0 doc.txt doc.txt.sig hash=sha256

BR, Jarkko

^ permalink raw reply	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2024-11-18  7:56 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-10 14:30 [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements Lukas Wunner
2024-09-10 18:49   ` Stefan Berger
2024-09-11 11:52   ` Jarkko Sakkinen
2024-09-12  7:59     ` Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend Lukas Wunner
2024-09-11 12:12   ` Jarkko Sakkinen
2024-09-12  7:54     ` Lukas Wunner
2024-09-12 14:19       ` Jarkko Sakkinen
2024-09-12 15:27         ` Lukas Wunner
2024-09-12 17:14           ` Jarkko Sakkinen
2024-11-18  7:56           ` Jarkko Sakkinen
2024-09-13 18:40   ` Jonathan Cameron
2024-09-10 14:30 ` [PATCH v2 03/19] crypto: ecdsa - Migrate to " Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 04/19] crypto: ecrdsa " Lukas Wunner
2024-09-11 12:49   ` Jarkko Sakkinen
2024-09-12  8:05     ` Lukas Wunner
2024-09-12 14:20       ` Jarkko Sakkinen
2024-09-10 14:30 ` [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks Lukas Wunner
2024-09-10 19:03   ` Stefan Berger
2024-09-11 12:54   ` Jarkko Sakkinen
2024-09-10 14:30 ` [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend Lukas Wunner
2024-09-11 12:56   ` Jarkko Sakkinen
2024-10-21 16:08   ` Klara Modin
2024-10-21 19:02     ` Lukas Wunner
2024-10-22 10:15       ` Klara Modin
2024-10-23 10:19       ` Klara Modin
2024-10-25  7:17         ` Lukas Wunner
2024-10-25 16:50           ` Eric Biggers
2024-10-26  9:40           ` Klara Modin
2024-10-28 11:45           ` Klara Modin
2024-09-10 14:30 ` [PATCH v2 07/19] crypto: rsassa-pkcs1 - Harden digest length verification Lukas Wunner
2024-09-11 12:58   ` Jarkko Sakkinen
2024-09-10 14:30 ` [PATCH v2 08/19] crypto: rsassa-pkcs1 - Avoid copying hash prefix Lukas Wunner
2024-09-11 13:00   ` Jarkko Sakkinen
2024-09-10 14:30 ` [PATCH v2 09/19] crypto: virtio - Drop sign/verify operations Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 10/19] crypto: drivers " Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 11/19] crypto: akcipher " Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 12/19] crypto: sig - Move crypto_sig_*() API calls to include file Lukas Wunner
2024-09-10 19:24   ` Stefan Berger
2024-09-10 14:30 ` [PATCH v2 13/19] ASN.1: Clean up include statements in public headers Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 14/19] crypto: ecdsa - Avoid signed integer overflow on signature decoding Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 15/19] crypto: ecdsa - Move X9.62 signature decoding into template Lukas Wunner
2024-09-10 20:46   ` Stefan Berger
2024-09-10 14:30 ` [PATCH v2 16/19] crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize() Lukas Wunner
2024-09-11 13:02   ` Jarkko Sakkinen
2024-09-12  8:12     ` Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 17/19] crypto: ecdsa - Move X9.62 signature size calculation into template Lukas Wunner
2024-09-10 14:30 ` [PATCH v2 18/19] crypto: ecdsa - Support P1363 signature decoding Lukas Wunner
2024-09-10 21:46   ` Stefan Berger
2024-09-10 14:30 ` [PATCH v2 19/19] crypto: ecrdsa - Fix signature size calculation Lukas Wunner
2024-10-01  9:17 ` [PATCH v2 00/19] Migrate to sig_alg and templatize ecdsa Lukas Wunner
2024-10-05  5:27 ` Herbert Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).