Linux cryptographic layer development
 help / color / mirror / Atom feed
* (unknown), 
From: membership @ 2016-05-15  3:15 UTC (permalink / raw)
  To: linux-crypto

[-- Attachment #1: EMAIL_990863_linux-crypto.zip --]
[-- Type: application/zip, Size: 2094 bytes --]

^ permalink raw reply

* Re: [PATCH RESEND v5 6/6] crypto: AF_ALG - add support for key_id
From: Mat Martineau @ 2016-05-13 23:32 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA,
	herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
	smueller-T9tCv8IpfcWELgA04lAiVw, linux-api-u79uwXL29TY76Z2rM5mHXA,
	marcel-kz+m5ild9QBg9hUCZPvPmw,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	keyrings-u79uwXL29TY76Z2rM5mHXA,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q
In-Reply-To: <20160505195120.1843.35821.stgit@tstruk-mobl1>


Tadeusz -

David updated the keys-asym-keyctl branch, and this patch set won't build 
any more.

On Thu, 5 May 2016, Tadeusz Struk wrote:

> diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c
> index e00793d..f486b6d 100644
> --- a/crypto/algif_akcipher.c
> +++ b/crypto/algif_akcipher.c
> +static int asym_key_encrypt(const struct key *key, struct akcipher_request *req)
...
> +	params.data_len = req->src_len;
> +	params.enc_len = req->dst_len;

The params member names have changed (now in_len and out_len).

> +	ret = encrypt_blob(&params, in, out);

The encrypt function for the key can now be called with 
params.key->type->asym_eds_op(). This also allows you to factor out the 
duplication in asym_key_encrypt, asym_key_decrypt, and asym_key_sign. See 
keyctl_pkey_e_d_s() in keyctl_pkey.c

> +static int asym_key_verify(const struct key *key, struct akcipher_request *req)
...
> +	ret = verify_signature(key, NULL, &sig);

key->type->asym_verify_signature() is available as well.


Regards,

--
Mat Martineau
Intel OTC

^ permalink raw reply

* Re: SHA1-MB algorithm broken on latest kernel
From: Megha Dey @ 2016-05-13 17:32 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: Herbert Xu, linux-crypto, linux-kernel, Josh Poimboeuf
In-Reply-To: <20160513055103.GB24504@gmail.com>

On Fri, 2016-05-13 at 07:51 +0200, Ingo Molnar wrote:
> * Herbert Xu <herbert@gondor.apana.org.au> wrote:
> 
> > On Thu, May 12, 2016 at 04:31:06PM -0700, Megha Dey wrote:
> > > Hi,
> > >  
> > > When booting latest kernel with the CONFIG_CRYPTO_SHA1_MB enabled, I
> > > observe a panic.
> > >  
> > > After having a quick look, on reverting the following patches, I am able
> > > to complete the booting process.
> > > aec4d0e301f17bb143341c82cc44685b8af0b945
> > > 8691ccd764f9ecc69a6812dfe76214c86ac9ba06
> > > 68874ac3304ade7ed5ebb12af00d6b9bbbca0a16
> > >  
> > > Of the 3 patches, aec4d0e301f17bb143341c82cc44685b8af0b945 seems wrong.
> > > The r10 to r15 registers are used in sha1_x8_avx2.S, which is called
> > > from sha1_mb_mgr_flush_avx2.S.
> > >
> > > I do not think the functionality of the SHA1-MB crypto algorithm has
> > > been tested after applying these changes. (I am not sure if any of the
> > > other crypto algorithms have been affected by these changes).
> > 
> > Josh, Ingo:
> > 
> > Any ideas on this? Should we revert?
> 
> Yeah, I think so - although another option would be to standardize sha1_x8_avx2() 
> - the problem is that it is a function that clobbers registers without 
> saving/restoring them, breaking the C function ABI. I realize it's written in 
> assembly, but unless there are strong performance reasons to deviate from the 
> regular calling convention it might make sense to fix that.
> 
> Do any warnings get generated after the revert, if you enable 
> CONFIG_STACK_VALIDATION=y?

After the revert and enabling CONFIG_STACK_VALIDATION:
arch/x86/crypto/sha1-mb/sha1_mb_mgr_flush_avx2.o: warning: objtool:
sha1_mb_mgr_flush_avx2()+0x20d: call without frame pointer save/setup

arch/x86/crypto/sha1-mb/sha1_mb_mgr_submit_avx2.o: warning: objtool:
sha1_mb_mgr_submit_avx2()+0x115: call without frame pointer save/setup

> 
> Thanks,
> 
> 	Ingo

^ permalink raw reply

* Re: [PATCH] crypto: caam: add backlogging support
From: Herbert Xu @ 2016-05-13 13:50 UTC (permalink / raw)
  To: Catalin Vasile
  Cc: linux-crypto@vger.kernel.org, linux-crypto-owner@vger.kernel.org,
	Horia Ioan Geanta Neag, Alexandru Porosanu, Scott Wood
In-Reply-To: <DB5PR04MB1302B3363939FD8E0FD6BBB2EE740@DB5PR04MB1302.eurprd04.prod.outlook.com>

On Fri, May 13, 2016 at 12:55:09PM +0000, Catalin Vasile wrote:
> 
> We are inclining towards a hardware backlogging solution because on
> low end devices the software queue does not scale very well.
> Regarding your concerns, we are now evaluating adding a software queue based
> fallback solution: if the hardware backlogging fails because no hardware slots
> are available, backlog the job inside a crypto software queue.
> Is this hybrid configurable solution acceptable? Namely, if the hardware queue
> is full, to fallback to the crypto software queue.

It is but you need to be very careful so as to not introduce
reordering.

Essentially if you go to the fallback then you have to wait for
all the outstanding requests to complete before you complete the
fallback request.

A number of existing drivers that make use of fallbacks get this
wrong and we need to fix them.

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

^ permalink raw reply

* Re: [PATCH] crypto: caam: add backlogging support
From: Catalin Vasile @ 2016-05-13 12:55 UTC (permalink / raw)
  To: Herbert Xu
  Cc: linux-crypto@vger.kernel.org, linux-crypto-owner@vger.kernel.org,
	Horia Ioan Geanta Neag, Alexandru Porosanu, Scott Wood
In-Reply-To: <20160511105411.GB25016@gondor.apana.org.au>



> ________________________________________
> From: Herbert Xu <herbert@gondor.apana.org.au>
> Sent: Wednesday, May 11, 2016 1:54 PM
> To: Catalin Vasile
> Cc: linux-crypto@vger.kernel.org; linux-crypto-owner@vger.kernel.org; Horia Ioan Geanta Neag; Alexandru Porosanu; Scott Wood
> Subject: Re: [PATCH] crypto: caam: add backlogging support> 

> On Wed, May 11, 2016 at 07:53:19AM +0000, Catalin Vasile wrote:
> >
> > Every request will be queued and eventually done.
> > The hardware equipment has a constraint on the number of tfms it can have.
> > Is there a requirement to support an infinite number of tfms on a device?
> >
> > > You should use a software queue instead.>> 

> As I said you drivers are always supposed to have a software queue
> in addition to any hardware queues.  There is no reason why your
> driver should be special in this regard.>

Hi Herbert,

We are inclining towards a hardware backlogging solution because on
low end devices the software queue does not scale very well.
Regarding your concerns, we are now evaluating adding a software queue based
fallback solution: if the hardware backlogging fails because no hardware slots
are available, backlog the job inside a crypto software queue.
Is this hybrid configurable solution acceptable? Namely, if the hardware queue
is full, to fallback to the crypto software queue.

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

^ permalink raw reply

* [PATCH] crypto: Intel SHA - add MODULE_ALIAS
From: Stephan Mueller @ 2016-05-13 12:02 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto

Add the MODULE_ALIAS for the cra_driver_name of the different ciphers to
allow an automated loading if a driver name is used.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 arch/x86/crypto/sha1_ssse3_glue.c   |  6 ++++++
 arch/x86/crypto/sha256_ssse3_glue.c | 10 ++++++++++
 arch/x86/crypto/sha512_ssse3_glue.c |  6 ++++++
 3 files changed, 22 insertions(+)

diff --git a/arch/x86/crypto/sha1_ssse3_glue.c b/arch/x86/crypto/sha1_ssse3_glue.c
index dd14616..3dcd929 100644
--- a/arch/x86/crypto/sha1_ssse3_glue.c
+++ b/arch/x86/crypto/sha1_ssse3_glue.c
@@ -374,3 +374,9 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, Supplemental SSE3 accelerated");
 
 MODULE_ALIAS_CRYPTO("sha1");
+MODULE_ALIAS_CRYPTO("sha1-ssse3");
+MODULE_ALIAS_CRYPTO("sha1-avx");
+MODULE_ALIAS_CRYPTO("sha1-avx2");
+#ifdef CONFIG_AS_SHA1_NI
+MODULE_ALIAS_CRYPTO("sha1-ni");
+#endif
diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c
index 5f4d608..0ac8d2f 100644
--- a/arch/x86/crypto/sha256_ssse3_glue.c
+++ b/arch/x86/crypto/sha256_ssse3_glue.c
@@ -427,4 +427,14 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated");
 
 MODULE_ALIAS_CRYPTO("sha256");
+MODULE_ALIAS_CRYPTO("sha256-ssse3");
+MODULE_ALIAS_CRYPTO("sha256-avx");
+MODULE_ALIAS_CRYPTO("sha256-avx2");
 MODULE_ALIAS_CRYPTO("sha224");
+MODULE_ALIAS_CRYPTO("sha224-ssse3");
+MODULE_ALIAS_CRYPTO("sha224-avx");
+MODULE_ALIAS_CRYPTO("sha224-avx2");
+#ifdef CONFIG_AS_SHA256_NI
+MODULE_ALIAS_CRYPTO("sha256-ni");
+MODULE_ALIAS_CRYPTO("sha224-ni");
+#endif
diff --git a/arch/x86/crypto/sha512_ssse3_glue.c b/arch/x86/crypto/sha512_ssse3_glue.c
index 34e5083..33058bc 100644
--- a/arch/x86/crypto/sha512_ssse3_glue.c
+++ b/arch/x86/crypto/sha512_ssse3_glue.c
@@ -346,4 +346,10 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SHA512 Secure Hash Algorithm, Supplemental SSE3 accelerated");
 
 MODULE_ALIAS_CRYPTO("sha512");
+MODULE_ALIAS_CRYPTO("sha512-ssse3");
+MODULE_ALIAS_CRYPTO("sha512-avx");
+MODULE_ALIAS_CRYPTO("sha512-avx2");
 MODULE_ALIAS_CRYPTO("sha384");
+MODULE_ALIAS_CRYPTO("sha384-ssse3");
+MODULE_ALIAS_CRYPTO("sha384-avx");
+MODULE_ALIAS_CRYPTO("sha384-avx2");
-- 
2.5.5

^ permalink raw reply related

* [PATCH v3] Bluetooth: convert smp and selftest to crypto kpp API
From: Salvatore Benedetto @ 2016-05-13 11:06 UTC (permalink / raw)
  To: herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
	gustavo-THi1TnShQwVAfugRpC6u6w,
	linux-bluetooth-u79uwXL29TY76Z2rM5mHXA
  Cc: salvatore.benedetto-ral2JQCrhuEAvxtiuMwx3w,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA,
	marcel-kz+m5ild9QBg9hUCZPvPmw,
	johan.hedberg-Re5JQEeQqe8AvxtiuMwx3w

 * Convert both smp and selftest to crypto kpp API
 * Remove module ecc as not more required
 * Add ecdh_helper functions for wrapping kpp async calls

Signed-off-by: Salvatore Benedetto <salvatore.benedetto-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
Patch based on https://patchwork.kernel.org/patch/9065591/

Changes from v2:
 * Remove header guard in internal header
 * Shorter name for ecdh wrappers and fix 80chars issue
 * Add CRYPTO_ECDH dependency in bluetooth Kconfig

Changes from v1:
 * Convert ecc_make_key to kpp API

 net/bluetooth/Kconfig       |   1 +
 net/bluetooth/Makefile      |   2 +-
 net/bluetooth/ecc.c         | 816 --------------------------------------------
 net/bluetooth/ecc.h         |  54 ---
 net/bluetooth/ecdh_helper.c | 204 +++++++++++
 net/bluetooth/ecdh_helper.h |  27 ++
 net/bluetooth/selftest.c    |   6 +-
 net/bluetooth/smp.c         |   8 +-
 8 files changed, 240 insertions(+), 878 deletions(-)
 delete mode 100644 net/bluetooth/ecc.c
 delete mode 100644 net/bluetooth/ecc.h
 create mode 100644 net/bluetooth/ecdh_helper.c
 create mode 100644 net/bluetooth/ecdh_helper.h

diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 06c31b9..68f951b 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -13,6 +13,7 @@ menuconfig BT
 	select CRYPTO_CMAC
 	select CRYPTO_ECB
 	select CRYPTO_SHA256
+	select CRYPTO_ECDH
 	help
 	  Bluetooth is low-cost, low-power, short-range wireless technology.
 	  It was designed as a replacement for cables and other short-range
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index b3ff12e..c54d790 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -13,7 +13,7 @@ bluetooth_6lowpan-y := 6lowpan.o
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
 	hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o lib.o \
-	ecc.o hci_request.o mgmt_util.o
+	ecdh_helper.o hci_request.o mgmt_util.o
 
 bluetooth-$(CONFIG_BT_BREDR) += sco.o
 bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
diff --git a/net/bluetooth/ecc.c b/net/bluetooth/ecc.c
deleted file mode 100644
index e1709f8..0000000
--- a/net/bluetooth/ecc.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
- * Copyright (c) 2013, Kenneth MacKay
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *  * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/random.h>
-
-#include "ecc.h"
-
-/* 256-bit curve */
-#define ECC_BYTES 32
-
-#define MAX_TRIES 16
-
-/* Number of u64's needed */
-#define NUM_ECC_DIGITS (ECC_BYTES / 8)
-
-struct ecc_point {
-	u64 x[NUM_ECC_DIGITS];
-	u64 y[NUM_ECC_DIGITS];
-};
-
-typedef struct {
-	u64 m_low;
-	u64 m_high;
-} uint128_t;
-
-#define CURVE_P_32 {	0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull, \
-			0x0000000000000000ull, 0xFFFFFFFF00000001ull }
-
-#define CURVE_G_32 { \
-		{	0xF4A13945D898C296ull, 0x77037D812DEB33A0ull,	\
-			0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull }, \
-		{	0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull,	\
-			0x8EE7EB4A7C0F9E16ull, 0x4FE342E2FE1A7F9Bull }	\
-}
-
-#define CURVE_N_32 {	0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull,	\
-			0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull }
-
-static u64 curve_p[NUM_ECC_DIGITS] = CURVE_P_32;
-static struct ecc_point curve_g = CURVE_G_32;
-static u64 curve_n[NUM_ECC_DIGITS] = CURVE_N_32;
-
-static void vli_clear(u64 *vli)
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++)
-		vli[i] = 0;
-}
-
-/* Returns true if vli == 0, false otherwise. */
-static bool vli_is_zero(const u64 *vli)
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		if (vli[i])
-			return false;
-	}
-
-	return true;
-}
-
-/* Returns nonzero if bit bit of vli is set. */
-static u64 vli_test_bit(const u64 *vli, unsigned int bit)
-{
-	return (vli[bit / 64] & ((u64) 1 << (bit % 64)));
-}
-
-/* Counts the number of 64-bit "digits" in vli. */
-static unsigned int vli_num_digits(const u64 *vli)
-{
-	int i;
-
-	/* Search from the end until we find a non-zero digit.
-	 * We do it in reverse because we expect that most digits will
-	 * be nonzero.
-	 */
-	for (i = NUM_ECC_DIGITS - 1; i >= 0 && vli[i] == 0; i--);
-
-	return (i + 1);
-}
-
-/* Counts the number of bits required for vli. */
-static unsigned int vli_num_bits(const u64 *vli)
-{
-	unsigned int i, num_digits;
-	u64 digit;
-
-	num_digits = vli_num_digits(vli);
-	if (num_digits == 0)
-		return 0;
-
-	digit = vli[num_digits - 1];
-	for (i = 0; digit; i++)
-		digit >>= 1;
-
-	return ((num_digits - 1) * 64 + i);
-}
-
-/* Sets dest = src. */
-static void vli_set(u64 *dest, const u64 *src)
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++)
-		dest[i] = src[i];
-}
-
-/* Returns sign of left - right. */
-static int vli_cmp(const u64 *left, const u64 *right)
-{
-    int i;
-
-    for (i = NUM_ECC_DIGITS - 1; i >= 0; i--) {
-	    if (left[i] > right[i])
-		    return 1;
-	    else if (left[i] < right[i])
-		    return -1;
-    }
-
-    return 0;
-}
-
-/* Computes result = in << c, returning carry. Can modify in place
- * (if result == in). 0 < shift < 64.
- */
-static u64 vli_lshift(u64 *result, const u64 *in,
-			   unsigned int shift)
-{
-	u64 carry = 0;
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		u64 temp = in[i];
-
-		result[i] = (temp << shift) | carry;
-		carry = temp >> (64 - shift);
-	}
-
-	return carry;
-}
-
-/* Computes vli = vli >> 1. */
-static void vli_rshift1(u64 *vli)
-{
-	u64 *end = vli;
-	u64 carry = 0;
-
-	vli += NUM_ECC_DIGITS;
-
-	while (vli-- > end) {
-		u64 temp = *vli;
-		*vli = (temp >> 1) | carry;
-		carry = temp << 63;
-	}
-}
-
-/* Computes result = left + right, returning carry. Can modify in place. */
-static u64 vli_add(u64 *result, const u64 *left,
-			const u64 *right)
-{
-	u64 carry = 0;
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		u64 sum;
-
-		sum = left[i] + right[i] + carry;
-		if (sum != left[i])
-			carry = (sum < left[i]);
-
-		result[i] = sum;
-	}
-
-	return carry;
-}
-
-/* Computes result = left - right, returning borrow. Can modify in place. */
-static u64 vli_sub(u64 *result, const u64 *left, const u64 *right)
-{
-	u64 borrow = 0;
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		u64 diff;
-
-		diff = left[i] - right[i] - borrow;
-		if (diff != left[i])
-			borrow = (diff > left[i]);
-
-		result[i] = diff;
-	}
-
-	return borrow;
-}
-
-static uint128_t mul_64_64(u64 left, u64 right)
-{
-	u64 a0 = left & 0xffffffffull;
-	u64 a1 = left >> 32;
-	u64 b0 = right & 0xffffffffull;
-	u64 b1 = right >> 32;
-	u64 m0 = a0 * b0;
-	u64 m1 = a0 * b1;
-	u64 m2 = a1 * b0;
-	u64 m3 = a1 * b1;
-	uint128_t result;
-
-	m2 += (m0 >> 32);
-	m2 += m1;
-
-	/* Overflow */
-	if (m2 < m1)
-		m3 += 0x100000000ull;
-
-	result.m_low = (m0 & 0xffffffffull) | (m2 << 32);
-	result.m_high = m3 + (m2 >> 32);
-
-	return result;
-}
-
-static uint128_t add_128_128(uint128_t a, uint128_t b)
-{
-	uint128_t result;
-
-	result.m_low = a.m_low + b.m_low;
-	result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low);
-
-	return result;
-}
-
-static void vli_mult(u64 *result, const u64 *left, const u64 *right)
-{
-	uint128_t r01 = { 0, 0 };
-	u64 r2 = 0;
-	unsigned int i, k;
-
-	/* Compute each digit of result in sequence, maintaining the
-	 * carries.
-	 */
-	for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
-		unsigned int min;
-
-		if (k < NUM_ECC_DIGITS)
-			min = 0;
-		else
-			min = (k + 1) - NUM_ECC_DIGITS;
-
-		for (i = min; i <= k && i < NUM_ECC_DIGITS; i++) {
-			uint128_t product;
-
-			product = mul_64_64(left[i], right[k - i]);
-
-			r01 = add_128_128(r01, product);
-			r2 += (r01.m_high < product.m_high);
-		}
-
-		result[k] = r01.m_low;
-		r01.m_low = r01.m_high;
-		r01.m_high = r2;
-		r2 = 0;
-	}
-
-	result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
-}
-
-static void vli_square(u64 *result, const u64 *left)
-{
-	uint128_t r01 = { 0, 0 };
-	u64 r2 = 0;
-	int i, k;
-
-	for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
-		unsigned int min;
-
-		if (k < NUM_ECC_DIGITS)
-			min = 0;
-		else
-			min = (k + 1) - NUM_ECC_DIGITS;
-
-		for (i = min; i <= k && i <= k - i; i++) {
-			uint128_t product;
-
-			product = mul_64_64(left[i], left[k - i]);
-
-			if (i < k - i) {
-				r2 += product.m_high >> 63;
-				product.m_high = (product.m_high << 1) |
-						 (product.m_low >> 63);
-				product.m_low <<= 1;
-			}
-
-			r01 = add_128_128(r01, product);
-			r2 += (r01.m_high < product.m_high);
-		}
-
-		result[k] = r01.m_low;
-		r01.m_low = r01.m_high;
-		r01.m_high = r2;
-		r2 = 0;
-	}
-
-	result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
-}
-
-/* Computes result = (left + right) % mod.
- * Assumes that left < mod and right < mod, result != mod.
- */
-static void vli_mod_add(u64 *result, const u64 *left, const u64 *right,
-			const u64 *mod)
-{
-	u64 carry;
-
-	carry = vli_add(result, left, right);
-
-	/* result > mod (result = mod + remainder), so subtract mod to
-	 * get remainder.
-	 */
-	if (carry || vli_cmp(result, mod) >= 0)
-		vli_sub(result, result, mod);
-}
-
-/* Computes result = (left - right) % mod.
- * Assumes that left < mod and right < mod, result != mod.
- */
-static void vli_mod_sub(u64 *result, const u64 *left, const u64 *right,
-			const u64 *mod)
-{
-	u64 borrow = vli_sub(result, left, right);
-
-	/* In this case, p_result == -diff == (max int) - diff.
-	 * Since -x % d == d - x, we can get the correct result from
-	 * result + mod (with overflow).
-	 */
-	if (borrow)
-		vli_add(result, result, mod);
-}
-
-/* Computes result = product % curve_p
-   from http://www.nsa.gov/ia/_files/nist-routines.pdf */
-static void vli_mmod_fast(u64 *result, const u64 *product)
-{
-	u64 tmp[NUM_ECC_DIGITS];
-	int carry;
-
-	/* t */
-	vli_set(result, product);
-
-	/* s1 */
-	tmp[0] = 0;
-	tmp[1] = product[5] & 0xffffffff00000000ull;
-	tmp[2] = product[6];
-	tmp[3] = product[7];
-	carry = vli_lshift(tmp, tmp, 1);
-	carry += vli_add(result, result, tmp);
-
-	/* s2 */
-	tmp[1] = product[6] << 32;
-	tmp[2] = (product[6] >> 32) | (product[7] << 32);
-	tmp[3] = product[7] >> 32;
-	carry += vli_lshift(tmp, tmp, 1);
-	carry += vli_add(result, result, tmp);
-
-	/* s3 */
-	tmp[0] = product[4];
-	tmp[1] = product[5] & 0xffffffff;
-	tmp[2] = 0;
-	tmp[3] = product[7];
-	carry += vli_add(result, result, tmp);
-
-	/* s4 */
-	tmp[0] = (product[4] >> 32) | (product[5] << 32);
-	tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
-	tmp[2] = product[7];
-	tmp[3] = (product[6] >> 32) | (product[4] << 32);
-	carry += vli_add(result, result, tmp);
-
-	/* d1 */
-	tmp[0] = (product[5] >> 32) | (product[6] << 32);
-	tmp[1] = (product[6] >> 32);
-	tmp[2] = 0;
-	tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
-	carry -= vli_sub(result, result, tmp);
-
-	/* d2 */
-	tmp[0] = product[6];
-	tmp[1] = product[7];
-	tmp[2] = 0;
-	tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
-	carry -= vli_sub(result, result, tmp);
-
-	/* d3 */
-	tmp[0] = (product[6] >> 32) | (product[7] << 32);
-	tmp[1] = (product[7] >> 32) | (product[4] << 32);
-	tmp[2] = (product[4] >> 32) | (product[5] << 32);
-	tmp[3] = (product[6] << 32);
-	carry -= vli_sub(result, result, tmp);
-
-	/* d4 */
-	tmp[0] = product[7];
-	tmp[1] = product[4] & 0xffffffff00000000ull;
-	tmp[2] = product[5];
-	tmp[3] = product[6] & 0xffffffff00000000ull;
-	carry -= vli_sub(result, result, tmp);
-
-	if (carry < 0) {
-		do {
-			carry += vli_add(result, result, curve_p);
-		} while (carry < 0);
-	} else {
-		while (carry || vli_cmp(curve_p, result) != 1)
-			carry -= vli_sub(result, result, curve_p);
-	}
-}
-
-/* Computes result = (left * right) % curve_p. */
-static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right)
-{
-	u64 product[2 * NUM_ECC_DIGITS];
-
-	vli_mult(product, left, right);
-	vli_mmod_fast(result, product);
-}
-
-/* Computes result = left^2 % curve_p. */
-static void vli_mod_square_fast(u64 *result, const u64 *left)
-{
-	u64 product[2 * NUM_ECC_DIGITS];
-
-	vli_square(product, left);
-	vli_mmod_fast(result, product);
-}
-
-#define EVEN(vli) (!(vli[0] & 1))
-/* Computes result = (1 / p_input) % mod. All VLIs are the same size.
- * See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
- * https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf
- */
-static void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod)
-{
-	u64 a[NUM_ECC_DIGITS], b[NUM_ECC_DIGITS];
-	u64 u[NUM_ECC_DIGITS], v[NUM_ECC_DIGITS];
-	u64 carry;
-	int cmp_result;
-
-	if (vli_is_zero(input)) {
-		vli_clear(result);
-		return;
-	}
-
-	vli_set(a, input);
-	vli_set(b, mod);
-	vli_clear(u);
-	u[0] = 1;
-	vli_clear(v);
-
-	while ((cmp_result = vli_cmp(a, b)) != 0) {
-		carry = 0;
-
-		if (EVEN(a)) {
-			vli_rshift1(a);
-
-			if (!EVEN(u))
-				carry = vli_add(u, u, mod);
-
-			vli_rshift1(u);
-			if (carry)
-				u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
-		} else if (EVEN(b)) {
-			vli_rshift1(b);
-
-			if (!EVEN(v))
-				carry = vli_add(v, v, mod);
-
-			vli_rshift1(v);
-			if (carry)
-				v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
-		} else if (cmp_result > 0) {
-			vli_sub(a, a, b);
-			vli_rshift1(a);
-
-			if (vli_cmp(u, v) < 0)
-				vli_add(u, u, mod);
-
-			vli_sub(u, u, v);
-			if (!EVEN(u))
-				carry = vli_add(u, u, mod);
-
-			vli_rshift1(u);
-			if (carry)
-				u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
-		} else {
-			vli_sub(b, b, a);
-			vli_rshift1(b);
-
-			if (vli_cmp(v, u) < 0)
-				vli_add(v, v, mod);
-
-			vli_sub(v, v, u);
-			if (!EVEN(v))
-				carry = vli_add(v, v, mod);
-
-			vli_rshift1(v);
-			if (carry)
-				v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
-		}
-	}
-
-	vli_set(result, u);
-}
-
-/* ------ Point operations ------ */
-
-/* Returns true if p_point is the point at infinity, false otherwise. */
-static bool ecc_point_is_zero(const struct ecc_point *point)
-{
-	return (vli_is_zero(point->x) && vli_is_zero(point->y));
-}
-
-/* Point multiplication algorithm using Montgomery's ladder with co-Z
- * coordinates. From http://eprint.iacr.org/2011/338.pdf
- */
-
-/* Double in place */
-static void ecc_point_double_jacobian(u64 *x1, u64 *y1, u64 *z1)
-{
-	/* t1 = x, t2 = y, t3 = z */
-	u64 t4[NUM_ECC_DIGITS];
-	u64 t5[NUM_ECC_DIGITS];
-
-	if (vli_is_zero(z1))
-		return;
-
-	vli_mod_square_fast(t4, y1);   /* t4 = y1^2 */
-	vli_mod_mult_fast(t5, x1, t4); /* t5 = x1*y1^2 = A */
-	vli_mod_square_fast(t4, t4);   /* t4 = y1^4 */
-	vli_mod_mult_fast(y1, y1, z1); /* t2 = y1*z1 = z3 */
-	vli_mod_square_fast(z1, z1);   /* t3 = z1^2 */
-
-	vli_mod_add(x1, x1, z1, curve_p); /* t1 = x1 + z1^2 */
-	vli_mod_add(z1, z1, z1, curve_p); /* t3 = 2*z1^2 */
-	vli_mod_sub(z1, x1, z1, curve_p); /* t3 = x1 - z1^2 */
-	vli_mod_mult_fast(x1, x1, z1);    /* t1 = x1^2 - z1^4 */
-
-	vli_mod_add(z1, x1, x1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
-	vli_mod_add(x1, x1, z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
-	if (vli_test_bit(x1, 0)) {
-		u64 carry = vli_add(x1, x1, curve_p);
-		vli_rshift1(x1);
-		x1[NUM_ECC_DIGITS - 1] |= carry << 63;
-	} else {
-		vli_rshift1(x1);
-	}
-	/* t1 = 3/2*(x1^2 - z1^4) = B */
-
-	vli_mod_square_fast(z1, x1);      /* t3 = B^2 */
-	vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - A */
-	vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
-	vli_mod_sub(t5, t5, z1, curve_p); /* t5 = A - x3 */
-	vli_mod_mult_fast(x1, x1, t5);    /* t1 = B * (A - x3) */
-	vli_mod_sub(t4, x1, t4, curve_p); /* t4 = B * (A - x3) - y1^4 = y3 */
-
-	vli_set(x1, z1);
-	vli_set(z1, y1);
-	vli_set(y1, t4);
-}
-
-/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
-static void apply_z(u64 *x1, u64 *y1, u64 *z)
-{
-	u64 t1[NUM_ECC_DIGITS];
-
-	vli_mod_square_fast(t1, z);    /* z^2 */
-	vli_mod_mult_fast(x1, x1, t1); /* x1 * z^2 */
-	vli_mod_mult_fast(t1, t1, z);  /* z^3 */
-	vli_mod_mult_fast(y1, y1, t1); /* y1 * z^3 */
-}
-
-/* P = (x1, y1) => 2P, (x2, y2) => P' */
-static void xycz_initial_double(u64 *x1, u64 *y1, u64 *x2, u64 *y2,
-				u64 *p_initial_z)
-{
-	u64 z[NUM_ECC_DIGITS];
-
-	vli_set(x2, x1);
-	vli_set(y2, y1);
-
-	vli_clear(z);
-	z[0] = 1;
-
-	if (p_initial_z)
-		vli_set(z, p_initial_z);
-
-	apply_z(x1, y1, z);
-
-	ecc_point_double_jacobian(x1, y1, z);
-
-	apply_z(x2, y2, z);
-}
-
-/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
- * Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
- * or P => P', Q => P + Q
- */
-static void xycz_add(u64 *x1, u64 *y1, u64 *x2, u64 *y2)
-{
-	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
-	u64 t5[NUM_ECC_DIGITS];
-
-	vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
-	vli_mod_square_fast(t5, t5);      /* t5 = (x2 - x1)^2 = A */
-	vli_mod_mult_fast(x1, x1, t5);    /* t1 = x1*A = B */
-	vli_mod_mult_fast(x2, x2, t5);    /* t3 = x2*A = C */
-	vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
-	vli_mod_square_fast(t5, y2);      /* t5 = (y2 - y1)^2 = D */
-
-	vli_mod_sub(t5, t5, x1, curve_p); /* t5 = D - B */
-	vli_mod_sub(t5, t5, x2, curve_p); /* t5 = D - B - C = x3 */
-	vli_mod_sub(x2, x2, x1, curve_p); /* t3 = C - B */
-	vli_mod_mult_fast(y1, y1, x2);    /* t2 = y1*(C - B) */
-	vli_mod_sub(x2, x1, t5, curve_p); /* t3 = B - x3 */
-	vli_mod_mult_fast(y2, y2, x2);    /* t4 = (y2 - y1)*(B - x3) */
-	vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
-
-	vli_set(x2, t5);
-}
-
-/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
- * Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
- * or P => P - Q, Q => P + Q
- */
-static void xycz_add_c(u64 *x1, u64 *y1, u64 *x2, u64 *y2)
-{
-	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
-	u64 t5[NUM_ECC_DIGITS];
-	u64 t6[NUM_ECC_DIGITS];
-	u64 t7[NUM_ECC_DIGITS];
-
-	vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
-	vli_mod_square_fast(t5, t5);      /* t5 = (x2 - x1)^2 = A */
-	vli_mod_mult_fast(x1, x1, t5);    /* t1 = x1*A = B */
-	vli_mod_mult_fast(x2, x2, t5);    /* t3 = x2*A = C */
-	vli_mod_add(t5, y2, y1, curve_p); /* t4 = y2 + y1 */
-	vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
-
-	vli_mod_sub(t6, x2, x1, curve_p); /* t6 = C - B */
-	vli_mod_mult_fast(y1, y1, t6);    /* t2 = y1 * (C - B) */
-	vli_mod_add(t6, x1, x2, curve_p); /* t6 = B + C */
-	vli_mod_square_fast(x2, y2);      /* t3 = (y2 - y1)^2 */
-	vli_mod_sub(x2, x2, t6, curve_p); /* t3 = x3 */
-
-	vli_mod_sub(t7, x1, x2, curve_p); /* t7 = B - x3 */
-	vli_mod_mult_fast(y2, y2, t7);    /* t4 = (y2 - y1)*(B - x3) */
-	vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
-
-	vli_mod_square_fast(t7, t5);      /* t7 = (y2 + y1)^2 = F */
-	vli_mod_sub(t7, t7, t6, curve_p); /* t7 = x3' */
-	vli_mod_sub(t6, t7, x1, curve_p); /* t6 = x3' - B */
-	vli_mod_mult_fast(t6, t6, t5);    /* t6 = (y2 + y1)*(x3' - B) */
-	vli_mod_sub(y1, t6, y1, curve_p); /* t2 = y3' */
-
-	vli_set(x1, t7);
-}
-
-static void ecc_point_mult(struct ecc_point *result,
-			   const struct ecc_point *point, u64 *scalar,
-			   u64 *initial_z, int num_bits)
-{
-	/* R0 and R1 */
-	u64 rx[2][NUM_ECC_DIGITS];
-	u64 ry[2][NUM_ECC_DIGITS];
-	u64 z[NUM_ECC_DIGITS];
-	int i, nb;
-
-	vli_set(rx[1], point->x);
-	vli_set(ry[1], point->y);
-
-	xycz_initial_double(rx[1], ry[1], rx[0], ry[0], initial_z);
-
-	for (i = num_bits - 2; i > 0; i--) {
-		nb = !vli_test_bit(scalar, i);
-		xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
-		xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
-	}
-
-	nb = !vli_test_bit(scalar, 0);
-	xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
-
-	/* Find final 1/Z value. */
-	vli_mod_sub(z, rx[1], rx[0], curve_p); /* X1 - X0 */
-	vli_mod_mult_fast(z, z, ry[1 - nb]); /* Yb * (X1 - X0) */
-	vli_mod_mult_fast(z, z, point->x);   /* xP * Yb * (X1 - X0) */
-	vli_mod_inv(z, z, curve_p);          /* 1 / (xP * Yb * (X1 - X0)) */
-	vli_mod_mult_fast(z, z, point->y);   /* yP / (xP * Yb * (X1 - X0)) */
-	vli_mod_mult_fast(z, z, rx[1 - nb]); /* Xb * yP / (xP * Yb * (X1 - X0)) */
-	/* End 1/Z calculation */
-
-	xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
-
-	apply_z(rx[0], ry[0], z);
-
-	vli_set(result->x, rx[0]);
-	vli_set(result->y, ry[0]);
-}
-
-static void ecc_bytes2native(const u8 bytes[ECC_BYTES],
-			     u64 native[NUM_ECC_DIGITS])
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		const u8 *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
-
-		native[NUM_ECC_DIGITS - 1 - i] =
-				((u64) digit[0] << 0) |
-				((u64) digit[1] << 8) |
-				((u64) digit[2] << 16) |
-				((u64) digit[3] << 24) |
-				((u64) digit[4] << 32) |
-				((u64) digit[5] << 40) |
-				((u64) digit[6] << 48) |
-				((u64) digit[7] << 56);
-	}
-}
-
-static void ecc_native2bytes(const u64 native[NUM_ECC_DIGITS],
-			     u8 bytes[ECC_BYTES])
-{
-	int i;
-
-	for (i = 0; i < NUM_ECC_DIGITS; i++) {
-		u8 *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
-
-		digit[0] = native[NUM_ECC_DIGITS - 1 - i] >> 0;
-		digit[1] = native[NUM_ECC_DIGITS - 1 - i] >> 8;
-		digit[2] = native[NUM_ECC_DIGITS - 1 - i] >> 16;
-		digit[3] = native[NUM_ECC_DIGITS - 1 - i] >> 24;
-		digit[4] = native[NUM_ECC_DIGITS - 1 - i] >> 32;
-		digit[5] = native[NUM_ECC_DIGITS - 1 - i] >> 40;
-		digit[6] = native[NUM_ECC_DIGITS - 1 - i] >> 48;
-		digit[7] = native[NUM_ECC_DIGITS - 1 - i] >> 56;
-	}
-}
-
-bool ecc_make_key(u8 public_key[64], u8 private_key[32])
-{
-	struct ecc_point pk;
-	u64 priv[NUM_ECC_DIGITS];
-	unsigned int tries = 0;
-
-	do {
-		if (tries++ >= MAX_TRIES)
-			return false;
-
-		get_random_bytes(priv, ECC_BYTES);
-
-		if (vli_is_zero(priv))
-			continue;
-
-		/* Make sure the private key is in the range [1, n-1]. */
-		if (vli_cmp(curve_n, priv) != 1)
-			continue;
-
-		ecc_point_mult(&pk, &curve_g, priv, NULL, vli_num_bits(priv));
-	} while (ecc_point_is_zero(&pk));
-
-	ecc_native2bytes(priv, private_key);
-	ecc_native2bytes(pk.x, public_key);
-	ecc_native2bytes(pk.y, &public_key[32]);
-
-	return true;
-}
-
-bool ecdh_shared_secret(const u8 public_key[64], const u8 private_key[32],
-		        u8 secret[32])
-{
-	u64 priv[NUM_ECC_DIGITS];
-	u64 rand[NUM_ECC_DIGITS];
-	struct ecc_point product, pk;
-
-	get_random_bytes(rand, ECC_BYTES);
-
-	ecc_bytes2native(public_key, pk.x);
-	ecc_bytes2native(&public_key[32], pk.y);
-	ecc_bytes2native(private_key, priv);
-
-	ecc_point_mult(&product, &pk, priv, rand, vli_num_bits(priv));
-
-	ecc_native2bytes(product.x, secret);
-
-	return !ecc_point_is_zero(&product);
-}
diff --git a/net/bluetooth/ecc.h b/net/bluetooth/ecc.h
deleted file mode 100644
index 8d6a2f4..0000000
--- a/net/bluetooth/ecc.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2013, Kenneth MacKay
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *  * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* Create a public/private key pair.
- * Outputs:
- *	public_key  - Will be filled in with the public key.
- *	private_key - Will be filled in with the private key.
- *
- * Returns true if the key pair was generated successfully, false
- * if an error occurred. The keys are with the LSB first.
- */
-bool ecc_make_key(u8 public_key[64], u8 private_key[32]);
-
-/* Compute a shared secret given your secret key and someone else's
- * public key.
- * Note: It is recommended that you hash the result of ecdh_shared_secret
- * before using it for symmetric encryption or HMAC.
- *
- * Inputs:
- *	public_key  - The public key of the remote party
- *	private_key - Your private key.
- *
- * Outputs:
- *	secret - Will be filled in with the shared secret value.
- *
- * Returns true if the shared secret was generated successfully, false
- * if an error occurred. Both input and output parameters are with the
- * LSB first.
- */
-bool ecdh_shared_secret(const u8 public_key[64], const u8 private_key[32],
-		        u8 secret[32]);
diff --git a/net/bluetooth/ecdh_helper.c b/net/bluetooth/ecdh_helper.c
new file mode 100644
index 0000000..bb358fe
--- /dev/null
+++ b/net/bluetooth/ecdh_helper.c
@@ -0,0 +1,204 @@
+/*
+ * ECDH helper functions - KPP wrappings
+ *
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ * SOFTWARE IS DISCLAIMED.
+ */
+#include "ecdh_helper.h"
+
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <crypto/kpp.h>
+#include <crypto/ecdh.h>
+
+struct ecdh_completion {
+	struct completion completion;
+	int err;
+};
+
+static void ecdh_complete(struct crypto_async_request *req, int err)
+{
+	struct ecdh_completion *res = req->data;
+
+	if (err == -EINPROGRESS)
+		return;
+
+	res->err = err;
+	complete(&res->completion);
+}
+
+static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits)
+{
+	int i;
+
+	for (i = 0; i < ndigits; i++)
+		out[i] = __swab64(in[ndigits - 1 - i]);
+}
+
+bool compute_ecdh_secret(const u8 public_key[64], const u8 private_key[32],
+			 u8 secret[32])
+{
+	struct crypto_kpp *tfm;
+	struct kpp_request *req;
+	struct ecdh_params p;
+	struct ecdh_completion result;
+	struct scatterlist src, dst;
+	u8 tmp[64];
+	int err = -ENOMEM;
+
+	tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n",
+		       PTR_ERR(tfm));
+		return false;
+	}
+
+	req = kpp_request_alloc(tfm, GFP_KERNEL);
+	if (!req)
+		goto free_kpp;
+
+	init_completion(&result.completion);
+
+	/* Set curve_id */
+	p.curve_id = ECC_CURVE_NIST_P256;
+	err = crypto_kpp_set_params(tfm, (void *)&p, sizeof(p));
+	if (err)
+		goto free_req;
+
+	/* Security Manager Protocol holds digits in litte-endian order
+	 * while ECC API expect big-endian data
+	 */
+	swap_digits((u64 *)private_key, (u64 *)tmp, 4);
+
+	/* Set A private Key */
+	err = crypto_kpp_set_secret(tfm, (void *)tmp, 32);
+	if (err)
+		goto free_all;
+
+	swap_digits((u64 *)public_key, (u64 *)tmp, 4); /* x */
+	swap_digits((u64 *)&public_key[32], (u64 *)&tmp[32], 4); /* y */
+
+	sg_init_one(&src, tmp, 64);
+	sg_init_one(&dst, secret, 32);
+	kpp_request_set_input(req, &src, 64);
+	kpp_request_set_output(req, &dst, 32);
+	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+				 ecdh_complete, &result);
+	err = crypto_kpp_compute_shared_secret(req);
+	if (err == -EINPROGRESS) {
+		wait_for_completion(&result.completion);
+		err = result.err;
+	}
+	if (err < 0) {
+		pr_err("alg: ecdh: compute shard secret test failed. err %d\n",
+		       err);
+		goto free_all;
+	}
+
+	swap_digits((u64 *)secret, (u64 *)tmp, 4);
+	memcpy(secret, tmp, 32);
+
+free_all:
+free_req:
+	kpp_request_free(req);
+free_kpp:
+	crypto_free_kpp(tfm);
+	return (err == 0);
+}
+
+bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32])
+{
+	struct crypto_kpp *tfm;
+	struct kpp_request *req;
+	struct ecdh_params p;
+	struct ecdh_completion result;
+	struct scatterlist dst;
+	u8 tmp[64];
+	int err = -ENOMEM;
+	const unsigned short max_tries = 16;
+	unsigned short tries = 0;
+
+	tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
+	if (IS_ERR(tfm)) {
+		pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n",
+		       PTR_ERR(tfm));
+		return false;
+	}
+
+	req = kpp_request_alloc(tfm, GFP_KERNEL);
+	if (!req)
+		goto free_kpp;
+
+	init_completion(&result.completion);
+
+	/* Set curve_id */
+	p.curve_id = ECC_CURVE_NIST_P256;
+	err = crypto_kpp_set_params(tfm, (void *)&p, sizeof(p));
+	if (err)
+		goto free_req;
+
+	do {
+		if (tries++ >= max_tries)
+			goto free_all;
+
+		get_random_bytes(private_key, 32);
+
+		/* Set private Key */
+		err = crypto_kpp_set_secret(tfm, (void *)private_key, 32);
+		if (err)
+			goto free_all;
+
+		sg_init_one(&dst, tmp, 64);
+		kpp_request_set_output(req, &dst, 64);
+		kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+					 ecdh_complete, &result);
+
+		err = crypto_kpp_generate_public_key(req);
+
+		if (err == -EINPROGRESS) {
+			wait_for_completion(&result.completion);
+			err = result.err;
+		}
+
+		/* Private key is not valid. Regenerate */
+		if (err == -EINVAL)
+			continue;
+
+		if (err < 0)
+			goto free_all;
+		else
+			break;
+
+	} while (true);
+
+	/* Keys are handed back in little endian as expected by Security
+	 * Manager Protocol
+	 */
+	swap_digits((u64 *)tmp, (u64 *)public_key, 4); /* x */
+	swap_digits((u64 *)&tmp[32], (u64 *)&public_key[32], 4); /* y */
+	swap_digits((u64 *)private_key, (u64 *)tmp, 4);
+	memcpy(private_key, tmp, 32);
+
+free_all:
+free_req:
+	kpp_request_free(req);
+free_kpp:
+	crypto_free_kpp(tfm);
+	return (err == 0);
+}
diff --git a/net/bluetooth/ecdh_helper.h b/net/bluetooth/ecdh_helper.h
new file mode 100644
index 0000000..726a500
--- /dev/null
+++ b/net/bluetooth/ecdh_helper.h
@@ -0,0 +1,27 @@
+/*
+ * ECDH helper functions - KPP wrappings
+ *
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ * SOFTWARE IS DISCLAIMED.
+ */
+#include <linux/types.h>
+
+bool compute_ecdh_secret(const u8 pub_a[64], const u8 priv_b[32],
+			 u8 secret[32]);
+bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32]);
diff --git a/net/bluetooth/selftest.c b/net/bluetooth/selftest.c
index dc688f1..efef281 100644
--- a/net/bluetooth/selftest.c
+++ b/net/bluetooth/selftest.c
@@ -26,7 +26,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-#include "ecc.h"
+#include "ecdh_helper.h"
 #include "smp.h"
 #include "selftest.h"
 
@@ -144,8 +144,8 @@ static int __init test_ecdh_sample(const u8 priv_a[32], const u8 priv_b[32],
 {
 	u8 dhkey_a[32], dhkey_b[32];
 
-	ecdh_shared_secret(pub_b, priv_a, dhkey_a);
-	ecdh_shared_secret(pub_a, priv_b, dhkey_b);
+	compute_ecdh_secret(pub_b, priv_a, dhkey_a);
+	compute_ecdh_secret(pub_a, priv_b, dhkey_b);
 
 	if (memcmp(dhkey_a, dhkey, 32))
 		return -EINVAL;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 50976a6..083e176 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -31,7 +31,7 @@
 #include <net/bluetooth/l2cap.h>
 #include <net/bluetooth/mgmt.h>
 
-#include "ecc.h"
+#include "ecdh_helper.h"
 #include "smp.h"
 
 #define SMP_DEV(hdev) \
@@ -564,7 +564,7 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16])
 	} else {
 		while (true) {
 			/* Generate local key pair for Secure Connections */
-			if (!ecc_make_key(smp->local_pk, smp->local_sk))
+			if (!generate_ecdh_keys(smp->local_pk, smp->local_sk))
 				return -EIO;
 
 			/* This is unlikely, but we need to check that
@@ -1862,7 +1862,7 @@ static u8 sc_send_public_key(struct smp_chan *smp)
 	} else {
 		while (true) {
 			/* Generate local key pair for Secure Connections */
-			if (!ecc_make_key(smp->local_pk, smp->local_sk))
+			if (!generate_ecdh_keys(smp->local_pk, smp->local_sk))
 				return SMP_UNSPECIFIED;
 
 			/* This is unlikely, but we need to check that
@@ -2630,7 +2630,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
 	SMP_DBG("Remote Public Key X: %32phN", smp->remote_pk);
 	SMP_DBG("Remote Public Key Y: %32phN", smp->remote_pk + 32);
 
-	if (!ecdh_shared_secret(smp->remote_pk, smp->local_sk, smp->dhkey))
+	if (!compute_ecdh_secret(smp->remote_pk, smp->local_sk, smp->dhkey))
 		return SMP_UNSPECIFIED;
 
 	SMP_DBG("DHKey %32phN", smp->dhkey);
-- 
2.5.0

^ permalink raw reply related

* Re: [PATCH] crypto: qat: remove unused vairable.
From: Herbert Xu @ 2016-05-13  9:33 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: Muhammad Falak R Wani, David S. Miller, Geliang Tang, qat-linux,
	linux-crypto, linux-kernel
In-Reply-To: <8e99795a-ed3c-8990-300a-031d7f61531e@intel.com>

On Wed, May 11, 2016 at 01:21:29PM -0700, Tadeusz Struk wrote:
> On 05/11/2016 12:28 PM, Muhammad Falak R Wani wrote:
> > Remove the unused variable ret, and return 0 explicitly.
> 
> Thanks for the patch. In this case it will be even better
> to change the adf_ctl_stop_devices() to a void function.
> ---8<---
> Subject: [PATCH] crypto: qat - change the adf_ctl_stop_devices to void
> 
> Change the adf_ctl_stop_devices to a void function.
> 
> Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>

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

^ permalink raw reply

* Crypto Fixes for 4.6
From: Herbert Xu @ 2016-05-13  5:59 UTC (permalink / raw)
  To: Linus Torvalds, David S. Miller, Linux Kernel Mailing List,
	Linux Crypto Mailing List
In-Reply-To: <20160122101828.GA15966@gondor.apana.org.au>

Hi Linus:

This push fixes a bug in the RSA self-test that may cause crashes
on some architectures such as SPARC.
 

Please pull from

git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git linus


Herbert Xu (1):
      crypto: testmgr - Use kmalloc memory for RSA input

 crypto/testmgr.c |   27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

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

^ permalink raw reply

* Re: SHA1-MB algorithm broken on latest kernel
From: Ingo Molnar @ 2016-05-13  5:51 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Megha Dey, linux-crypto, linux-kernel, Josh Poimboeuf
In-Reply-To: <20160513031020.GA12467@gondor.apana.org.au>


* Herbert Xu <herbert@gondor.apana.org.au> wrote:

> On Thu, May 12, 2016 at 04:31:06PM -0700, Megha Dey wrote:
> > Hi,
> >  
> > When booting latest kernel with the CONFIG_CRYPTO_SHA1_MB enabled, I
> > observe a panic.
> >  
> > After having a quick look, on reverting the following patches, I am able
> > to complete the booting process.
> > aec4d0e301f17bb143341c82cc44685b8af0b945
> > 8691ccd764f9ecc69a6812dfe76214c86ac9ba06
> > 68874ac3304ade7ed5ebb12af00d6b9bbbca0a16
> >  
> > Of the 3 patches, aec4d0e301f17bb143341c82cc44685b8af0b945 seems wrong.
> > The r10 to r15 registers are used in sha1_x8_avx2.S, which is called
> > from sha1_mb_mgr_flush_avx2.S.
> >
> > I do not think the functionality of the SHA1-MB crypto algorithm has
> > been tested after applying these changes. (I am not sure if any of the
> > other crypto algorithms have been affected by these changes).
> 
> Josh, Ingo:
> 
> Any ideas on this? Should we revert?

Yeah, I think so - although another option would be to standardize sha1_x8_avx2() 
- the problem is that it is a function that clobbers registers without 
saving/restoring them, breaking the C function ABI. I realize it's written in 
assembly, but unless there are strong performance reasons to deviate from the 
regular calling convention it might make sense to fix that.

Do any warnings get generated after the revert, if you enable 
CONFIG_STACK_VALIDATION=y?

Thanks,

	Ingo

^ permalink raw reply

* Re: SHA1-MB algorithm broken on latest kernel
From: Herbert Xu @ 2016-05-13  3:10 UTC (permalink / raw)
  To: Megha Dey; +Cc: linux-crypto, linux-kernel, Josh Poimboeuf, Ingo Molnar
In-Reply-To: <1463095866.2594.8.camel@megha-Z97X-UD7-TH>

On Thu, May 12, 2016 at 04:31:06PM -0700, Megha Dey wrote:
> Hi,
>  
> When booting latest kernel with the CONFIG_CRYPTO_SHA1_MB enabled, I
> observe a panic.
>  
> After having a quick look, on reverting the following patches, I am able
> to complete the booting process.
> aec4d0e301f17bb143341c82cc44685b8af0b945
> 8691ccd764f9ecc69a6812dfe76214c86ac9ba06
> 68874ac3304ade7ed5ebb12af00d6b9bbbca0a16
>  
> Of the 3 patches, aec4d0e301f17bb143341c82cc44685b8af0b945 seems wrong.
> The r10 to r15 registers are used in sha1_x8_avx2.S, which is called
> from sha1_mb_mgr_flush_avx2.S.
>  
> I do not think the functionality of the SHA1-MB crypto algorithm has
> been tested after applying these changes. (I am not sure if any of the
> other crypto algorithms have been affected by these changes).

Josh, Ingo:

Any ideas on this? Should we revert?

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

^ permalink raw reply

* SHA1-MB algorithm broken on latest kernel
From: Megha Dey @ 2016-05-12 23:31 UTC (permalink / raw)
  To: Herbert Xu; +Cc: linux-crypto, linux-kernel

Hi,
 
When booting latest kernel with the CONFIG_CRYPTO_SHA1_MB enabled, I
observe a panic.
 
After having a quick look, on reverting the following patches, I am able
to complete the booting process.
aec4d0e301f17bb143341c82cc44685b8af0b945
8691ccd764f9ecc69a6812dfe76214c86ac9ba06
68874ac3304ade7ed5ebb12af00d6b9bbbca0a16
 
Of the 3 patches, aec4d0e301f17bb143341c82cc44685b8af0b945 seems wrong.
The r10 to r15 registers are used in sha1_x8_avx2.S, which is called
from sha1_mb_mgr_flush_avx2.S.
 
I do not think the functionality of the SHA1-MB crypto algorithm has
been tested after applying these changes. (I am not sure if any of the
other crypto algorithms have been affected by these changes).
 
Thanks,
Megha

^ permalink raw reply

* RE: [PATCH v2] Bluetooth: convert smp and selftest to crypto kpp API
From: Benedetto, Salvatore @ 2016-05-12 20:28 UTC (permalink / raw)
  To: Hedberg, Johan
  Cc: herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org,
	gustavo-THi1TnShQwVAfugRpC6u6w@public.gmane.org,
	linux-bluetooth-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-crypto-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	marcel-kz+m5ild9QBg9hUCZPvPmw@public.gmane.org,
	Benedetto, Salvatore
In-Reply-To: <20160512180455.GA4802-ae+CCJ+dGXjCW7GOcxkI+ioyn5ZhHHrn@public.gmane.org>

Hi Johan,

> -----Original Message-----
> From: linux-crypto-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org [mailto:linux-crypto-
> owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org] On Behalf Of Johan Hedberg
> Sent: Thursday, May 12, 2016 7:05 PM
> To: Benedetto, Salvatore <salvatore.benedetto-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Cc: herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org; gustavo-THi1TnShQwVAfugRpC6u6w@public.gmane.org; linux-
> bluetooth-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-crypto-u79uwXL29TY76Z2rM5mHXA@public.gmane.org;
> marcel-kz+m5ild9QBg9hUCZPvPmw@public.gmane.org
> Subject: Re: [PATCH v2] Bluetooth: convert smp and selftest to crypto kpp
> API
> 
> Hi Salvatore,
> 
> On Mon, May 09, 2016, Salvatore Benedetto wrote:
> >  * Convert both smp and selftest to crypto kpp API
> >  * Remove module ecc as not more required
> >  * Add ecdh_helper functions for wrapping kpp async calls
> >
> > This patch has been tested *only* with selftest, which is called on
> > module loading. smp-tester passes all tests but the first one, which
> > often times out. Same behavior is observed without this patch though.
> >
> > This patch is based on https://patchwork.kernel.org/patch/9050061/
> >
> > Signed-off-by: Salvatore Benedetto <salvatore.benedetto-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> > ---
> >  net/bluetooth/Makefile      |   2 +-
> >  net/bluetooth/ecc.c         | 816 --------------------------------------------
> >  net/bluetooth/ecc.h         |  54 ---
> >  net/bluetooth/ecdh_helper.c | 204 +++++++++++
> > net/bluetooth/ecdh_helper.h |  32 ++
> >  net/bluetooth/selftest.c    |   6 +-
> >  net/bluetooth/smp.c         |   8 +-
> >  7 files changed, 244 insertions(+), 878 deletions(-)  delete mode
> > 100644 net/bluetooth/ecc.c  delete mode 100644 net/bluetooth/ecc.h
> > create mode 100644 net/bluetooth/ecdh_helper.c  create mode 100644
> > net/bluetooth/ecdh_helper.h
> 
> I tried this together with your kpp patches and I was able to successfully pair,
> so from that perspective we're fine and I have no objections for those
> patches being merged.
> 
> There are a couple of things to improve with this patch however:
> 
> The first issue is that you're missing a 'select CRYPTO_ECDH' in
> net/bluetooth/Kconfig. Without this you'll end up creating a kernel that
> either doesn't build or a module that doesn't load.
> 

Right the module won't load. I'll fix this.

> > +#ifndef __ECDH_HELPER_H
> > +#define __ECDH_HELPER_H
> 
> Please leave out these include guards for internal headers. We try to avoid
> them there to force keeping the dependency chains simple. I realize you
> might have copied this from smp.h (which is the only internal header I could
> see having this) so that might need fixing in a separate patch.
> 

Actually I didn't pay much attention to this as I always use them.
I'll remove it.

> > +bool compute_ecdh_shared_secret(const u8 pub_a[64], const u8
> priv_b[32],
> > +				u8 secret[32]);
> > +bool generate_ecdh_key_pair(u8 public_key[64], u8 private_key[32]);
> 
> Could you try to come up with some shorter names than these since they
> cause the line lengths to go past 80 chars. In fact, can't you just keep the
> same names as our ecc.c was using. I don't think those names are taken by
> your new kpp code?

They actually are used internally by the ecc module I reworked.
I'll rename them to compute_ecdh_secret() and generate_ecdh_keys() which
fixes the 80 chars per line issue.

I'll send a v3.

Thanks for reviewing.

Regards,
Salvatore 

^ permalink raw reply

* Re: [PATCH v6 0/3] Key-agreement Protocol Primitives (KPP) API
From: Marcel Holtmann @ 2016-05-12 19:34 UTC (permalink / raw)
  To: Salvatore Benedetto; +Cc: herbert, linux-crypto
In-Reply-To: <1462951563-50042-1-git-send-email-salvatore.benedetto@intel.com>

Hi Herbert,

> the following patchset introduces a new API for abstracting key-agreement
> protocols such as DH and ECDH. It provides the primitives required for implementing
> the protocol, thus the name KPP (Key-agreement Protocol Primitives).
> 
> Regards,
> Salvatore
> 
> Changes from v5:
> * Fix ecdh loading in fips mode.
> 
> Changes from v4:
> * If fips_enabled is set allow only P256 (or higher) as Stephan suggested
> * Pass ndigits as argument to ecdh_make_pub_key and ecdh_shared_secret
>  so that VLA can be used like in the rest of the module
> 
> Changes from v3:
> * Move curve ID definition to public header ecdh.h as users need to
>  have access to those ids when selecting the curve
> 
> Changes from v2:
> * Add support for ECDH (curve P192 and P256). I reused the ecc module
>  already present in net/bluetooth and extended it in order to select
>  different curves at runtime. Code for P192 was taken from tinycrypt.
> 
> Changes from v1:
> * Change check in dh_check_params_length based on Stephan review
> 
> 
> Salvatore Benedetto (3):
>  crypto: Key-agreement Protocol Primitives API (KPP)
>  crypto: kpp - Add DH software implementation
>  crypto: kpp - Add ECDH software support

we have tested this with the Bluetooth subsystem to use ECDH for key generation and shared secret generation. This seems to work as expected. Feel free to merge this patchset.

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel

^ permalink raw reply

* Re: [PATCH 3/3] crypto: caam - add support for RSA algorithm
From: Horia Ioan Geanta Neag @ 2016-05-12 19:20 UTC (permalink / raw)
  To: Tudor-Dan Ambarus, herbert@gondor.apana.org.au
  Cc: linux-crypto@vger.kernel.org
In-Reply-To: <1463065578-14017-4-git-send-email-tudor-dan.ambarus@nxp.com>

On 5/12/2016 6:06 PM, Tudor Ambarus wrote:
> Add RSA support to caam driver.
> 
> Coauthored-by: Yashpal Dutta <yashpal.dutta@freescale.com>
> 
> Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
> ---
>  drivers/crypto/caam/Kconfig    |  12 ++
>  drivers/crypto/caam/Makefile   |   4 +
>  drivers/crypto/caam/caampkc.c  | 466 +++++++++++++++++++++++++++++++++++++++++
>  drivers/crypto/caam/caampkc.h  |  94 +++++++++
>  drivers/crypto/caam/desc.h     |   2 +
>  drivers/crypto/caam/pdb.h      |  16 +-
>  drivers/crypto/caam/pkc_desc.c | 138 ++++++++++++
>  7 files changed, 731 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/crypto/caam/caampkc.c
>  create mode 100644 drivers/crypto/caam/caampkc.h
>  create mode 100644 drivers/crypto/caam/pkc_desc.c
> 
> diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
> index 5652a53..44449ba 100644
> --- a/drivers/crypto/caam/Kconfig
> +++ b/drivers/crypto/caam/Kconfig
> @@ -99,6 +99,18 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API
>  	  To compile this as a module, choose M here: the module
>  	  will be called caamhash.
>  
> +config CRYPTO_DEV_FSL_CAAM_PKC_API
> +        tristate "Register public key cryptography implementations with Crypto API"
> +        depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
> +        default y
> +        select CRYPTO_RSA
> +        help
> +          Selecting this will allow SEC Public key support for RSA.
> +          Supported cryptographic primitives: encryption, decryption,
> +          signature and verification.
> +          To compile this as a module, choose M here: the module
> +          will be called caam_pkc.
> +
>  config CRYPTO_DEV_FSL_CAAM_RNG_API
>  	tristate "Register caam device for hwrng API"
>  	depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
> diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
> index 550758a..399ad55 100644
> --- a/drivers/crypto/caam/Makefile
> +++ b/drivers/crypto/caam/Makefile
> @@ -5,11 +5,15 @@ ifeq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG), y)
>  	EXTRA_CFLAGS := -DDEBUG
>  endif
>  
> +ccflags-y += -I$(srctree)/crypto
> +
>  obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
>  obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
>  obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
>  obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
>  obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
> +obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o
>  
>  caam-objs := ctrl.o
>  caam_jr-objs := jr.o key_gen.o error.o
> +caam_pkc-y := caampkc.o pkc_desc.o
> diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c
> new file mode 100644
> index 0000000..34ffa87
> --- /dev/null
> +++ b/drivers/crypto/caam/caampkc.c
> @@ -0,0 +1,466 @@
> +/*
> + * caam - Freescale FSL CAAM support for Public Key Cryptography
> + *
> + * Copyright 2016 Freescale Semiconductor, Inc.
> + *
> + * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
> + * all the desired key parameters, input and output pointers.
> + */
> +#include <linux/dma-mapping.h>
> +#include <linux/fips.h>
> +#include "compat.h"
> +#include "caampkc.h"
> +#include "sg_sw_sec4.h"
> +#include "regs.h"
> +#include "intern.h"
> +#include "jr.h"
> +#include "error.h"
> +
> +static void rsa_io_unmap(struct device *dev, struct rsa_edesc *edesc,
> +			 struct akcipher_request *req)
> +{
> +	dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
> +	dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
> +}
> +
> +static void rsa_pub_unmap(struct device *dev, struct rsa_edesc *edesc,
> +			  struct akcipher_request *req)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *key = &ctx->key;
> +	struct rsa_pub_desc *hw_desc = (struct rsa_pub_desc *)edesc->hw_desc;
> +
> +	dma_unmap_single(dev, hw_desc->n_dma, key->n_sz, DMA_TO_DEVICE);
> +	dma_unmap_single(dev, hw_desc->e_dma, key->e_sz, DMA_TO_DEVICE);
> +}
> +
> +static void rsa_priv_f1_unmap(struct device *dev, struct rsa_edesc *edesc,
> +			      struct akcipher_request *req)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *key = &ctx->key;
> +	struct rsa_priv_f1_desc *hw_desc =
> +			(struct rsa_priv_f1_desc *)edesc->hw_desc;
> +
> +	dma_unmap_single(dev, hw_desc->n_dma, key->n_sz, DMA_TO_DEVICE);
> +	dma_unmap_single(dev, hw_desc->d_dma, key->n_sz, DMA_TO_DEVICE);
> +}
> +
> +static size_t skip_to_nonzero(u8 *ptr, size_t nbytes)
> +{
> +	size_t nr_zeros = 0;
> +
> +	while (!(*ptr) && nbytes) {
> +		nbytes--;
> +		ptr++;
> +		nr_zeros++;
> +	}
> +
> +	return nr_zeros;
> +}
> +
> +static size_t scatterwalk_skip_zeros(struct scatter_walk *walk, size_t nbytes)
> +{
> +	size_t len_this_page, nr_zeros, cnt = 0;
> +	u8 *vaddr, *ptr;
> +
> +	for (;;) {
> +		nr_zeros = 0;
> +		len_this_page = scatterwalk_pagelen(walk);
> +
> +		if (len_this_page > nbytes)
> +			len_this_page = nbytes;
> +
> +		vaddr = scatterwalk_map(walk);
> +		ptr = vaddr;
> +		nr_zeros = skip_to_nonzero(ptr, len_this_page);
> +		scatterwalk_unmap(vaddr);
> +
> +		/* count total number of zeros */
> +		cnt += nr_zeros;
> +
> +		/* advance scatterwalk to the nonzero data */
> +		scatterwalk_advance(walk, nr_zeros);
> +
> +		if (nr_zeros < len_this_page || nbytes == len_this_page)
> +			break;
> +
> +		nbytes -= len_this_page;
> +
> +		scatterwalk_pagedone(walk, 0, 1);
> +	}
> +
> +	return cnt;
> +}
> +
> +/*
> + * This function drops the leading zeros and copies the data to the initial
> + * pointer so that it can be freed later on. Returns the updated data length.
> + */
> +static size_t drop_leading_zeros(struct scatterlist *sg, size_t nbytes)
> +{
> +	struct scatter_walk walk_src, walk_dst;
> +	size_t nr_zeros = 0;
> +
> +	scatterwalk_start(&walk_src, sg);
> +	nr_zeros = scatterwalk_skip_zeros(&walk_src, nbytes);
> +
> +	if (nr_zeros) {
> +		nbytes = nbytes - nr_zeros;
> +
> +		scatterwalk_start(&walk_dst, sg);
> +		scatterwalk_sg_copychunks(&walk_dst, &walk_src, nbytes);
> +		scatterwalk_done(&walk_dst, 0, 0);
> +	}
> +
> +	scatterwalk_done(&walk_src, 0, 0);
> +
> +	return nbytes;
> +}
> +
> +/* RSA Job Completion handler */
> +static void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void *context)
> +{
> +	struct akcipher_request *req = context;
> +	struct rsa_edesc *edesc;
> +
> +	if (err)
> +		caam_jr_strstatus(dev, err);
> +
> +	/*
> +	 * RSA's output is expected to be a big integer. Drop the leading
> +	 * zeros since they are not meaningful in the world of numbers.
> +	 */
> +	req->dst_len = drop_leading_zeros(req->dst, req->dst_len);
> +
> +	edesc = container_of(desc, struct rsa_edesc, hw_desc[0]);
> +
> +	rsa_pub_unmap(dev, edesc, req);
> +	rsa_io_unmap(dev, edesc, req);
> +	kfree(edesc);
> +
> +	akcipher_request_complete(req, err);
> +}
> +
> +static void rsa_priv_f1_done(struct device *dev, u32 *desc, u32 err,
> +			     void *context)
> +{
> +	struct akcipher_request *req = context;
> +	struct rsa_edesc *edesc;
> +
> +	if (err)
> +		caam_jr_strstatus(dev, err);
> +
> +	/*
> +	 * RSA's output is expected to be a big integer. Drop the leading
> +	 * zeros since they are not meaningful in the world of numbers.
> +	 */
> +	req->dst_len = drop_leading_zeros(req->dst, req->dst_len);
> +
> +	edesc = container_of(desc, struct rsa_edesc, hw_desc[0]);
> +
> +	rsa_priv_f1_unmap(dev, edesc, req);
> +	rsa_io_unmap(dev, edesc, req);
> +	kfree(edesc);
> +
> +	akcipher_request_complete(req, err);
> +}
> +
> +static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req,
> +					 size_t desclen)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct device *dev = ctx->dev;
> +	struct rsa_edesc *edesc;
> +	gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
> +		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
> +	int sgc;
> +	int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
> +	int src_nents, dst_nents;
> +
> +	src_nents = sg_nents_for_len(req->src, req->src_len);
> +	dst_nents = sg_nents_for_len(req->dst, req->dst_len);
> +
> +	if (src_nents > 1)
> +		sec4_sg_len = src_nents;
> +	if (dst_nents > 1)
> +		sec4_sg_len += dst_nents;
> +
> +	sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
> +
> +	/* allocate space for base edesc, hw desc commands and link tables */
> +	edesc = kzalloc(sizeof(*edesc) + desclen + sec4_sg_bytes,
> +			GFP_DMA | flags);
> +	if (!edesc)
> +		return ERR_PTR(-ENOMEM);
> +
> +	sgc = dma_map_sg(dev, req->src, src_nents, DMA_TO_DEVICE);
> +	if (unlikely(!sgc)) {
> +		dev_err(dev, "unable to map source\n");
> +		goto src_fail;
> +	}
> +
> +	sgc = dma_map_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
> +	if (unlikely(!sgc)) {
> +		dev_err(dev, "unable to map destination\n");
> +		goto dst_fail;
> +	}
> +
> +	edesc->sec4_sg = (void *)edesc + sizeof(*edesc) + desclen;
> +
> +	sec4_sg_index = 0;
> +	if (src_nents > 1) {
> +		sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0);
> +		sec4_sg_index += src_nents;
> +	}
> +	if (dst_nents > 1) {
> +		sg_to_sec4_sg_last(req->dst, dst_nents,
> +				   edesc->sec4_sg + sec4_sg_index, 0);
> +	}
> +
> +	/* Save nents for later use in Job Descriptor. */
> +	edesc->src_nents = src_nents;
> +	edesc->dst_nents = dst_nents;
> +
> +	if (!sec4_sg_bytes)
> +		return edesc;
> +
> +	edesc->sec4_sg_dma = dma_map_single(dev, edesc->sec4_sg,
> +					    sec4_sg_bytes, DMA_TO_DEVICE);

Where is sec4_sg_dma unmapped?

> +	if (dma_mapping_error(dev, edesc->sec4_sg_dma)) {
> +		dev_err(dev, "unable to map S/G table\n");
> +		goto sec4_sg_fail;
> +	}
> +
> +	return edesc;
> +
> +sec4_sg_fail:
> +	dma_unmap_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
> +dst_fail:
> +	dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE);
> +src_fail:
> +	kfree(edesc);
> +	return ERR_PTR(-ENOMEM);
> +}
> +
> +static int caam_rsa_enc(struct akcipher_request *req)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *key = &ctx->key;
> +	struct device *jrdev = ctx->dev;
> +	struct rsa_edesc *edesc = NULL;
> +	size_t desclen = sizeof(struct rsa_pub_desc);
> +	int ret;
> +
> +	if (unlikely(!key->n || !key->e))
> +		return -EINVAL;
> +
> +	if (req->dst_len < key->n_sz) {
> +		req->dst_len = key->n_sz;
> +		dev_err(jrdev, "Output buffer length less than parameter n\n");
> +		return -EOVERFLOW;
> +	}
> +
> +	/* Allocate extended descriptor. */
> +	edesc = rsa_edesc_alloc(req, desclen);
> +	if (IS_ERR(edesc))
> +		return PTR_ERR(edesc);
> +
> +	/* Initialize Job Descriptor. */
> +	ret = init_rsa_pub_desc(req, edesc);
> +	if (ret)
> +		goto init_fail;
> +
> +	ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_pub_done, req);
> +	if (!ret)
> +		return -EINPROGRESS;
> +
> +	rsa_pub_unmap(jrdev, edesc, req);
> +
> +init_fail:
> +	rsa_io_unmap(jrdev, edesc, req);
> +	kfree(edesc);
> +	return ret;
> +}
> +
> +static int caam_rsa_dec(struct akcipher_request *req)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *key = &ctx->key;
> +	struct device *jrdev = ctx->dev;
> +	struct rsa_edesc *edesc = NULL;
> +	size_t desclen = sizeof(struct rsa_priv_f1_desc);
> +	int ret;
> +
> +	if (unlikely(!key->n || !key->d))
> +		return -EINVAL;
> +
> +	if (req->dst_len < key->n_sz) {
> +		req->dst_len = key->n_sz;

Be consistent with caam_rsa_enc(): either do a dev_err() here, or remove
the error message in caam_rsa_enc().

> +		return -EOVERFLOW;
> +	}
> +
> +	/* Allocate extended descriptor. */
> +	edesc = rsa_edesc_alloc(req, desclen);
> +	if (IS_ERR(edesc))
> +		return PTR_ERR(edesc);
> +
> +	/* Initialize Job Descriptor. */
> +	ret = init_rsa_priv_f1_desc(req, edesc);
> +	if (ret)
> +		goto init_fail;
> +
> +	ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_priv_f1_done, req);
> +	if (!ret)
> +		return -EINPROGRESS;
> +
> +	rsa_priv_f1_unmap(jrdev, edesc, req);
> +
> +init_fail:
> +	rsa_io_unmap(jrdev, edesc, req);
> +	kfree(edesc);
> +	return ret;
> +}
> +
> +static int caam_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
> +				unsigned int keylen)
> +{
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *rsa_key = &ctx->key;
> +
> +	return rsa_parse_pub_key(rsa_key, key, keylen);
> +}
> +
> +static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
> +				 unsigned int keylen)
> +{
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *rsa_key = &ctx->key;
> +
> +	return rsa_parse_priv_key(rsa_key, key, keylen);
> +}
> +
> +static int caam_rsa_max_size(struct crypto_akcipher *tfm)
> +{
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *key = &ctx->key;
> +
> +	return (key->n) ? key->n_sz : -EINVAL;
> +}
> +
> +/* Per session pkc's driver context creation function */
> +static int caam_rsa_init_tfm(struct crypto_akcipher *tfm)
> +{
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *key = &ctx->key;
> +
> +	ctx->dev = caam_jr_alloc();
> +
> +	if (IS_ERR(ctx->dev)) {
> +		dev_err(ctx->dev, "Job Ring Device allocation for transform failed\n");
> +		return PTR_ERR(ctx->dev);
> +	}
> +
> +	key->flags = GFP_DMA | GFP_KERNEL;
> +	return 0;
> +}
> +
> +/* Per session pkc's driver context cleanup function */
> +static void caam_rsa_exit_tfm(struct crypto_akcipher *tfm)
> +{
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *key = &ctx->key;
> +
> +	rsa_free_key(key);
> +	caam_jr_free(ctx->dev);
> +}
> +
> +static struct akcipher_alg caam_rsa = {
> +	.encrypt = caam_rsa_enc,
> +	.decrypt = caam_rsa_dec,
> +	.sign = caam_rsa_dec,
> +	.verify = caam_rsa_enc,
> +	.set_pub_key = caam_rsa_set_pub_key,
> +	.set_priv_key = caam_rsa_set_priv_key,
> +	.max_size = caam_rsa_max_size,
> +	.init = caam_rsa_init_tfm,
> +	.exit = caam_rsa_exit_tfm,
> +	.base = {
> +		.cra_name = "rsa",
> +		.cra_driver_name = "rsa-caam",
> +		.cra_priority = 3000,
> +		.cra_module = THIS_MODULE,
> +		.cra_alignmask = 0,
> +		.cra_ctxsize = sizeof(struct caam_rsa_ctx),
> +	},
> +};
> +
> +/* Public Key Cryptography module initialization handler */
> +static int __init caam_pkc_init(void)
> +{
> +	struct device_node *dev_node;
> +	struct platform_device *pdev;
> +	struct device *ctrldev;
> +	struct caam_drv_private *priv;
> +	u32 cha_inst, pk_inst;
> +	int err = 0;
> +
> +	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
> +	if (!dev_node) {
> +		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
> +		if (!dev_node)
> +			return -ENODEV;
> +	}
> +
> +	pdev = of_find_device_by_node(dev_node);
> +	if (!pdev) {
> +		of_node_put(dev_node);
> +		return -ENODEV;
> +	}
> +
> +	ctrldev = &pdev->dev;
> +	priv = dev_get_drvdata(ctrldev);
> +	of_node_put(dev_node);
> +
> +	/*
> +	 * If priv is NULL, it's probably because the caam driver wasn't
> +	 * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
> +	 */
> +	if (!priv)
> +		return -ENODEV;
> +
> +	/* Determine public key hardware accelerator presence. */
> +	cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
> +	pk_inst = (cha_inst & CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT;
> +
> +	/* Do not register algorithms if PKHA is not present. */
> +	if (!pk_inst)
> +		return -ENODEV;
> +
> +	caam_rsa.base.cra_flags = 0;
> +	err = crypto_register_akcipher(&caam_rsa);
> +	if (err)
> +		dev_warn(ctrldev, "%s alg registration failed\n",
> +			 caam_rsa.base.cra_driver_name);
> +	else
> +		dev_info(ctrldev, "caam algorithms registered in /proc/crypto\n");

Be specific which type of algorithms are being registered (pkc / asym).

> +
> +	return err;
> +}
> +
> +static void __exit caam_pkc_exit(void)
> +{
> +	crypto_unregister_akcipher(&caam_rsa);
> +}
> +
> +module_init(caam_pkc_init);
> +module_exit(caam_pkc_exit);
> +
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_DESCRIPTION("FSL CAAM support for PKC functions of crypto API");
> +MODULE_AUTHOR("Freescale Semiconductor");
> diff --git a/drivers/crypto/caam/caampkc.h b/drivers/crypto/caam/caampkc.h
> new file mode 100644
> index 0000000..398a881
> --- /dev/null
> +++ b/drivers/crypto/caam/caampkc.h
> @@ -0,0 +1,94 @@
> +/*
> + * caam - Freescale FSL CAAM support for Public Key Cryptography descriptors
> + *
> + * Copyright 2016 Freescale Semiconductor, Inc.
> + *
> + * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
> + * all the desired key parameters, input and output pointers.
> + */
> +
> +#ifndef _PKC_DESC_H_
> +#define _PKC_DESC_H_
> +
> +#include <crypto/internal/rsa.h>
> +#include <crypto/akcipher.h>
> +#include <crypto/internal/akcipher.h>
> +#include "desc_constr.h"
> +#include "pdb.h"
> +#include "rsapubkey-asn1.h"
> +#include "rsaprivkey-asn1.h"
> +
> +/**
> + * caam_rsa_ctx - per session context.
> + * @key: RSA key structure
> + * @dev: device structure
> + */
> +struct caam_rsa_ctx {
> +	struct rsa_key key;
> +	struct device *dev;
> +};
> +
> +/**
> + * RSA Pub_Key Descriptor
> + * @desc_hdr: Job Descriptor Header command
> + * @sgf: scatter-gather field
> + * @f_dma: dma address of input data
> + * @g_dma: dma address of ecrypted output data

s/ecrypted/encrypted

> + * @n_dma: dma address of RSA public exponent

modulus

> + * @dma_e: dma address of RSA public exponent

s/dma_e/e_dma

> + * @f_len: length in octets of the input data
> + * @op: RSA Operation command
> + */
> +struct rsa_pub_desc {
> +	u32		desc_hdr;
> +	u32		sgf;
> +	dma_addr_t	f_dma;
> +	dma_addr_t	g_dma;
> +	dma_addr_t	n_dma;
> +	dma_addr_t	e_dma;
> +	u32		f_len;
> +	u32		op;
> +} __packed;
> +
> +/**
> + * Form1 Priv_key Decryption Descriptor.
> + * Private key is represented by (n,d).
> + * @desc_hdr: Job Descriptor Header command
> + * @sgf: scatter-gather field
> + * @g_dma: dma address of ecrypted input data

s/ecrypted/encrypted

> + * @f_dma: dma address of output data
> + * @n_dma: dma address of RSA public exponent

modulus

> + * @dma_d: dma address of RSA private exponent

s/dma_d/d_dma

> + * @op: RSA Operation command
> + */
> +struct rsa_priv_f1_desc {
> +	u32		desc_hdr;
> +	u32		sgf;
> +	dma_addr_t	g_dma;
> +	dma_addr_t	f_dma;
> +	dma_addr_t	n_dma;
> +	dma_addr_t	d_dma;
> +	u32		op;
> +} __packed;
> +
> +/**
> + * rsa_edesc - s/w-extended rsa descriptor
> + * @src_nents: number of segments in input scatterlist
> + * @dst_nents: number of segments in output scatterlist
> + * @sec4_sg_dma: dma address of h/w link table
> + * @sec4_sg: pointer to h/w link table
> + * @hw_desc: descriptor followed by link tables if any
> + */
> +struct rsa_edesc {
> +	int src_nents;
> +	int dst_nents;
> +	dma_addr_t sec4_sg_dma;
> +	struct sec4_sg_entry *sec4_sg;
> +	u32 hw_desc[];
> +};
> +
> +/* Descriptor construction primitives. */
> +int init_rsa_pub_desc(struct akcipher_request *req, struct rsa_edesc *edesc);
> +int init_rsa_priv_f1_desc(struct akcipher_request *req,
> +			  struct rsa_edesc *edesc);
> +#endif
> diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
> index 1e93c6a..7e5c027 100644
> --- a/drivers/crypto/caam/desc.h
> +++ b/drivers/crypto/caam/desc.h
> @@ -454,6 +454,8 @@ struct sec4_sg_entry {
>  #define OP_PCLID_PUBLICKEYPAIR	(0x14 << OP_PCLID_SHIFT)
>  #define OP_PCLID_DSASIGN	(0x15 << OP_PCLID_SHIFT)
>  #define OP_PCLID_DSAVERIFY	(0x16 << OP_PCLID_SHIFT)
> +#define OP_PCLID_RSAENC_PUBKEY  (0x18 << OP_PCLID_SHIFT)
> +#define OP_PCLID_RSADEC_PRVKEY  (0x19 << OP_PCLID_SHIFT)
>  
>  /* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */
>  #define OP_PCLID_IPSEC		(0x01 << OP_PCLID_SHIFT)
> diff --git a/drivers/crypto/caam/pdb.h b/drivers/crypto/caam/pdb.h
> index 3a87c0c..1c68d7b 100644
> --- a/drivers/crypto/caam/pdb.h
> +++ b/drivers/crypto/caam/pdb.h
> @@ -1,7 +1,7 @@
>  /*
>   * CAAM Protocol Data Block (PDB) definition header file
>   *
> - * Copyright 2008-2012 Freescale Semiconductor, Inc.
> + * Copyright 2008-2016 Freescale Semiconductor, Inc.
>   *
>   */
>  
> @@ -399,4 +399,18 @@ struct dsa_verify_pdb {
>  	u8 *ab; /* only used if ECC processing */
>  };
>  
> +/* RSA Protocol Data Block */
> +#define RSA_PDB_SGF_SHIFT       28
> +#define RSA_PDB_E_SHIFT         12
> +#define RSA_PDB_E_MASK          (0xFFF << RSA_PDB_E_SHIFT)
> +#define RSA_PDB_D_SHIFT         12
> +#define RSA_PDB_D_MASK          (0xFFF << RSA_PDB_D_SHIFT)
> +
> +#define RSA_PDB_SGF_F           (0x8 << RSA_PDB_SGF_SHIFT)
> +#define RSA_PDB_SGF_G           (0x4 << RSA_PDB_SGF_SHIFT)
> +#define RSA_PRIV_PDB_SGF_F      (0x4 << RSA_PDB_SGF_SHIFT)
> +#define RSA_PRIV_PDB_SGF_G      (0x8 << RSA_PDB_SGF_SHIFT)
> +
> +#define RSA_PRIV_KEY_FRM_1      0
> +
>  #endif
> diff --git a/drivers/crypto/caam/pkc_desc.c b/drivers/crypto/caam/pkc_desc.c
> new file mode 100644
> index 0000000..25c0690
> --- /dev/null
> +++ b/drivers/crypto/caam/pkc_desc.c
> @@ -0,0 +1,138 @@
> +/*
> + * caam - Freescale FSL CAAM support for Public Key Cryptography descriptors
> + *
> + * Copyright 2016 Freescale Semiconductor, Inc.
> + *
> + * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
> + * all the desired key parameters, input and output pointers.
> + */
> +#include "caampkc.h"
> +
> +/* Descriptor for RSA Public operation */
> +int init_rsa_pub_desc(struct akcipher_request *req, struct rsa_edesc *edesc)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *key = &ctx->key;
> +	struct device *dev = ctx->dev;
> +	struct rsa_pub_desc *desc = (struct rsa_pub_desc *)edesc->hw_desc;
> +	u32 start_idx, desc_size;
> +	int sec4_sg_index = 0;
> +
> +	/*
> +	 * The PDB has static fields and can be initialized before writing
> +	 * a specific command. Map the memory first, since it can be a point
> +	 * of failure.
> +	 */
> +	desc->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, desc->n_dma)) {
> +		dev_err(dev, "Unable to map  modulus memory\n");
> +		goto n_fail;
> +	}
> +
> +	desc->e_dma = dma_map_single(dev, key->e, key->e_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, desc->e_dma)) {
> +		dev_err(dev, "Unable to map exponent memory\n");
> +		goto e_fail;
> +	}
> +
> +	desc_size = sizeof(*desc) / CAAM_CMD_SZ;

Descriptor has a few addresses in it, thus you'll also have to use
CAAM_PTR_SZ.

> +	start_idx = (desc_size - 1) & HDR_START_IDX_MASK;
> +	init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
> +		      (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
> +
> +	sec4_sg_index = 0;
> +	if (edesc->src_nents > 1) {
> +		desc->sgf |= RSA_PDB_SGF_F;
> +		desc->f_dma = edesc->sec4_sg_dma;
> +		sec4_sg_index += edesc->src_nents;
> +	} else {
> +		desc->f_dma = sg_dma_address(req->src);
> +	}
> +
> +	if (edesc->dst_nents > 1) {
> +		desc->sgf |= RSA_PDB_SGF_G;
> +		desc->g_dma = edesc->sec4_sg_dma +
> +			sec4_sg_index * sizeof(struct sec4_sg_entry);
> +	} else {
> +		desc->g_dma = sg_dma_address(req->dst);
> +	}
> +
> +	desc->sgf |= (key->e_sz << RSA_PDB_E_SHIFT) | key->n_sz;
> +	desc->f_len = req->src_len;
> +	desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
> +		   OP_PCLID_RSAENC_PUBKEY;
> +	return 0;
> +
> +e_fail:
> +	dma_unmap_single(dev, desc->n_dma, key->n_sz, DMA_TO_DEVICE);
> +n_fail:
> +	dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
> +	dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
> +	kfree(edesc);
> +	return -ENOMEM;
> +}
> +
> +/* Descriptor for RSA Private operation */
> +int init_rsa_priv_f1_desc(struct akcipher_request *req, struct rsa_edesc *edesc)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +	struct rsa_key *key = &ctx->key;
> +	struct device *dev = ctx->dev;
> +	struct rsa_priv_f1_desc *desc =
> +			(struct rsa_priv_f1_desc *)edesc->hw_desc;
> +	int sec4_sg_index = 0;
> +	u32 start_idx, desc_size;
> +
> +	/*
> +	 * The PDB has static fields and can be initialized before writing
> +	 * a specific command. Map the memory first, since it can be a point
> +	 * of failure.
> +	 */
> +	desc->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, desc->n_dma)) {
> +		dev_err(dev, "Unable to map  modulus memory\n");
> +		goto n_fail;
> +	}
> +
> +	desc->d_dma = dma_map_single(dev, key->d, key->n_sz, DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, desc->d_dma)) {
> +		dev_err(dev, "Unable to map exponent memory\n");
> +		goto d_fail;
> +	}
> +
> +	desc_size = sizeof(*desc) / CAAM_CMD_SZ;

Descriptor has a few addresses in it, thus you'll also have to use
CAAM_PTR_SZ.

> +	start_idx = (desc_size - 1) & HDR_START_IDX_MASK;
> +	init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
> +		      (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
> +
> +	if (edesc->src_nents > 1) {
> +		desc->sgf |= RSA_PRIV_PDB_SGF_G;
> +		desc->g_dma = edesc->sec4_sg_dma;
> +		sec4_sg_index += edesc->src_nents;
> +	} else {
> +		desc->g_dma = sg_dma_address(req->src);
> +	}
> +
> +	if (edesc->dst_nents > 1) {
> +		desc->sgf |= RSA_PRIV_PDB_SGF_F;
> +		desc->f_dma = edesc->sec4_sg_dma +
> +			sec4_sg_index * sizeof(struct sec4_sg_entry);
> +	} else {
> +		desc->f_dma = sg_dma_address(req->dst);
> +	}
> +
> +	desc->sgf |= (key->n_sz << RSA_PDB_D_SHIFT) | key->n_sz;
> +	desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
> +		   OP_PCLID_RSADEC_PRVKEY | RSA_PRIV_KEY_FRM_1;
> +	return 0;
> +
> +d_fail:
> +	dma_unmap_single(dev, desc->n_dma, key->n_sz, DMA_TO_DEVICE);
> +n_fail:
> +	dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
> +	dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
> +	kfree(edesc);
> +	return -ENOMEM;
> +}
> 

^ permalink raw reply

* Re: [PATCH v2] Bluetooth: convert smp and selftest to crypto kpp API
From: Johan Hedberg @ 2016-05-12 18:04 UTC (permalink / raw)
  To: Salvatore Benedetto
  Cc: herbert, gustavo, linux-bluetooth, linux-crypto, marcel
In-Reply-To: <1462831206-2947-1-git-send-email-salvatore.benedetto@intel.com>

Hi Salvatore,

On Mon, May 09, 2016, Salvatore Benedetto wrote:
>  * Convert both smp and selftest to crypto kpp API
>  * Remove module ecc as not more required
>  * Add ecdh_helper functions for wrapping kpp async calls
> 
> This patch has been tested *only* with selftest, which is called on
> module loading. smp-tester passes all tests but the first one, which
> often times out. Same behavior is observed without this patch though.
> 
> This patch is based on https://patchwork.kernel.org/patch/9050061/
> 
> Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
> ---
>  net/bluetooth/Makefile      |   2 +-
>  net/bluetooth/ecc.c         | 816 --------------------------------------------
>  net/bluetooth/ecc.h         |  54 ---
>  net/bluetooth/ecdh_helper.c | 204 +++++++++++
>  net/bluetooth/ecdh_helper.h |  32 ++
>  net/bluetooth/selftest.c    |   6 +-
>  net/bluetooth/smp.c         |   8 +-
>  7 files changed, 244 insertions(+), 878 deletions(-)
>  delete mode 100644 net/bluetooth/ecc.c
>  delete mode 100644 net/bluetooth/ecc.h
>  create mode 100644 net/bluetooth/ecdh_helper.c
>  create mode 100644 net/bluetooth/ecdh_helper.h

I tried this together with your kpp patches and I was able to
successfully pair, so from that perspective we're fine and I have no
objections for those patches being merged.

There are a couple of things to improve with this patch however:

The first issue is that you're missing a 'select CRYPTO_ECDH' in
net/bluetooth/Kconfig. Without this you'll end up creating a kernel that
either doesn't build or a module that doesn't load.

> +#ifndef __ECDH_HELPER_H
> +#define __ECDH_HELPER_H

Please leave out these include guards for internal headers. We try to
avoid them there to force keeping the dependency chains simple. I
realize you might have copied this from smp.h (which is the only
internal header I could see having this) so that might need fixing in a
separate patch.

> +bool compute_ecdh_shared_secret(const u8 pub_a[64], const u8 priv_b[32],
> +				u8 secret[32]);
> +bool generate_ecdh_key_pair(u8 public_key[64], u8 private_key[32]);

Could you try to come up with some shorter names than these since they
cause the line lengths to go past 80 chars. In fact, can't you just keep
the same names as our ecc.c was using. I don't think those names are
taken by your new kpp code?

Johan

^ permalink raw reply

* Re: [RFC PATCH 5/8] KEYS: Provide software public key query function [ver 3]
From: Mat Martineau @ 2016-05-12 17:01 UTC (permalink / raw)
  To: David Howells
  Cc: Mat Martineau, tadeusz.struk, linux-kernel, linux-security-module,
	keyrings, linux-crypto, dwmw2
In-Reply-To: <25139.1463048363@warthog.procyon.org.uk>


On Thu, 12 May 2016, David Howells wrote:

> Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:
>
>>> +	len = crypto_akcipher_maxsize(tfm);
>>> +	info->key_size = len * 8;
>>> +	info->max_data_size = len;
>>> +	info->max_sig_size = len;
>>> +	info->max_enc_size = len;
>>> +	info->max_dec_size = len;
>>
>> If len > UINT16_MAX, should UINT16_MAX be reported as the max size? Similar
>> question for len*8 and key_size.
>
> key_size is 32 bits, but the other sizes are all 16 bits, so you would need a
> 524288-bit key to exceed their capacity.  I'm not sure that's likely anytime
> soon, but should I just make all the sizes 32-bit anyway?

Given that cryto_akcipher_maxsize() returns an int and keyctl_pkey_query 
is part of the userspace API, I support bumping the sizes to 32-bit.

--
Mat Martineau
Intel OTC

^ permalink raw reply

* [PATCH v2] crypto: rsa - return raw integers for the ASN.1 parser
From: Tudor Ambarus @ 2016-05-12 15:00 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Tudor Ambarus

Return kmalloced raw integers with no other processing.
The scope is to have only one ANS.1 parser for the RSA keys.

Update the RSA software implementation so that it does
the MPI conversion on top.

Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
---
Changes from initial patch:
- remove device related variables from the generic helper
- move struct rsa_mpi_key to rsa.c; the helper now handles
raw integers.
- cosmetics on error path for rsa_get_n,e,d functions

 crypto/rsa.c                  | 132 ++++++++++++++++++++++++++++++------------
 crypto/rsa_helper.c           | 111 +++++++++++++++++++++++++----------
 include/crypto/internal/rsa.h |  20 +++++--
 3 files changed, 190 insertions(+), 73 deletions(-)

diff --git a/crypto/rsa.c b/crypto/rsa.c
index 77d737f..c181ad9 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -14,12 +14,24 @@
 #include <crypto/internal/akcipher.h>
 #include <crypto/akcipher.h>
 #include <crypto/algapi.h>
+#include <linux/mpi.h>
+
+struct rsa_mpi_key {
+	MPI n;
+	MPI e;
+	MPI d;
+};
+
+struct rsa_ctx {
+	struct rsa_key key;
+	struct rsa_mpi_key mpi_key;
+};
 
 /*
  * RSAEP function [RFC3447 sec 5.1.1]
  * c = m^e mod n;
  */
-static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m)
+static int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m)
 {
 	/* (1) Validate 0 <= m < n */
 	if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
@@ -33,7 +45,7 @@ static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m)
  * RSADP function [RFC3447 sec 5.1.2]
  * m = c^d mod n;
  */
-static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c)
+static int _rsa_dec(const struct rsa_mpi_key *key, MPI m, MPI c)
 {
 	/* (1) Validate 0 <= c < n */
 	if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0)
@@ -47,7 +59,7 @@ static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c)
  * RSASP1 function [RFC3447 sec 5.2.1]
  * s = m^d mod n
  */
-static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m)
+static int _rsa_sign(const struct rsa_mpi_key *key, MPI s, MPI m)
 {
 	/* (1) Validate 0 <= m < n */
 	if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
@@ -61,7 +73,7 @@ static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m)
  * RSAVP1 function [RFC3447 sec 5.2.2]
  * m = s^e mod n;
  */
-static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s)
+static int _rsa_verify(const struct rsa_mpi_key *key, MPI m, MPI s)
 {
 	/* (1) Validate 0 <= s < n */
 	if (mpi_cmp_ui(s, 0) < 0 || mpi_cmp(s, key->n) >= 0)
@@ -71,15 +83,17 @@ static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s)
 	return mpi_powm(m, s, key->e, key->n);
 }
 
-static inline struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm)
+static inline struct rsa_mpi_key *rsa_get_key(struct crypto_akcipher *tfm)
 {
-	return akcipher_tfm_ctx(tfm);
+	struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+	return &ctx->mpi_key;
 }
 
 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);
+	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
 	MPI m, c = mpi_alloc(0);
 	int ret = 0;
 	int sign;
@@ -118,7 +132,7 @@ err_free_c:
 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);
+	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
 	MPI c, m = mpi_alloc(0);
 	int ret = 0;
 	int sign;
@@ -156,7 +170,7 @@ err_free_m:
 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);
+	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
 	MPI m, s = mpi_alloc(0);
 	int ret = 0;
 	int sign;
@@ -195,7 +209,7 @@ err_free_s:
 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);
+	const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
 	MPI s, m = mpi_alloc(0);
 	int ret = 0;
 	int sign;
@@ -233,66 +247,107 @@ err_free_m:
 	return ret;
 }
 
-static int rsa_check_key_length(unsigned int len)
+static void rsa_free_mpi_key(struct rsa_mpi_key *key)
 {
-	switch (len) {
-	case 512:
-	case 1024:
-	case 1536:
-	case 2048:
-	case 3072:
-	case 4096:
-		return 0;
-	}
-
-	return -EINVAL;
+	mpi_free(key->d);
+	mpi_free(key->e);
+	mpi_free(key->n);
+	key->d = NULL;
+	key->e = NULL;
+	key->n = NULL;
 }
 
 static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
 			   unsigned int keylen)
 {
-	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+	struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *pkey = &ctx->key;
+	struct rsa_mpi_key *mpi_key = &ctx->mpi_key;
 	int ret;
 
+	/* Free the old MPI key if any */
+	rsa_free_mpi_key(mpi_key);
+
 	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;
+	mpi_key->e = mpi_read_raw_data(pkey->e, pkey->e_sz);
+	if (!mpi_key->e)
+		goto err;
+
+	mpi_key->n = mpi_read_raw_data(pkey->n, pkey->n_sz);
+	if (!mpi_key->n)
+		goto err;
+
+	return 0;
+
+err:
+	rsa_free_mpi_key(mpi_key);
+	rsa_free_key(pkey);
+	return -ENOMEM;
 }
 
 static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
 			    unsigned int keylen)
 {
-	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+	struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *pkey = &ctx->key;
+	struct rsa_mpi_key *mpi_key = &ctx->mpi_key;
 	int ret;
 
+	/* Free the old MPI key if any */
+	rsa_free_mpi_key(mpi_key);
+
 	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;
+	mpi_key->d = mpi_read_raw_data(pkey->d, pkey->n_sz);
+	if (!mpi_key->d)
+		goto err;
+
+	mpi_key->e = mpi_read_raw_data(pkey->e, pkey->e_sz);
+	if (!mpi_key->e)
+		goto err;
+
+	mpi_key->n = mpi_read_raw_data(pkey->n, pkey->n_sz);
+	if (!mpi_key->n)
+		goto err;
+
+	return 0;
+
+err:
+	rsa_free_mpi_key(mpi_key);
+	rsa_free_key(pkey);
+	return -ENOMEM;
 }
 
 static int rsa_max_size(struct crypto_akcipher *tfm)
 {
-	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+	struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *pkey = &ctx->key;
+
+	return pkey->n ? pkey->n_sz : -EINVAL;
+}
+
+static int rsa_init_tfm(struct crypto_akcipher *tfm)
+{
+	struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *pkey = &ctx->key;
 
-	return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
+	pkey->flags = GFP_KERNEL;
+
+	return 0;
 }
 
 static void rsa_exit_tfm(struct crypto_akcipher *tfm)
 {
-	struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+	struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *pkey = &ctx->key;
+	struct rsa_mpi_key *mpi_key = &ctx->mpi_key;
 
+	rsa_free_mpi_key(mpi_key);
 	rsa_free_key(pkey);
 }
 
@@ -304,13 +359,14 @@ static struct akcipher_alg rsa = {
 	.set_priv_key = rsa_set_priv_key,
 	.set_pub_key = rsa_set_pub_key,
 	.max_size = rsa_max_size,
+	.init = rsa_init_tfm,
 	.exit = rsa_exit_tfm,
 	.base = {
 		.cra_name = "rsa",
 		.cra_driver_name = "rsa-generic",
 		.cra_priority = 100,
 		.cra_module = THIS_MODULE,
-		.cra_ctxsize = sizeof(struct rsa_key),
+		.cra_ctxsize = sizeof(struct rsa_ctx),
 	},
 };
 
diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
index d226f48..95a4747 100644
--- a/crypto/rsa_helper.c
+++ b/crypto/rsa_helper.c
@@ -14,28 +14,56 @@
 #include <linux/export.h>
 #include <linux/err.h>
 #include <linux/fips.h>
+#include <linux/slab.h>
 #include <crypto/internal/rsa.h>
 #include "rsapubkey-asn1.h"
 #include "rsaprivkey-asn1.h"
 
+static int rsa_check_key_length(unsigned int len)
+{
+	switch (len) {
+	case 512:
+	case 1024:
+	case 1536:
+	case 2048:
+	case 3072:
+	case 4096:
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
 	      const void *value, size_t vlen)
 {
 	struct rsa_key *key = context;
+	const char *ptr = value;
+	int ret;
 
-	key->n = mpi_read_raw_data(value, vlen);
-
-	if (!key->n)
-		return -ENOMEM;
+	while (!*ptr && vlen) {
+		ptr++;
+		vlen--;
+	}
 
 	/* In FIPS mode only allow key size 2K & 3K */
-	if (fips_enabled && (mpi_get_size(key->n) != 256 &&
-			     mpi_get_size(key->n) != 384)) {
+	if (fips_enabled && (vlen != 256 && vlen != 384)) {
 		pr_err("RSA: key size not allowed in FIPS mode\n");
-		mpi_free(key->n);
-		key->n = NULL;
 		return -EINVAL;
 	}
+	/* invalid key size provided */
+	ret = rsa_check_key_length(vlen << 3);
+	if (ret)
+		return ret;
+
+	key->n = kzalloc(vlen, key->flags);
+	if (!key->n)
+		return -ENOMEM;
+
+	memcpy(key->n, ptr, vlen);
+
+	key->n_sz = vlen;
+
 	return 0;
 }
 
@@ -43,12 +71,24 @@ int rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
 	      const void *value, size_t vlen)
 {
 	struct rsa_key *key = context;
+	const char *ptr = value;
 
-	key->e = mpi_read_raw_data(value, vlen);
+	while (!*ptr && vlen) {
+		ptr++;
+		vlen--;
+	}
+
+	if (!key->n_sz || !vlen || vlen > key->n_sz)
+		return -EINVAL;
 
+	key->e = kzalloc(vlen, key->flags);
 	if (!key->e)
 		return -ENOMEM;
 
+	memcpy(key->e, ptr, vlen);
+
+	key->e_sz = vlen;
+
 	return 0;
 }
 
@@ -56,31 +96,29 @@ int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
 	      const void *value, size_t vlen)
 {
 	struct rsa_key *key = context;
+	const char *ptr = value;
 
-	key->d = mpi_read_raw_data(value, vlen);
+	while (!*ptr && vlen) {
+		ptr++;
+		vlen--;
+	}
 
-	if (!key->d)
-		return -ENOMEM;
+	if (!key->n_sz || !vlen || vlen > key->n_sz)
+		return -EINVAL;
 
 	/* In FIPS mode only allow key size 2K & 3K */
-	if (fips_enabled && (mpi_get_size(key->d) != 256 &&
-			     mpi_get_size(key->d) != 384)) {
+	if (fips_enabled && (vlen != 256 && vlen != 384)) {
 		pr_err("RSA: key size not allowed in FIPS mode\n");
-		mpi_free(key->d);
-		key->d = NULL;
 		return -EINVAL;
 	}
-	return 0;
-}
 
-static void free_mpis(struct rsa_key *key)
-{
-	mpi_free(key->n);
-	mpi_free(key->e);
-	mpi_free(key->d);
-	key->n = NULL;
-	key->e = NULL;
-	key->d = NULL;
+	key->d = kzalloc(vlen, key->flags);
+	if (!key->d)
+		return -ENOMEM;
+
+	memcpy(key->d, ptr, vlen);
+
+	return 0;
 }
 
 /**
@@ -90,7 +128,14 @@ static void free_mpis(struct rsa_key *key)
  */
 void rsa_free_key(struct rsa_key *key)
 {
-	free_mpis(key);
+	kzfree(key->d);
+	kfree(key->e);
+	kfree(key->n);
+	key->d = NULL;
+	key->e = NULL;
+	key->n = NULL;
+	key->n_sz = 0;
+	key->e_sz = 0;
 }
 EXPORT_SYMBOL_GPL(rsa_free_key);
 
@@ -109,14 +154,16 @@ int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
 {
 	int ret;
 
-	free_mpis(rsa_key);
+	/* Free the old key if any */
+	rsa_free_key(rsa_key);
+
 	ret = asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len);
 	if (ret < 0)
 		goto error;
 
 	return 0;
 error:
-	free_mpis(rsa_key);
+	rsa_free_key(rsa_key);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(rsa_parse_pub_key);
@@ -136,14 +183,16 @@ int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
 {
 	int ret;
 
-	free_mpis(rsa_key);
+	/* Free the old key if any */
+	rsa_free_key(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);
+	rsa_free_key(rsa_key);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(rsa_parse_priv_key);
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
index c7585bd..bafb974 100644
--- a/include/crypto/internal/rsa.h
+++ b/include/crypto/internal/rsa.h
@@ -12,12 +12,24 @@
  */
 #ifndef _RSA_HELPER_
 #define _RSA_HELPER_
-#include <linux/mpi.h>
+#include <linux/types.h>
 
+/**
+ * rsa_key - RSA key structure
+ * @n           : RSA modulus raw byte stream
+ * @e           : RSA public exponent raw byte stream
+ * @d           : RSA private exponent raw byte stream
+ * @n_sz        : length in bytes of RSA modulus n
+ * @e_sz        : length in bytes of RSA public exponent
+ * @flags       : gfp_t key allocation flags
+ */
 struct rsa_key {
-	MPI n;
-	MPI e;
-	MPI d;
+	u8 *n;
+	u8 *e;
+	u8 *d;
+	size_t n_sz;
+	size_t e_sz;
+	gfp_t flags;
 };
 
 int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 1/3] crypto: scatterwak - Add scatterwalk_sg_copychunks
From: Tudor Ambarus @ 2016-05-12 15:06 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Tudor Ambarus
In-Reply-To: <1463065578-14017-1-git-send-email-tudor-dan.ambarus@nxp.com>

This patch adds the function scatterwalk_sg_copychunks which writes
a chunk of data from a scatterwalk to another scatterwalk.
It will be used by caam driver to remove the leading zeros
for the output data of the RSA algorithm, after the computation completes.

Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
---
 crypto/scatterwalk.c         | 26 ++++++++++++++++++++++++++
 include/crypto/scatterwalk.h |  2 ++
 2 files changed, 28 insertions(+)

diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index ea5815c..bc3222d 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -125,6 +125,32 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
 }
 EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy);
 
+void scatterwalk_sg_copychunks(struct scatter_walk *dest,
+			       struct scatter_walk *src, size_t nbytes)
+{
+	for (;;) {
+		unsigned int len_this_page = scatterwalk_pagelen(dest);
+		u8 *vaddr;
+
+		if (len_this_page > nbytes)
+			len_this_page = nbytes;
+
+		vaddr = scatterwalk_map(dest);
+		scatterwalk_copychunks(vaddr, src, len_this_page, 0);
+		scatterwalk_unmap(vaddr);
+
+		scatterwalk_advance(dest, len_this_page);
+
+		if (nbytes == len_this_page)
+			break;
+
+		nbytes -= len_this_page;
+
+		scatterwalk_pagedone(dest, 0, 1);
+	}
+}
+EXPORT_SYMBOL_GPL(scatterwalk_sg_copychunks);
+
 int scatterwalk_bytes_sglen(struct scatterlist *sg, int num_bytes)
 {
 	int offset = 0, n = 0;
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 35f99b6..8b799c5 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -86,6 +86,8 @@ static inline void scatterwalk_unmap(void *vaddr)
 void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
 void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
 			    size_t nbytes, int out);
+void scatterwalk_sg_copychunks(struct scatter_walk *dest,
+			       struct scatter_walk *src, size_t nbytes);
 void *scatterwalk_map(struct scatter_walk *walk);
 void scatterwalk_done(struct scatter_walk *walk, int out, int more);
 
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 2/3] crypto: scatterwalk - export scatterwalk_pagedone
From: Tudor Ambarus @ 2016-05-12 15:06 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Tudor Ambarus
In-Reply-To: <1463065578-14017-1-git-send-email-tudor-dan.ambarus@nxp.com>

Used in caam driver. Export the symbol since the caam driver
can be built as a module.

Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
---
 crypto/scatterwalk.c         | 5 +++--
 include/crypto/scatterwalk.h | 2 ++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index bc3222d..03d34f9 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -47,8 +47,8 @@ void *scatterwalk_map(struct scatter_walk *walk)
 }
 EXPORT_SYMBOL_GPL(scatterwalk_map);
 
-static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
-				 unsigned int more)
+void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+			  unsigned int more)
 {
 	if (out) {
 		struct page *page;
@@ -69,6 +69,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
 			scatterwalk_start(walk, sg_next(walk->sg));
 	}
 }
+EXPORT_SYMBOL_GPL(scatterwalk_pagedone);
 
 void scatterwalk_done(struct scatter_walk *walk, int out, int more)
 {
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 8b799c5..6535a20 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -89,6 +89,8 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
 void scatterwalk_sg_copychunks(struct scatter_walk *dest,
 			       struct scatter_walk *src, size_t nbytes);
 void *scatterwalk_map(struct scatter_walk *walk);
+void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+			  unsigned int more);
 void scatterwalk_done(struct scatter_walk *walk, int out, int more);
 
 void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 3/3] crypto: caam - add support for RSA algorithm
From: Tudor Ambarus @ 2016-05-12 15:06 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Tudor Ambarus
In-Reply-To: <1463065578-14017-1-git-send-email-tudor-dan.ambarus@nxp.com>

Add RSA support to caam driver.

Coauthored-by: Yashpal Dutta <yashpal.dutta@freescale.com>

Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
---
 drivers/crypto/caam/Kconfig    |  12 ++
 drivers/crypto/caam/Makefile   |   4 +
 drivers/crypto/caam/caampkc.c  | 466 +++++++++++++++++++++++++++++++++++++++++
 drivers/crypto/caam/caampkc.h  |  94 +++++++++
 drivers/crypto/caam/desc.h     |   2 +
 drivers/crypto/caam/pdb.h      |  16 +-
 drivers/crypto/caam/pkc_desc.c | 138 ++++++++++++
 7 files changed, 731 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/caam/caampkc.c
 create mode 100644 drivers/crypto/caam/caampkc.h
 create mode 100644 drivers/crypto/caam/pkc_desc.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 5652a53..44449ba 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -99,6 +99,18 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API
 	  To compile this as a module, choose M here: the module
 	  will be called caamhash.
 
+config CRYPTO_DEV_FSL_CAAM_PKC_API
+        tristate "Register public key cryptography implementations with Crypto API"
+        depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
+        default y
+        select CRYPTO_RSA
+        help
+          Selecting this will allow SEC Public key support for RSA.
+          Supported cryptographic primitives: encryption, decryption,
+          signature and verification.
+          To compile this as a module, choose M here: the module
+          will be called caam_pkc.
+
 config CRYPTO_DEV_FSL_CAAM_RNG_API
 	tristate "Register caam device for hwrng API"
 	depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 550758a..399ad55 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -5,11 +5,15 @@ ifeq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG), y)
 	EXTRA_CFLAGS := -DDEBUG
 endif
 
+ccflags-y += -I$(srctree)/crypto
+
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o
 
 caam-objs := ctrl.o
 caam_jr-objs := jr.o key_gen.o error.o
+caam_pkc-y := caampkc.o pkc_desc.o
diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c
new file mode 100644
index 0000000..34ffa87
--- /dev/null
+++ b/drivers/crypto/caam/caampkc.c
@@ -0,0 +1,466 @@
+/*
+ * caam - Freescale FSL CAAM support for Public Key Cryptography
+ *
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
+ * all the desired key parameters, input and output pointers.
+ */
+#include <linux/dma-mapping.h>
+#include <linux/fips.h>
+#include "compat.h"
+#include "caampkc.h"
+#include "sg_sw_sec4.h"
+#include "regs.h"
+#include "intern.h"
+#include "jr.h"
+#include "error.h"
+
+static void rsa_io_unmap(struct device *dev, struct rsa_edesc *edesc,
+			 struct akcipher_request *req)
+{
+	dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
+	dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
+}
+
+static void rsa_pub_unmap(struct device *dev, struct rsa_edesc *edesc,
+			  struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *key = &ctx->key;
+	struct rsa_pub_desc *hw_desc = (struct rsa_pub_desc *)edesc->hw_desc;
+
+	dma_unmap_single(dev, hw_desc->n_dma, key->n_sz, DMA_TO_DEVICE);
+	dma_unmap_single(dev, hw_desc->e_dma, key->e_sz, DMA_TO_DEVICE);
+}
+
+static void rsa_priv_f1_unmap(struct device *dev, struct rsa_edesc *edesc,
+			      struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *key = &ctx->key;
+	struct rsa_priv_f1_desc *hw_desc =
+			(struct rsa_priv_f1_desc *)edesc->hw_desc;
+
+	dma_unmap_single(dev, hw_desc->n_dma, key->n_sz, DMA_TO_DEVICE);
+	dma_unmap_single(dev, hw_desc->d_dma, key->n_sz, DMA_TO_DEVICE);
+}
+
+static size_t skip_to_nonzero(u8 *ptr, size_t nbytes)
+{
+	size_t nr_zeros = 0;
+
+	while (!(*ptr) && nbytes) {
+		nbytes--;
+		ptr++;
+		nr_zeros++;
+	}
+
+	return nr_zeros;
+}
+
+static size_t scatterwalk_skip_zeros(struct scatter_walk *walk, size_t nbytes)
+{
+	size_t len_this_page, nr_zeros, cnt = 0;
+	u8 *vaddr, *ptr;
+
+	for (;;) {
+		nr_zeros = 0;
+		len_this_page = scatterwalk_pagelen(walk);
+
+		if (len_this_page > nbytes)
+			len_this_page = nbytes;
+
+		vaddr = scatterwalk_map(walk);
+		ptr = vaddr;
+		nr_zeros = skip_to_nonzero(ptr, len_this_page);
+		scatterwalk_unmap(vaddr);
+
+		/* count total number of zeros */
+		cnt += nr_zeros;
+
+		/* advance scatterwalk to the nonzero data */
+		scatterwalk_advance(walk, nr_zeros);
+
+		if (nr_zeros < len_this_page || nbytes == len_this_page)
+			break;
+
+		nbytes -= len_this_page;
+
+		scatterwalk_pagedone(walk, 0, 1);
+	}
+
+	return cnt;
+}
+
+/*
+ * This function drops the leading zeros and copies the data to the initial
+ * pointer so that it can be freed later on. Returns the updated data length.
+ */
+static size_t drop_leading_zeros(struct scatterlist *sg, size_t nbytes)
+{
+	struct scatter_walk walk_src, walk_dst;
+	size_t nr_zeros = 0;
+
+	scatterwalk_start(&walk_src, sg);
+	nr_zeros = scatterwalk_skip_zeros(&walk_src, nbytes);
+
+	if (nr_zeros) {
+		nbytes = nbytes - nr_zeros;
+
+		scatterwalk_start(&walk_dst, sg);
+		scatterwalk_sg_copychunks(&walk_dst, &walk_src, nbytes);
+		scatterwalk_done(&walk_dst, 0, 0);
+	}
+
+	scatterwalk_done(&walk_src, 0, 0);
+
+	return nbytes;
+}
+
+/* RSA Job Completion handler */
+static void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void *context)
+{
+	struct akcipher_request *req = context;
+	struct rsa_edesc *edesc;
+
+	if (err)
+		caam_jr_strstatus(dev, err);
+
+	/*
+	 * RSA's output is expected to be a big integer. Drop the leading
+	 * zeros since they are not meaningful in the world of numbers.
+	 */
+	req->dst_len = drop_leading_zeros(req->dst, req->dst_len);
+
+	edesc = container_of(desc, struct rsa_edesc, hw_desc[0]);
+
+	rsa_pub_unmap(dev, edesc, req);
+	rsa_io_unmap(dev, edesc, req);
+	kfree(edesc);
+
+	akcipher_request_complete(req, err);
+}
+
+static void rsa_priv_f1_done(struct device *dev, u32 *desc, u32 err,
+			     void *context)
+{
+	struct akcipher_request *req = context;
+	struct rsa_edesc *edesc;
+
+	if (err)
+		caam_jr_strstatus(dev, err);
+
+	/*
+	 * RSA's output is expected to be a big integer. Drop the leading
+	 * zeros since they are not meaningful in the world of numbers.
+	 */
+	req->dst_len = drop_leading_zeros(req->dst, req->dst_len);
+
+	edesc = container_of(desc, struct rsa_edesc, hw_desc[0]);
+
+	rsa_priv_f1_unmap(dev, edesc, req);
+	rsa_io_unmap(dev, edesc, req);
+	kfree(edesc);
+
+	akcipher_request_complete(req, err);
+}
+
+static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req,
+					 size_t desclen)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct device *dev = ctx->dev;
+	struct rsa_edesc *edesc;
+	gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+		       CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+	int sgc;
+	int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
+	int src_nents, dst_nents;
+
+	src_nents = sg_nents_for_len(req->src, req->src_len);
+	dst_nents = sg_nents_for_len(req->dst, req->dst_len);
+
+	if (src_nents > 1)
+		sec4_sg_len = src_nents;
+	if (dst_nents > 1)
+		sec4_sg_len += dst_nents;
+
+	sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
+
+	/* allocate space for base edesc, hw desc commands and link tables */
+	edesc = kzalloc(sizeof(*edesc) + desclen + sec4_sg_bytes,
+			GFP_DMA | flags);
+	if (!edesc)
+		return ERR_PTR(-ENOMEM);
+
+	sgc = dma_map_sg(dev, req->src, src_nents, DMA_TO_DEVICE);
+	if (unlikely(!sgc)) {
+		dev_err(dev, "unable to map source\n");
+		goto src_fail;
+	}
+
+	sgc = dma_map_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
+	if (unlikely(!sgc)) {
+		dev_err(dev, "unable to map destination\n");
+		goto dst_fail;
+	}
+
+	edesc->sec4_sg = (void *)edesc + sizeof(*edesc) + desclen;
+
+	sec4_sg_index = 0;
+	if (src_nents > 1) {
+		sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0);
+		sec4_sg_index += src_nents;
+	}
+	if (dst_nents > 1) {
+		sg_to_sec4_sg_last(req->dst, dst_nents,
+				   edesc->sec4_sg + sec4_sg_index, 0);
+	}
+
+	/* Save nents for later use in Job Descriptor. */
+	edesc->src_nents = src_nents;
+	edesc->dst_nents = dst_nents;
+
+	if (!sec4_sg_bytes)
+		return edesc;
+
+	edesc->sec4_sg_dma = dma_map_single(dev, edesc->sec4_sg,
+					    sec4_sg_bytes, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, edesc->sec4_sg_dma)) {
+		dev_err(dev, "unable to map S/G table\n");
+		goto sec4_sg_fail;
+	}
+
+	return edesc;
+
+sec4_sg_fail:
+	dma_unmap_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
+dst_fail:
+	dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE);
+src_fail:
+	kfree(edesc);
+	return ERR_PTR(-ENOMEM);
+}
+
+static int caam_rsa_enc(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *key = &ctx->key;
+	struct device *jrdev = ctx->dev;
+	struct rsa_edesc *edesc = NULL;
+	size_t desclen = sizeof(struct rsa_pub_desc);
+	int ret;
+
+	if (unlikely(!key->n || !key->e))
+		return -EINVAL;
+
+	if (req->dst_len < key->n_sz) {
+		req->dst_len = key->n_sz;
+		dev_err(jrdev, "Output buffer length less than parameter n\n");
+		return -EOVERFLOW;
+	}
+
+	/* Allocate extended descriptor. */
+	edesc = rsa_edesc_alloc(req, desclen);
+	if (IS_ERR(edesc))
+		return PTR_ERR(edesc);
+
+	/* Initialize Job Descriptor. */
+	ret = init_rsa_pub_desc(req, edesc);
+	if (ret)
+		goto init_fail;
+
+	ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_pub_done, req);
+	if (!ret)
+		return -EINPROGRESS;
+
+	rsa_pub_unmap(jrdev, edesc, req);
+
+init_fail:
+	rsa_io_unmap(jrdev, edesc, req);
+	kfree(edesc);
+	return ret;
+}
+
+static int caam_rsa_dec(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *key = &ctx->key;
+	struct device *jrdev = ctx->dev;
+	struct rsa_edesc *edesc = NULL;
+	size_t desclen = sizeof(struct rsa_priv_f1_desc);
+	int ret;
+
+	if (unlikely(!key->n || !key->d))
+		return -EINVAL;
+
+	if (req->dst_len < key->n_sz) {
+		req->dst_len = key->n_sz;
+		return -EOVERFLOW;
+	}
+
+	/* Allocate extended descriptor. */
+	edesc = rsa_edesc_alloc(req, desclen);
+	if (IS_ERR(edesc))
+		return PTR_ERR(edesc);
+
+	/* Initialize Job Descriptor. */
+	ret = init_rsa_priv_f1_desc(req, edesc);
+	if (ret)
+		goto init_fail;
+
+	ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_priv_f1_done, req);
+	if (!ret)
+		return -EINPROGRESS;
+
+	rsa_priv_f1_unmap(jrdev, edesc, req);
+
+init_fail:
+	rsa_io_unmap(jrdev, edesc, req);
+	kfree(edesc);
+	return ret;
+}
+
+static int caam_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+				unsigned int keylen)
+{
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *rsa_key = &ctx->key;
+
+	return rsa_parse_pub_key(rsa_key, key, keylen);
+}
+
+static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+				 unsigned int keylen)
+{
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *rsa_key = &ctx->key;
+
+	return rsa_parse_priv_key(rsa_key, key, keylen);
+}
+
+static int caam_rsa_max_size(struct crypto_akcipher *tfm)
+{
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *key = &ctx->key;
+
+	return (key->n) ? key->n_sz : -EINVAL;
+}
+
+/* Per session pkc's driver context creation function */
+static int caam_rsa_init_tfm(struct crypto_akcipher *tfm)
+{
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *key = &ctx->key;
+
+	ctx->dev = caam_jr_alloc();
+
+	if (IS_ERR(ctx->dev)) {
+		dev_err(ctx->dev, "Job Ring Device allocation for transform failed\n");
+		return PTR_ERR(ctx->dev);
+	}
+
+	key->flags = GFP_DMA | GFP_KERNEL;
+	return 0;
+}
+
+/* Per session pkc's driver context cleanup function */
+static void caam_rsa_exit_tfm(struct crypto_akcipher *tfm)
+{
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *key = &ctx->key;
+
+	rsa_free_key(key);
+	caam_jr_free(ctx->dev);
+}
+
+static struct akcipher_alg caam_rsa = {
+	.encrypt = caam_rsa_enc,
+	.decrypt = caam_rsa_dec,
+	.sign = caam_rsa_dec,
+	.verify = caam_rsa_enc,
+	.set_pub_key = caam_rsa_set_pub_key,
+	.set_priv_key = caam_rsa_set_priv_key,
+	.max_size = caam_rsa_max_size,
+	.init = caam_rsa_init_tfm,
+	.exit = caam_rsa_exit_tfm,
+	.base = {
+		.cra_name = "rsa",
+		.cra_driver_name = "rsa-caam",
+		.cra_priority = 3000,
+		.cra_module = THIS_MODULE,
+		.cra_alignmask = 0,
+		.cra_ctxsize = sizeof(struct caam_rsa_ctx),
+	},
+};
+
+/* Public Key Cryptography module initialization handler */
+static int __init caam_pkc_init(void)
+{
+	struct device_node *dev_node;
+	struct platform_device *pdev;
+	struct device *ctrldev;
+	struct caam_drv_private *priv;
+	u32 cha_inst, pk_inst;
+	int err = 0;
+
+	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+	if (!dev_node) {
+		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+		if (!dev_node)
+			return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(dev_node);
+	if (!pdev) {
+		of_node_put(dev_node);
+		return -ENODEV;
+	}
+
+	ctrldev = &pdev->dev;
+	priv = dev_get_drvdata(ctrldev);
+	of_node_put(dev_node);
+
+	/*
+	 * If priv is NULL, it's probably because the caam driver wasn't
+	 * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+	 */
+	if (!priv)
+		return -ENODEV;
+
+	/* Determine public key hardware accelerator presence. */
+	cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
+	pk_inst = (cha_inst & CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT;
+
+	/* Do not register algorithms if PKHA is not present. */
+	if (!pk_inst)
+		return -ENODEV;
+
+	caam_rsa.base.cra_flags = 0;
+	err = crypto_register_akcipher(&caam_rsa);
+	if (err)
+		dev_warn(ctrldev, "%s alg registration failed\n",
+			 caam_rsa.base.cra_driver_name);
+	else
+		dev_info(ctrldev, "caam algorithms registered in /proc/crypto\n");
+
+	return err;
+}
+
+static void __exit caam_pkc_exit(void)
+{
+	crypto_unregister_akcipher(&caam_rsa);
+}
+
+module_init(caam_pkc_init);
+module_exit(caam_pkc_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL CAAM support for PKC functions of crypto API");
+MODULE_AUTHOR("Freescale Semiconductor");
diff --git a/drivers/crypto/caam/caampkc.h b/drivers/crypto/caam/caampkc.h
new file mode 100644
index 0000000..398a881
--- /dev/null
+++ b/drivers/crypto/caam/caampkc.h
@@ -0,0 +1,94 @@
+/*
+ * caam - Freescale FSL CAAM support for Public Key Cryptography descriptors
+ *
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
+ * all the desired key parameters, input and output pointers.
+ */
+
+#ifndef _PKC_DESC_H_
+#define _PKC_DESC_H_
+
+#include <crypto/internal/rsa.h>
+#include <crypto/akcipher.h>
+#include <crypto/internal/akcipher.h>
+#include "desc_constr.h"
+#include "pdb.h"
+#include "rsapubkey-asn1.h"
+#include "rsaprivkey-asn1.h"
+
+/**
+ * caam_rsa_ctx - per session context.
+ * @key: RSA key structure
+ * @dev: device structure
+ */
+struct caam_rsa_ctx {
+	struct rsa_key key;
+	struct device *dev;
+};
+
+/**
+ * RSA Pub_Key Descriptor
+ * @desc_hdr: Job Descriptor Header command
+ * @sgf: scatter-gather field
+ * @f_dma: dma address of input data
+ * @g_dma: dma address of ecrypted output data
+ * @n_dma: dma address of RSA public exponent
+ * @dma_e: dma address of RSA public exponent
+ * @f_len: length in octets of the input data
+ * @op: RSA Operation command
+ */
+struct rsa_pub_desc {
+	u32		desc_hdr;
+	u32		sgf;
+	dma_addr_t	f_dma;
+	dma_addr_t	g_dma;
+	dma_addr_t	n_dma;
+	dma_addr_t	e_dma;
+	u32		f_len;
+	u32		op;
+} __packed;
+
+/**
+ * Form1 Priv_key Decryption Descriptor.
+ * Private key is represented by (n,d).
+ * @desc_hdr: Job Descriptor Header command
+ * @sgf: scatter-gather field
+ * @g_dma: dma address of ecrypted input data
+ * @f_dma: dma address of output data
+ * @n_dma: dma address of RSA public exponent
+ * @dma_d: dma address of RSA private exponent
+ * @op: RSA Operation command
+ */
+struct rsa_priv_f1_desc {
+	u32		desc_hdr;
+	u32		sgf;
+	dma_addr_t	g_dma;
+	dma_addr_t	f_dma;
+	dma_addr_t	n_dma;
+	dma_addr_t	d_dma;
+	u32		op;
+} __packed;
+
+/**
+ * rsa_edesc - s/w-extended rsa descriptor
+ * @src_nents: number of segments in input scatterlist
+ * @dst_nents: number of segments in output scatterlist
+ * @sec4_sg_dma: dma address of h/w link table
+ * @sec4_sg: pointer to h/w link table
+ * @hw_desc: descriptor followed by link tables if any
+ */
+struct rsa_edesc {
+	int src_nents;
+	int dst_nents;
+	dma_addr_t sec4_sg_dma;
+	struct sec4_sg_entry *sec4_sg;
+	u32 hw_desc[];
+};
+
+/* Descriptor construction primitives. */
+int init_rsa_pub_desc(struct akcipher_request *req, struct rsa_edesc *edesc);
+int init_rsa_priv_f1_desc(struct akcipher_request *req,
+			  struct rsa_edesc *edesc);
+#endif
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 1e93c6a..7e5c027 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -454,6 +454,8 @@ struct sec4_sg_entry {
 #define OP_PCLID_PUBLICKEYPAIR	(0x14 << OP_PCLID_SHIFT)
 #define OP_PCLID_DSASIGN	(0x15 << OP_PCLID_SHIFT)
 #define OP_PCLID_DSAVERIFY	(0x16 << OP_PCLID_SHIFT)
+#define OP_PCLID_RSAENC_PUBKEY  (0x18 << OP_PCLID_SHIFT)
+#define OP_PCLID_RSADEC_PRVKEY  (0x19 << OP_PCLID_SHIFT)
 
 /* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */
 #define OP_PCLID_IPSEC		(0x01 << OP_PCLID_SHIFT)
diff --git a/drivers/crypto/caam/pdb.h b/drivers/crypto/caam/pdb.h
index 3a87c0c..1c68d7b 100644
--- a/drivers/crypto/caam/pdb.h
+++ b/drivers/crypto/caam/pdb.h
@@ -1,7 +1,7 @@
 /*
  * CAAM Protocol Data Block (PDB) definition header file
  *
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2016 Freescale Semiconductor, Inc.
  *
  */
 
@@ -399,4 +399,18 @@ struct dsa_verify_pdb {
 	u8 *ab; /* only used if ECC processing */
 };
 
+/* RSA Protocol Data Block */
+#define RSA_PDB_SGF_SHIFT       28
+#define RSA_PDB_E_SHIFT         12
+#define RSA_PDB_E_MASK          (0xFFF << RSA_PDB_E_SHIFT)
+#define RSA_PDB_D_SHIFT         12
+#define RSA_PDB_D_MASK          (0xFFF << RSA_PDB_D_SHIFT)
+
+#define RSA_PDB_SGF_F           (0x8 << RSA_PDB_SGF_SHIFT)
+#define RSA_PDB_SGF_G           (0x4 << RSA_PDB_SGF_SHIFT)
+#define RSA_PRIV_PDB_SGF_F      (0x4 << RSA_PDB_SGF_SHIFT)
+#define RSA_PRIV_PDB_SGF_G      (0x8 << RSA_PDB_SGF_SHIFT)
+
+#define RSA_PRIV_KEY_FRM_1      0
+
 #endif
diff --git a/drivers/crypto/caam/pkc_desc.c b/drivers/crypto/caam/pkc_desc.c
new file mode 100644
index 0000000..25c0690
--- /dev/null
+++ b/drivers/crypto/caam/pkc_desc.c
@@ -0,0 +1,138 @@
+/*
+ * caam - Freescale FSL CAAM support for Public Key Cryptography descriptors
+ *
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
+ * all the desired key parameters, input and output pointers.
+ */
+#include "caampkc.h"
+
+/* Descriptor for RSA Public operation */
+int init_rsa_pub_desc(struct akcipher_request *req, struct rsa_edesc *edesc)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *key = &ctx->key;
+	struct device *dev = ctx->dev;
+	struct rsa_pub_desc *desc = (struct rsa_pub_desc *)edesc->hw_desc;
+	u32 start_idx, desc_size;
+	int sec4_sg_index = 0;
+
+	/*
+	 * The PDB has static fields and can be initialized before writing
+	 * a specific command. Map the memory first, since it can be a point
+	 * of failure.
+	 */
+	desc->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, desc->n_dma)) {
+		dev_err(dev, "Unable to map  modulus memory\n");
+		goto n_fail;
+	}
+
+	desc->e_dma = dma_map_single(dev, key->e, key->e_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, desc->e_dma)) {
+		dev_err(dev, "Unable to map exponent memory\n");
+		goto e_fail;
+	}
+
+	desc_size = sizeof(*desc) / CAAM_CMD_SZ;
+	start_idx = (desc_size - 1) & HDR_START_IDX_MASK;
+	init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
+		      (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+
+	sec4_sg_index = 0;
+	if (edesc->src_nents > 1) {
+		desc->sgf |= RSA_PDB_SGF_F;
+		desc->f_dma = edesc->sec4_sg_dma;
+		sec4_sg_index += edesc->src_nents;
+	} else {
+		desc->f_dma = sg_dma_address(req->src);
+	}
+
+	if (edesc->dst_nents > 1) {
+		desc->sgf |= RSA_PDB_SGF_G;
+		desc->g_dma = edesc->sec4_sg_dma +
+			sec4_sg_index * sizeof(struct sec4_sg_entry);
+	} else {
+		desc->g_dma = sg_dma_address(req->dst);
+	}
+
+	desc->sgf |= (key->e_sz << RSA_PDB_E_SHIFT) | key->n_sz;
+	desc->f_len = req->src_len;
+	desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+		   OP_PCLID_RSAENC_PUBKEY;
+	return 0;
+
+e_fail:
+	dma_unmap_single(dev, desc->n_dma, key->n_sz, DMA_TO_DEVICE);
+n_fail:
+	dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
+	dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
+	kfree(edesc);
+	return -ENOMEM;
+}
+
+/* Descriptor for RSA Private operation */
+int init_rsa_priv_f1_desc(struct akcipher_request *req, struct rsa_edesc *edesc)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct rsa_key *key = &ctx->key;
+	struct device *dev = ctx->dev;
+	struct rsa_priv_f1_desc *desc =
+			(struct rsa_priv_f1_desc *)edesc->hw_desc;
+	int sec4_sg_index = 0;
+	u32 start_idx, desc_size;
+
+	/*
+	 * The PDB has static fields and can be initialized before writing
+	 * a specific command. Map the memory first, since it can be a point
+	 * of failure.
+	 */
+	desc->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, desc->n_dma)) {
+		dev_err(dev, "Unable to map  modulus memory\n");
+		goto n_fail;
+	}
+
+	desc->d_dma = dma_map_single(dev, key->d, key->n_sz, DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, desc->d_dma)) {
+		dev_err(dev, "Unable to map exponent memory\n");
+		goto d_fail;
+	}
+
+	desc_size = sizeof(*desc) / CAAM_CMD_SZ;
+	start_idx = (desc_size - 1) & HDR_START_IDX_MASK;
+	init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
+		      (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+
+	if (edesc->src_nents > 1) {
+		desc->sgf |= RSA_PRIV_PDB_SGF_G;
+		desc->g_dma = edesc->sec4_sg_dma;
+		sec4_sg_index += edesc->src_nents;
+	} else {
+		desc->g_dma = sg_dma_address(req->src);
+	}
+
+	if (edesc->dst_nents > 1) {
+		desc->sgf |= RSA_PRIV_PDB_SGF_F;
+		desc->f_dma = edesc->sec4_sg_dma +
+			sec4_sg_index * sizeof(struct sec4_sg_entry);
+	} else {
+		desc->f_dma = sg_dma_address(req->dst);
+	}
+
+	desc->sgf |= (key->n_sz << RSA_PDB_D_SHIFT) | key->n_sz;
+	desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+		   OP_PCLID_RSADEC_PRVKEY | RSA_PRIV_KEY_FRM_1;
+	return 0;
+
+d_fail:
+	dma_unmap_single(dev, desc->n_dma, key->n_sz, DMA_TO_DEVICE);
+n_fail:
+	dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
+	dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
+	kfree(edesc);
+	return -ENOMEM;
+}
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v5 0/3] crypto: caam - add support for RSA algorithm
From: Tudor Ambarus @ 2016-05-12 15:06 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, Tudor Ambarus

Depends on:
[PATCH v2] crypto: rsa - return raw integers for the ASN.1 parser

Changes from v4:
- sync with ASN.1 parser

Changes from v3:
- sync with ASN.1 parser

Changes from v2:
- sync with ASN.1 parser

Changes from initial patch:
- fix memory leaks on error path
- rename struct akcipher_alg rsa to caam_rsa

Tudor Ambarus (3):
  crypto: scatterwak - Add scatterwalk_sg_copychunks
  crypto: scatterwalk - export scatterwalk_pagedone
  crypto: caam - add support for RSA algorithm

 crypto/scatterwalk.c           |  31 ++-
 drivers/crypto/caam/Kconfig    |  12 ++
 drivers/crypto/caam/Makefile   |   4 +
 drivers/crypto/caam/caampkc.c  | 466 +++++++++++++++++++++++++++++++++++++++++
 drivers/crypto/caam/caampkc.h  |  94 +++++++++
 drivers/crypto/caam/desc.h     |   2 +
 drivers/crypto/caam/pdb.h      |  16 +-
 drivers/crypto/caam/pkc_desc.c | 138 ++++++++++++
 include/crypto/scatterwalk.h   |   4 +
 9 files changed, 764 insertions(+), 3 deletions(-)
 create mode 100644 drivers/crypto/caam/caampkc.c
 create mode 100644 drivers/crypto/caam/caampkc.h
 create mode 100644 drivers/crypto/caam/pkc_desc.c

-- 
1.8.3.1

^ permalink raw reply

* Re: [RFC PATCH 2/8] KEYS: Provide keyctls to drive the new key type ops for asymmetric keys [ver 3]
From: David Woodhouse @ 2016-05-12 11:04 UTC (permalink / raw)
  To: Mat Martineau, David Howells
  Cc: tadeusz.struk, linux-kernel, linux-security-module, keyrings,
	linux-crypto
In-Reply-To: <alpine.OSX.2.20.1605111426140.16566@mjmartin-mac01.local>

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

On Wed, 2016-05-11 at 15:17 -0700, Mat Martineau wrote:
> 
> On Wed, 11 May 2016, David Howells wrote:
> 
> > diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
> > index ca72b70a24b9..01c2ae28a8c0 100644
> > --- a/Documentation/security/keys.txt
> > +++ b/Documentation/security/keys.txt
> > +     If the key needs to be unlocked with a password, a logon-type key that
> > +     holds the password may be given as the password argument
> ...
> > +     If the key must be unlocked with a password before it can be used,
> > +     password_id should point to a logon-type key that holds this.
> 
> It should be noted that the password_id should be 0 if no password is to 
> be used.

Hm, I would like to properly explore the use cases for these passwords,
before any API is set in stone.

To start with, I'll insist quite strongly that we should never be
passing an encrypted key into the kernel alongside the password needed
to decrypt it. We should let userspace do that gruntwork, and pass in a
canonical DER PKCS#8 (or PKCS#1) blob. As I said before, the other way
lies madness, and requests to support all the obscure formats that keys
are stored in.

So where *might* we want a password... mostly for things like TPM and
other crypto hardware (USB tokens, HSMs). And the usage model there is
normally that the password isn't tied to the *key*, it's a password or
PIN to unlock the *device*.

So I'm not quite sure this 'password_id' makes much sense at all...
unless the idea is that you load the (encrypted) key in advance and
then request the password *later* on demand, in order to use it? Is
that something we really need to support?

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 5760 bytes --]

^ permalink raw reply

* Re: [RFC PATCH 8/8] KEYS: Implement PKCS#8 RSA Private Key parser [ver 3]
From: David Howells @ 2016-05-12 10:20 UTC (permalink / raw)
  To: Mat Martineau
  Cc: dhowells, tadeusz.struk, linux-kernel, linux-security-module,
	keyrings, linux-crypto, dwmw2
In-Reply-To: <alpine.OSX.2.20.1605111707120.16566@mjmartin-mac01.local>

Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:

> > # PKCS#7 message handling
> 
> Update to PKCS#8

I guess I've typed PKCS#7 too many times :-)

David

^ permalink raw reply

* Re: [RFC PATCH 5/8] KEYS: Provide software public key query function [ver 3]
From: David Howells @ 2016-05-12 10:19 UTC (permalink / raw)
  To: Mat Martineau, tadeusz.struk
  Cc: dhowells, linux-kernel, linux-security-module, keyrings,
	linux-crypto, dwmw2
In-Reply-To: <alpine.OSX.2.20.1605111624090.16566@mjmartin-mac01.local>

Mat Martineau <mathew.j.martineau@linux.intel.com> wrote:

> > +	len = crypto_akcipher_maxsize(tfm);
> > +	info->key_size = len * 8;
> > +	info->max_data_size = len;
> > +	info->max_sig_size = len;
> > +	info->max_enc_size = len;
> > +	info->max_dec_size = len;
> 
> If len > UINT16_MAX, should UINT16_MAX be reported as the max size? Similar
> question for len*8 and key_size.

key_size is 32 bits, but the other sizes are all 16 bits, so you would need a
524288-bit key to exceed their capacity.  I'm not sure that's likely anytime
soon, but should I just make all the sizes 32-bit anyway?

David

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox