2016-06-22 19:49:15 +03:00
/*
* 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 .
*/
# ifndef _CRYPTO_ECC_H
# define _CRYPTO_ECC_H
2021-03-04 09:35:47 +03:00
# include <crypto/ecc_curve.h>
2021-07-21 11:39:05 +03:00
# include <asm/unaligned.h>
2021-03-04 09:35:47 +03:00
crypto: ecrdsa - add EC-RDSA (GOST 34.10) algorithm
Add Elliptic Curve Russian Digital Signature Algorithm (GOST R
34.10-2012, RFC 7091, ISO/IEC 14888-3) is one of the Russian (and since
2018 the CIS countries) cryptographic standard algorithms (called GOST
algorithms). Only signature verification is supported, with intent to be
used in the IMA.
Summary of the changes:
* crypto/Kconfig:
- EC-RDSA is added into Public-key cryptography section.
* crypto/Makefile:
- ecrdsa objects are added.
* crypto/asymmetric_keys/x509_cert_parser.c:
- Recognize EC-RDSA and Streebog OIDs.
* include/linux/oid_registry.h:
- EC-RDSA OIDs are added to the enum. Also, a two currently not
implemented curve OIDs are added for possible extension later (to
not change numbering and grouping).
* crypto/ecc.c:
- Kenneth MacKay copyright date is updated to 2014, because
vli_mmod_slow, ecc_point_add, ecc_point_mult_shamir are based on his
code from micro-ecc.
- Functions needed for ecrdsa are EXPORT_SYMBOL'ed.
- New functions:
vli_is_negative - helper to determine sign of vli;
vli_from_be64 - unpack big-endian array into vli (used for
a signature);
vli_from_le64 - unpack little-endian array into vli (used for
a public key);
vli_uadd, vli_usub - add/sub u64 value to/from vli (used for
increment/decrement);
mul_64_64 - optimized to use __int128 where appropriate, this speeds
up point multiplication (and as a consequence signature
verification) by the factor of 1.5-2;
vli_umult - multiply vli by a small value (speeds up point
multiplication by another factor of 1.5-2, depending on vli sizes);
vli_mmod_special - module reduction for some form of Pseudo-Mersenne
primes (used for the curves A);
vli_mmod_special2 - module reduction for another form of
Pseudo-Mersenne primes (used for the curves B);
vli_mmod_barrett - module reduction using pre-computed value (used
for the curve C);
vli_mmod_slow - more general module reduction which is much slower
(used when the modulus is subgroup order);
vli_mod_mult_slow - modular multiplication;
ecc_point_add - add two points;
ecc_point_mult_shamir - add two points multiplied by scalars in one
combined multiplication (this gives speed up by another factor 2 in
compare to two separate multiplications).
ecc_is_pubkey_valid_partial - additional samity check is added.
- Updated vli_mmod_fast with non-strict heuristic to call optimal
module reduction function depending on the prime value;
- All computations for the previously defined (two NIST) curves should
not unaffected.
* crypto/ecc.h:
- Newly exported functions are documented.
* crypto/ecrdsa_defs.h
- Five curves are defined.
* crypto/ecrdsa.c:
- Signature verification is implemented.
* crypto/ecrdsa_params.asn1, crypto/ecrdsa_pub_key.asn1:
- Templates for BER decoder for EC-RDSA parameters and public key.
Cc: linux-integrity@vger.kernel.org
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-04-11 18:51:20 +03:00
/* One digit is u64 qword. */
2018-03-30 19:55:44 +03:00
# define ECC_CURVE_NIST_P192_DIGITS 3
# define ECC_CURVE_NIST_P256_DIGITS 4
2021-03-17 00:07:34 +03:00
# define ECC_CURVE_NIST_P384_DIGITS 6
# define ECC_MAX_DIGITS (512 / 64) /* due to ecrdsa */
2016-06-22 19:49:15 +03:00
# define ECC_DIGITS_TO_BYTES_SHIFT 3
2021-03-17 00:07:32 +03:00
# define ECC_MAX_BYTES (ECC_MAX_DIGITS << ECC_DIGITS_TO_BYTES_SHIFT)
crypto: ecrdsa - add EC-RDSA (GOST 34.10) algorithm
Add Elliptic Curve Russian Digital Signature Algorithm (GOST R
34.10-2012, RFC 7091, ISO/IEC 14888-3) is one of the Russian (and since
2018 the CIS countries) cryptographic standard algorithms (called GOST
algorithms). Only signature verification is supported, with intent to be
used in the IMA.
Summary of the changes:
* crypto/Kconfig:
- EC-RDSA is added into Public-key cryptography section.
* crypto/Makefile:
- ecrdsa objects are added.
* crypto/asymmetric_keys/x509_cert_parser.c:
- Recognize EC-RDSA and Streebog OIDs.
* include/linux/oid_registry.h:
- EC-RDSA OIDs are added to the enum. Also, a two currently not
implemented curve OIDs are added for possible extension later (to
not change numbering and grouping).
* crypto/ecc.c:
- Kenneth MacKay copyright date is updated to 2014, because
vli_mmod_slow, ecc_point_add, ecc_point_mult_shamir are based on his
code from micro-ecc.
- Functions needed for ecrdsa are EXPORT_SYMBOL'ed.
- New functions:
vli_is_negative - helper to determine sign of vli;
vli_from_be64 - unpack big-endian array into vli (used for
a signature);
vli_from_le64 - unpack little-endian array into vli (used for
a public key);
vli_uadd, vli_usub - add/sub u64 value to/from vli (used for
increment/decrement);
mul_64_64 - optimized to use __int128 where appropriate, this speeds
up point multiplication (and as a consequence signature
verification) by the factor of 1.5-2;
vli_umult - multiply vli by a small value (speeds up point
multiplication by another factor of 1.5-2, depending on vli sizes);
vli_mmod_special - module reduction for some form of Pseudo-Mersenne
primes (used for the curves A);
vli_mmod_special2 - module reduction for another form of
Pseudo-Mersenne primes (used for the curves B);
vli_mmod_barrett - module reduction using pre-computed value (used
for the curve C);
vli_mmod_slow - more general module reduction which is much slower
(used when the modulus is subgroup order);
vli_mod_mult_slow - modular multiplication;
ecc_point_add - add two points;
ecc_point_mult_shamir - add two points multiplied by scalars in one
combined multiplication (this gives speed up by another factor 2 in
compare to two separate multiplications).
ecc_is_pubkey_valid_partial - additional samity check is added.
- Updated vli_mmod_fast with non-strict heuristic to call optimal
module reduction function depending on the prime value;
- All computations for the previously defined (two NIST) curves should
not unaffected.
* crypto/ecc.h:
- Newly exported functions are documented.
* crypto/ecrdsa_defs.h
- Five curves are defined.
* crypto/ecrdsa.c:
- Signature verification is implemented.
* crypto/ecrdsa_params.asn1, crypto/ecrdsa_pub_key.asn1:
- Templates for BER decoder for EC-RDSA parameters and public key.
Cc: linux-integrity@vger.kernel.org
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-04-11 18:51:20 +03:00
# define ECC_POINT_INIT(x, y, ndigits) (struct ecc_point) { x, y, ndigits }
2021-03-17 00:07:32 +03:00
/**
* ecc_swap_digits ( ) - Copy ndigits from big endian array to native array
* @ in : Input array
* @ out : Output array
* @ ndigits : Number of digits to copy
*/
2021-07-21 11:39:05 +03:00
static inline void ecc_swap_digits ( const void * in , u64 * out , unsigned int ndigits )
2021-03-17 00:07:32 +03:00
{
const __be64 * src = ( __force __be64 * ) in ;
int i ;
for ( i = 0 ; i < ndigits ; i + + )
2021-07-21 11:39:05 +03:00
out [ i ] = get_unaligned_be64 ( & src [ ndigits - 1 - i ] ) ;
2021-03-17 00:07:32 +03:00
}
2016-06-22 19:49:15 +03:00
/**
* ecc_is_key_valid ( ) - Validate a given ECDH private key
*
* @ curve_id : id representing the curve to use
2017-05-25 10:18:03 +03:00
* @ ndigits : curve ' s number of digits
2016-06-22 19:49:15 +03:00
* @ private_key : private key to be used for the given curve
2017-05-25 10:18:03 +03:00
* @ private_key_len : private key length
2016-06-22 19:49:15 +03:00
*
* Returns 0 if the key is acceptable , a negative value otherwise
*/
int ecc_is_key_valid ( unsigned int curve_id , unsigned int ndigits ,
2017-05-25 10:18:05 +03:00
const u64 * private_key , unsigned int private_key_len ) ;
2016-06-22 19:49:15 +03:00
2017-05-30 17:52:48 +03:00
/**
* ecc_gen_privkey ( ) - Generates an ECC private key .
* The private key is a random integer in the range 0 < random < n , where n is a
* prime that is the order of the cyclic subgroup generated by the distinguished
* point G .
* @ curve_id : id representing the curve to use
* @ ndigits : curve number of digits
* @ private_key : buffer for storing the generated private key
*
* Returns 0 if the private key was generated successfully , a negative value
* if an error occurred .
*/
int ecc_gen_privkey ( unsigned int curve_id , unsigned int ndigits , u64 * privkey ) ;
2016-06-22 19:49:15 +03:00
/**
2017-05-30 15:37:56 +03:00
* ecc_make_pub_key ( ) - Compute an ECC public key
2016-06-22 19:49:15 +03:00
*
* @ curve_id : id representing the curve to use
2017-05-25 10:18:03 +03:00
* @ ndigits : curve ' s number of digits
2016-06-22 19:49:15 +03:00
* @ private_key : pregenerated private key for the given curve
2017-05-25 10:18:03 +03:00
* @ public_key : buffer for storing the generated public key
2016-06-22 19:49:15 +03:00
*
* Returns 0 if the public key was generated successfully , a negative value
* if an error occurred .
*/
2017-05-30 15:37:56 +03:00
int ecc_make_pub_key ( const unsigned int curve_id , unsigned int ndigits ,
const u64 * private_key , u64 * public_key ) ;
2016-06-22 19:49:15 +03:00
/**
2016-06-24 09:20:22 +03:00
* crypto_ecdh_shared_secret ( ) - Compute a shared secret
2016-06-22 19:49:15 +03:00
*
* @ curve_id : id representing the curve to use
2017-05-25 10:18:03 +03:00
* @ ndigits : curve ' s number of digits
2016-06-22 19:49:15 +03:00
* @ private_key : private key of part A
* @ public_key : public key of counterpart B
* @ secret : buffer for storing the calculated shared secret
*
2016-06-24 09:20:22 +03:00
* Note : It is recommended that you hash the result of crypto_ecdh_shared_secret
2016-06-22 19:49:15 +03:00
* before using it for symmetric encryption or HMAC .
*
* Returns 0 if the shared secret was generated successfully , a negative value
* if an error occurred .
*/
2016-06-24 09:20:22 +03:00
int crypto_ecdh_shared_secret ( unsigned int curve_id , unsigned int ndigits ,
2017-05-25 10:18:05 +03:00
const u64 * private_key , const u64 * public_key ,
u64 * secret ) ;
2019-04-11 18:51:19 +03:00
/**
* 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 - 56 A 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 ) ;
2020-07-20 20:09:23 +03:00
/**
* ecc_is_pubkey_valid_full ( ) - Full public key validation
*
* @ curve : elliptic curve domain parameters
* @ pk : public key as a point
*
* Valdiate public key according to SP800 - 56 A section 5.6 .2 .3 .3 ECC Full
* Public - Key Validation Routine .
*
* Return : 0 if validation is successful , - EINVAL if validation is failed .
*/
int ecc_is_pubkey_valid_full ( const struct ecc_curve * curve ,
struct ecc_point * pk ) ;
2019-04-11 18:51:19 +03:00
/**
* 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 ) ;
crypto: ecrdsa - add EC-RDSA (GOST 34.10) algorithm
Add Elliptic Curve Russian Digital Signature Algorithm (GOST R
34.10-2012, RFC 7091, ISO/IEC 14888-3) is one of the Russian (and since
2018 the CIS countries) cryptographic standard algorithms (called GOST
algorithms). Only signature verification is supported, with intent to be
used in the IMA.
Summary of the changes:
* crypto/Kconfig:
- EC-RDSA is added into Public-key cryptography section.
* crypto/Makefile:
- ecrdsa objects are added.
* crypto/asymmetric_keys/x509_cert_parser.c:
- Recognize EC-RDSA and Streebog OIDs.
* include/linux/oid_registry.h:
- EC-RDSA OIDs are added to the enum. Also, a two currently not
implemented curve OIDs are added for possible extension later (to
not change numbering and grouping).
* crypto/ecc.c:
- Kenneth MacKay copyright date is updated to 2014, because
vli_mmod_slow, ecc_point_add, ecc_point_mult_shamir are based on his
code from micro-ecc.
- Functions needed for ecrdsa are EXPORT_SYMBOL'ed.
- New functions:
vli_is_negative - helper to determine sign of vli;
vli_from_be64 - unpack big-endian array into vli (used for
a signature);
vli_from_le64 - unpack little-endian array into vli (used for
a public key);
vli_uadd, vli_usub - add/sub u64 value to/from vli (used for
increment/decrement);
mul_64_64 - optimized to use __int128 where appropriate, this speeds
up point multiplication (and as a consequence signature
verification) by the factor of 1.5-2;
vli_umult - multiply vli by a small value (speeds up point
multiplication by another factor of 1.5-2, depending on vli sizes);
vli_mmod_special - module reduction for some form of Pseudo-Mersenne
primes (used for the curves A);
vli_mmod_special2 - module reduction for another form of
Pseudo-Mersenne primes (used for the curves B);
vli_mmod_barrett - module reduction using pre-computed value (used
for the curve C);
vli_mmod_slow - more general module reduction which is much slower
(used when the modulus is subgroup order);
vli_mod_mult_slow - modular multiplication;
ecc_point_add - add two points;
ecc_point_mult_shamir - add two points multiplied by scalars in one
combined multiplication (this gives speed up by another factor 2 in
compare to two separate multiplications).
ecc_is_pubkey_valid_partial - additional samity check is added.
- Updated vli_mmod_fast with non-strict heuristic to call optimal
module reduction function depending on the prime value;
- All computations for the previously defined (two NIST) curves should
not unaffected.
* crypto/ecc.h:
- Newly exported functions are documented.
* crypto/ecrdsa_defs.h
- Five curves are defined.
* crypto/ecrdsa.c:
- Signature verification is implemented.
* crypto/ecrdsa_params.asn1, crypto/ecrdsa_pub_key.asn1:
- Templates for BER decoder for EC-RDSA parameters and public key.
Cc: linux-integrity@vger.kernel.org
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-04-11 18:51:20 +03:00
/**
* vli_from_be64 ( ) - Load vli from big - endian u64 array
*
* @ dest : destination vli
* @ src : source array of u64 BE values
* @ ndigits : length of both vli and array
*/
void vli_from_be64 ( u64 * dest , const void * src , unsigned int ndigits ) ;
/**
* vli_from_le64 ( ) - Load vli from little - endian u64 array
*
* @ dest : destination vli
* @ src : source array of u64 LE values
* @ ndigits : length of both vli and array
*/
void vli_from_le64 ( u64 * dest , const void * src , unsigned int ndigits ) ;
2019-04-11 18:51:19 +03:00
/**
* 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 ) ;
crypto: ecrdsa - add EC-RDSA (GOST 34.10) algorithm
Add Elliptic Curve Russian Digital Signature Algorithm (GOST R
34.10-2012, RFC 7091, ISO/IEC 14888-3) is one of the Russian (and since
2018 the CIS countries) cryptographic standard algorithms (called GOST
algorithms). Only signature verification is supported, with intent to be
used in the IMA.
Summary of the changes:
* crypto/Kconfig:
- EC-RDSA is added into Public-key cryptography section.
* crypto/Makefile:
- ecrdsa objects are added.
* crypto/asymmetric_keys/x509_cert_parser.c:
- Recognize EC-RDSA and Streebog OIDs.
* include/linux/oid_registry.h:
- EC-RDSA OIDs are added to the enum. Also, a two currently not
implemented curve OIDs are added for possible extension later (to
not change numbering and grouping).
* crypto/ecc.c:
- Kenneth MacKay copyright date is updated to 2014, because
vli_mmod_slow, ecc_point_add, ecc_point_mult_shamir are based on his
code from micro-ecc.
- Functions needed for ecrdsa are EXPORT_SYMBOL'ed.
- New functions:
vli_is_negative - helper to determine sign of vli;
vli_from_be64 - unpack big-endian array into vli (used for
a signature);
vli_from_le64 - unpack little-endian array into vli (used for
a public key);
vli_uadd, vli_usub - add/sub u64 value to/from vli (used for
increment/decrement);
mul_64_64 - optimized to use __int128 where appropriate, this speeds
up point multiplication (and as a consequence signature
verification) by the factor of 1.5-2;
vli_umult - multiply vli by a small value (speeds up point
multiplication by another factor of 1.5-2, depending on vli sizes);
vli_mmod_special - module reduction for some form of Pseudo-Mersenne
primes (used for the curves A);
vli_mmod_special2 - module reduction for another form of
Pseudo-Mersenne primes (used for the curves B);
vli_mmod_barrett - module reduction using pre-computed value (used
for the curve C);
vli_mmod_slow - more general module reduction which is much slower
(used when the modulus is subgroup order);
vli_mod_mult_slow - modular multiplication;
ecc_point_add - add two points;
ecc_point_mult_shamir - add two points multiplied by scalars in one
combined multiplication (this gives speed up by another factor 2 in
compare to two separate multiplications).
ecc_is_pubkey_valid_partial - additional samity check is added.
- Updated vli_mmod_fast with non-strict heuristic to call optimal
module reduction function depending on the prime value;
- All computations for the previously defined (two NIST) curves should
not unaffected.
* crypto/ecc.h:
- Newly exported functions are documented.
* crypto/ecrdsa_defs.h
- Five curves are defined.
* crypto/ecrdsa.c:
- Signature verification is implemented.
* crypto/ecrdsa_params.asn1, crypto/ecrdsa_pub_key.asn1:
- Templates for BER decoder for EC-RDSA parameters and public key.
Cc: linux-integrity@vger.kernel.org
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-04-11 18:51:20 +03:00
/**
* vli_mod_mult_slow ( ) - Modular multiplication
*
* @ result : where to write result value
* @ left : vli number to multiply with @ right
* @ right : vli number to multiply with @ left
* @ mod : modulus
* @ ndigits : length of all vlis
*
* Note : Assumes that mod is big enough curve order .
*/
void vli_mod_mult_slow ( u64 * result , const u64 * left , const u64 * right ,
const u64 * mod , unsigned int ndigits ) ;
/**
* ecc_point_mult_shamir ( ) - Add two points multiplied by scalars
*
* @ result : resulting point
* @ x : scalar to multiply with @ p
* @ p : point to multiply with @ x
* @ y : scalar to multiply with @ q
* @ q : point to multiply with @ y
* @ curve : curve
*
* Returns result = x * p + x * q over the curve .
* This works faster than two multiplications and addition .
*/
void ecc_point_mult_shamir ( const struct ecc_point * result ,
const u64 * x , const struct ecc_point * p ,
const u64 * y , const struct ecc_point * q ,
const struct ecc_curve * curve ) ;
2016-06-22 19:49:15 +03:00
# endif