crypto: akcipher - Changes to asymmetric key API

Setkey function has been split into set_priv_key and set_pub_key.
Akcipher requests takes sgl for src and dst instead of void *.
Users of the API i.e. two existing RSA implementation and
test mgr code have been updated accordingly.

Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/crypto/Makefile b/crypto/Makefile
index e2c5981..d897e0b 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -31,10 +31,13 @@
 obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
 obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
 
-$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h
-clean-files += rsakey-asn1.c rsakey-asn1.h
+$(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
+$(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
+clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
+clean-files += rsaprivkey-asn1.c rsaprivkey-asn1.h
 
-rsa_generic-y := rsakey-asn1.o
+rsa_generic-y := rsapubkey-asn1.o
+rsa_generic-y += rsaprivkey-asn1.o
 rsa_generic-y += rsa.o
 rsa_generic-y += rsa_helper.o
 obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
diff --git a/crypto/rsa.c b/crypto/rsa.c
index 466003e..1093e04 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -97,24 +97,21 @@
 		goto err_free_c;
 	}
 
-	m = mpi_read_raw_data(req->src, req->src_len);
-	if (!m) {
-		ret = -ENOMEM;
+	ret = -ENOMEM;
+	m = mpi_read_raw_from_sgl(req->src, req->src_len);
+	if (!m)
 		goto err_free_c;
-	}
 
 	ret = _rsa_enc(pkey, c, m);
 	if (ret)
 		goto err_free_m;
 
-	ret = mpi_read_buffer(c, req->dst, req->dst_len, &req->dst_len, &sign);
+	ret = mpi_write_to_sgl(c, req->dst, &req->dst_len, &sign);
 	if (ret)
 		goto err_free_m;
 
-	if (sign < 0) {
+	if (sign < 0)
 		ret = -EBADMSG;
-		goto err_free_m;
-	}
 
 err_free_m:
 	mpi_free(m);
@@ -145,25 +142,21 @@
 		goto err_free_m;
 	}
 
-	c = mpi_read_raw_data(req->src, req->src_len);
-	if (!c) {
-		ret = -ENOMEM;
+	ret = -ENOMEM;
+	c = mpi_read_raw_from_sgl(req->src, req->src_len);
+	if (!c)
 		goto err_free_m;
-	}
 
 	ret = _rsa_dec(pkey, m, c);
 	if (ret)
 		goto err_free_c;
 
-	ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign);
+	ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign);
 	if (ret)
 		goto err_free_c;
 
-	if (sign < 0) {
+	if (sign < 0)
 		ret = -EBADMSG;
-		goto err_free_c;
-	}
-
 err_free_c:
 	mpi_free(c);
 err_free_m:
@@ -193,24 +186,21 @@
 		goto err_free_s;
 	}
 
-	m = mpi_read_raw_data(req->src, req->src_len);
-	if (!m) {
-		ret = -ENOMEM;
+	ret = -ENOMEM;
+	m = mpi_read_raw_from_sgl(req->src, req->src_len);
+	if (!m)
 		goto err_free_s;
-	}
 
 	ret = _rsa_sign(pkey, s, m);
 	if (ret)
 		goto err_free_m;
 
-	ret = mpi_read_buffer(s, req->dst, req->dst_len, &req->dst_len, &sign);
+	ret = mpi_write_to_sgl(s, req->dst, &req->dst_len, &sign);
 	if (ret)
 		goto err_free_m;
 
-	if (sign < 0) {
+	if (sign < 0)
 		ret = -EBADMSG;
-		goto err_free_m;
-	}
 
 err_free_m:
 	mpi_free(m);
@@ -241,7 +231,8 @@
 		goto err_free_m;
 	}
 
-	s = mpi_read_raw_data(req->src, req->src_len);
+	ret = -ENOMEM;
+	s = mpi_read_raw_from_sgl(req->src, req->src_len);
 	if (!s) {
 		ret = -ENOMEM;
 		goto err_free_m;
@@ -251,14 +242,12 @@
 	if (ret)
 		goto err_free_s;
 
-	ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign);
+	ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign);
 	if (ret)
 		goto err_free_s;
 
-	if (sign < 0) {
+	if (sign < 0)
 		ret = -EBADMSG;
-		goto err_free_s;
-	}
 
 err_free_s:
 	mpi_free(s);
@@ -282,13 +271,13 @@
 	return -EINVAL;
 }
 
-static int rsa_setkey(struct crypto_akcipher *tfm, const void *key,
-		      unsigned int keylen)
+static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+			   unsigned int keylen)
 {
 	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
 	int ret;
 
-	ret = rsa_parse_key(pkey, key, keylen);
+	ret = rsa_parse_pub_key(pkey, key, keylen);
 	if (ret)
 		return ret;
 
@@ -299,6 +288,30 @@
 	return ret;
 }
 
+static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+			    unsigned int keylen)
+{
+	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+	int ret;
+
+	ret = rsa_parse_priv_key(pkey, key, keylen);
+	if (ret)
+		return ret;
+
+	if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) {
+		rsa_free_key(pkey);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int rsa_max_size(struct crypto_akcipher *tfm)
+{
+	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+
+	return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
+}
+
 static void rsa_exit_tfm(struct crypto_akcipher *tfm)
 {
 	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
@@ -311,7 +324,9 @@
 	.decrypt = rsa_dec,
 	.sign = rsa_sign,
 	.verify = rsa_verify,
-	.setkey = rsa_setkey,
+	.set_priv_key = rsa_set_priv_key,
+	.set_pub_key = rsa_set_pub_key,
+	.max_size = rsa_max_size,
 	.exit = rsa_exit_tfm,
 	.base = {
 		.cra_name = "rsa",
diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
index 8d96ce9..d226f48 100644
--- a/crypto/rsa_helper.c
+++ b/crypto/rsa_helper.c
@@ -15,7 +15,8 @@
 #include <linux/err.h>
 #include <linux/fips.h>
 #include <crypto/internal/rsa.h>
-#include "rsakey-asn1.h"
+#include "rsapubkey-asn1.h"
+#include "rsaprivkey-asn1.h"
 
 int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
 	      const void *value, size_t vlen)
@@ -94,8 +95,8 @@
 EXPORT_SYMBOL_GPL(rsa_free_key);
 
 /**
- * rsa_parse_key() - extracts an rsa key from BER encoded buffer
- *		     and stores it in the provided struct rsa_key
+ * rsa_parse_pub_key() - extracts an rsa public key from BER encoded buffer
+ *			 and stores it in the provided struct rsa_key
  *
  * @rsa_key:	struct rsa_key key representation
  * @key:	key in BER format
@@ -103,13 +104,13 @@
  *
  * Return:	0 on success or error code in case of error
  */
-int rsa_parse_key(struct rsa_key *rsa_key, const void *key,
-		  unsigned int key_len)
+int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
+		      unsigned int key_len)
 {
 	int ret;
 
 	free_mpis(rsa_key);
-	ret = asn1_ber_decoder(&rsakey_decoder, rsa_key, key, key_len);
+	ret = asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len);
 	if (ret < 0)
 		goto error;
 
@@ -118,4 +119,31 @@
 	free_mpis(rsa_key);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(rsa_parse_key);
+EXPORT_SYMBOL_GPL(rsa_parse_pub_key);
+
+/**
+ * rsa_parse_pub_key() - extracts an rsa private key from BER encoded buffer
+ *			 and stores it in the provided struct rsa_key
+ *
+ * @rsa_key:	struct rsa_key key representation
+ * @key:	key in BER format
+ * @key_len:	length of key
+ *
+ * Return:	0 on success or error code in case of error
+ */
+int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
+		       unsigned int key_len)
+{
+	int ret;
+
+	free_mpis(rsa_key);
+	ret = asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+error:
+	free_mpis(rsa_key);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rsa_parse_priv_key);
diff --git a/crypto/rsakey.asn1 b/crypto/rsakey.asn1
deleted file mode 100644
index 3c7b5df..0000000
--- a/crypto/rsakey.asn1
+++ /dev/null
@@ -1,5 +0,0 @@
-RsaKey ::= SEQUENCE {
-	n INTEGER ({ rsa_get_n }),
-	e INTEGER ({ rsa_get_e }),
-	d INTEGER ({ rsa_get_d })
-}
diff --git a/crypto/rsaprivkey.asn1 b/crypto/rsaprivkey.asn1
new file mode 100644
index 0000000..731aea5
--- /dev/null
+++ b/crypto/rsaprivkey.asn1
@@ -0,0 +1,11 @@
+RsaPrivKey ::= SEQUENCE {
+	version		INTEGER,
+	n		INTEGER ({ rsa_get_n }),
+	e		INTEGER ({ rsa_get_e }),
+	d		INTEGER ({ rsa_get_d }),
+	prime1		INTEGER,
+	prime2		INTEGER,
+	exponent1	INTEGER,
+	exponent2	INTEGER,
+	coefficient	INTEGER
+}
diff --git a/crypto/rsapubkey.asn1 b/crypto/rsapubkey.asn1
new file mode 100644
index 0000000..725498e
--- /dev/null
+++ b/crypto/rsapubkey.asn1
@@ -0,0 +1,4 @@
+RsaPubKey ::= SEQUENCE {
+	n INTEGER ({ rsa_get_n }),
+	e INTEGER ({ rsa_get_e })
+}
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 523c9b9..25032b0 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1845,34 +1845,34 @@
 	struct tcrypt_result result;
 	unsigned int out_len_max, out_len = 0;
 	int err = -ENOMEM;
+	struct scatterlist src, dst, src_tab[2];
 
 	req = akcipher_request_alloc(tfm, GFP_KERNEL);
 	if (!req)
 		return err;
 
 	init_completion(&result.completion);
-	err = crypto_akcipher_setkey(tfm, vecs->key, vecs->key_len);
+
+	if (vecs->public_key_vec)
+		err = crypto_akcipher_set_pub_key(tfm, vecs->key,
+						  vecs->key_len);
+	else
+		err = crypto_akcipher_set_priv_key(tfm, vecs->key,
+						   vecs->key_len);
 	if (err)
 		goto free_req;
 
-	akcipher_request_set_crypt(req, vecs->m, outbuf_enc, vecs->m_size,
-				   out_len);
-	/* expect this to fail, and update the required buf len */
-	crypto_akcipher_encrypt(req);
-	out_len = req->dst_len;
-	if (!out_len) {
-		err = -EINVAL;
-		goto free_req;
-	}
-
-	out_len_max = out_len;
-	err = -ENOMEM;
+	out_len_max = crypto_akcipher_maxsize(tfm);
 	outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
 	if (!outbuf_enc)
 		goto free_req;
 
-	akcipher_request_set_crypt(req, vecs->m, outbuf_enc, vecs->m_size,
-				   out_len);
+	sg_init_table(src_tab, 2);
+	sg_set_buf(&src_tab[0], vecs->m, 8);
+	sg_set_buf(&src_tab[1], vecs->m + 8, vecs->m_size - 8);
+	sg_init_one(&dst, outbuf_enc, out_len_max);
+	akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size,
+				   out_len_max);
 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				      tcrypt_complete, &result);
 
@@ -1882,13 +1882,13 @@
 		pr_err("alg: rsa: encrypt test failed. err %d\n", err);
 		goto free_all;
 	}
-	if (out_len != vecs->c_size) {
+	if (req->dst_len != vecs->c_size) {
 		pr_err("alg: rsa: encrypt test failed. Invalid output len\n");
 		err = -EINVAL;
 		goto free_all;
 	}
 	/* verify that encrypted message is equal to expected */
-	if (memcmp(vecs->c, outbuf_enc, vecs->c_size)) {
+	if (memcmp(vecs->c, sg_virt(req->dst), vecs->c_size)) {
 		pr_err("alg: rsa: encrypt test failed. Invalid output\n");
 		err = -EINVAL;
 		goto free_all;
@@ -1903,9 +1903,10 @@
 		err = -ENOMEM;
 		goto free_all;
 	}
+	sg_init_one(&src, vecs->c, vecs->c_size);
+	sg_init_one(&dst, outbuf_dec, out_len_max);
 	init_completion(&result.completion);
-	akcipher_request_set_crypt(req, outbuf_enc, outbuf_dec, vecs->c_size,
-				   out_len);
+	akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max);
 
 	/* Run RSA decrypt - m = c^d mod n;*/
 	err = wait_async_op(&result, crypto_akcipher_decrypt(req));
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 64b8a80..e10582d 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -149,7 +149,8 @@
 	{
 #ifndef CONFIG_CRYPTO_FIPS
 	.key =
-	"\x30\x81\x88" /* sequence of 136 bytes */
+	"\x30\x81\x9A" /* sequence of 154 bytes */
+	"\x02\x01\x01" /* version - integer of 1 byte */
 	"\x02\x41" /* modulus - integer of 65 bytes */
 	"\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
 	"\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
@@ -161,19 +162,25 @@
 	"\x0A\x03\x37\x48\x62\x64\x87\x69\x5F\x5F\x30\xBC\x38\xB9\x8B\x44"
 	"\xC2\xCD\x2D\xFF\x43\x40\x98\xCD\x20\xD8\xA1\x38\xD0\x90\xBF\x64"
 	"\x79\x7C\x3F\xA7\xA2\xCD\xCB\x3C\xD1\xE0\xBD\xBA\x26\x54\xB4\xF9"
-	"\xDF\x8E\x8A\xE5\x9D\x73\x3D\x9F\x33\xB3\x01\x62\x4A\xFD\x1D\x51",
+	"\xDF\x8E\x8A\xE5\x9D\x73\x3D\x9F\x33\xB3\x01\x62\x4A\xFD\x1D\x51"
+	"\x02\x01\x00" /* prime1 - integer of 1 byte */
+	"\x02\x01\x00" /* prime2 - integer of 1 byte */
+	"\x02\x01\x00" /* exponent1 - integer of 1 byte */
+	"\x02\x01\x00" /* exponent2 - integer of 1 byte */
+	"\x02\x01\x00", /* coefficient - integer of 1 byte */
 	.m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a",
 	.c =
 	"\x63\x1c\xcd\x7b\xe1\x7e\xe4\xde\xc9\xa8\x89\xa1\x74\xcb\x3c\x63"
 	"\x7d\x24\xec\x83\xc3\x15\xe4\x7f\x73\x05\x34\xd1\xec\x22\xbb\x8a"
 	"\x5e\x32\x39\x6d\xc1\x1d\x7d\x50\x3b\x9f\x7a\xad\xf0\x2e\x25\x53"
 	"\x9f\x6e\xbd\x4c\x55\x84\x0c\x9b\xcf\x1a\x4b\x51\x1e\x9e\x0c\x06",
-	.key_len = 139,
+	.key_len = 157,
 	.m_size = 8,
 	.c_size = 64,
 	}, {
 	.key =
-	"\x30\x82\x01\x0B" /* sequence of 267 bytes */
+	"\x30\x82\x01\x1D" /* sequence of 285 bytes */
+	"\x02\x01\x01" /* version - integer of 1 byte */
 	"\x02\x81\x81" /* modulus - integer of 129 bytes */
 	"\x00\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71"
 	"\xF7\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5"
@@ -194,8 +201,13 @@
 	"\x44\xE5\x6A\xAF\x68\xC5\x6C\x09\x2C\xD3\x8D\xC3\xBE\xF5\xD2\x0A"
 	"\x93\x99\x26\xED\x4F\x74\xA1\x3E\xDD\xFB\xE1\xA1\xCE\xCC\x48\x94"
 	"\xAF\x94\x28\xC2\xB7\xB8\x88\x3F\xE4\x46\x3A\x4B\xC8\x5B\x1C\xB3"
-	"\xC1",
-	.key_len = 271,
+	"\xC1"
+	"\x02\x01\x00" /* prime1 - integer of 1 byte */
+	"\x02\x01\x00" /* prime2 - integer of 1 byte */
+	"\x02\x01\x00" /* exponent1 - integer of 1 byte */
+	"\x02\x01\x00" /* exponent2 - integer of 1 byte */
+	"\x02\x01\x00", /* coefficient - integer of 1 byte */
+	.key_len = 289,
 	.m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a",
 	.c =
 	"\x74\x1b\x55\xac\x47\xb5\x08\x0a\x6e\x2b\x2d\xf7\x94\xb8\x8a\x95"
@@ -211,7 +223,8 @@
 	}, {
 #endif
 	.key =
-	"\x30\x82\x02\x0D" /* sequence of 525 bytes */
+	"\x30\x82\x02\x1F" /* sequence of 543 bytes */
+	"\x02\x01\x01" /* version - integer of 1 byte */
 	"\x02\x82\x01\x00" /* modulus - integer of 256 bytes */
 	"\xDB\x10\x1A\xC2\xA3\xF1\xDC\xFF\x13\x6B\xED\x44\xDF\xF0\x02\x6D"
 	"\x13\xC7\x88\xDA\x70\x6B\x54\xF1\xE8\x27\xDC\xC3\x0F\x99\x6A\xFA"
@@ -246,8 +259,13 @@
 	"\x77\xAF\x51\x27\x5B\x5E\x69\xB8\x81\xE6\x11\xC5\x43\x23\x81\x04"
 	"\x62\xFF\xE9\x46\xB8\xD8\x44\xDB\xA5\xCC\x31\x54\x34\xCE\x3E\x82"
 	"\xD6\xBF\x7A\x0B\x64\x21\x6D\x88\x7E\x5B\x45\x12\x1E\x63\x8D\x49"
-	"\xA7\x1D\xD9\x1E\x06\xCD\xE8\xBA\x2C\x8C\x69\x32\xEA\xBE\x60\x71",
-	.key_len = 529,
+	"\xA7\x1D\xD9\x1E\x06\xCD\xE8\xBA\x2C\x8C\x69\x32\xEA\xBE\x60\x71"
+	"\x02\x01\x00" /* prime1 - integer of 1 byte */
+	"\x02\x01\x00" /* prime2 - integer of 1 byte */
+	"\x02\x01\x00" /* exponent1 - integer of 1 byte */
+	"\x02\x01\x00" /* exponent2 - integer of 1 byte */
+	"\x02\x01\x00", /* coefficient - integer of 1 byte */
+	.key_len = 547,
 	.m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a",
 	.c =
 	"\xb2\x97\x76\xb4\xae\x3e\x38\x3c\x7e\x64\x1f\xcc\xa2\x7f\xf6\xbe"