crypto: ecc - make ecc into separate module

ecc.c have algorithms that could be used togeter by ecdh and ecrdsa.
Make it separate module. Add CRYPTO_ECC into Kconfig. EXPORT_SYMBOL and
document to what seems appropriate. Move structs ecc_point and ecc_curve
from ecc_curve_defs.h into ecc.h.

No code changes.

Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Vitaly Chikunov 2019-04-11 18:51:19 +03:00 committed by Herbert Xu
parent 3d6228a505
commit 4a2289dae0
5 changed files with 122 additions and 23 deletions

View File

@ -248,8 +248,12 @@ config CRYPTO_DH
help help
Generic implementation of the Diffie-Hellman algorithm. Generic implementation of the Diffie-Hellman algorithm.
config CRYPTO_ECC
tristate
config CRYPTO_ECDH config CRYPTO_ECDH
tristate "ECDH algorithm" tristate "ECDH algorithm"
select CRYPTO_ECC
select CRYPTO_KPP select CRYPTO_KPP
select CRYPTO_RNG_DEFAULT select CRYPTO_RNG_DEFAULT
help help

View File

@ -147,8 +147,8 @@ obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o
obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o
obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o
obj-$(CONFIG_CRYPTO_OFB) += ofb.o obj-$(CONFIG_CRYPTO_OFB) += ofb.o
obj-$(CONFIG_CRYPTO_ECC) += ecc.o
ecdh_generic-y := ecc.o
ecdh_generic-y += ecdh.o ecdh_generic-y += ecdh.o
ecdh_generic-y += ecdh_helper.o ecdh_generic-y += ecdh_helper.o
obj-$(CONFIG_CRYPTO_ECDH) += ecdh_generic.o obj-$(CONFIG_CRYPTO_ECDH) += ecdh_generic.o

View File

@ -24,6 +24,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <linux/module.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/swab.h> #include <linux/swab.h>
@ -112,7 +113,7 @@ static void vli_clear(u64 *vli, unsigned int ndigits)
} }
/* Returns true if vli == 0, false otherwise. */ /* Returns true if vli == 0, false otherwise. */
static bool vli_is_zero(const u64 *vli, unsigned int ndigits) bool vli_is_zero(const u64 *vli, unsigned int ndigits)
{ {
int i; int i;
@ -123,6 +124,7 @@ static bool vli_is_zero(const u64 *vli, unsigned int ndigits)
return true; return true;
} }
EXPORT_SYMBOL(vli_is_zero);
/* Returns nonzero if bit bit of vli is set. */ /* Returns nonzero if bit bit of vli is set. */
static u64 vli_test_bit(const u64 *vli, unsigned int bit) static u64 vli_test_bit(const u64 *vli, unsigned int bit)
@ -171,7 +173,7 @@ static void vli_set(u64 *dest, const u64 *src, unsigned int ndigits)
} }
/* Returns sign of left - right. */ /* Returns sign of left - right. */
static int vli_cmp(const u64 *left, const u64 *right, unsigned int ndigits) int vli_cmp(const u64 *left, const u64 *right, unsigned int ndigits)
{ {
int i; int i;
@ -184,6 +186,7 @@ static int vli_cmp(const u64 *left, const u64 *right, unsigned int ndigits)
return 0; return 0;
} }
EXPORT_SYMBOL(vli_cmp);
/* Computes result = in << c, returning carry. Can modify in place /* Computes result = in << c, returning carry. Can modify in place
* (if result == in). 0 < shift < 64. * (if result == in). 0 < shift < 64.
@ -240,7 +243,7 @@ static u64 vli_add(u64 *result, const u64 *left, const u64 *right,
} }
/* Computes result = left - right, returning borrow. Can modify in place. */ /* Computes result = left - right, returning borrow. Can modify in place. */
static u64 vli_sub(u64 *result, const u64 *left, const u64 *right, u64 vli_sub(u64 *result, const u64 *left, const u64 *right,
unsigned int ndigits) unsigned int ndigits)
{ {
u64 borrow = 0; u64 borrow = 0;
@ -258,6 +261,7 @@ static u64 vli_sub(u64 *result, const u64 *left, const u64 *right,
return borrow; return borrow;
} }
EXPORT_SYMBOL(vli_sub);
static uint128_t mul_64_64(u64 left, u64 right) static uint128_t mul_64_64(u64 left, u64 right)
{ {
@ -557,7 +561,7 @@ static void vli_mod_square_fast(u64 *result, const u64 *left,
* See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" * See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
* https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf * https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf
*/ */
static void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod, void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod,
unsigned int ndigits) unsigned int ndigits)
{ {
u64 a[ECC_MAX_DIGITS], b[ECC_MAX_DIGITS]; u64 a[ECC_MAX_DIGITS], b[ECC_MAX_DIGITS];
@ -630,6 +634,7 @@ static void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod,
vli_set(result, u, ndigits); vli_set(result, u, ndigits);
} }
EXPORT_SYMBOL(vli_mod_inv);
/* ------ Point operations ------ */ /* ------ Point operations ------ */
@ -948,6 +953,7 @@ int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits,
return __ecc_is_key_valid(curve, private_key, ndigits); return __ecc_is_key_valid(curve, private_key, ndigits);
} }
EXPORT_SYMBOL(ecc_is_key_valid);
/* /*
* ECC private keys are generated using the method of extra random bits, * ECC private keys are generated using the method of extra random bits,
@ -1000,6 +1006,7 @@ int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey)
return 0; return 0;
} }
EXPORT_SYMBOL(ecc_gen_privkey);
int ecc_make_pub_key(unsigned int curve_id, unsigned int ndigits, int ecc_make_pub_key(unsigned int curve_id, unsigned int ndigits,
const u64 *private_key, u64 *public_key) const u64 *private_key, u64 *public_key)
@ -1036,10 +1043,11 @@ err_free_point:
out: out:
return ret; return ret;
} }
EXPORT_SYMBOL(ecc_make_pub_key);
/* SP800-56A section 5.6.2.3.4 partial verification: ephemeral keys only */ /* SP800-56A section 5.6.2.3.4 partial verification: ephemeral keys only */
static int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve, int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
struct ecc_point *pk) struct ecc_point *pk)
{ {
u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS]; u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS];
@ -1064,8 +1072,8 @@ static int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
EXPORT_SYMBOL(ecc_is_pubkey_valid_partial);
int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits, int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
const u64 *private_key, const u64 *public_key, const u64 *private_key, const u64 *public_key,
@ -1121,3 +1129,6 @@ err_alloc_product:
out: out:
return ret; return ret;
} }
EXPORT_SYMBOL(crypto_ecdh_shared_secret);
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -32,6 +32,41 @@
#define ECC_DIGITS_TO_BYTES_SHIFT 3 #define ECC_DIGITS_TO_BYTES_SHIFT 3
/**
* struct ecc_point - elliptic curve point in affine coordinates
*
* @x: X coordinate in vli form.
* @y: Y coordinate in vli form.
* @ndigits: Length of vlis in u64 qwords.
*/
struct ecc_point {
u64 *x;
u64 *y;
u8 ndigits;
};
/**
* struct ecc_curve - definition of elliptic curve
*
* @name: Short name of the curve.
* @g: Generator point of the curve.
* @p: Prime number, if Barrett's reduction is used for this curve
* pre-calculated value 'mu' is appended to the @p after ndigits.
* Use of Barrett's reduction is heuristically determined in
* vli_mmod_fast().
* @n: Order of the curve group.
* @a: Curve parameter a.
* @b: Curve parameter b.
*/
struct ecc_curve {
char *name;
struct ecc_point g;
u64 *p;
u64 *n;
u64 *a;
u64 *b;
};
/** /**
* ecc_is_key_valid() - Validate a given ECDH private key * ecc_is_key_valid() - Validate a given ECDH private key
* *
@ -91,4 +126,68 @@ int ecc_make_pub_key(const unsigned int curve_id, unsigned int ndigits,
int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits, int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
const u64 *private_key, const u64 *public_key, const u64 *private_key, const u64 *public_key,
u64 *secret); u64 *secret);
/**
* ecc_is_pubkey_valid_partial() - Partial public key validation
*
* @curve: elliptic curve domain parameters
* @pk: public key as a point
*
* Valdiate public key according to SP800-56A section 5.6.2.3.4 ECC Partial
* Public-Key Validation Routine.
*
* Note: There is no check that the public key is in the correct elliptic curve
* subgroup.
*
* Return: 0 if validation is successful, -EINVAL if validation is failed.
*/
int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
struct ecc_point *pk);
/**
* vli_is_zero() - Determine is vli is zero
*
* @vli: vli to check.
* @ndigits: length of the @vli
*/
bool vli_is_zero(const u64 *vli, unsigned int ndigits);
/**
* vli_cmp() - compare left and right vlis
*
* @left: vli
* @right: vli
* @ndigits: length of both vlis
*
* Returns sign of @left - @right, i.e. -1 if @left < @right,
* 0 if @left == @right, 1 if @left > @right.
*/
int vli_cmp(const u64 *left, const u64 *right, unsigned int ndigits);
/**
* vli_sub() - Subtracts right from left
*
* @result: where to write result
* @left: vli
* @right vli
* @ndigits: length of all vlis
*
* Note: can modify in-place.
*
* Return: carry bit.
*/
u64 vli_sub(u64 *result, const u64 *left, const u64 *right,
unsigned int ndigits);
/**
* vli_mod_inv() - Modular inversion
*
* @result: where to write vli number
* @input: vli value to operate on
* @mod: modulus
* @ndigits: length of all vlis
*/
void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod,
unsigned int ndigits);
#endif #endif

View File

@ -2,21 +2,6 @@
#ifndef _CRYTO_ECC_CURVE_DEFS_H #ifndef _CRYTO_ECC_CURVE_DEFS_H
#define _CRYTO_ECC_CURVE_DEFS_H #define _CRYTO_ECC_CURVE_DEFS_H
struct ecc_point {
u64 *x;
u64 *y;
u8 ndigits;
};
struct ecc_curve {
char *name;
struct ecc_point g;
u64 *p;
u64 *n;
u64 *a;
u64 *b;
};
/* NIST P-192: a = p - 3 */ /* NIST P-192: a = p - 3 */
static u64 nist_p192_g_x[] = { 0xF4FF0AFD82FF1012ull, 0x7CBF20EB43A18800ull, static u64 nist_p192_g_x[] = { 0xF4FF0AFD82FF1012ull, 0x7CBF20EB43A18800ull,
0x188DA80EB03090F6ull }; 0x188DA80EB03090F6ull };