Message ID | 20150909161532.2828.990.stgit@tstruk-mobl1 (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Herbert Xu |
Headers | show |
Am Mittwoch, 9. September 2015, 09:15:32 schrieb Tadeusz Struk: Hi Tadeusz, >Rsa updates to reflect the API changes. > >Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> >--- > crypto/Makefile | 12 ++- > crypto/rsa.c | 188 >++++++++++++++++++++++++++++++++++------- crypto/rsa_helper.c | >42 ++++++++- > crypto/rsakey.asn1 | 5 - > crypto/rsaprivkey.asn1 | 11 ++ > crypto/rsapubkey.asn1 | 4 + > include/crypto/internal/rsa.h | 7 +- > 7 files changed, 220 insertions(+), 49 deletions(-) > delete mode 100644 crypto/rsakey.asn1 > create mode 100644 crypto/rsaprivkey.asn1 > create mode 100644 crypto/rsapubkey.asn1 > >diff --git a/crypto/Makefile b/crypto/Makefile >index 65e91da..d897e0b 100644 >--- a/crypto/Makefile >+++ b/crypto/Makefile >@@ -31,8 +31,16 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o > 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 := 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 > > cryptomgr-y := algboss.o testmgr.o > >diff --git a/crypto/rsa.c b/crypto/rsa.c >index 93feae2..f5b956c 100644 >--- a/crypto/rsa.c >+++ b/crypto/rsa.c >@@ -13,6 +13,7 @@ > #include <crypto/internal/rsa.h> > #include <crypto/internal/akcipher.h> > #include <crypto/akcipher.h> >+#include <crypto/scatterwalk.h> > > /* > * RSAEP function [RFC3447 sec 5.1.1] >@@ -80,34 +81,57 @@ static int rsa_enc(struct akcipher_request *req) > struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); > const struct rsa_key *pkey = rsa_get_key(tfm); > MPI m, c = mpi_alloc(0); >+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst); unsigned int? > int ret = 0; > int sign; > > if (!c) > return -ENOMEM; > >- if (unlikely(!pkey->n || !pkey->e)) { >+ if (unlikely(!pkey->n || !pkey->e || !src_len)) { > ret = -EINVAL; > goto err_free_c; > } > >- if (req->dst_len < mpi_get_size(pkey->n)) { >- req->dst_len = mpi_get_size(pkey->n); >+ if (dst_len < mpi_get_size(pkey->n)) { >+ req->out_len = mpi_get_size(pkey->n); > ret = -EOVERFLOW; > goto err_free_c; > } > >- m = mpi_read_raw_data(req->src, req->src_len); >- if (!m) { >- ret = -ENOMEM; >- goto err_free_c; >+ ret = -ENOMEM; >+ if (sg_is_last(req->src)) { >+ m = mpi_read_raw_data(sg_virt(req->src), src_len); >+ } else { >+ void *ptr = kmalloc(src_len, GFP_KERNEL); >+ >+ if (!ptr) >+ goto err_free_c; >+ >+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0); >+ m = mpi_read_raw_data(ptr, src_len); >+ kfree(ptr); > } >+ 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); >+ if (sg_is_last(req->dst)) { >+ ret = mpi_read_buffer(c, sg_virt(req->dst), dst_len, >+ &req->out_len, &sign); >+ } else { >+ void *ptr = kmalloc(dst_len, GFP_KERNEL); >+ >+ if (!ptr) >+ goto err_free_m; >+ >+ ret = mpi_read_buffer(c, ptr, dst_len, &req->out_len, &sign); >+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1); >+ kfree(ptr); Just a question: this code is present 4 times, can that be put into a separate inline? >+ } > if (ret) > goto err_free_m; > >@@ -128,34 +152,57 @@ static int rsa_dec(struct akcipher_request *req) > struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); > const struct rsa_key *pkey = rsa_get_key(tfm); > MPI c, m = mpi_alloc(0); >+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst); unsigned int? > int ret = 0; > int sign; > > if (!m) > return -ENOMEM; > >- if (unlikely(!pkey->n || !pkey->d)) { >+ if (unlikely(!pkey->n || !pkey->d || !src_len)) { > ret = -EINVAL; > goto err_free_m; > } > >- if (req->dst_len < mpi_get_size(pkey->n)) { >- req->dst_len = mpi_get_size(pkey->n); >+ if (dst_len < mpi_get_size(pkey->n)) { >+ req->out_len = mpi_get_size(pkey->n); > ret = -EOVERFLOW; > goto err_free_m; > } > >- c = mpi_read_raw_data(req->src, req->src_len); >- if (!c) { >- ret = -ENOMEM; >- goto err_free_m; >+ ret = -ENOMEM; >+ if (sg_is_last(req->src)) { >+ c = mpi_read_raw_data(sg_virt(req->src), src_len); >+ } else { >+ void *ptr = kmalloc(src_len, GFP_KERNEL); >+ >+ if (!ptr) >+ goto err_free_m; >+ >+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0); >+ c = mpi_read_raw_data(ptr, src_len); >+ kfree(ptr); > } >+ 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); >+ if (sg_is_last(req->dst)) { >+ ret = mpi_read_buffer(m, sg_virt(req->dst), dst_len, >+ &req->out_len, &sign); >+ } else { >+ void *ptr = kmalloc(dst_len, GFP_KERNEL); >+ >+ if (!ptr) >+ goto err_free_c; >+ >+ ret = mpi_read_buffer(m, ptr, dst_len, &req->out_len, &sign); >+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1); >+ kfree(ptr); >+ } > if (ret) > goto err_free_c; > >@@ -176,34 +223,58 @@ static int rsa_sign(struct akcipher_request *req) > struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); > const struct rsa_key *pkey = rsa_get_key(tfm); > MPI m, s = mpi_alloc(0); >+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst); unsigned int? > int ret = 0; > int sign; > > if (!s) > return -ENOMEM; > >- if (unlikely(!pkey->n || !pkey->d)) { >+ if (unlikely(!pkey->n || !pkey->d || !src_len)) { > ret = -EINVAL; > goto err_free_s; > } > >- if (req->dst_len < mpi_get_size(pkey->n)) { >- req->dst_len = mpi_get_size(pkey->n); >+ if (dst_len < mpi_get_size(pkey->n)) { >+ req->out_len = mpi_get_size(pkey->n); > ret = -EOVERFLOW; > goto err_free_s; > } > >- m = mpi_read_raw_data(req->src, req->src_len); >- if (!m) { >- ret = -ENOMEM; >- goto err_free_s; >+ ret = -ENOMEM; >+ if (sg_is_last(req->src)) { >+ m = mpi_read_raw_data(sg_virt(req->src), src_len); >+ } else { >+ void *ptr = kmalloc(src_len, GFP_KERNEL); >+ >+ if (!ptr) >+ goto err_free_s; >+ >+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0); >+ m = mpi_read_raw_data(ptr, src_len); >+ kfree(ptr); >+ > } >+ 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); >+ if (sg_is_last(req->dst)) { >+ ret = mpi_read_buffer(s, sg_virt(req->dst), dst_len, >+ &req->out_len, &sign); >+ } else { >+ void *ptr = kmalloc(dst_len, GFP_KERNEL); >+ >+ if (!ptr) >+ goto err_free_m; >+ >+ ret = mpi_read_buffer(s, ptr, dst_len, &req->out_len, &sign); >+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1); >+ kfree(ptr); >+ } > if (ret) > goto err_free_m; > >@@ -224,24 +295,37 @@ static int rsa_verify(struct akcipher_request *req) > struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); > const struct rsa_key *pkey = rsa_get_key(tfm); > MPI s, m = mpi_alloc(0); >+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst); unsigned int? > int ret = 0; > int sign; > > if (!m) > return -ENOMEM; > >- if (unlikely(!pkey->n || !pkey->e)) { >+ if (unlikely(!pkey->n || !pkey->e || !src_len)) { > ret = -EINVAL; > goto err_free_m; > } > >- if (req->dst_len < mpi_get_size(pkey->n)) { >- req->dst_len = mpi_get_size(pkey->n); >+ if (dst_len < mpi_get_size(pkey->n)) { >+ req->out_len = mpi_get_size(pkey->n); > ret = -EOVERFLOW; > goto err_free_m; > } > >- s = mpi_read_raw_data(req->src, req->src_len); >+ ret = -ENOMEM; >+ if (sg_is_last(req->src)) { >+ s = mpi_read_raw_data(sg_virt(req->src), src_len); >+ } else { >+ void *ptr = kmalloc(src_len, GFP_KERNEL); >+ >+ if (!ptr) >+ goto err_free_m; >+ >+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0); >+ s = mpi_read_raw_data(ptr, src_len); >+ kfree(ptr); >+ } > if (!s) { > ret = -ENOMEM; > goto err_free_m; >@@ -251,7 +335,19 @@ static int rsa_verify(struct akcipher_request *req) > if (ret) > goto err_free_s; > >- ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign); >+ if (sg_is_last(req->dst)) { >+ ret = mpi_read_buffer(m, sg_virt(req->dst), dst_len, >+ &req->out_len, &sign); >+ } else { >+ void *ptr = kmalloc(dst_len, GFP_KERNEL); >+ >+ if (!ptr) >+ goto err_free_s; >+ >+ ret = mpi_read_buffer(m, ptr, dst_len, &req->out_len, &sign); >+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1); >+ kfree(ptr); >+ } > if (ret) > goto err_free_s; > >@@ -282,13 +378,30 @@ static int rsa_check_key_length(unsigned int len) > 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_pub_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_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_key(pkey, key, keylen); >+ ret = rsa_parse_priv_key(pkey, key, keylen); > if (ret) > return ret; > >@@ -299,6 +412,13 @@ static int rsa_setkey(struct crypto_akcipher *tfm, const >void *key, return ret; > } > >+static int rsa_get_len(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 +431,9 @@ static struct akcipher_alg rsa = { > .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, >+ .get_len = rsa_get_len, > .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 @@ void rsa_free_key(struct rsa_key *key) > 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 @@ EXPORT_SYMBOL_GPL(rsa_free_key); > * > * 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 @@ error: > 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_parse_*priv*_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/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h >index a8c8636..f997e2d 100644 >--- a/include/crypto/internal/rsa.h >+++ b/include/crypto/internal/rsa.h >@@ -20,8 +20,11 @@ struct rsa_key { > MPI d; > }; > >-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 rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key, >+ unsigned int key_len); > > void rsa_free_key(struct rsa_key *rsa_key); > #endif > >-- >To unsubscribe from this list: send the line "unsubscribe linux-crypto" in >the body of a message to majordomo@vger.kernel.org >More majordomo info at http://vger.kernel.org/majordomo-info.html Ciao Stephan -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 09/09/2015 09:35 AM, Stephan Mueller wrote: >> + if (sg_is_last(req->dst)) { >> >+ ret = mpi_read_buffer(c, sg_virt(req->dst), dst_len, >> >+ &req->out_len, &sign); >> >+ } else { >> >+ void *ptr = kmalloc(dst_len, GFP_KERNEL); >> >+ >> >+ if (!ptr) >> >+ goto err_free_m; >> >+ >> >+ ret = mpi_read_buffer(c, ptr, dst_len, &req->out_len, &sign); >> >+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1); >> >+ kfree(ptr); > Just a question: this code is present 4 times, can that be put into a separate > inline? > I have put it like this because it is easier to read. All 4 functions use different variable names according to the spec. -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/crypto/Makefile b/crypto/Makefile index 65e91da..d897e0b 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -31,8 +31,16 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o 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 := 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 cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/rsa.c b/crypto/rsa.c index 93feae2..f5b956c 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -13,6 +13,7 @@ #include <crypto/internal/rsa.h> #include <crypto/internal/akcipher.h> #include <crypto/akcipher.h> +#include <crypto/scatterwalk.h> /* * RSAEP function [RFC3447 sec 5.1.1] @@ -80,34 +81,57 @@ static int rsa_enc(struct akcipher_request *req) struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); const struct rsa_key *pkey = rsa_get_key(tfm); MPI m, c = mpi_alloc(0); + int src_len = sg_len(req->src), dst_len = sg_len(req->dst); int ret = 0; int sign; if (!c) return -ENOMEM; - if (unlikely(!pkey->n || !pkey->e)) { + if (unlikely(!pkey->n || !pkey->e || !src_len)) { ret = -EINVAL; goto err_free_c; } - if (req->dst_len < mpi_get_size(pkey->n)) { - req->dst_len = mpi_get_size(pkey->n); + if (dst_len < mpi_get_size(pkey->n)) { + req->out_len = mpi_get_size(pkey->n); ret = -EOVERFLOW; goto err_free_c; } - m = mpi_read_raw_data(req->src, req->src_len); - if (!m) { - ret = -ENOMEM; - goto err_free_c; + ret = -ENOMEM; + if (sg_is_last(req->src)) { + m = mpi_read_raw_data(sg_virt(req->src), src_len); + } else { + void *ptr = kmalloc(src_len, GFP_KERNEL); + + if (!ptr) + goto err_free_c; + + scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0); + m = mpi_read_raw_data(ptr, src_len); + kfree(ptr); } + 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); + if (sg_is_last(req->dst)) { + ret = mpi_read_buffer(c, sg_virt(req->dst), dst_len, + &req->out_len, &sign); + } else { + void *ptr = kmalloc(dst_len, GFP_KERNEL); + + if (!ptr) + goto err_free_m; + + ret = mpi_read_buffer(c, ptr, dst_len, &req->out_len, &sign); + scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1); + kfree(ptr); + } if (ret) goto err_free_m; @@ -128,34 +152,57 @@ static int rsa_dec(struct akcipher_request *req) struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); const struct rsa_key *pkey = rsa_get_key(tfm); MPI c, m = mpi_alloc(0); + int src_len = sg_len(req->src), dst_len = sg_len(req->dst); int ret = 0; int sign; if (!m) return -ENOMEM; - if (unlikely(!pkey->n || !pkey->d)) { + if (unlikely(!pkey->n || !pkey->d || !src_len)) { ret = -EINVAL; goto err_free_m; } - if (req->dst_len < mpi_get_size(pkey->n)) { - req->dst_len = mpi_get_size(pkey->n); + if (dst_len < mpi_get_size(pkey->n)) { + req->out_len = mpi_get_size(pkey->n); ret = -EOVERFLOW; goto err_free_m; } - c = mpi_read_raw_data(req->src, req->src_len); - if (!c) { - ret = -ENOMEM; - goto err_free_m; + ret = -ENOMEM; + if (sg_is_last(req->src)) { + c = mpi_read_raw_data(sg_virt(req->src), src_len); + } else { + void *ptr = kmalloc(src_len, GFP_KERNEL); + + if (!ptr) + goto err_free_m; + + scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0); + c = mpi_read_raw_data(ptr, src_len); + kfree(ptr); } + 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); + if (sg_is_last(req->dst)) { + ret = mpi_read_buffer(m, sg_virt(req->dst), dst_len, + &req->out_len, &sign); + } else { + void *ptr = kmalloc(dst_len, GFP_KERNEL); + + if (!ptr) + goto err_free_c; + + ret = mpi_read_buffer(m, ptr, dst_len, &req->out_len, &sign); + scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1); + kfree(ptr); + } if (ret) goto err_free_c; @@ -176,34 +223,58 @@ static int rsa_sign(struct akcipher_request *req) struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); const struct rsa_key *pkey = rsa_get_key(tfm); MPI m, s = mpi_alloc(0); + int src_len = sg_len(req->src), dst_len = sg_len(req->dst); int ret = 0; int sign; if (!s) return -ENOMEM; - if (unlikely(!pkey->n || !pkey->d)) { + if (unlikely(!pkey->n || !pkey->d || !src_len)) { ret = -EINVAL; goto err_free_s; } - if (req->dst_len < mpi_get_size(pkey->n)) { - req->dst_len = mpi_get_size(pkey->n); + if (dst_len < mpi_get_size(pkey->n)) { + req->out_len = mpi_get_size(pkey->n); ret = -EOVERFLOW; goto err_free_s; } - m = mpi_read_raw_data(req->src, req->src_len); - if (!m) { - ret = -ENOMEM; - goto err_free_s; + ret = -ENOMEM; + if (sg_is_last(req->src)) { + m = mpi_read_raw_data(sg_virt(req->src), src_len); + } else { + void *ptr = kmalloc(src_len, GFP_KERNEL); + + if (!ptr) + goto err_free_s; + + scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0); + m = mpi_read_raw_data(ptr, src_len); + kfree(ptr); + } + 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); + if (sg_is_last(req->dst)) { + ret = mpi_read_buffer(s, sg_virt(req->dst), dst_len, + &req->out_len, &sign); + } else { + void *ptr = kmalloc(dst_len, GFP_KERNEL); + + if (!ptr) + goto err_free_m; + + ret = mpi_read_buffer(s, ptr, dst_len, &req->out_len, &sign); + scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1); + kfree(ptr); + } if (ret) goto err_free_m; @@ -224,24 +295,37 @@ static int rsa_verify(struct akcipher_request *req) struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); const struct rsa_key *pkey = rsa_get_key(tfm); MPI s, m = mpi_alloc(0); + int src_len = sg_len(req->src), dst_len = sg_len(req->dst); int ret = 0; int sign; if (!m) return -ENOMEM; - if (unlikely(!pkey->n || !pkey->e)) { + if (unlikely(!pkey->n || !pkey->e || !src_len)) { ret = -EINVAL; goto err_free_m; } - if (req->dst_len < mpi_get_size(pkey->n)) { - req->dst_len = mpi_get_size(pkey->n); + if (dst_len < mpi_get_size(pkey->n)) { + req->out_len = mpi_get_size(pkey->n); ret = -EOVERFLOW; goto err_free_m; } - s = mpi_read_raw_data(req->src, req->src_len); + ret = -ENOMEM; + if (sg_is_last(req->src)) { + s = mpi_read_raw_data(sg_virt(req->src), src_len); + } else { + void *ptr = kmalloc(src_len, GFP_KERNEL); + + if (!ptr) + goto err_free_m; + + scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0); + s = mpi_read_raw_data(ptr, src_len); + kfree(ptr); + } if (!s) { ret = -ENOMEM; goto err_free_m; @@ -251,7 +335,19 @@ static int rsa_verify(struct akcipher_request *req) if (ret) goto err_free_s; - ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign); + if (sg_is_last(req->dst)) { + ret = mpi_read_buffer(m, sg_virt(req->dst), dst_len, + &req->out_len, &sign); + } else { + void *ptr = kmalloc(dst_len, GFP_KERNEL); + + if (!ptr) + goto err_free_s; + + ret = mpi_read_buffer(m, ptr, dst_len, &req->out_len, &sign); + scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1); + kfree(ptr); + } if (ret) goto err_free_s; @@ -282,13 +378,30 @@ static int rsa_check_key_length(unsigned int len) 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_pub_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_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_key(pkey, key, keylen); + ret = rsa_parse_priv_key(pkey, key, keylen); if (ret) return ret; @@ -299,6 +412,13 @@ static int rsa_setkey(struct crypto_akcipher *tfm, const void *key, return ret; } +static int rsa_get_len(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 +431,9 @@ static struct akcipher_alg rsa = { .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, + .get_len = rsa_get_len, .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 @@ void rsa_free_key(struct rsa_key *key) 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 @@ EXPORT_SYMBOL_GPL(rsa_free_key); * * 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 @@ error: 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/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h index a8c8636..f997e2d 100644 --- a/include/crypto/internal/rsa.h +++ b/include/crypto/internal/rsa.h @@ -20,8 +20,11 @@ struct rsa_key { MPI d; }; -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 rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key, + unsigned int key_len); void rsa_free_key(struct rsa_key *rsa_key); #endif
Rsa updates to reflect the API changes. Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> --- crypto/Makefile | 12 ++- crypto/rsa.c | 188 ++++++++++++++++++++++++++++++++++------- crypto/rsa_helper.c | 42 ++++++++- crypto/rsakey.asn1 | 5 - crypto/rsaprivkey.asn1 | 11 ++ crypto/rsapubkey.asn1 | 4 + include/crypto/internal/rsa.h | 7 +- 7 files changed, 220 insertions(+), 49 deletions(-) delete mode 100644 crypto/rsakey.asn1 create mode 100644 crypto/rsaprivkey.asn1 create mode 100644 crypto/rsapubkey.asn1 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html