Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2013, Kenneth MacKay
0003  * All rights reserved.
0004  *
0005  * Redistribution and use in source and binary forms, with or without
0006  * modification, are permitted provided that the following conditions are
0007  * met:
0008  *  * Redistributions of source code must retain the above copyright
0009  *   notice, this list of conditions and the following disclaimer.
0010  *  * Redistributions in binary form must reproduce the above copyright
0011  *    notice, this list of conditions and the following disclaimer in the
0012  *    documentation and/or other materials provided with the distribution.
0013  *
0014  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0015  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0016  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0017  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0018  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0019  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0020  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0021  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0022  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0024  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025  */
0026 #ifndef _CRYPTO_ECC_H
0027 #define _CRYPTO_ECC_H
0028 
0029 #include <crypto/ecc_curve.h>
0030 #include <asm/unaligned.h>
0031 
0032 /* One digit is u64 qword. */
0033 #define ECC_CURVE_NIST_P192_DIGITS  3
0034 #define ECC_CURVE_NIST_P256_DIGITS  4
0035 #define ECC_CURVE_NIST_P384_DIGITS  6
0036 #define ECC_MAX_DIGITS              (512 / 64) /* due to ecrdsa */
0037 
0038 #define ECC_DIGITS_TO_BYTES_SHIFT 3
0039 
0040 #define ECC_MAX_BYTES (ECC_MAX_DIGITS << ECC_DIGITS_TO_BYTES_SHIFT)
0041 
0042 #define ECC_POINT_INIT(x, y, ndigits)   (struct ecc_point) { x, y, ndigits }
0043 
0044 /**
0045  * ecc_swap_digits() - Copy ndigits from big endian array to native array
0046  * @in:       Input array
0047  * @out:      Output array
0048  * @ndigits:  Number of digits to copy
0049  */
0050 static inline void ecc_swap_digits(const void *in, u64 *out, unsigned int ndigits)
0051 {
0052     const __be64 *src = (__force __be64 *)in;
0053     int i;
0054 
0055     for (i = 0; i < ndigits; i++)
0056         out[i] = get_unaligned_be64(&src[ndigits - 1 - i]);
0057 }
0058 
0059 /**
0060  * ecc_is_key_valid() - Validate a given ECDH private key
0061  *
0062  * @curve_id:       id representing the curve to use
0063  * @ndigits:        curve's number of digits
0064  * @private_key:    private key to be used for the given curve
0065  * @private_key_len:    private key length
0066  *
0067  * Returns 0 if the key is acceptable, a negative value otherwise
0068  */
0069 int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits,
0070              const u64 *private_key, unsigned int private_key_len);
0071 
0072 /**
0073  * ecc_gen_privkey() -  Generates an ECC private key.
0074  * The private key is a random integer in the range 0 < random < n, where n is a
0075  * prime that is the order of the cyclic subgroup generated by the distinguished
0076  * point G.
0077  * @curve_id:       id representing the curve to use
0078  * @ndigits:        curve number of digits
0079  * @private_key:    buffer for storing the generated private key
0080  *
0081  * Returns 0 if the private key was generated successfully, a negative value
0082  * if an error occurred.
0083  */
0084 int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey);
0085 
0086 /**
0087  * ecc_make_pub_key() - Compute an ECC public key
0088  *
0089  * @curve_id:       id representing the curve to use
0090  * @ndigits:        curve's number of digits
0091  * @private_key:    pregenerated private key for the given curve
0092  * @public_key:     buffer for storing the generated public key
0093  *
0094  * Returns 0 if the public key was generated successfully, a negative value
0095  * if an error occurred.
0096  */
0097 int ecc_make_pub_key(const unsigned int curve_id, unsigned int ndigits,
0098              const u64 *private_key, u64 *public_key);
0099 
0100 /**
0101  * crypto_ecdh_shared_secret() - Compute a shared secret
0102  *
0103  * @curve_id:       id representing the curve to use
0104  * @ndigits:        curve's number of digits
0105  * @private_key:    private key of part A
0106  * @public_key:     public key of counterpart B
0107  * @secret:     buffer for storing the calculated shared secret
0108  *
0109  * Note: It is recommended that you hash the result of crypto_ecdh_shared_secret
0110  * before using it for symmetric encryption or HMAC.
0111  *
0112  * Returns 0 if the shared secret was generated successfully, a negative value
0113  * if an error occurred.
0114  */
0115 int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
0116                   const u64 *private_key, const u64 *public_key,
0117                   u64 *secret);
0118 
0119 /**
0120  * ecc_is_pubkey_valid_partial() - Partial public key validation
0121  *
0122  * @curve:      elliptic curve domain parameters
0123  * @pk:         public key as a point
0124  *
0125  * Valdiate public key according to SP800-56A section 5.6.2.3.4 ECC Partial
0126  * Public-Key Validation Routine.
0127  *
0128  * Note: There is no check that the public key is in the correct elliptic curve
0129  * subgroup.
0130  *
0131  * Return: 0 if validation is successful, -EINVAL if validation is failed.
0132  */
0133 int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
0134                 struct ecc_point *pk);
0135 
0136 /**
0137  * ecc_is_pubkey_valid_full() - Full public key validation
0138  *
0139  * @curve:      elliptic curve domain parameters
0140  * @pk:         public key as a point
0141  *
0142  * Valdiate public key according to SP800-56A section 5.6.2.3.3 ECC Full
0143  * Public-Key Validation Routine.
0144  *
0145  * Return: 0 if validation is successful, -EINVAL if validation is failed.
0146  */
0147 int ecc_is_pubkey_valid_full(const struct ecc_curve *curve,
0148                  struct ecc_point *pk);
0149 
0150 /**
0151  * vli_is_zero() - Determine is vli is zero
0152  *
0153  * @vli:        vli to check.
0154  * @ndigits:        length of the @vli
0155  */
0156 bool vli_is_zero(const u64 *vli, unsigned int ndigits);
0157 
0158 /**
0159  * vli_cmp() - compare left and right vlis
0160  *
0161  * @left:       vli
0162  * @right:      vli
0163  * @ndigits:        length of both vlis
0164  *
0165  * Returns sign of @left - @right, i.e. -1 if @left < @right,
0166  * 0 if @left == @right, 1 if @left > @right.
0167  */
0168 int vli_cmp(const u64 *left, const u64 *right, unsigned int ndigits);
0169 
0170 /**
0171  * vli_sub() - Subtracts right from left
0172  *
0173  * @result:     where to write result
0174  * @left:       vli
0175  * @right       vli
0176  * @ndigits:        length of all vlis
0177  *
0178  * Note: can modify in-place.
0179  *
0180  * Return: carry bit.
0181  */
0182 u64 vli_sub(u64 *result, const u64 *left, const u64 *right,
0183         unsigned int ndigits);
0184 
0185 /**
0186  * vli_from_be64() - Load vli from big-endian u64 array
0187  *
0188  * @dest:       destination vli
0189  * @src:        source array of u64 BE values
0190  * @ndigits:        length of both vli and array
0191  */
0192 void vli_from_be64(u64 *dest, const void *src, unsigned int ndigits);
0193 
0194 /**
0195  * vli_from_le64() - Load vli from little-endian u64 array
0196  *
0197  * @dest:       destination vli
0198  * @src:        source array of u64 LE values
0199  * @ndigits:        length of both vli and array
0200  */
0201 void vli_from_le64(u64 *dest, const void *src, unsigned int ndigits);
0202 
0203 /**
0204  * vli_mod_inv() - Modular inversion
0205  *
0206  * @result:     where to write vli number
0207  * @input:      vli value to operate on
0208  * @mod:        modulus
0209  * @ndigits:        length of all vlis
0210  */
0211 void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod,
0212          unsigned int ndigits);
0213 
0214 /**
0215  * vli_mod_mult_slow() - Modular multiplication
0216  *
0217  * @result:     where to write result value
0218  * @left:       vli number to multiply with @right
0219  * @right:      vli number to multiply with @left
0220  * @mod:        modulus
0221  * @ndigits:        length of all vlis
0222  *
0223  * Note: Assumes that mod is big enough curve order.
0224  */
0225 void vli_mod_mult_slow(u64 *result, const u64 *left, const u64 *right,
0226                const u64 *mod, unsigned int ndigits);
0227 
0228 /**
0229  * vli_num_bits() - Counts the number of bits required for vli.
0230  *
0231  * @vli:        vli to check.
0232  * @ndigits:        Length of the @vli
0233  *
0234  * Return: The number of bits required to represent @vli.
0235  */
0236 unsigned int vli_num_bits(const u64 *vli, unsigned int ndigits);
0237 
0238 /**
0239  * ecc_aloc_point() - Allocate ECC point.
0240  *
0241  * @ndigits:        Length of vlis in u64 qwords.
0242  *
0243  * Return: Pointer to the allocated point or NULL if allocation failed.
0244  */
0245 struct ecc_point *ecc_alloc_point(unsigned int ndigits);
0246 
0247 /**
0248  * ecc_free_point() - Free ECC point.
0249  *
0250  * @p:          The point to free.
0251  */
0252 void ecc_free_point(struct ecc_point *p);
0253 
0254 /**
0255  * ecc_point_is_zero() - Check if point is zero.
0256  *
0257  * @p:          Point to check for zero.
0258  *
0259  * Return: true if point is the point at infinity, false otherwise.
0260  */
0261 bool ecc_point_is_zero(const struct ecc_point *point);
0262 
0263 /**
0264  * ecc_point_mult_shamir() - Add two points multiplied by scalars
0265  *
0266  * @result:     resulting point
0267  * @x:          scalar to multiply with @p
0268  * @p:          point to multiply with @x
0269  * @y:          scalar to multiply with @q
0270  * @q:          point to multiply with @y
0271  * @curve:      curve
0272  *
0273  * Returns result = x * p + x * q over the curve.
0274  * This works faster than two multiplications and addition.
0275  */
0276 void ecc_point_mult_shamir(const struct ecc_point *result,
0277                const u64 *x, const struct ecc_point *p,
0278                const u64 *y, const struct ecc_point *q,
0279                const struct ecc_curve *curve);
0280 
0281 #endif