2021-04-20 11:46:44

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 00/18] Implement RSASSA-PSS signature verification

Linux currently supports RSA PKCSv1.5 encoding scheme for
signing / verification. This adds support for RSASSA PSS signature
verification as described in RFC8017 [1].

Patch 1 extends the x509 certificate parser to unpack PSS signature
parameters.
Patches 2-8 pull out the common functions / struct definitions from
rsa-pkcs1pad.c into rsa-common.c, to be shared across RSA encoding
scheme implementations.
Patches 9, 10 provide some more plumbing to export the data needed to
perform PSS operations (salt length, RSA modulus).
Patches 11-16 set up PSS scaffolding and provide the verification
operation per RFC8017.
Patches 17, 18 turn the final knobs on to allow lowering PSS signatures
for verification via keyctl.

The patchset is available as a git tree at [2].

Testing:
The implementation was tested by adding reference public keys to the
kernel's keyring via `keyctl padd` and then verifying a known
message digest / signature against this public key via `keyctl pkey_verify`.
The reference vectors were taken from:
- the Wycheproof testsuite [3]
- FIPS 186-2 and 186-4 test vectors [4]

The test harness is available at [5].

Example keyctl usage for PSS verification:
rsa_bits=4096 # 2048/3072/4096
hash_algo=sha256 # sha1/sha224/sha256/sha384/sha512
saltlen=32
# Generate keys, certificate:
openssl req -x509 -newkey rsa:$rsa_bits -nodes -keyout private.pem -out cert.der \
-days 100 -outform der -$hash_algo -sigopt rsa_padding_mode:pss \
-sigopt rsa_pss_saltlen:$saltlen -sigopt rsa_mgf1_md:$hash_algo

# Sign data.txt:
openssl dgst -${hash_algo} -sign private.pem -sigopt rsa_padding_mode:pss \
-sigopt rsa_pss_saltlen:${saltlen} -out sig.bin data.txt

# Digest data.txt:
openssl dgst -${hash_algo} -binary -out data.${hash_algo}.raw data.txt

# Load pubkey into the kernel's keyring:
kv=$(keyctl padd asymmetric "test-key" @u < cert.der)

# Verify with `enc=pss`:
keyctl pkey_verify $kv "0" data.${hash_algo}.raw \
sig.bin "enc=pss hash=${hash_algo} saltlen=${saltlen} mgfhash=${hash_algo}"

v3:
- Rename pkey_verify parameter for salt length to "saltlen".
- Update Documentation/security/keys/core.rst.
- Add validation for the hash algorithm passed to psspad_setup_shash.

v2:
- Allow certificates where mgf hash algorithm is different from the digest hash
algorithm.
- Fix sparse warnings on "X.509: Parse RSASSA-PSS style certificates".

https://lore.kernel.org/lkml/[email protected]/
https://github.com/varadgautam/kernel/tree/rsassa-psspad-v2

v1 is available at:
https://lore.kernel.org/lkml/[email protected]/
https://github.com/varadgautam/kernel/tree/rsassa-psspad

[1] https://tools.ietf.org/html/rfc8017#section-8.1
[2] https://github.com/varadgautam/kernel/tree/rsassa-psspad-v3
[3] https://github.com/google/wycheproof/blob/master/testvectors/
[4] https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/digital-signatures#rsavs
[5] https://github.com/varadgautam/keyctl-rsa-tests


Varad Gautam (18):
X.509: Parse RSASSA-PSS style certificates
crypto: rsa-pkcs1pad: Rename pkcs1pad-specific functions to rsapad
crypto: rsa-pkcs1pad: Extract pkcs1pad_create into a generic helper
crypto: rsa-pkcs1pad: Pull out child req processing code into helpers
crypto: rsa-pkcs1pad: Rename pkcs1pad_* structs to rsapad_*
crypto: rsa: Start moving RSA common code to rsa-common
crypto: rsa: Move more common code to rsa-common
crypto: rsa: Move rsapad_akcipher_setup_child and callback to
rsa-common
crypto: Extend akcipher API to pass signature parameters
crypto: rsa: Move struct rsa_mpi_key definition to rsa.h
crypto: Scaffolding for RSA-PSS signature style
crypto: rsa-psspad: Introduce shash alloc/dealloc helpers
crypto: rsa-psspad: Get signature parameters from a given signature
crypto: Implement MGF1 Mask Generation Function for RSASSA-PSS
crypto: rsa-psspad: Provide PSS signature verify operation
crypto: rsa-psspad: Implement signature verify callback
crypto: Accept pss as valid encoding during signature verification
keyctl_pkey: Add pkey parameters slen and mgfhash for PSS

Documentation/security/keys/core.rst | 14 +-
crypto/Kconfig | 6 +
crypto/Makefile | 2 +
crypto/asymmetric_keys/Makefile | 5 +-
crypto/asymmetric_keys/asymmetric_type.c | 2 +
crypto/asymmetric_keys/public_key.c | 18 +-
crypto/asymmetric_keys/x509_cert_parser.c | 148 ++++++++
crypto/asymmetric_keys/x509_rsassa.asn1 | 17 +
crypto/rsa-common.c | 291 ++++++++++++++++
crypto/rsa-pkcs1pad.c | 400 +++-------------------
crypto/rsa-psspad.c | 310 +++++++++++++++++
crypto/rsa.c | 26 +-
include/crypto/akcipher.h | 26 ++
include/crypto/internal/rsa-common.h | 61 ++++
include/crypto/internal/rsa.h | 10 +
include/crypto/public_key.h | 4 +
include/linux/keyctl.h | 2 +
include/linux/oid_registry.h | 3 +
security/keys/keyctl_pkey.c | 13 +
19 files changed, 993 insertions(+), 365 deletions(-)
create mode 100644 crypto/asymmetric_keys/x509_rsassa.asn1
create mode 100644 crypto/rsa-common.c
create mode 100644 crypto/rsa-psspad.c
create mode 100644 include/crypto/internal/rsa-common.h

--
2.30.2


2021-04-20 11:46:44

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 01/18] X.509: Parse RSASSA-PSS style certificates

An X.509 wrapper for a RSASSA-PSS signature contains additional
signature parameters over the PKCSv.15 encoding scheme. Extend the
x509 parser to allow parsing RSASSA-PSS encoded certificates, with
the defaults taken from RFC8017.

References: https://tools.ietf.org/html/rfc8017#appendix-C
Signed-off-by: Varad Gautam <[email protected]>
---
crypto/asymmetric_keys/Makefile | 5 +-
crypto/asymmetric_keys/x509_cert_parser.c | 148 ++++++++++++++++++++++
crypto/asymmetric_keys/x509_rsassa.asn1 | 17 +++
include/crypto/public_key.h | 4 +
include/linux/oid_registry.h | 3 +
5 files changed, 176 insertions(+), 1 deletion(-)
create mode 100644 crypto/asymmetric_keys/x509_rsassa.asn1

diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index 28b91adba2aed..f79ed8e8ef8e2 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -20,15 +20,18 @@ obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
x509_key_parser-y := \
x509.asn1.o \
x509_akid.asn1.o \
+ x509_rsassa.asn1.o \
x509_cert_parser.o \
x509_public_key.o

$(obj)/x509_cert_parser.o: \
$(obj)/x509.asn1.h \
- $(obj)/x509_akid.asn1.h
+ $(obj)/x509_akid.asn1.h \
+ $(obj)/x509_rsassa.asn1.h

$(obj)/x509.asn1.o: $(obj)/x509.asn1.c $(obj)/x509.asn1.h
$(obj)/x509_akid.asn1.o: $(obj)/x509_akid.asn1.c $(obj)/x509_akid.asn1.h
+$(obj)/x509_rsassa.asn1.o: $(obj)/x509_rsassa.asn1.c $(obj)/x509_rsassa.asn1.h

#
# PKCS#8 private key handling
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 52c9b455fc7df..19cd162acdb06 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -15,6 +15,7 @@
#include "x509_parser.h"
#include "x509.asn1.h"
#include "x509_akid.asn1.h"
+#include "x509_rsassa.asn1.h"

struct x509_parse_context {
struct x509_certificate *cert; /* Certificate being constructed */
@@ -38,6 +39,8 @@ struct x509_parse_context {
const void *raw_akid; /* Raw authorityKeyId in ASN.1 */
const void *akid_raw_issuer; /* Raw directoryName in authorityKeyId */
unsigned akid_raw_issuer_size;
+ const void *raw_sig_params; /* Signature AlgorithmIdentifier.parameters */
+ unsigned raw_sig_params_size;
};

/*
@@ -101,6 +104,15 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
}
}

+ if (strcmp(ctx->cert->sig->encoding, "pss") == 0) {
+ pr_devel("rsa enc=pss hash=%s mgf=%s mgf_hash=%s salt=0x%x tf=0x%x\n",
+ ctx->cert->sig->hash_algo,
+ ctx->cert->sig->mgf,
+ ctx->cert->sig->mgf_hash_algo,
+ ctx->cert->sig->salt_length,
+ ctx->cert->sig->trailer_field);
+ }
+
ret = -ENOMEM;
cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL);
if (!cert->pub->key)
@@ -194,6 +206,7 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct x509_parse_context *ctx = context;
+ int ret = 0;

pr_debug("PubKey Algo: %u\n", ctx->last_oid);

@@ -238,6 +251,35 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
case OID_SM2_with_SM3:
ctx->cert->sig->hash_algo = "sm3";
goto sm2;
+
+ case OID_rsassaPSS:
+ /* For rsassaPSS, the hash algorithm is packed as a mandatory
+ * parameter in AlgorithmIdentifier.parameters.
+ */
+ if (ctx->raw_sig_params == NULL && ctx->raw_sig_params_size != 1)
+ return -EBADMSG;
+
+ ctx->cert->sig->pkey_algo = "rsa";
+ ctx->cert->sig->encoding = "pss";
+ ctx->algo_oid = ctx->last_oid;
+ if (ctx->raw_sig_params) {
+ ret = asn1_ber_decoder(&x509_rsassa_decoder, ctx,
+ ctx->raw_sig_params,
+ ctx->raw_sig_params_size);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Fill in RSASSA-PSS-params defaults if left out. */
+ if (!ctx->cert->sig->hash_algo)
+ ctx->cert->sig->hash_algo = "sha1";
+ if (!ctx->cert->sig->mgf)
+ ctx->cert->sig->mgf = "mgf1";
+ if (!ctx->cert->sig->mgf_hash_algo)
+ ctx->cert->sig->mgf_hash_algo = "sha1";
+ ctx->cert->sig->trailer_field = 0xbc;
+
+ return 0;
}

rsa_pkcs1:
@@ -439,6 +481,18 @@ int x509_note_params(void *context, size_t hdrlen,
{
struct x509_parse_context *ctx = context;

+ if (ctx->last_oid == OID_rsassaPSS && !ctx->raw_sig_params) {
+ /* Stash AlgorithmIdentifier.parameters for RSASSA-PSS. */
+ ctx->raw_sig_params_size = vlen + hdrlen;
+ if (ctx->raw_sig_params_size) {
+ ctx->raw_sig_params = value - hdrlen;
+ } else {
+ ctx->raw_sig_params = NULL;
+ ctx->raw_sig_params_size = 1;
+ }
+ return 0;
+ }
+
/*
* AlgorithmIdentifier is used three times in the x509, we should skip
* first and ignore third, using second one which is after subject and
@@ -705,3 +759,97 @@ int x509_akid_note_serial(void *context, size_t hdrlen,
ctx->cert->sig->auth_ids[0] = kid;
return 0;
}
+
+int x509_note_hash_algo(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ const char **ptr = NULL;
+
+ if (ctx->last_oid != OID_rsassaPSS)
+ return -EBADMSG;
+
+ if (ctx->cert->sig->mgf)
+ ptr = &ctx->cert->sig->mgf_hash_algo;
+ else
+ ptr = &ctx->cert->sig->hash_algo;
+
+ switch (look_up_OID(value, vlen)) {
+ case OID_sha224:
+ *ptr = "sha224";
+ break;
+ case OID_sha256:
+ *ptr = "sha256";
+ break;
+ case OID_sha384:
+ *ptr = "sha384";
+ break;
+ case OID_sha512:
+ *ptr = "sha512";
+ break;
+ case OID_sha1:
+ default:
+ *ptr = "sha1";
+ break;
+ }
+
+ return 0;
+}
+
+int x509_note_hash_algo_params(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ return -EOPNOTSUPP;
+}
+
+int x509_note_mgf(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ if (ctx->last_oid != OID_rsassaPSS)
+ return -EBADMSG;
+
+ /* RFC8017 PKCS1MGFAlgorithms */
+ if (look_up_OID(value, vlen) != OID_mgf1)
+ return -EINVAL;
+
+ ctx->cert->sig->mgf = "mgf1";
+
+ return 0;
+}
+
+int x509_note_salt_length(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ if (ctx->last_oid != OID_rsassaPSS)
+ return -EBADMSG;
+
+ if (!value || !vlen || vlen > sizeof(ctx->cert->sig->salt_length))
+ return -EINVAL;
+
+ ctx->cert->sig->salt_length = (vlen == 2) ?
+ be16_to_cpu(*((__force __be16 *) value)) : *((u8 *) value);
+
+ return 0;
+}
+
+int x509_note_trailer_field(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ if (ctx->last_oid != OID_rsassaPSS)
+ return -EBADMSG;
+
+ /* trailerField 0xbc per RFC8017 A.2.3 regardless of if
+ * specified. */
+ return 0;
+}
diff --git a/crypto/asymmetric_keys/x509_rsassa.asn1 b/crypto/asymmetric_keys/x509_rsassa.asn1
new file mode 100644
index 0000000000000..e524b978856d2
--- /dev/null
+++ b/crypto/asymmetric_keys/x509_rsassa.asn1
@@ -0,0 +1,17 @@
+-- RFC8017
+RSASSA-PSS-params ::= SEQUENCE {
+ hashAlgorithm [0] HashAlgorithm DEFAULT,
+ maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT,
+ saltLength [2] INTEGER DEFAULT ({ x509_note_salt_length }),
+ trailerField [3] INTEGER DEFAULT ({ x509_note_trailer_field })
+}
+
+HashAlgorithm ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER ({ x509_note_hash_algo }),
+ parameters ANY OPTIONAL ({ x509_note_hash_algo_params })
+}
+
+MaskGenAlgorithm ::= SEQUENCE {
+ mgf OBJECT IDENTIFIER ({ x509_note_mgf }),
+ parameters HashAlgorithm
+}
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index 47accec68cb0f..f36834c8bb139 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -46,6 +46,10 @@ struct public_key_signature {
const char *encoding;
const void *data;
unsigned int data_size;
+ const char *mgf;
+ const char *mgf_hash_algo;
+ u16 salt_length;
+ u16 trailer_field;
};

extern void public_key_signature_free(struct public_key_signature *sig);
diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h
index 4462ed2c18cdd..c247adc8a41e4 100644
--- a/include/linux/oid_registry.h
+++ b/include/linux/oid_registry.h
@@ -113,6 +113,9 @@ enum OID {
OID_SM2_with_SM3, /* 1.2.156.10197.1.501 */
OID_sm3WithRSAEncryption, /* 1.2.156.10197.1.504 */

+ OID_mgf1, /* 1.2.840.113549.1.1.8 */
+ OID_rsassaPSS, /* 1.2.840.113549.1.1.10 */
+
OID__NR
};

--
2.30.2

2021-04-20 11:46:44

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 02/18] crypto: rsa-pkcs1pad: Rename pkcs1pad-specific functions to rsapad

The existing RSA implementation supports PKCSv1.5 style signature
paddings via rsa-pkcs1pad. A lot of the functionality implemented
for rsa-pkcs1pad can be reused across other RSA padding schemes.
Rename such functions as rsapad_* before moving them out of
rsa-pkcs1pad.c.

Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-pkcs1pad.c | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 8ac3e73e8ea65..83ba7540a53ac 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -104,7 +104,7 @@ struct pkcs1pad_request {
struct akcipher_request child_req;
};

-static int pkcs1pad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+static int rsapad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
@@ -125,7 +125,7 @@ static int pkcs1pad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
return 0;
}

-static int pkcs1pad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+static int rsapad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
@@ -146,7 +146,7 @@ static int pkcs1pad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
return 0;
}

-static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
+static unsigned int rsapad_get_max_size(struct crypto_akcipher *tfm)
{
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);

@@ -159,8 +159,8 @@ static unsigned int pkcs1pad_get_max_size(struct crypto_akcipher *tfm)
return ctx->key_size;
}

-static void pkcs1pad_sg_set_buf(struct scatterlist *sg, void *buf, size_t len,
- struct scatterlist *next)
+static void rsapad_akcipher_sg_set_buf(struct scatterlist *sg, void *buf,
+ size_t len, struct scatterlist *next)
{
int nsegs = next ? 2 : 1;

@@ -256,7 +256,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
req_ctx->in_buf[i] = 1 + prandom_u32_max(255);
req_ctx->in_buf[ps_end] = 0x00;

- pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
+ rsapad_akcipher_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);
@@ -357,7 +357,7 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
if (!req_ctx->out_buf)
return -ENOMEM;

- pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf,
+ rsapad_akcipher_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);
@@ -415,7 +415,7 @@ static int pkcs1pad_sign(struct akcipher_request *req)
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,
+ rsapad_akcipher_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);
@@ -545,7 +545,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
if (!req_ctx->out_buf)
return -ENOMEM;

- pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf,
+ rsapad_akcipher_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);
@@ -564,7 +564,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
return err;
}

-static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
+static int rsapad_akcipher_init_tfm(struct crypto_akcipher *tfm)
{
struct akcipher_instance *inst = akcipher_alg_instance(tfm);
struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
@@ -579,14 +579,14 @@ static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
return 0;
}

-static void pkcs1pad_exit_tfm(struct crypto_akcipher *tfm)
+static void rsapad_akcipher_exit_tfm(struct crypto_akcipher *tfm)
{
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);

crypto_free_akcipher(ctx->child);
}

-static void pkcs1pad_free(struct akcipher_instance *inst)
+static void rsapad_akcipher_free(struct akcipher_instance *inst)
{
struct pkcs1pad_inst_ctx *ctx = akcipher_instance_ctx(inst);
struct crypto_akcipher_spawn *spawn = &ctx->spawn;
@@ -656,24 +656,24 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx);

- inst->alg.init = pkcs1pad_init_tfm;
- inst->alg.exit = pkcs1pad_exit_tfm;
+ inst->alg.init = rsapad_akcipher_init_tfm;
+ inst->alg.exit = rsapad_akcipher_exit_tfm;

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;
+ inst->alg.set_pub_key = rsapad_set_pub_key;
+ inst->alg.set_priv_key = rsapad_set_priv_key;
+ inst->alg.max_size = rsapad_get_max_size;
inst->alg.reqsize = sizeof(struct pkcs1pad_request) + rsa_alg->reqsize;

- inst->free = pkcs1pad_free;
+ inst->free = rsapad_akcipher_free;

err = akcipher_register_instance(tmpl, inst);
if (err) {
err_free_inst:
- pkcs1pad_free(inst);
+ rsapad_akcipher_free(inst);
}
return err;
}
--
2.30.2

2021-04-20 11:46:45

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 03/18] crypto: rsa-pkcs1pad: Extract pkcs1pad_create into a generic helper

which can be reused by other signature padding schemes as
rsapad_akcipher_create. This will be moved out of rsa-pkcs1pad.c to
be used across rsa-*pad implementations.

Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-pkcs1pad.c | 48 ++++++++++++++++++++++++++++++-------------
1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 83ba7540a53ac..849573f6b44b3 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -595,7 +595,21 @@ static void rsapad_akcipher_free(struct akcipher_instance *inst)
kfree(inst);
}

-static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
+static struct akcipher_alg pkcs1pad_alg = {
+ .init = rsapad_akcipher_init_tfm,
+ .exit = rsapad_akcipher_exit_tfm,
+
+ .encrypt = pkcs1pad_encrypt,
+ .decrypt = pkcs1pad_decrypt,
+ .sign = pkcs1pad_sign,
+ .verify = pkcs1pad_verify,
+ .set_pub_key = rsapad_set_pub_key,
+ .set_priv_key = rsapad_set_priv_key,
+ .max_size = rsapad_get_max_size
+};
+
+static int rsapad_akcipher_create(struct crypto_template *tmpl, struct rtattr **tb,
+ struct akcipher_alg *alg)
{
u32 mask;
struct akcipher_instance *inst;
@@ -625,12 +639,12 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
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)",
+ CRYPTO_MAX_ALG_NAME, "%s(%s)", tmpl->name,
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)",
+ CRYPTO_MAX_ALG_NAME, "%s(%s)", tmpl->name,
rsa_alg->base.cra_driver_name) >=
CRYPTO_MAX_ALG_NAME)
goto err_free_inst;
@@ -642,12 +656,13 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
}

if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
- "pkcs1pad(%s,%s)", rsa_alg->base.cra_name,
+ "%s(%s,%s)", tmpl->name, 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)",
+ CRYPTO_MAX_ALG_NAME, "%s(%s,%s)",
+ tmpl->name,
rsa_alg->base.cra_driver_name,
hash_name) >= CRYPTO_MAX_ALG_NAME)
goto err_free_inst;
@@ -656,16 +671,16 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx);

- inst->alg.init = rsapad_akcipher_init_tfm;
- inst->alg.exit = rsapad_akcipher_exit_tfm;
+ inst->alg.init = alg->init;
+ inst->alg.exit = alg->exit;

- 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 = rsapad_set_pub_key;
- inst->alg.set_priv_key = rsapad_set_priv_key;
- inst->alg.max_size = rsapad_get_max_size;
+ inst->alg.encrypt = alg->encrypt;
+ inst->alg.decrypt = alg->decrypt;
+ inst->alg.sign = alg->sign;
+ inst->alg.verify = alg->verify;
+ inst->alg.set_pub_key = alg->set_pub_key;
+ inst->alg.set_priv_key = alg->set_priv_key;
+ inst->alg.max_size = alg->max_size;
inst->alg.reqsize = sizeof(struct pkcs1pad_request) + rsa_alg->reqsize;

inst->free = rsapad_akcipher_free;
@@ -678,6 +693,11 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
return err;
}

+static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+ return rsapad_akcipher_create(tmpl, tb, &pkcs1pad_alg);
+}
+
struct crypto_template rsa_pkcs1pad_tmpl = {
.name = "pkcs1pad",
.create = pkcs1pad_create,
--
2.30.2

2021-04-20 11:46:56

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 04/18] crypto: rsa-pkcs1pad: Pull out child req processing code into helpers

rsa-pkcs1pad operations that require using RSA primitives rely on
creating an akcipher child RSA transform and processing the results
in the operation-specific callback. Add helpers
rsapad_akcipher_setup_child and rsapad_akcipher_req_complete for req
setup and callback handling, and switch pkcs1pad operations to use
these.

Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-pkcs1pad.c | 106 +++++++++++++++++++-----------------------
1 file changed, 49 insertions(+), 57 deletions(-)

diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 849573f6b44b3..6329c79316d24 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -171,6 +171,38 @@ static void rsapad_akcipher_sg_set_buf(struct scatterlist *sg, void *buf,
sg_chain(sg, nsegs, next);
}

+typedef int (*rsa_akcipher_complete_cb)(struct akcipher_request *, int);
+static void rsapad_akcipher_req_complete(struct crypto_async_request *child_async_req,
+ int err, rsa_akcipher_complete_cb cb)
+{
+ struct akcipher_request *req = child_async_req->data;
+ struct crypto_async_request async_req;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ async_req.data = req->base.data;
+ async_req.tfm = crypto_akcipher_tfm(crypto_akcipher_reqtfm(req));
+ async_req.flags = child_async_req->flags;
+ req->base.complete(&async_req, cb(req, err));
+}
+
+static void rsapad_akcipher_setup_child(struct akcipher_request *req,
+ struct scatterlist *src_sg,
+ struct scatterlist *dst_sg,
+ unsigned int src_len,
+ unsigned int dst_len,
+ crypto_completion_t cb)
+{
+ 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);
+
+ akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
+ akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, cb, req);
+ akcipher_request_set_crypt(&req_ctx->child_req, src_sg, dst_sg, src_len, dst_len);
+}
+
static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
@@ -213,17 +245,8 @@ static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
static void pkcs1pad_encrypt_sign_complete_cb(
struct crypto_async_request *child_async_req, int err)
{
- struct akcipher_request *req = child_async_req->data;
- struct crypto_async_request async_req;
-
- if (err == -EINPROGRESS)
- return;
-
- async_req.data = req->base.data;
- async_req.tfm = crypto_akcipher_tfm(crypto_akcipher_reqtfm(req));
- async_req.flags = child_async_req->flags;
- req->base.complete(&async_req,
- pkcs1pad_encrypt_sign_complete(req, err));
+ rsapad_akcipher_req_complete(child_async_req, err,
+ pkcs1pad_encrypt_sign_complete);
}

static int pkcs1pad_encrypt(struct akcipher_request *req)
@@ -259,13 +282,10 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
rsapad_akcipher_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);
+ rsapad_akcipher_setup_child(req, req_ctx->in_sg, req->dst,
+ ctx->key_size - 1, req->dst_len,
+ pkcs1pad_encrypt_sign_complete_cb);

err = crypto_akcipher_encrypt(&req_ctx->child_req);
if (err != -EINPROGRESS && err != -EBUSY)
@@ -331,16 +351,7 @@ static int pkcs1pad_decrypt_complete(struct akcipher_request *req, int err)
static void pkcs1pad_decrypt_complete_cb(
struct crypto_async_request *child_async_req, int err)
{
- struct akcipher_request *req = child_async_req->data;
- struct crypto_async_request async_req;
-
- if (err == -EINPROGRESS)
- return;
-
- async_req.data = req->base.data;
- async_req.tfm = crypto_akcipher_tfm(crypto_akcipher_reqtfm(req));
- async_req.flags = child_async_req->flags;
- req->base.complete(&async_req, pkcs1pad_decrypt_complete(req, err));
+ rsapad_akcipher_req_complete(child_async_req, err, pkcs1pad_decrypt_complete);
}

static int pkcs1pad_decrypt(struct akcipher_request *req)
@@ -360,14 +371,10 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
rsapad_akcipher_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_decrypt_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, req->src_len,
- ctx->key_size);
+ rsapad_akcipher_setup_child(req, req->src, req_ctx->out_sg,
+ req->src_len, ctx->key_size,
+ pkcs1pad_decrypt_complete_cb);

err = crypto_akcipher_decrypt(&req_ctx->child_req);
if (err != -EINPROGRESS && err != -EBUSY)
@@ -418,13 +425,10 @@ static int pkcs1pad_sign(struct akcipher_request *req)
rsapad_akcipher_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);
+ rsapad_akcipher_setup_child(req, req_ctx->in_sg, req->dst,
+ ctx->key_size - 1, req->dst_len,
+ pkcs1pad_encrypt_sign_complete_cb);

err = crypto_akcipher_decrypt(&req_ctx->child_req);
if (err != -EINPROGRESS && err != -EBUSY)
@@ -509,16 +513,8 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
static void pkcs1pad_verify_complete_cb(
struct crypto_async_request *child_async_req, int err)
{
- struct akcipher_request *req = child_async_req->data;
- struct crypto_async_request async_req;
-
- if (err == -EINPROGRESS)
- return;
-
- async_req.data = req->base.data;
- async_req.tfm = crypto_akcipher_tfm(crypto_akcipher_reqtfm(req));
- async_req.flags = child_async_req->flags;
- req->base.complete(&async_req, pkcs1pad_verify_complete(req, err));
+ rsapad_akcipher_req_complete(child_async_req, err,
+ pkcs1pad_verify_complete);
}

/*
@@ -548,14 +544,10 @@ static int pkcs1pad_verify(struct akcipher_request *req)
rsapad_akcipher_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, req->src_len,
- ctx->key_size);
+ rsapad_akcipher_setup_child(req, req->src, req_ctx->out_sg,
+ req->src_len, ctx->key_size,
+ pkcs1pad_verify_complete_cb);

err = crypto_akcipher_encrypt(&req_ctx->child_req);
if (err != -EINPROGRESS && err != -EBUSY)
--
2.30.2

2021-04-20 11:47:02

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 05/18] crypto: rsa-pkcs1pad: Rename pkcs1pad_* structs to rsapad_*

Use generic naming to share with other padding scheme implementations.
These will be moved out of rsa-pkcs1pad.c.

Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-pkcs1pad.c | 62 +++++++++++++++++++++----------------------
1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 6329c79316d24..e76fc98a537a4 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -88,17 +88,17 @@ static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
return NULL;
}

-struct pkcs1pad_ctx {
+struct rsapad_tfm_ctx {
struct crypto_akcipher *child;
unsigned int key_size;
};

-struct pkcs1pad_inst_ctx {
+struct rsapad_inst_ctx {
struct crypto_akcipher_spawn spawn;
const struct rsa_asn1_template *digest_info;
};

-struct pkcs1pad_request {
+struct rsapad_akciper_req_ctx {
struct scatterlist in_sg[2], out_sg[1];
uint8_t *in_buf, *out_buf;
struct akcipher_request child_req;
@@ -107,7 +107,7 @@ struct pkcs1pad_request {
static int rsapad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
- struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
int err;

ctx->key_size = 0;
@@ -128,7 +128,7 @@ static int rsapad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
static int rsapad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
- struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
int err;

ctx->key_size = 0;
@@ -148,7 +148,7 @@ static int rsapad_set_priv_key(struct crypto_akcipher *tfm, const void *key,

static unsigned int rsapad_get_max_size(struct crypto_akcipher *tfm)
{
- struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);

/*
* The maximum destination buffer size for the encrypt/sign operations
@@ -195,8 +195,8 @@ static void rsapad_akcipher_setup_child(struct akcipher_request *req,
crypto_completion_t cb)
{
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 rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);

akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, cb, req);
@@ -206,8 +206,8 @@ static void rsapad_akcipher_setup_child(struct akcipher_request *req,
static int pkcs1pad_encrypt_sign_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 rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
unsigned int pad_len;
unsigned int len;
u8 *out_buf;
@@ -252,8 +252,8 @@ static void pkcs1pad_encrypt_sign_complete_cb(
static int pkcs1pad_encrypt(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 rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
int err;
unsigned int i, ps_end;

@@ -297,8 +297,8 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
static int pkcs1pad_decrypt_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 rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
unsigned int dst_len;
unsigned int pos;
u8 *out_buf;
@@ -357,8 +357,8 @@ static void pkcs1pad_decrypt_complete_cb(
static int pkcs1pad_decrypt(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 rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
int err;

if (!ctx->key_size || req->src_len != ctx->key_size)
@@ -386,10 +386,10 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
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 rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
struct akcipher_instance *inst = akcipher_alg_instance(tfm);
- struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
+ struct rsapad_inst_ctx *ictx = akcipher_instance_ctx(inst);
const struct rsa_asn1_template *digest_info = ictx->digest_info;
int err;
unsigned int ps_end, digest_size = 0;
@@ -440,10 +440,10 @@ static int pkcs1pad_sign(struct akcipher_request *req)
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 rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
struct akcipher_instance *inst = akcipher_alg_instance(tfm);
- struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
+ struct rsapad_inst_ctx *ictx = akcipher_instance_ctx(inst);
const struct rsa_asn1_template *digest_info = ictx->digest_info;
unsigned int dst_len;
unsigned int pos;
@@ -528,8 +528,8 @@ static void pkcs1pad_verify_complete_cb(
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);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
int err;

if (WARN_ON(req->dst) ||
@@ -559,8 +559,8 @@ static int pkcs1pad_verify(struct akcipher_request *req)
static int rsapad_akcipher_init_tfm(struct crypto_akcipher *tfm)
{
struct akcipher_instance *inst = akcipher_alg_instance(tfm);
- struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
- struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_inst_ctx *ictx = akcipher_instance_ctx(inst);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
struct crypto_akcipher *child_tfm;

child_tfm = crypto_spawn_akcipher(&ictx->spawn);
@@ -573,14 +573,14 @@ static int rsapad_akcipher_init_tfm(struct crypto_akcipher *tfm)

static void rsapad_akcipher_exit_tfm(struct crypto_akcipher *tfm)
{
- struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);

crypto_free_akcipher(ctx->child);
}

static void rsapad_akcipher_free(struct akcipher_instance *inst)
{
- struct pkcs1pad_inst_ctx *ctx = akcipher_instance_ctx(inst);
+ struct rsapad_inst_ctx *ctx = akcipher_instance_ctx(inst);
struct crypto_akcipher_spawn *spawn = &ctx->spawn;

crypto_drop_akcipher(spawn);
@@ -605,7 +605,7 @@ static int rsapad_akcipher_create(struct crypto_template *tmpl, struct rtattr **
{
u32 mask;
struct akcipher_instance *inst;
- struct pkcs1pad_inst_ctx *ctx;
+ struct rsapad_inst_ctx *ctx;
struct akcipher_alg *rsa_alg;
const char *hash_name;
int err;
@@ -661,7 +661,7 @@ static int rsapad_akcipher_create(struct crypto_template *tmpl, struct rtattr **
}

inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
- inst->alg.base.cra_ctxsize = sizeof(struct pkcs1pad_ctx);
+ inst->alg.base.cra_ctxsize = sizeof(struct rsapad_tfm_ctx);

inst->alg.init = alg->init;
inst->alg.exit = alg->exit;
@@ -673,7 +673,7 @@ static int rsapad_akcipher_create(struct crypto_template *tmpl, struct rtattr **
inst->alg.set_pub_key = alg->set_pub_key;
inst->alg.set_priv_key = alg->set_priv_key;
inst->alg.max_size = alg->max_size;
- inst->alg.reqsize = sizeof(struct pkcs1pad_request) + rsa_alg->reqsize;
+ inst->alg.reqsize = sizeof(struct rsapad_akciper_req_ctx) + rsa_alg->reqsize;

inst->free = rsapad_akcipher_free;

--
2.30.2

2021-04-20 11:47:09

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 06/18] crypto: rsa: Start moving RSA common code to rsa-common

Move out helpers from rsa-pkcs1pad.c which will be shared across
rsa-*pad implementations.

Signed-off-by: Varad Gautam <[email protected]>
---
crypto/Makefile | 1 +
crypto/rsa-common.c | 76 ++++++++++++++++++++++
crypto/rsa-pkcs1pad.c | 97 +---------------------------
include/crypto/internal/rsa-common.h | 37 +++++++++++
4 files changed, 115 insertions(+), 96 deletions(-)
create mode 100644 crypto/rsa-common.c
create mode 100644 include/crypto/internal/rsa-common.h

diff --git a/crypto/Makefile b/crypto/Makefile
index cf23affb16780..57a85b2b3429b 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -39,6 +39,7 @@ rsa_generic-y := rsapubkey.asn1.o
rsa_generic-y += rsaprivkey.asn1.o
rsa_generic-y += rsa.o
rsa_generic-y += rsa_helper.o
+rsa_generic-y += rsa-common.o
rsa_generic-y += rsa-pkcs1pad.o
obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o

diff --git a/crypto/rsa-common.c b/crypto/rsa-common.c
new file mode 100644
index 0000000000000..60073c56e3748
--- /dev/null
+++ b/crypto/rsa-common.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2015 Intel Corporation
+ * Copyright (C) 2021 SUSE
+ *
+ */
+
+#include <crypto/internal/rsa-common.h>
+
+/*
+ * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
+ */
+static const u8 rsa_digest_info_md5[] = {
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
+ 0x05, 0x00, 0x04, 0x10
+};
+
+static const u8 rsa_digest_info_sha1[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+ 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+ 0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 rsa_digest_info_rmd160[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+ 0x2b, 0x24, 0x03, 0x02, 0x01,
+ 0x05, 0x00, 0x04, 0x14
+};
+
+static const u8 rsa_digest_info_sha224[] = {
+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+ 0x05, 0x00, 0x04, 0x1c
+};
+
+static const u8 rsa_digest_info_sha256[] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+ 0x05, 0x00, 0x04, 0x20
+};
+
+static const u8 rsa_digest_info_sha384[] = {
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+ 0x05, 0x00, 0x04, 0x30
+};
+
+static const u8 rsa_digest_info_sha512[] = {
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+ 0x05, 0x00, 0x04, 0x40
+};
+
+static const struct rsa_asn1_template rsa_asn1_templates[] = {
+#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
+ _(md5),
+ _(sha1),
+ _(rmd160),
+ _(sha256),
+ _(sha384),
+ _(sha512),
+ _(sha224),
+ { NULL }
+#undef _
+};
+
+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;
+}
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index e76fc98a537a4..ffb7220b3d10a 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -5,104 +5,9 @@
* Copyright (c) 2015 Intel Corporation
*/

-#include <crypto/algapi.h>
-#include <crypto/akcipher.h>
-#include <crypto/internal/akcipher.h>
-#include <crypto/internal/rsa.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
+#include <crypto/internal/rsa-common.h>
#include <linux/module.h>
#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 struct rsa_asn1_template {
- const char *name;
- const u8 *data;
- size_t size;
-} rsa_asn1_templates[] = {
-#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
- _(md5),
- _(sha1),
- _(rmd160),
- _(sha256),
- _(sha384),
- _(sha512),
- _(sha224),
- { NULL }
-#undef _
-};
-
-static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
-{
- const struct rsa_asn1_template *p;
-
- for (p = rsa_asn1_templates; p->name; p++)
- if (strcmp(name, p->name) == 0)
- return p;
- return NULL;
-}
-
-struct rsapad_tfm_ctx {
- struct crypto_akcipher *child;
- unsigned int key_size;
-};
-
-struct rsapad_inst_ctx {
- struct crypto_akcipher_spawn spawn;
- const struct rsa_asn1_template *digest_info;
-};
-
-struct rsapad_akciper_req_ctx {
- struct scatterlist in_sg[2], out_sg[1];
- uint8_t *in_buf, *out_buf;
- struct akcipher_request child_req;
-};

static int rsapad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
diff --git a/include/crypto/internal/rsa-common.h b/include/crypto/internal/rsa-common.h
new file mode 100644
index 0000000000000..ecdce0cdafaa3
--- /dev/null
+++ b/include/crypto/internal/rsa-common.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2015 Intel Corporation
+ * Copyright (C) 2021 SUSE
+ *
+ */
+#ifndef _RSA_COMMON_
+#define _RSA_COMMON_
+
+#include <crypto/algapi.h>
+#include <crypto/internal/akcipher.h>
+#include <linux/scatterlist.h>
+
+struct rsa_asn1_template {
+ const char *name;
+ const u8 *data;
+ size_t size;
+};
+const struct rsa_asn1_template *rsa_lookup_asn1(const char *name);
+
+struct rsapad_tfm_ctx {
+ struct crypto_akcipher *child;
+ unsigned int key_size;
+};
+
+struct rsapad_inst_ctx {
+ struct crypto_akcipher_spawn spawn;
+ const struct rsa_asn1_template *digest_info;
+};
+
+struct rsapad_akciper_req_ctx {
+ struct scatterlist in_sg[2], out_sg[1];
+ uint8_t *in_buf, *out_buf;
+ struct akcipher_request child_req;
+};
+
+#endif
--
2.30.2

2021-04-20 11:47:19

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 08/18] crypto: rsa: Move rsapad_akcipher_setup_child and callback to rsa-common

Pull out more common code from rsa-pkcs1pad into rsa-common.

Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-common.c | 31 +++++++++++++++++++++++++++
crypto/rsa-pkcs1pad.c | 32 ----------------------------
include/crypto/internal/rsa-common.h | 9 ++++++++
3 files changed, 40 insertions(+), 32 deletions(-)

diff --git a/crypto/rsa-common.c b/crypto/rsa-common.c
index d70d7d405165f..6ed258a782875 100644
--- a/crypto/rsa-common.c
+++ b/crypto/rsa-common.c
@@ -75,6 +75,37 @@ const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
return NULL;
}

+void rsapad_akcipher_req_complete(struct crypto_async_request *child_async_req,
+ int err, rsa_akcipher_complete_cb cb)
+{
+ struct akcipher_request *req = child_async_req->data;
+ struct crypto_async_request async_req;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ async_req.data = req->base.data;
+ async_req.tfm = crypto_akcipher_tfm(crypto_akcipher_reqtfm(req));
+ async_req.flags = child_async_req->flags;
+ req->base.complete(&async_req, cb(req, err));
+}
+
+void rsapad_akcipher_setup_child(struct akcipher_request *req,
+ struct scatterlist *src_sg,
+ struct scatterlist *dst_sg,
+ unsigned int src_len,
+ unsigned int dst_len,
+ crypto_completion_t cb)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
+
+ akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
+ akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, cb, req);
+ akcipher_request_set_crypt(&req_ctx->child_req, src_sg, dst_sg, src_len, dst_len);
+}
+
int rsapad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 30b0193b7352a..6fa207732fcbe 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -9,38 +9,6 @@
#include <linux/module.h>
#include <linux/random.h>

-typedef int (*rsa_akcipher_complete_cb)(struct akcipher_request *, int);
-static void rsapad_akcipher_req_complete(struct crypto_async_request *child_async_req,
- int err, rsa_akcipher_complete_cb cb)
-{
- struct akcipher_request *req = child_async_req->data;
- struct crypto_async_request async_req;
-
- if (err == -EINPROGRESS)
- return;
-
- async_req.data = req->base.data;
- async_req.tfm = crypto_akcipher_tfm(crypto_akcipher_reqtfm(req));
- async_req.flags = child_async_req->flags;
- req->base.complete(&async_req, cb(req, err));
-}
-
-static void rsapad_akcipher_setup_child(struct akcipher_request *req,
- struct scatterlist *src_sg,
- struct scatterlist *dst_sg,
- unsigned int src_len,
- unsigned int dst_len,
- crypto_completion_t cb)
-{
- struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
- struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
-
- akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
- akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, cb, req);
- akcipher_request_set_crypt(&req_ctx->child_req, src_sg, dst_sg, src_len, dst_len);
-}
-
static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
diff --git a/include/crypto/internal/rsa-common.h b/include/crypto/internal/rsa-common.h
index a6f20cce610ab..4fa3cf5a989cc 100644
--- a/include/crypto/internal/rsa-common.h
+++ b/include/crypto/internal/rsa-common.h
@@ -34,6 +34,15 @@ struct rsapad_akciper_req_ctx {
struct akcipher_request child_req;
};

+typedef int (*rsa_akcipher_complete_cb)(struct akcipher_request *, int);
+void rsapad_akcipher_req_complete(struct crypto_async_request *child_async_req,
+ int err, rsa_akcipher_complete_cb cb);
+void rsapad_akcipher_setup_child(struct akcipher_request *req,
+ struct scatterlist *src_sg,
+ struct scatterlist *dst_sg,
+ unsigned int src_len,
+ unsigned int dst_len,
+ crypto_completion_t cb);
int rsapad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen);
int rsapad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
--
2.30.2

2021-04-20 11:47:22

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 09/18] crypto: Extend akcipher API to pass signature parameters

For certain signature encoding schemes (eg. RSASSA-PSS), the
verify/sign operation behavior depends on information contained in
the signature blob. Allow passing this down to the crypto_template by
introducing a crypto_akcipher_set_sig_params() call.

Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-common.c | 1 +
include/crypto/akcipher.h | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+)

diff --git a/crypto/rsa-common.c b/crypto/rsa-common.c
index 6ed258a782875..f80cdfcc1f9ee 100644
--- a/crypto/rsa-common.c
+++ b/crypto/rsa-common.c
@@ -277,6 +277,7 @@ int rsapad_akcipher_create(struct crypto_template *tmpl, struct rtattr **tb,
inst->alg.set_pub_key = alg->set_pub_key;
inst->alg.set_priv_key = alg->set_priv_key;
inst->alg.max_size = alg->max_size;
+ inst->alg.set_sig_params = alg->set_sig_params;
inst->alg.reqsize = sizeof(struct rsapad_akciper_req_ctx) + rsa_alg->reqsize;

inst->free = rsapad_akcipher_free;
diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index 1d3aa252cabaf..a0e8720294293 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -101,6 +101,8 @@ struct akcipher_alg {
unsigned int (*max_size)(struct crypto_akcipher *tfm);
int (*init)(struct crypto_akcipher *tfm);
void (*exit)(struct crypto_akcipher *tfm);
+ int (*set_sig_params)(struct crypto_akcipher *tfm, const void *sig,
+ unsigned int sig_len);

unsigned int reqsize;
struct crypto_alg base;
@@ -413,4 +415,28 @@ static inline int crypto_akcipher_set_priv_key(struct crypto_akcipher *tfm,

return alg->set_priv_key(tfm, key, keylen);
}
+
+/**
+ * crypto_akcipher_set_sig_params() - Invoke set sig params operation
+ *
+ * Use this if the verification/signing operation behavior depends on
+ * parameters contained in the signature.
+ *
+ * @tfm: tfm handle
+ * @sig: ptr to a struct public_key_signature to extract info from
+ * @siglen: Length of sig - should be unnecessary if you pass the struct.
+ *
+ * Return: zero on success; error code in case of error
+ */
+static inline int crypto_akcipher_set_sig_params(struct crypto_akcipher *tfm,
+ const void *sig,
+ unsigned int siglen)
+{
+ struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
+
+ if (alg->set_sig_params)
+ return alg->set_sig_params(tfm, sig, siglen);
+ else
+ return -EOPNOTSUPP;
+}
#endif
--
2.30.2

2021-04-20 11:47:25

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 07/18] crypto: rsa: Move more common code to rsa-common

Move helpers for setting public/private keys, RSA akcipher
instance setup, keysize querying etc. to rsa-common.c.

Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-common.c | 183 +++++++++++++++++++++++++++
crypto/rsa-pkcs1pad.c | 183 ---------------------------
include/crypto/internal/rsa-common.h | 13 ++
3 files changed, 196 insertions(+), 183 deletions(-)

diff --git a/crypto/rsa-common.c b/crypto/rsa-common.c
index 60073c56e3748..d70d7d405165f 100644
--- a/crypto/rsa-common.c
+++ b/crypto/rsa-common.c
@@ -74,3 +74,186 @@ const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
return p;
return NULL;
}
+
+int rsapad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ struct rsapad_tfm_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 -EOPNOTSUPP;
+
+ ctx->key_size = err;
+ return 0;
+}
+
+int rsapad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ struct rsapad_tfm_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 -EOPNOTSUPP;
+
+ ctx->key_size = err;
+ return 0;
+}
+
+unsigned int rsapad_get_max_size(struct crypto_akcipher *tfm)
+{
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ /*
+ * The maximum destination buffer size for the encrypt/sign operations
+ * will be the same as for RSA, even though it's smaller for
+ * decrypt/verify.
+ */
+
+ return ctx->key_size;
+}
+
+void rsapad_akcipher_sg_set_buf(struct scatterlist *sg, void *buf,
+ size_t len, struct scatterlist *next)
+{
+ int nsegs = next ? 2 : 1;
+
+ sg_init_table(sg, nsegs);
+ sg_set_buf(sg, buf, len);
+
+ if (next)
+ sg_chain(sg, nsegs, next);
+}
+
+int rsapad_akcipher_init_tfm(struct crypto_akcipher *tfm)
+{
+ struct akcipher_instance *inst = akcipher_alg_instance(tfm);
+ struct rsapad_inst_ctx *ictx = akcipher_instance_ctx(inst);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_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;
+}
+
+void rsapad_akcipher_exit_tfm(struct crypto_akcipher *tfm)
+{
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ crypto_free_akcipher(ctx->child);
+}
+
+void rsapad_akcipher_free(struct akcipher_instance *inst)
+{
+ struct rsapad_inst_ctx *ctx = akcipher_instance_ctx(inst);
+ struct crypto_akcipher_spawn *spawn = &ctx->spawn;
+
+ crypto_drop_akcipher(spawn);
+ kfree(inst);
+}
+
+int rsapad_akcipher_create(struct crypto_template *tmpl, struct rtattr **tb,
+ struct akcipher_alg *alg)
+{
+ u32 mask;
+ struct akcipher_instance *inst;
+ struct rsapad_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);
+ if (err)
+ return err;
+
+ inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+ if (!inst)
+ return -ENOMEM;
+
+ ctx = akcipher_instance_ctx(inst);
+
+ err = crypto_grab_akcipher(&ctx->spawn, akcipher_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);
+
+ 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, "%s(%s)", tmpl->name,
+ 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, "%s(%s)", tmpl->name,
+ 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,
+ "%s(%s,%s)", tmpl->name, 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, "%s(%s,%s)",
+ tmpl->name,
+ 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 rsapad_tfm_ctx);
+
+ inst->alg.init = alg->init;
+ inst->alg.exit = alg->exit;
+
+ inst->alg.encrypt = alg->encrypt;
+ inst->alg.decrypt = alg->decrypt;
+ inst->alg.sign = alg->sign;
+ inst->alg.verify = alg->verify;
+ inst->alg.set_pub_key = alg->set_pub_key;
+ inst->alg.set_priv_key = alg->set_priv_key;
+ inst->alg.max_size = alg->max_size;
+ inst->alg.reqsize = sizeof(struct rsapad_akciper_req_ctx) + rsa_alg->reqsize;
+
+ inst->free = rsapad_akcipher_free;
+
+ err = akcipher_register_instance(tmpl, inst);
+ if (err) {
+err_free_inst:
+ rsapad_akcipher_free(inst);
+ }
+ return err;
+}
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index ffb7220b3d10a..30b0193b7352a 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -9,73 +9,6 @@
#include <linux/module.h>
#include <linux/random.h>

-static int rsapad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
- unsigned int keylen)
-{
- struct rsapad_tfm_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;
-}
-
-static int rsapad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
- unsigned int keylen)
-{
- struct rsapad_tfm_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;
-}
-
-static unsigned int rsapad_get_max_size(struct crypto_akcipher *tfm)
-{
- struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
-
- /*
- * The maximum destination buffer size for the encrypt/sign operations
- * will be the same as for RSA, even though it's smaller for
- * decrypt/verify.
- */
-
- return ctx->key_size;
-}
-
-static void rsapad_akcipher_sg_set_buf(struct scatterlist *sg, void *buf,
- size_t len, struct scatterlist *next)
-{
- int nsegs = next ? 2 : 1;
-
- sg_init_table(sg, nsegs);
- sg_set_buf(sg, buf, len);
-
- if (next)
- sg_chain(sg, nsegs, next);
-}
-
typedef int (*rsa_akcipher_complete_cb)(struct akcipher_request *, int);
static void rsapad_akcipher_req_complete(struct crypto_async_request *child_async_req,
int err, rsa_akcipher_complete_cb cb)
@@ -461,37 +394,6 @@ static int pkcs1pad_verify(struct akcipher_request *req)
return err;
}

-static int rsapad_akcipher_init_tfm(struct crypto_akcipher *tfm)
-{
- struct akcipher_instance *inst = akcipher_alg_instance(tfm);
- struct rsapad_inst_ctx *ictx = akcipher_instance_ctx(inst);
- struct rsapad_tfm_ctx *ctx = akcipher_tfm_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 rsapad_akcipher_exit_tfm(struct crypto_akcipher *tfm)
-{
- struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
-
- crypto_free_akcipher(ctx->child);
-}
-
-static void rsapad_akcipher_free(struct akcipher_instance *inst)
-{
- struct rsapad_inst_ctx *ctx = akcipher_instance_ctx(inst);
- struct crypto_akcipher_spawn *spawn = &ctx->spawn;
-
- crypto_drop_akcipher(spawn);
- kfree(inst);
-}
-
static struct akcipher_alg pkcs1pad_alg = {
.init = rsapad_akcipher_init_tfm,
.exit = rsapad_akcipher_exit_tfm,
@@ -505,91 +407,6 @@ static struct akcipher_alg pkcs1pad_alg = {
.max_size = rsapad_get_max_size
};

-static int rsapad_akcipher_create(struct crypto_template *tmpl, struct rtattr **tb,
- struct akcipher_alg *alg)
-{
- u32 mask;
- struct akcipher_instance *inst;
- struct rsapad_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);
- if (err)
- return err;
-
- inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
- if (!inst)
- return -ENOMEM;
-
- ctx = akcipher_instance_ctx(inst);
-
- err = crypto_grab_akcipher(&ctx->spawn, akcipher_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);
-
- 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, "%s(%s)", tmpl->name,
- 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, "%s(%s)", tmpl->name,
- 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,
- "%s(%s,%s)", tmpl->name, 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, "%s(%s,%s)",
- tmpl->name,
- 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 rsapad_tfm_ctx);
-
- inst->alg.init = alg->init;
- inst->alg.exit = alg->exit;
-
- inst->alg.encrypt = alg->encrypt;
- inst->alg.decrypt = alg->decrypt;
- inst->alg.sign = alg->sign;
- inst->alg.verify = alg->verify;
- inst->alg.set_pub_key = alg->set_pub_key;
- inst->alg.set_priv_key = alg->set_priv_key;
- inst->alg.max_size = alg->max_size;
- inst->alg.reqsize = sizeof(struct rsapad_akciper_req_ctx) + rsa_alg->reqsize;
-
- inst->free = rsapad_akcipher_free;
-
- err = akcipher_register_instance(tmpl, inst);
- if (err) {
-err_free_inst:
- rsapad_akcipher_free(inst);
- }
- return err;
-}
-
static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
{
return rsapad_akcipher_create(tmpl, tb, &pkcs1pad_alg);
diff --git a/include/crypto/internal/rsa-common.h b/include/crypto/internal/rsa-common.h
index ecdce0cdafaa3..a6f20cce610ab 100644
--- a/include/crypto/internal/rsa-common.h
+++ b/include/crypto/internal/rsa-common.h
@@ -34,4 +34,17 @@ struct rsapad_akciper_req_ctx {
struct akcipher_request child_req;
};

+int rsapad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen);
+int rsapad_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen);
+unsigned int rsapad_get_max_size(struct crypto_akcipher *tfm);
+void rsapad_akcipher_sg_set_buf(struct scatterlist *sg, void *buf,
+ size_t len, struct scatterlist *next);
+int rsapad_akcipher_init_tfm(struct crypto_akcipher *tfm);
+void rsapad_akcipher_exit_tfm(struct crypto_akcipher *tfm);
+void rsapad_akcipher_free(struct akcipher_instance *inst);
+int rsapad_akcipher_create(struct crypto_template *tmpl, struct rtattr **tb,
+ struct akcipher_alg *alg);
+
#endif
--
2.30.2

2021-04-20 11:47:43

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 15/18] crypto: rsa-psspad: Provide PSS signature verify operation

Trigger RSA transform on the signature being verified from
psspad_verify, to produce intermediary data which will be handled
in the psspad_verify_complete callback.

Reference: https://tools.ietf.org/html/rfc8017#section-8.1.2
Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-psspad.c | 53 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 48 insertions(+), 5 deletions(-)

diff --git a/crypto/rsa-psspad.c b/crypto/rsa-psspad.c
index 990c2cda552a7..4e8525d89172d 100644
--- a/crypto/rsa-psspad.c
+++ b/crypto/rsa-psspad.c
@@ -124,7 +124,50 @@ static int pkcs1_mgf1(u8 *seed, unsigned int seed_len,
return ret;
}

-static int psspad_s_v_e_d(struct akcipher_request *req)
+static int psspad_verify_complete(struct akcipher_request *req, int err)
+{
+ return -EOPNOTSUPP;
+}
+
+static void psspad_verify_complete_cb(struct crypto_async_request *child_async_req,
+ int err)
+{
+ rsapad_akcipher_req_complete(child_async_req, err,
+ psspad_verify_complete);
+}
+
+static int psspad_verify(struct akcipher_request *req)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
+ int err;
+
+ if (WARN_ON(req->dst) ||
+ WARN_ON(!req->dst_len) ||
+ !ctx->key_size || req->src_len < ctx->key_size)
+ return -EINVAL;
+
+ req_ctx->out_buf = kmalloc(ctx->key_size + req->dst_len, GFP_KERNEL);
+ if (!req_ctx->out_buf)
+ return -ENOMEM;
+
+ rsapad_akcipher_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf,
+ ctx->key_size, NULL);
+
+ /* Reuse input buffer, output to a new buffer */
+ rsapad_akcipher_setup_child(req, req->src, req_ctx->out_sg,
+ req->src_len, ctx->key_size,
+ psspad_verify_complete_cb);
+
+ err = crypto_akcipher_encrypt(&req_ctx->child_req);
+ if (err != -EINPROGRESS && err != -EBUSY)
+ return psspad_verify_complete(req, err);
+
+ return err;
+}
+
+static int psspad_s_e_d(struct akcipher_request *req)
{
return -EOPNOTSUPP;
}
@@ -133,10 +176,10 @@ static struct akcipher_alg psspad_alg = {
.init = rsapad_akcipher_init_tfm,
.exit = rsapad_akcipher_exit_tfm,

- .encrypt = psspad_s_v_e_d,
- .decrypt = psspad_s_v_e_d,
- .sign = psspad_s_v_e_d,
- .verify = psspad_s_v_e_d,
+ .encrypt = psspad_s_e_d,
+ .decrypt = psspad_s_e_d,
+ .sign = psspad_s_e_d,
+ .verify = psspad_verify,
.set_pub_key = rsapad_set_pub_key,
.set_priv_key = rsapad_set_priv_key,
.max_size = rsapad_get_max_size,
--
2.30.2

2021-04-20 11:47:50

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 16/18] crypto: rsa-psspad: Implement signature verify callback

The RSA output must be processed as per the EMSA-PSS-VERIFY operation
from RFC8017, which forms the core of the PSS signature verification.

Implement the verification callback, which operates on the RSA output
buffer.

Reference: https://tools.ietf.org/html/rfc8017#section-9.1.2
Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-psspad.c | 114 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 113 insertions(+), 1 deletion(-)

diff --git a/crypto/rsa-psspad.c b/crypto/rsa-psspad.c
index 4e8525d89172d..c6f8fb43cb01e 100644
--- a/crypto/rsa-psspad.c
+++ b/crypto/rsa-psspad.c
@@ -8,6 +8,7 @@

#include <crypto/hash.h>
#include <crypto/internal/akcipher.h>
+#include <crypto/internal/rsa.h>
#include <crypto/internal/rsa-common.h>
#include <crypto/public_key.h>

@@ -126,7 +127,118 @@ static int pkcs1_mgf1(u8 *seed, unsigned int seed_len,

static int psspad_verify_complete(struct akcipher_request *req, int err)
{
- return -EOPNOTSUPP;
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsapad_tfm_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsapad_akciper_req_ctx *req_ctx = akcipher_request_ctx(req);
+ struct akcipher_instance *inst = akcipher_alg_instance(tfm);
+ struct rsapad_inst_ctx *ictx = akcipher_instance_ctx(inst);
+ const struct rsa_asn1_template *digest_info = ictx->digest_info;
+ struct crypto_shash *hash_tfm = NULL;
+ struct shash_desc *desc = NULL;
+ struct rsa_mpi_key *pkey = akcipher_tfm_ctx(ctx->child);
+
+ u8 *em, *h, *salt, *maskeddb;
+ unsigned int em_len, em_bits, h_len, s_len, maskeddb_len;
+ u8 *m_hash, *db_mask, *db, *h_;
+ static u8 zeroes[8] = { 0 };
+ unsigned int pos;
+
+ if (err)
+ goto out;
+
+ err = -EINVAL;
+ if (!digest_info)
+ goto out;
+
+ em = req_ctx->out_buf;
+ em_len = ctx->key_size;
+ em_bits = mpi_get_nbits(pkey->n) - 1;
+ if ((em_bits & 0x7) == 0) {
+ em_len--;
+ em++;
+ }
+
+ h_len = req->dst_len;
+ s_len = ictx->salt_len;
+
+ if (em_len < h_len + s_len + 2)
+ goto out;
+
+ if (em[em_len - 1] != 0xbc)
+ goto out;
+
+ maskeddb = em;
+ maskeddb_len = em_len - h_len - 1;
+ h = em + maskeddb_len;
+
+ if (em[0] & ~((u8) 0xff >> (8 * em_len - em_bits)))
+ goto out;
+
+ db_mask = kzalloc(maskeddb_len, GFP_KERNEL);
+ if (!db_mask) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = psspad_setup_shash(&hash_tfm, &desc, ictx->mgf_hash_algo);
+ if (err < 0)
+ goto out_db_mask;
+
+ err = pkcs1_mgf1(h, h_len, desc, db_mask, maskeddb_len);
+ if (err < 0)
+ goto out_shash;
+
+ for (pos = 0; pos < maskeddb_len; pos++)
+ maskeddb[pos] ^= db_mask[pos];
+ db = maskeddb;
+
+ db[0] &= ((u8) 0xff >> (8 * em_len - em_bits));
+
+ err = -EINVAL;
+ for (pos = 0; pos < em_len - h_len - s_len - 2; pos++) {
+ if (db[pos] != 0)
+ goto out_shash;
+ }
+ if (db[pos] != 0x01)
+ goto out_shash;
+
+ salt = db + (maskeddb_len - s_len);
+
+ m_hash = req_ctx->out_buf + ctx->key_size;
+ sg_pcopy_to_buffer(req->src,
+ sg_nents_for_len(req->src, req->src_len + req->dst_len),
+ m_hash,
+ req->dst_len, ctx->key_size);
+
+ if (strcmp(ictx->mgf_hash_algo, digest_info->name) != 0) {
+ psspad_free_shash(hash_tfm, desc);
+ err = psspad_setup_shash(&hash_tfm, &desc, digest_info->name);
+ if (err < 0)
+ goto out_db_mask;
+ }
+
+ err = crypto_shash_init(desc);
+ if (!err)
+ err = crypto_shash_update(desc, zeroes, 8);
+ if (!err)
+ err = crypto_shash_update(desc, m_hash, h_len);
+ if (!err)
+ err = crypto_shash_finup(desc, salt, s_len, m_hash);
+ if (err < 0)
+ goto out_shash;
+
+ h_ = m_hash;
+
+ if (memcmp(h_, h, h_len) != 0)
+ err = -EKEYREJECTED;
+
+out_shash:
+ psspad_free_shash(hash_tfm, desc);
+out_db_mask:
+ kfree(db_mask);
+out:
+ kfree_sensitive(req_ctx->out_buf);
+ return err;
}

static void psspad_verify_complete_cb(struct crypto_async_request *child_async_req,
--
2.30.2

2021-04-20 11:48:02

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 17/18] crypto: Accept pss as valid encoding during signature verification

Accept pss encoding for public_key_verify_signature. If
CONFIG_CRYPTO_RSASSA_PSS is disabled, crypto_alloc_akcipher will
fail to find a pss backend anyway.

Signed-off-by: Varad Gautam <[email protected]>
Acked-by: Jarkko Sakkinen <[email protected]>
---
crypto/asymmetric_keys/public_key.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index 788a4ba1e2e74..b9cc83ba7a127 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -69,19 +69,20 @@ int software_key_determine_akcipher(const char *encoding,
{
int n;

- if (strcmp(encoding, "pkcs1") == 0) {
+ if (strcmp(encoding, "pkcs1") == 0 || strcmp(encoding, "pss") == 0) {
/* The data wangled by the RSA algorithm is typically padded
* and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
- * sec 8.2].
+ * sec 8.2] or EMSA-PSS [RFC8017 sec 9.1].
*/
if (!hash_algo)
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
- "pkcs1pad(%s)",
+ "%spad(%s)",
+ encoding,
pkey->pkey_algo);
else
n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
- "pkcs1pad(%s,%s)",
- pkey->pkey_algo, hash_algo);
+ "%spad(%s,%s)",
+ encoding, pkey->pkey_algo, hash_algo);
return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
}

@@ -363,6 +364,13 @@ int public_key_verify_signature(const struct public_key *pkey,
goto error_free_key;
}

+ if (strcmp(sig->encoding, "pss") == 0) {
+ ret = crypto_akcipher_set_sig_params(tfm, sig, sizeof(*sig));
+ if (ret) {
+ goto error_free_key;
+ }
+ }
+
sg_init_table(src_sg, 2);
sg_set_buf(&src_sg[0], sig->s, sig->s_size);
sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
--
2.30.2

2021-04-20 11:49:00

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 13/18] crypto: rsa-psspad: Get signature parameters from a given signature

Implement akcipher_alg->set_sig_params for rsassa-psspad to receive the
salt length and MGF hash function for the signature being verified.

Signed-off-by: Varad Gautam <[email protected]>
---
crypto/rsa-psspad.c | 21 ++++++++++++++++++++-
include/crypto/internal/rsa-common.h | 2 ++
2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/crypto/rsa-psspad.c b/crypto/rsa-psspad.c
index 40bb6d1dd2067..0a9c0f9e9f0fe 100644
--- a/crypto/rsa-psspad.c
+++ b/crypto/rsa-psspad.c
@@ -9,6 +9,7 @@
#include <crypto/hash.h>
#include <crypto/internal/akcipher.h>
#include <crypto/internal/rsa-common.h>
+#include <crypto/public_key.h>

static bool psspad_check_hash_algo(const char *hash_algo)
{
@@ -52,6 +53,23 @@ static void psspad_free_shash(struct crypto_shash *hash_tfm, struct shash_desc *
crypto_free_shash(hash_tfm);
}

+static int psspad_set_sig_params(struct crypto_akcipher *tfm,
+ const void *sig,
+ unsigned int siglen)
+{
+ struct akcipher_instance *inst = akcipher_alg_instance(tfm);
+ struct rsapad_inst_ctx *ictx = akcipher_instance_ctx(inst);
+ const struct public_key_signature *s = sig;
+
+ if (!sig)
+ return -EINVAL;
+
+ ictx->salt_len = s->salt_length;
+ ictx->mgf_hash_algo = s->mgf_hash_algo;
+
+ return 0;
+}
+
static int psspad_s_v_e_d(struct akcipher_request *req)
{
return -EOPNOTSUPP;
@@ -67,7 +85,8 @@ static struct akcipher_alg psspad_alg = {
.verify = psspad_s_v_e_d,
.set_pub_key = rsapad_set_pub_key,
.set_priv_key = rsapad_set_priv_key,
- .max_size = rsapad_get_max_size
+ .max_size = rsapad_get_max_size,
+ .set_sig_params = psspad_set_sig_params
};

static int psspad_create(struct crypto_template *tmpl, struct rtattr **tb)
diff --git a/include/crypto/internal/rsa-common.h b/include/crypto/internal/rsa-common.h
index 4fa3cf5a989cc..8b7ba0174d5bf 100644
--- a/include/crypto/internal/rsa-common.h
+++ b/include/crypto/internal/rsa-common.h
@@ -26,6 +26,8 @@ struct rsapad_tfm_ctx {
struct rsapad_inst_ctx {
struct crypto_akcipher_spawn spawn;
const struct rsa_asn1_template *digest_info;
+ u16 salt_len;
+ const char *mgf_hash_algo;
};

struct rsapad_akciper_req_ctx {
--
2.30.2

2021-04-20 11:49:07

by Varad Gautam

[permalink] [raw]
Subject: [PATCH v3 18/18] keyctl_pkey: Add pkey parameters saltlen and mgfhash for PSS

keyctl pkey_* operations accept enc and hash parameters at present.
RSASSA-PSS signatures also require passing in the signature salt
length and the mgf hash function.

Add parameters:
- 'saltlen' to feed in salt length of a PSS signature.
- 'mgfhash' to feed in the hash function used for MGF.

Signed-off-by: Varad Gautam <[email protected]>
CC: Jarkko Sakkinen <[email protected]>
CC: Ben Boeckel <[email protected]>
---
v3: Rename slen to saltlen, update Documentation/security/keys/core.rst.

Documentation/security/keys/core.rst | 14 +++++++++++++-
crypto/asymmetric_keys/asymmetric_type.c | 2 ++
include/linux/keyctl.h | 2 ++
security/keys/keyctl_pkey.c | 13 +++++++++++++
4 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst
index b3ed5c581034c..4bd774c56899e 100644
--- a/Documentation/security/keys/core.rst
+++ b/Documentation/security/keys/core.rst
@@ -1022,6 +1022,15 @@ The keyctl syscall functions are:
which hash function was used, the hash function can be
specified with this, eg. "hash=sha256".

+ ``mgfhash=<algo>`` In case of "RSASSA-PSS" ("enc=pss"), this specifies
+ the hash function used with the Mask Generation Function
+ to generate a signature, eg. "mgfhash=sha256". Supported
+ hashes are: sha1, sha224, sha256, sha384, and sha512.
+
+ ``saltlen=<salt_length>`` In case of "RSASSA-PSS" ("enc=pss"), this
+ specifies the salt length as a u16, used to generate a
+ signature. Eg. "saltlen=32".
+
The ``__spare[]`` space in the parameter block must be set to 0. This is
intended, amongst other things, to allow the passing of passphrases
required to unlock a key.
@@ -1700,6 +1709,8 @@ The structure has a number of fields, some of which are mandatory:
__u32 in2_len;
};
enum kernel_pkey_operation op : 8;
+ __u16 salt_len;
+ const char *mgf_hash_algo;
};

This includes the key to be used; a string indicating the encoding to use
@@ -1707,7 +1718,8 @@ The structure has a number of fields, some of which are mandatory:
RSASSA-PKCS1-v1.5 or RSAES-PKCS1-v1.5 encoding or "raw" if no encoding);
the name of the hash algorithm used to generate the data for a signature
(if appropriate); the sizes of the input and output (or second input)
- buffers; and the ID of the operation to be performed.
+ buffers; the ID of the operation to be performed; salt length to be used
+ in case of RSASSA-PSS; and hash algorithm used with MGF for RSASSA-PSS.

For a given operation ID, the input and output buffers are used as
follows::
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index ad8af3d70ac04..2d3419509ec35 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -571,6 +571,8 @@ static int asymmetric_key_verify_signature(struct kernel_pkey_params *params,
.hash_algo = params->hash_algo,
.digest = (void *)in,
.s = (void *)in2,
+ .salt_length = params->salt_len,
+ .mgf_hash_algo = params->mgf_hash_algo,
};

return verify_signature(params->key, &sig);
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 5b79847207ef2..b0122ac6e11c9 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -37,6 +37,8 @@ struct kernel_pkey_params {
__u32 in2_len; /* 2nd input data size (verify) */
};
enum kernel_pkey_operation op : 8;
+ __u16 salt_len;
+ const char *mgf_hash_algo;
};

#endif /* __LINUX_KEYCTL_H */
diff --git a/security/keys/keyctl_pkey.c b/security/keys/keyctl_pkey.c
index 5de0d599a2748..019f112474dcd 100644
--- a/security/keys/keyctl_pkey.c
+++ b/security/keys/keyctl_pkey.c
@@ -24,11 +24,15 @@ enum {
Opt_err,
Opt_enc, /* "enc=<encoding>" eg. "enc=oaep" */
Opt_hash, /* "hash=<digest-name>" eg. "hash=sha1" */
+ Opt_saltlen, /* "saltlen=<salt-length>" eg. "saltlen=32" */
+ Opt_mgfhash, /* "mgfhash=<digest-name>" eg. "mgfhash=sha1" */
};

static const match_table_t param_keys = {
{ Opt_enc, "enc=%s" },
{ Opt_hash, "hash=%s" },
+ { Opt_saltlen, "saltlen=%u" },
+ { Opt_mgfhash, "mgfhash=%s" },
{ Opt_err, NULL }
};

@@ -63,6 +67,15 @@ static int keyctl_pkey_params_parse(struct kernel_pkey_params *params)
params->hash_algo = q;
break;

+ case Opt_saltlen:
+ if (kstrtou16(q, 0, &params->salt_len))
+ return -EINVAL;
+ break;
+
+ case Opt_mgfhash:
+ params->mgf_hash_algo = q;
+ break;
+
default:
return -EINVAL;
}
--
2.30.2

2021-04-20 13:28:03

by Ben Boeckel

[permalink] [raw]
Subject: Re: [PATCH v3 18/18] keyctl_pkey: Add pkey parameters saltlen and mgfhash for PSS

On Tue, Apr 20, 2021 at 13:41:23 +0200, Varad Gautam wrote:
> keyctl pkey_* operations accept enc and hash parameters at present.
> RSASSA-PSS signatures also require passing in the signature salt
> length and the mgf hash function.
>
> Add parameters:
> - 'saltlen' to feed in salt length of a PSS signature.
> - 'mgfhash' to feed in the hash function used for MGF.
>
> Signed-off-by: Varad Gautam <[email protected]>
> CC: Jarkko Sakkinen <[email protected]>
> CC: Ben Boeckel <[email protected]>
> ---
> v3: Rename slen to saltlen, update Documentation/security/keys/core.rst.
>
> Documentation/security/keys/core.rst | 14 +++++++++++++-
> crypto/asymmetric_keys/asymmetric_type.c | 2 ++
> include/linux/keyctl.h | 2 ++
> security/keys/keyctl_pkey.c | 13 +++++++++++++
> 4 files changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/security/keys/core.rst b/Documentation/security/keys/core.rst
> index b3ed5c581034c..4bd774c56899e 100644
> --- a/Documentation/security/keys/core.rst
> +++ b/Documentation/security/keys/core.rst
> @@ -1022,6 +1022,15 @@ The keyctl syscall functions are:
> which hash function was used, the hash function can be
> specified with this, eg. "hash=sha256".
>
> + ``mgfhash=<algo>`` In case of "RSASSA-PSS" ("enc=pss"), this specifies
> + the hash function used with the Mask Generation Function
> + to generate a signature, eg. "mgfhash=sha256". Supported
> + hashes are: sha1, sha224, sha256, sha384, and sha512.
> +
> + ``saltlen=<salt_length>`` In case of "RSASSA-PSS" ("enc=pss"), this
> + specifies the salt length as a u16, used to generate a
^

This feels like it is missing a comma at the designated location (after
`length` if the whitespace gets mangled).

> + signature. Eg. "saltlen=32".
> +
> The ``__spare[]`` space in the parameter block must be set to 0. This is
> intended, amongst other things, to allow the passing of passphrases
> required to unlock a key.
> @@ -1700,6 +1709,8 @@ The structure has a number of fields, some of which are mandatory:
> __u32 in2_len;
> };
> enum kernel_pkey_operation op : 8;
> + __u16 salt_len;
> + const char *mgf_hash_algo;
> };
>
> This includes the key to be used; a string indicating the encoding to use
> @@ -1707,7 +1718,8 @@ The structure has a number of fields, some of which are mandatory:
> RSASSA-PKCS1-v1.5 or RSAES-PKCS1-v1.5 encoding or "raw" if no encoding);
> the name of the hash algorithm used to generate the data for a signature
> (if appropriate); the sizes of the input and output (or second input)
> - buffers; and the ID of the operation to be performed.
> + buffers; the ID of the operation to be performed; salt length to be used
> + in case of RSASSA-PSS; and hash algorithm used with MGF for RSASSA-PSS.
>
> For a given operation ID, the input and output buffers are used as
> follows::

Thanks for the docs, they look good to me overall. Other than the comma:

Acked-by: Ben Boeckel <[email protected]>

--Ben