Skip to contentSkip to conversation

Migrate to sig_alg and templatize ecdsa

PATCH In review Lukas Wunner 7 participants 53 messages Sep 10, 2024 – Nov 18, 2024

Subsystems (18)
lore
Share & tools
lore

Lukas Wunner

author maintainer
#0 lore raw

v2 cover Migrate to sig_alg and templatize ecdsa

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 at 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
Signature · 1 line
2.43.0
author maintainer
#1 lore raw

PATCH v2 1/19 crypto: ecdsa - Drop unused test vector elements

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.

---
 crypto/testmgr.h | 115 +++++------------------------------------------
 1 file changed, 10 insertions(+), 105 deletions(-)
crypto/testmgr.h +10 -105
index 9b38501a17b2..ed1640f3e352 100644
@@ -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"
Signature · 1 line
2.43.0
reviewer Reviewed-by on v2 1/19
#2 lore raw

Re: [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements

Quoted 421 lines · Lukas Wunner

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.

---
  crypto/testmgr.h | 115 +++++------------------------------------------
  1 file changed, 10 insertions(+), 105 deletions(-)
crypto/testmgr.h +10 -104
index 9b38501a17b2..ed1640f3e352 100644
@@ -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,

crypto/testmgr.h static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = { · line 1111

Quoted 10 lines
crypto/testmgr.h +0 -1
  	.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"
maintainer
#3 lore raw

Re: [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements

In reply to Lukas Wunner
Quoted 3 lines · Lukas Wunner

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

author maintainer
#4 lore raw

Re: [PATCH v2 01/19] crypto: ecdsa - Drop unused test vector elements

Quoted 16 lines · Jarkko Sakkinen
Quoted 3 lines · Lukas Wunner

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.

Quoted 4 lines

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

author maintainer
#5 lore raw

PATCH v2 2/19 crypto: sig - Introduce sig_alg backend

In reply to Lukas Wunner

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/[email protected]/

"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/[email protected]/

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.

---
 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
Documentation/crypto/api-sig.rst new file +15 -0
new file mode 100644
index 000000000000..e5e87e106884
@@ -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
+
Documentation/crypto/api.rst +1 -0
index ff31c30561d4..8b2a90521886 100644
@@ -10,4 +10,5 @@ Programming Interface
    api-digest
    api-rng
    api-akcipher
+   api-sig
    api-kpp
Documentation/crypto/architecture.rst +2 -0
index 646c3380a7ed..15dcd62fd22f 100644
@@ -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
crypto/sig.c +141 -2

206 lines not on this page · raw message

crypto/testmgr.c +115 -0

139 lines not on this page · raw message

crypto/testmgr.h +13 -0
index ed1640f3e352..39dd1d558883 100644
@@ -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;
include/crypto/internal/sig.h +80 -0

88 lines not on this page · raw message

include/crypto/sig.h +61 -0

73 lines not on this page · raw message

include/uapi/linux/cryptouser.h +5 -0
index 20a6c0fc149e..db05e0419972 100644
@@ -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))
 
Signature · 1 line
2.43.0
maintainer
#6 lore raw

Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend

Quoted 75 lines · Lukas Wunner

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/[email protected]/

"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/[email protected]/

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.

---
 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
Documentation/crypto/api-sig.rst new file +15 -0
new file mode 100644
index 000000000000..e5e87e106884
@@ -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
+
Documentation/crypto/api.rst +1 -0
index ff31c30561d4..8b2a90521886 100644
@@ -10,4 +10,5 @@ Programming Interface
    api-digest
    api-rng
    api-akcipher
+   api-sig
    api-kpp
Documentation/crypto/architecture.rst +0 -0
index 646c3380a7ed..15dcd62fd22f 100644

Documentation/crypto/architecture.rst the aforementioned cipher types: · line 221

Quoted 8 lines
Documentation/crypto/architecture.rst +2 -0
@@ -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.

Quoted 19 lines
crypto/sig.c +8 -0
index 7645bedf3a1f..4f36ceb7a90b 100644
@@ -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)

crypto/sig.c line 44

Quoted 10 lines
crypto/sig.c +8 -0
 		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

author maintainer
#7 lore raw

Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend

Quoted 18 lines · Jarkko Sakkinen

crypto/sig.c line 44

Quoted 13 lines

static int crypto_sig_init_tfm(struct crypto_tfm *tfm) {

crypto/sig.c +8 -0
 	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

Quoted 1 line

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

maintainer
#8 lore raw

Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend

Quoted 19 lines · Lukas Wunner
Quoted 18 lines · Jarkko Sakkinen

crypto/sig.c line 44

Quoted 13 lines

static int crypto_sig_init_tfm(struct crypto_tfm *tfm) {

crypto/sig.c +8 -0
 	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

Quoted 3 lines
Quoted 1 line

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

author maintainer
#9 lore raw

Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend

Quoted 7 lines · Jarkko Sakkinen

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/[email protected]/

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

maintainer
#10 lore raw

Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend

Quoted 9 lines · Lukas Wunner
Quoted 7 lines · Jarkko Sakkinen

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.

Quoted 6 lines

I assume you're referring to:
https://lore.kernel.org/all/[email protected]/

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.

Quoted 3 lines

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!

Quoted 16 lines

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.

Quoted 4 lines

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 :-)

Quoted 4 lines

Thanks,

Lukas

BR, Jarkko

maintainer
#11 lore raw

Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend

In reply to Lukas Wunner
Quoted 11 lines · Lukas Wunner
Quoted 7 lines · Jarkko Sakkinen

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/[email protected]/

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

Quoted 2 lines

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

No.

Quoted 1 line

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

Yes.

Quoted 4 lines

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

#12 lore raw

Re: [PATCH v2 02/19] crypto: sig - Introduce sig_alg backend

In reply to Lukas Wunner
Quoted 19 lines · On Tue, 10 Sep 2024 16:30:12 +0200 Lukas Wunner <[email protected]> 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/[email protected]/

"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/[email protected]/

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.

Quoted 7 lines

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.

Hi Lukas,

A few trivial comments.

Jonathan

Quoted 7 lines
crypto/sig.c +0 -0
index 7645bedf3a1f..4f36ceb7a90b 100644
@@ -68,6 +93,14 @@ EXPORT_SYMBOL_GPL(crypto_alloc_sig);
 

crypto/sig.c EXPORT_SYMBOL_GPL(crypto_alloc_sig); · line 103

Quoted 10 lines
crypto/sig.c +8 -0
 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.

Quoted 8 lines
crypto/sig.c +0 -0
 	struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
 
 	return crypto_akcipher_maxsize(*ctx);
crypto/testmgr.c +0 -0
index f02cb075bd68..bb21378aa510 100644

...

crypto/testmgr.c static int alg_test_akcipher(const struct alg_test_desc *desc, · line 4329

Quoted 7 lines
crypto/testmgr.c +3 -0
@@ -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.

crypto/testmgr.c static int alg_test_akcipher(const struct alg_test_desc *desc, · line 4335

Quoted 6 lines
crypto/testmgr.c +6 -0
+	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

include/crypto/internal/sig.h line 82

Quoted 6 lines

index 97cb26ef8115..b16648c1a986 100644

include/crypto/internal/sig.h +2 -0
 
+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.

Quoted 3 lines
include/crypto/internal/sig.h +3 -0
+{
+	return crypto_spawn_tfm2(&spawn->base);
+}
author maintainer
#13 lore raw

PATCH v2 3/19 crypto: ecdsa - Migrate to sig_alg backend

In reply to Lukas Wunner

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.

---
 crypto/Kconfig   |  2 +-
 crypto/ecdsa.c   | 99 ++++++++++++++++++++----------------------------
 crypto/testmgr.c | 17 ++++-----
 crypto/testmgr.h | 27 ++-----------
 4 files changed, 55 insertions(+), 90 deletions(-)
crypto/Kconfig +1 -1
index 84778611e2d7..89b728c72f07 100644
@@ -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,
crypto/ecdsa.c +42 -57

221 lines not on this page · raw message

crypto/testmgr.c +8 -9
index bb21378aa510..81ac32c9dd3e 100644
@@ -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",
crypto/testmgr.h +4 -23
index 39dd1d558883..a4987610fcb5 100644
@@ -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,
 	},
 };
 
Signature · 1 line
2.43.0
author maintainer
#14 lore raw

PATCH v2 4/19 crypto: ecrdsa - Migrate to sig_alg backend

In reply to Lukas Wunner

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.

---
 crypto/Kconfig   |  2 +-
 crypto/ecrdsa.c  | 56 +++++++++++++++++++++---------------------------
 crypto/testmgr.c |  4 ++--
 crypto/testmgr.h |  7 +-----
 4 files changed, 28 insertions(+), 41 deletions(-)
crypto/Kconfig +1 -1
index 89b728c72f07..e8488b8c45e3 100644
@@ -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
crypto/ecrdsa.c +24 -32

116 lines not on this page · raw message

crypto/testmgr.c +2 -2
index 81ac32c9dd3e..0542817a9456 100644
@@ -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)",
crypto/testmgr.h +1 -6
index a4987610fcb5..fd4823c26d93 100644
@@ -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,
 	},
 };
 
Signature · 1 line
2.43.0
maintainer
#15 lore raw

Re: [PATCH v2 04/19] crypto: ecrdsa - Migrate to sig_alg backend

Quoted 78 lines · Lukas Wunner

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.

---
 crypto/Kconfig   |  2 +-
 crypto/ecrdsa.c  | 56 +++++++++++++++++++++---------------------------
 crypto/testmgr.c |  4 ++--
 crypto/testmgr.h |  7 +-----
 4 files changed, 28 insertions(+), 41 deletions(-)
crypto/Kconfig +1 -1
index 89b728c72f07..e8488b8c45e3 100644
@@ -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
crypto/ecrdsa.c +9 -11
index 3811f3805b5d..7383dd11089b 100644
@@ -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 ||

crypto/ecrdsa.c static int ecrdsa_verify(struct akcipher_request *req) · line 100

Quoted 10 lines
crypto/ecrdsa.c +5 -4
-	    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

author maintainer
#16 lore raw

Re: [PATCH v2 04/19] crypto: ecrdsa - Migrate to sig_alg backend

Quoted 5 lines · Jarkko Sakkinen
Quoted 4 lines · Lukas Wunner

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.

[...]

Quoted 21 lines
Quoted 7 lines
crypto/ecrdsa.c +2 -2
 	if (!ctx->curve ||
 	    !ctx->digest ||
-	    !req->src ||
+	    !src ||
+	    !digest ||
 	    !ctx->pub_key.x ||
-	    req->dst_len != ctx->digest_len ||

crypto/ecrdsa.c static int ecrdsa_verify(struct akcipher_request *req) · line 100

Quoted 10 lines
crypto/ecrdsa.c +5 -4
-	    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.

Quoted 2 lines

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

maintainer
#17 lore raw

Re: [PATCH v2 04/19] crypto: ecrdsa - Migrate to sig_alg backend

Quoted 28 lines · Lukas Wunner
Quoted 5 lines · Jarkko Sakkinen
Quoted 4 lines · Lukas Wunner

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.

[...]

Quoted 21 lines
Quoted 7 lines
crypto/ecrdsa.c +2 -2
 	if (!ctx->curve ||
 	    !ctx->digest ||
-	    !req->src ||
+	    !src ||
+	    !digest ||
 	    !ctx->pub_key.x ||
-	    req->dst_len != ctx->digest_len ||

crypto/ecrdsa.c static int ecrdsa_verify(struct akcipher_request *req) · line 100

Quoted 10 lines
crypto/ecrdsa.c +5 -4
-	    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.

Quoted 8 lines
Quoted 2 lines

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

author maintainer
#18 lore raw

PATCH v2 5/19 crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks

In reply to Lukas Wunner

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.

---
 crypto/rsa-pkcs1pad.c         | 30 ++----------------------------
 include/crypto/internal/rsa.h | 28 ++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 28 deletions(-)
crypto/rsa-pkcs1pad.c +2 -28
index cd501195f34a..3c5fe8c93938 100644
@@ -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)
include/crypto/internal/rsa.h +28 -0
index e870133f4b77..754f687134df 100644
@@ -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
Signature · 1 line
2.43.0
reviewer Reviewed-by on v2 5/19
#19 lore raw

Re: [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks

Quoted 100 lines · Lukas Wunner

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.

---
  crypto/rsa-pkcs1pad.c         | 30 ++----------------------------
  include/crypto/internal/rsa.h | 28 ++++++++++++++++++++++++++++
  2 files changed, 30 insertions(+), 28 deletions(-)
crypto/rsa-pkcs1pad.c +2 -28
index cd501195f34a..3c5fe8c93938 100644
@@ -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)
include/crypto/internal/rsa.h +20 -0
index e870133f4b77..754f687134df 100644
@@ -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 */

include/crypto/internal/rsa.h int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key, · line 85

Quoted 10 lines
include/crypto/internal/rsa.h +8 -0
+	err = crypto_akcipher_maxsize(child);
+	if (err > PAGE_SIZE)
+		return -ENOTSUPP;
+
+	*key_size = err;
+	return 0;
+}
+
  extern struct crypto_template rsa_pkcs1pad_tmpl;
  #endif
maintainer
#20 lore raw

Re: [PATCH v2 05/19] crypto: rsa-pkcs1pad - Deduplicate set_{pub,priv}_key callbacks

In reply to Lukas Wunner
Quoted 9 lines · Lukas Wunner

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...

Quoted 69 lines
---
 crypto/rsa-pkcs1pad.c         | 30 ++----------------------------
 include/crypto/internal/rsa.h | 28 ++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 28 deletions(-)
crypto/rsa-pkcs1pad.c +2 -28
index cd501195f34a..3c5fe8c93938 100644
@@ -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)
include/crypto/internal/rsa.h +1 -0
index e870133f4b77..754f687134df 100644
@@ -8,6 +8,7 @@
 #ifndef _RSA_HELPER_
 #define _RSA_HELPER_
 #include <linux/types.h>
+#include <crypto/akcipher.h>
 
 /**
  * rsa_key - RSA key structure

include/crypto/internal/rsa.h int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key, · line 59

Quoted 6 lines
include/crypto/internal/rsa.h +3 -0
@@ -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>
*/

Quoted 16 lines
include/crypto/internal/rsa.h +16 -0
+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 */

include/crypto/internal/rsa.h int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key, · line 85

Quoted 10 lines
include/crypto/internal/rsa.h +8 -0
+	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

author maintainer
#21 lore raw

PATCH v2 6/19 crypto: rsassa-pkcs1 - Migrate to sig_alg backend

In reply to Lukas Wunner

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.

---
 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
crypto/Kconfig +1 -0
index e8488b8c45e3..94ef57c9e936 100644
@@ -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
crypto/Makefile +1 -0
index 4c99e5d376f6..7de29bf843e9 100644
@@ -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
crypto/asymmetric_keys/public_key.c +8 -2
index 422940a6706a..3fb27ecd65f6 100644
@@ -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;
crypto/rsa-pkcs1pad.c +16 -325

414 lines not on this page · raw message

crypto/rsa.c +13 -4
index d9be9e86097e..89e9fd9f6d7f 100644
@@ -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);
 }
crypto/rsassa-pkcs1.c new file +422 -0

422 lines not on this page · raw message

crypto/testmgr.c +13 -9
index 0542817a9456..91dc29e79dd6 100644
@@ -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,
 	}, {
crypto/testmgr.h +1 -2
index fd4823c26d93..d29d03fec852 100644
@@ -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,
 	}
 };
 
include/crypto/internal/rsa.h +1 -0
index 754f687134df..071a1951b992 100644
@@ -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
include/linux/slab.h +1 -0
index eb2bf4629157..11b620b0ba1d 100644
@@ -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
security/integrity/ima/ima_main.c +3 -3
index f04f43af651c..280a3feeba45 100644
@@ -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;
Signature · 1 line
2.43.0
maintainer
#22 lore raw

Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

Quoted 55 lines · Lukas Wunner

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().

Quoted 8 lines

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.

Quoted 1,084 lines
---
 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
crypto/Kconfig +1 -0
index e8488b8c45e3..94ef57c9e936 100644
@@ -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
crypto/Makefile +1 -0
index 4c99e5d376f6..7de29bf843e9 100644
@@ -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
crypto/asymmetric_keys/public_key.c +8 -2
index 422940a6706a..3fb27ecd65f6 100644
@@ -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;
crypto/rsa-pkcs1pad.c +16 -325
index 3c5fe8c93938..50bdb18e7b48 100644
@@ -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;
crypto/rsa.c +13 -4
index d9be9e86097e..89e9fd9f6d7f 100644
@@ -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);
 }
crypto/rsassa-pkcs1.c new file +422 -0
new file mode 100644
index 000000000000..779c080fc013
@@ -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");
crypto/testmgr.c +13 -9
index 0542817a9456..91dc29e79dd6 100644
@@ -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,
 	}, {
crypto/testmgr.h +1 -2
index fd4823c26d93..d29d03fec852 100644
@@ -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,
 	}
 };
 
include/crypto/internal/rsa.h +1 -0
index 754f687134df..071a1951b992 100644
@@ -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
include/linux/slab.h +1 -0
index eb2bf4629157..11b620b0ba1d 100644
@@ -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
security/integrity/ima/ima_main.c +3 -3
index f04f43af651c..280a3feeba45 100644
@@ -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;
#23 lore raw

Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

In reply to Lukas Wunner

Hi,

Quoted 60 lines · Lukas Wunner

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.

Quoted 1 line

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.

Quoted 5 lines

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.

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

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
author maintainer
#24 lore raw

Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

Quoted 6 lines · Klara Modin
Quoted 5 lines · Lukas Wunner

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.

[...]

Quoted 2 lines

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 --

crypto/asymmetric_keys/public_key.c +9 -1
index c98c158..af19f9c 100644
@@ -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;
#25 lore raw

Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

Quoted 58 lines · Lukas Wunner
Quoted 6 lines · Klara Modin
Quoted 5 lines · Lukas Wunner

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.

[...]

Quoted 2 lines

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 --

crypto/asymmetric_keys/public_key.c +4 -0
index c98c158..af19f9c 100644
@@ -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.

crypto/asymmetric_keys/public_key.c static int software_key_query(const struct kernel_pkey_params *params, · line 186

Quoted 10 lines
crypto/asymmetric_keys/public_key.c +5 -1
+	 */
+	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

Tested-by
#26 lore raw

Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

In reply to Lukas Wunner
Quoted 58 lines · Lukas Wunner
Quoted 6 lines · Klara Modin
Quoted 5 lines · Lukas Wunner

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.

[...]

Quoted 2 lines

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 --

crypto/asymmetric_keys/public_key.c +4 -0
index c98c158..af19f9c 100644
@@ -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.

crypto/asymmetric_keys/public_key.c static int software_key_query(const struct kernel_pkey_params *params, · line 186

Quoted 10 lines
crypto/asymmetric_keys/public_key.c +5 -1
+	 */
+	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)

author maintainer
#27 lore raw

Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

Quoted 4 lines · Klara Modin
Quoted 3 lines · Lukas Wunner
Quoted 2 lines · Klara Modin

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

[...]

Quoted 5 lines
Quoted 5 lines

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.

[...]

Quoted 8 lines

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 --

crypto/asymmetric_keys/public_key.c +1 -1
index c98c158..bbd07a9 100644
@@ -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);
crypto/rsassa-pkcs1.c +16 -4
index 9c28f1c..4d077fc9 100644
@@ -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 */
crypto/testmgr.c +6 -0
index 7d768f0..86126be 100644
@@ -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,
crypto/testmgr.h +55 -0

61 lines not on this page · raw message

#28 lore raw

Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

Quoted 4 lines · Lukas Wunner

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).

[...]

Quoted 4 lines

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

#29 lore raw

Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

In reply to Lukas Wunner
Quoted 54 lines · Lukas Wunner
Quoted 4 lines · Klara Modin
Quoted 3 lines · Lukas Wunner
Quoted 2 lines · Klara Modin

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

[...]

Quoted 5 lines
Quoted 5 lines

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.

[...]

Quoted 8 lines

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.

Quoted 9 lines

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 [email protected] to the CC which is on my own server, maybe that'll work better)

Regards,
Klara Modin

Quoted 167 lines

-- >8 --

crypto/asymmetric_keys/public_key.c +1 -1
index c98c158..bbd07a9 100644
@@ -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);
crypto/rsassa-pkcs1.c +16 -4
index 9c28f1c..4d077fc9 100644
@@ -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 */
crypto/testmgr.c +6 -0
index 7d768f0..86126be 100644
@@ -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,
crypto/testmgr.h +55 -0
index 55aae18..d4c232a 100644
@@ -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[] = {
Tested-by
#30 lore raw

Re: [PATCH v2 06/19] crypto: rsassa-pkcs1 - Migrate to sig_alg backend

In reply to Lukas Wunner
Quoted 54 lines · Lukas Wunner
Quoted 4 lines · Klara Modin
Quoted 3 lines · Lukas Wunner
Quoted 2 lines · Klara Modin

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

[...]

Quoted 5 lines
Quoted 5 lines

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.

[...]

Quoted 8 lines

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.

Quoted 8 lines

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,

Quoted 168 lines

-- >8 --

crypto/asymmetric_keys/public_key.c +1 -1
index c98c158..bbd07a9 100644
@@ -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);
crypto/rsassa-pkcs1.c +16 -4
index 9c28f1c..4d077fc9 100644
@@ -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 */
crypto/testmgr.c +6 -0
index 7d768f0..86126be 100644
@@ -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,
crypto/testmgr.h +55 -0
index 55aae18..d4c232a 100644
@@ -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[] = {
author maintainer
#31 lore raw

PATCH v2 7/19 crypto: rsassa-pkcs1 - Harden digest length verification

In reply to Lukas Wunner

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.

---
 crypto/rsassa-pkcs1.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)
crypto/rsassa-pkcs1.c +19 -1
index 779c080fc013..8f42a5712806 100644
@@ -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 */
Signature · 1 line
2.43.0
maintainer
#32 lore raw

Re: [PATCH v2 07/19] crypto: rsassa-pkcs1 - Harden digest length verification

Quoted 34 lines · Lukas Wunner

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.

---
 crypto/rsassa-pkcs1.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)
crypto/rsassa-pkcs1.c +1 -0
index 779c080fc013..8f42a5712806 100644
@@ -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;
 }

crypto/rsassa-pkcs1.c static const struct hash_prefix *rsassa_pkcs1_find_hash_prefix(const char *name) · line 130

Quoted 10 lines
crypto/rsassa-pkcs1.c +9 -0
 
+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.

Quoted 19 lines
crypto/rsassa-pkcs1.c +8 -0
+	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;
 

crypto/rsassa-pkcs1.c static int rsassa_pkcs1_verify(struct crypto_sig *tfm, · line 241

Quoted 8 lines
crypto/rsassa-pkcs1.c +1 -1
@@ -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

author maintainer
#33 lore raw

PATCH v2 8/19 crypto: rsassa-pkcs1 - Avoid copying hash prefix

In reply to Lukas Wunner

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.

---
 crypto/rsassa-pkcs1.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
crypto/rsassa-pkcs1.c +10 -8
index 8f42a5712806..b291ec0944a2 100644
@@ -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,
Signature · 1 line
2.43.0
maintainer
#34 lore raw

Re: [PATCH v2 08/19] crypto: rsassa-pkcs1 - Avoid copying hash prefix

Quoted 51 lines · Lukas Wunner

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.

---
 crypto/rsassa-pkcs1.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
crypto/rsassa-pkcs1.c +6 -5
index 8f42a5712806..b291ec0944a2 100644
@@ -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);

crypto/rsassa-pkcs1.c static int rsassa_pkcs1_sign(struct crypto_sig *tfm, · line 198

Quoted 10 lines
crypto/rsassa-pkcs1.c +4 -3
-	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

author maintainer
#35 lore raw

PATCH v2 9/19 crypto: virtio - Drop sign/verify operations

In reply to Lukas Wunner

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/[email protected]/

"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/[email protected]/

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.

---
 .../virtio/virtio_crypto_akcipher_algs.c      | 65 ++++++-------------
 include/uapi/linux/virtio_crypto.h            |  1 +
 2 files changed, 22 insertions(+), 44 deletions(-)
drivers/crypto/virtio/virtio_crypto_akcipher_algs.c +21 -44
index cb92b7fa99c6..48fee07b7e51 100644
@@ -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),
include/uapi/linux/virtio_crypto.h +1 -0
index 71a54a6849ca..2fccb64c9d6b 100644
@@ -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 \
Signature · 1 line
2.43.0
author maintainer
#36 lore raw

PATCH v2 10/19 crypto: drivers - Drop sign/verify operations

In reply to Lukas Wunner

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.

---
 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(-)
drivers/crypto/aspeed/aspeed-acry.c +0 -2
index b4613bd4ad96..7a1e153733e1 100644
@@ -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,
drivers/crypto/hisilicon/hpre/hpre_crypto.c +0 -2
index 764532a6ca82..bdd7e1df8a06 100644
@@ -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,
drivers/crypto/starfive/jh7110-rsa.c +0 -2
index a778c4846025..d109c743f076 100644
@@ -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,
Signature · 1 line
2.43.0
author maintainer
#37 lore raw

PATCH v2 11/19 crypto: akcipher - Drop sign/verify operations

In reply to Lukas Wunner

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.

---
 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(-)
Documentation/crypto/api-akcipher.rst +1 -1
index 40aa8746e2a1..6f47cc70eca0 100644
@@ -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
 --------------------------------
crypto/akcipher.c +19 -45

112 lines not on this page · raw message

crypto/internal.h +0 -19
index aee31319be2e..0008621aaa98 100644
@@ -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)
 {
crypto/sig.c +0 -70

137 lines not on this page · raw message

crypto/testmgr.c +36 -83

193 lines not on this page · raw message

crypto/testmgr.h +0 -4
index d29d03fec852..e10b6d7f2cd9 100644
@@ -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 {
include/crypto/akcipher.h +8 -61

118 lines not on this page · raw message

include/crypto/internal/akcipher.h +2 -2
index a0fba4b2eccf..14ee62bc52b6 100644
@@ -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
  */
Signature · 1 line
2.43.0
author maintainer
#38 lore raw

PATCH v2 12/19 crypto: sig - Move crypto_sig_*() API calls to include file

In reply to Lukas Wunner

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.

---
 crypto/sig.c         | 46 -------------------------------------------
 include/crypto/sig.h | 47 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 36 insertions(+), 57 deletions(-)
crypto/sig.c +0 -46
index 1e6b0d677472..84d0ea9fd73b 100644
@@ -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;
include/crypto/sig.h +36 -11

75 lines not on this page · raw message

Signature · 1 line
2.43.0
reviewer Reviewed-by on v2 12/19
#39 lore raw

Re: [PATCH v2 12/19] crypto: sig - Move crypto_sig_*() API calls to include file

Quoted 146 lines · Lukas Wunner

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.

---
  crypto/sig.c         | 46 -------------------------------------------
  include/crypto/sig.h | 47 +++++++++++++++++++++++++++++++++-----------
  2 files changed, 36 insertions(+), 57 deletions(-)
crypto/sig.c +0 -46
index 1e6b0d677472..84d0ea9fd73b 100644
@@ -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;
include/crypto/sig.h +29 -9
index f0f52a7c5ae7..bbc902642bf5 100644
@@ -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
   */

include/crypto/sig.h int crypto_sig_set_pubkey(struct crypto_sig *tfm, · line 226

Quoted 10 lines
include/crypto/sig.h +7 -2
-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
author maintainer
#40 lore raw

PATCH v2 13/19 ASN.1: Clean up include statements in public headers

In reply to Lukas Wunner

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.

---
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(-)
include/linux/asn1_decoder.h +1 -0
index 83f9c6e1e5e9..b41bce82a191 100644
@@ -9,6 +9,7 @@
 #define _LINUX_ASN1_DECODER_H
 
 #include <linux/asn1.h>
+#include <linux/types.h>
 
 struct asn1_decoder;
 
include/linux/asn1_encoder.h +0 -1
index 08cd0c2ad34f..d17484dffb74 100644
@@ -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 *
Signature · 1 line
2.43.0
author maintainer
#41 lore raw

PATCH v2 14/19 crypto: ecdsa - Avoid signed integer overflow on signature decoding

In reply to Lukas Wunner

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.

---
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(-)
crypto/ecdsa.c +7 -12
index 3b9873f56b0a..4a0ca93c99ea 100644
@@ -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);
 
Signature · 1 line
2.43.0
author maintainer
#42 lore raw

PATCH v2 15/19 crypto: ecdsa - Move X9.62 signature decoding into template

In reply to Lukas Wunner

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.

---
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
crypto/Makefile +2 -1
index 7de29bf843e9..af43a1bd1cfa 100644
@@ -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
 
crypto/asymmetric_keys/public_key.c +3 -0
index 3fb27ecd65f6..cc6d48cafa2b 100644
@@ -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;
crypto/ecdsa-x962.c new file +201 -0

201 lines not on this page · raw message

crypto/ecdsa.c +13 -66

122 lines not on this page · raw message

crypto/testmgr.c +27 -0
index fdebdafdf027..19c1d01a064f 100644
@@ -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,
crypto/testmgr.h +696 -3

733 lines not on this page · raw message

include/crypto/internal/ecc.h +13 -0
index 0717a53ae732..68db975e0963 100644
@@ -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
Signature · 1 line
2.43.0
reviewer Tested-by on v2 15/19
#43 lore raw

Re: [PATCH v2 15/19] crypto: ecdsa - Move X9.62 signature decoding into template

Quoted 21 lines · Lukas Wunner

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.

Quoted 5 lines

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

I ran my signature verification test cases over this:

author maintainer
#44 lore raw

PATCH v2 16/19 crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize()

In reply to Lukas Wunner

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.

---
 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(-)
Documentation/crypto/api-sig.rst +1 -1
index e5e87e106884..10dabc87df02 100644
@@ -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
 
crypto/asymmetric_keys/public_key.c +2 -2
index cc6d48cafa2b..8bf5aa329c26 100644
@@ -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)) {
crypto/ecdsa-x962.c +4 -4
index 022e654c075d..8a15232dfa77 100644
@@ -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;
crypto/ecdsa.c +5 -5
index 1f7c29468a86..6cb0a6ce9de1 100644
@@ -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 = {
crypto/ecrdsa.c +2 -2
index 7383dd11089b..f981b31f4249 100644
@@ -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",
crypto/rsassa-pkcs1.c +2 -2
index b291ec0944a2..9c28f1c62826 100644
@@ -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;
 
crypto/sig.c +1 -1
index 84d0ea9fd73b..7a3521bee29a 100644
@@ -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);
crypto/testmgr.c +1 -1
index 19c1d01a064f..287ed2daadf4 100644
@@ -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;
include/crypto/sig.h +7 -7
index bbc902642bf5..a3ef17c5f72f 100644
@@ -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);
 }
 
 /**
Signature · 1 line
2.43.0
maintainer
#45 lore raw

Re: [PATCH v2 16/19] crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize()

Quoted 7 lines · Lukas Wunner

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.

Quoted 6 lines

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?

BR, Jarkko

author maintainer
#46 lore raw

Re: [PATCH v2 16/19] crypto: sig - Rename crypto_sig_maxsize() to crypto_sig_keysize()

Quoted 8 lines · Jarkko Sakkinen
Quoted 7 lines · Lukas Wunner

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.

Quoted 6 lines
Quoted 4 lines

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

author maintainer
#47 lore raw

PATCH v2 17/19 crypto: ecdsa - Move X9.62 signature size calculation into template

In reply to Lukas Wunner

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/[email protected]/

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.

---
 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(-)
Documentation/crypto/api-sig.rst +1 -1
index 10dabc87df02..aaec18e26d54 100644
@@ -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
 
crypto/asymmetric_keys/public_key.c +4 -34
index 8bf5aa329c26..ec2c0e009b49 100644
@@ -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;
 
crypto/ecdsa-x962.c +36 -0
index 8a15232dfa77..6a77c13e192b 100644
@@ -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;
crypto/ecdsa.c +16 -0
index 6cb0a6ce9de1..cf8e0c5d1dd8 100644
@@ -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 = {
crypto/sig.c +4 -0
index 7a3521bee29a..be5ac0e59384 100644
@@ -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);
include/crypto/sig.h +38 -0
index a3ef17c5f72f..cff41ad93824 100644
@@ -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
  *
Signature · 1 line
2.43.0
author maintainer
#48 lore raw

PATCH v2 18/19 crypto: ecdsa - Support P1363 signature decoding

In reply to Lukas Wunner

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."

---
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
crypto/Makefile +1 -0
index af43a1bd1cfa..81be78d39c2d 100644
@@ -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
 
crypto/asymmetric_keys/public_key.c +2 -1
index ec2c0e009b49..c98c1588802b 100644
@@ -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
crypto/ecdsa-p1363.c new file +159 -0

159 lines not on this page · raw message

crypto/ecdsa.c +8 -0
index cf8e0c5d1dd8..117526d15dde 100644
@@ -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);
crypto/testmgr.c +18 -0
index 287ed2daadf4..bf266dedd07f 100644
@@ -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,
crypto/testmgr.h +28 -0
index 2bd77eaafdf6..55aae1859d2c 100644
@@ -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.
  */
include/crypto/internal/ecc.h +1 -0
index 68db975e0963..71483e5305e1 100644
@@ -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
Signature · 1 line
2.43.0
reviewer Reviewed-by on v2 18/19
#49 lore raw

Re: [PATCH v2 18/19] crypto: ecdsa - Support P1363 signature decoding

Quoted 18 lines · Lukas Wunner

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."

Quoted 3 lines
author maintainer
#50 lore raw

PATCH v2 19/19 crypto: ecrdsa - Fix signature size calculation

In reply to Lukas Wunner

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().

---
 crypto/ecrdsa.c | 8 ++++++++
 1 file changed, 8 insertions(+)
crypto/ecrdsa.c +8 -0
index f981b31f4249..b3dd8a3ddeb7 100644
@@ -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",
Signature · 1 line
2.43.0
author maintainer
#51 lore raw
In reply to Lukas Wunner

Hi Herbert,

Quoted 13 lines · Lukas Wunner

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]).

Quoted 7 lines

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

maintainer
#52 lore raw
In reply to Lukas Wunner
Quoted 105 lines · Lukas Wunner

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 at 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 +
Quoted 11 lines
 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
Signature · 1 line
2.43.0

All applied. Thanks.

Signature · 3 lines
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt