1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Copyright (c) 2013, Kenneth MacKay 3*4882a593Smuzhiyun * All rights reserved. 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or without 6*4882a593Smuzhiyun * modification, are permitted provided that the following conditions are 7*4882a593Smuzhiyun * met: 8*4882a593Smuzhiyun * * Redistributions of source code must retain the above copyright 9*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer. 10*4882a593Smuzhiyun * * Redistributions in binary form must reproduce the above copyright 11*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer in the 12*4882a593Smuzhiyun * documentation and/or other materials provided with the distribution. 13*4882a593Smuzhiyun * 14*4882a593Smuzhiyun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15*4882a593Smuzhiyun * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16*4882a593Smuzhiyun * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17*4882a593Smuzhiyun * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18*4882a593Smuzhiyun * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19*4882a593Smuzhiyun * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20*4882a593Smuzhiyun * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*4882a593Smuzhiyun * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*4882a593Smuzhiyun * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*4882a593Smuzhiyun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24*4882a593Smuzhiyun * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*4882a593Smuzhiyun */ 26*4882a593Smuzhiyun #ifndef _CRYPTO_ECC_H 27*4882a593Smuzhiyun #define _CRYPTO_ECC_H 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun /* One digit is u64 qword. */ 30*4882a593Smuzhiyun #define ECC_CURVE_NIST_P192_DIGITS 3 31*4882a593Smuzhiyun #define ECC_CURVE_NIST_P256_DIGITS 4 32*4882a593Smuzhiyun #define ECC_MAX_DIGITS (512 / 64) 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun #define ECC_DIGITS_TO_BYTES_SHIFT 3 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun /** 37*4882a593Smuzhiyun * struct ecc_point - elliptic curve point in affine coordinates 38*4882a593Smuzhiyun * 39*4882a593Smuzhiyun * @x: X coordinate in vli form. 40*4882a593Smuzhiyun * @y: Y coordinate in vli form. 41*4882a593Smuzhiyun * @ndigits: Length of vlis in u64 qwords. 42*4882a593Smuzhiyun */ 43*4882a593Smuzhiyun struct ecc_point { 44*4882a593Smuzhiyun u64 *x; 45*4882a593Smuzhiyun u64 *y; 46*4882a593Smuzhiyun u8 ndigits; 47*4882a593Smuzhiyun }; 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun #define ECC_POINT_INIT(x, y, ndigits) (struct ecc_point) { x, y, ndigits } 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun /** 52*4882a593Smuzhiyun * struct ecc_curve - definition of elliptic curve 53*4882a593Smuzhiyun * 54*4882a593Smuzhiyun * @name: Short name of the curve. 55*4882a593Smuzhiyun * @g: Generator point of the curve. 56*4882a593Smuzhiyun * @p: Prime number, if Barrett's reduction is used for this curve 57*4882a593Smuzhiyun * pre-calculated value 'mu' is appended to the @p after ndigits. 58*4882a593Smuzhiyun * Use of Barrett's reduction is heuristically determined in 59*4882a593Smuzhiyun * vli_mmod_fast(). 60*4882a593Smuzhiyun * @n: Order of the curve group. 61*4882a593Smuzhiyun * @a: Curve parameter a. 62*4882a593Smuzhiyun * @b: Curve parameter b. 63*4882a593Smuzhiyun */ 64*4882a593Smuzhiyun struct ecc_curve { 65*4882a593Smuzhiyun char *name; 66*4882a593Smuzhiyun struct ecc_point g; 67*4882a593Smuzhiyun u64 *p; 68*4882a593Smuzhiyun u64 *n; 69*4882a593Smuzhiyun u64 *a; 70*4882a593Smuzhiyun u64 *b; 71*4882a593Smuzhiyun }; 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun /** 74*4882a593Smuzhiyun * ecc_is_key_valid() - Validate a given ECDH private key 75*4882a593Smuzhiyun * 76*4882a593Smuzhiyun * @curve_id: id representing the curve to use 77*4882a593Smuzhiyun * @ndigits: curve's number of digits 78*4882a593Smuzhiyun * @private_key: private key to be used for the given curve 79*4882a593Smuzhiyun * @private_key_len: private key length 80*4882a593Smuzhiyun * 81*4882a593Smuzhiyun * Returns 0 if the key is acceptable, a negative value otherwise 82*4882a593Smuzhiyun */ 83*4882a593Smuzhiyun int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits, 84*4882a593Smuzhiyun const u64 *private_key, unsigned int private_key_len); 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun /** 87*4882a593Smuzhiyun * ecc_gen_privkey() - Generates an ECC private key. 88*4882a593Smuzhiyun * The private key is a random integer in the range 0 < random < n, where n is a 89*4882a593Smuzhiyun * prime that is the order of the cyclic subgroup generated by the distinguished 90*4882a593Smuzhiyun * point G. 91*4882a593Smuzhiyun * @curve_id: id representing the curve to use 92*4882a593Smuzhiyun * @ndigits: curve number of digits 93*4882a593Smuzhiyun * @private_key: buffer for storing the generated private key 94*4882a593Smuzhiyun * 95*4882a593Smuzhiyun * Returns 0 if the private key was generated successfully, a negative value 96*4882a593Smuzhiyun * if an error occurred. 97*4882a593Smuzhiyun */ 98*4882a593Smuzhiyun int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey); 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun /** 101*4882a593Smuzhiyun * ecc_make_pub_key() - Compute an ECC public key 102*4882a593Smuzhiyun * 103*4882a593Smuzhiyun * @curve_id: id representing the curve to use 104*4882a593Smuzhiyun * @ndigits: curve's number of digits 105*4882a593Smuzhiyun * @private_key: pregenerated private key for the given curve 106*4882a593Smuzhiyun * @public_key: buffer for storing the generated public key 107*4882a593Smuzhiyun * 108*4882a593Smuzhiyun * Returns 0 if the public key was generated successfully, a negative value 109*4882a593Smuzhiyun * if an error occurred. 110*4882a593Smuzhiyun */ 111*4882a593Smuzhiyun int ecc_make_pub_key(const unsigned int curve_id, unsigned int ndigits, 112*4882a593Smuzhiyun const u64 *private_key, u64 *public_key); 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun /** 115*4882a593Smuzhiyun * crypto_ecdh_shared_secret() - Compute a shared secret 116*4882a593Smuzhiyun * 117*4882a593Smuzhiyun * @curve_id: id representing the curve to use 118*4882a593Smuzhiyun * @ndigits: curve's number of digits 119*4882a593Smuzhiyun * @private_key: private key of part A 120*4882a593Smuzhiyun * @public_key: public key of counterpart B 121*4882a593Smuzhiyun * @secret: buffer for storing the calculated shared secret 122*4882a593Smuzhiyun * 123*4882a593Smuzhiyun * Note: It is recommended that you hash the result of crypto_ecdh_shared_secret 124*4882a593Smuzhiyun * before using it for symmetric encryption or HMAC. 125*4882a593Smuzhiyun * 126*4882a593Smuzhiyun * Returns 0 if the shared secret was generated successfully, a negative value 127*4882a593Smuzhiyun * if an error occurred. 128*4882a593Smuzhiyun */ 129*4882a593Smuzhiyun int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits, 130*4882a593Smuzhiyun const u64 *private_key, const u64 *public_key, 131*4882a593Smuzhiyun u64 *secret); 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun /** 134*4882a593Smuzhiyun * ecc_is_pubkey_valid_partial() - Partial public key validation 135*4882a593Smuzhiyun * 136*4882a593Smuzhiyun * @curve: elliptic curve domain parameters 137*4882a593Smuzhiyun * @pk: public key as a point 138*4882a593Smuzhiyun * 139*4882a593Smuzhiyun * Valdiate public key according to SP800-56A section 5.6.2.3.4 ECC Partial 140*4882a593Smuzhiyun * Public-Key Validation Routine. 141*4882a593Smuzhiyun * 142*4882a593Smuzhiyun * Note: There is no check that the public key is in the correct elliptic curve 143*4882a593Smuzhiyun * subgroup. 144*4882a593Smuzhiyun * 145*4882a593Smuzhiyun * Return: 0 if validation is successful, -EINVAL if validation is failed. 146*4882a593Smuzhiyun */ 147*4882a593Smuzhiyun int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve, 148*4882a593Smuzhiyun struct ecc_point *pk); 149*4882a593Smuzhiyun 150*4882a593Smuzhiyun /** 151*4882a593Smuzhiyun * ecc_is_pubkey_valid_full() - Full public key validation 152*4882a593Smuzhiyun * 153*4882a593Smuzhiyun * @curve: elliptic curve domain parameters 154*4882a593Smuzhiyun * @pk: public key as a point 155*4882a593Smuzhiyun * 156*4882a593Smuzhiyun * Valdiate public key according to SP800-56A section 5.6.2.3.3 ECC Full 157*4882a593Smuzhiyun * Public-Key Validation Routine. 158*4882a593Smuzhiyun * 159*4882a593Smuzhiyun * Return: 0 if validation is successful, -EINVAL if validation is failed. 160*4882a593Smuzhiyun */ 161*4882a593Smuzhiyun int ecc_is_pubkey_valid_full(const struct ecc_curve *curve, 162*4882a593Smuzhiyun struct ecc_point *pk); 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun /** 165*4882a593Smuzhiyun * vli_is_zero() - Determine is vli is zero 166*4882a593Smuzhiyun * 167*4882a593Smuzhiyun * @vli: vli to check. 168*4882a593Smuzhiyun * @ndigits: length of the @vli 169*4882a593Smuzhiyun */ 170*4882a593Smuzhiyun bool vli_is_zero(const u64 *vli, unsigned int ndigits); 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun /** 173*4882a593Smuzhiyun * vli_cmp() - compare left and right vlis 174*4882a593Smuzhiyun * 175*4882a593Smuzhiyun * @left: vli 176*4882a593Smuzhiyun * @right: vli 177*4882a593Smuzhiyun * @ndigits: length of both vlis 178*4882a593Smuzhiyun * 179*4882a593Smuzhiyun * Returns sign of @left - @right, i.e. -1 if @left < @right, 180*4882a593Smuzhiyun * 0 if @left == @right, 1 if @left > @right. 181*4882a593Smuzhiyun */ 182*4882a593Smuzhiyun int vli_cmp(const u64 *left, const u64 *right, unsigned int ndigits); 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun /** 185*4882a593Smuzhiyun * vli_sub() - Subtracts right from left 186*4882a593Smuzhiyun * 187*4882a593Smuzhiyun * @result: where to write result 188*4882a593Smuzhiyun * @left: vli 189*4882a593Smuzhiyun * @right vli 190*4882a593Smuzhiyun * @ndigits: length of all vlis 191*4882a593Smuzhiyun * 192*4882a593Smuzhiyun * Note: can modify in-place. 193*4882a593Smuzhiyun * 194*4882a593Smuzhiyun * Return: carry bit. 195*4882a593Smuzhiyun */ 196*4882a593Smuzhiyun u64 vli_sub(u64 *result, const u64 *left, const u64 *right, 197*4882a593Smuzhiyun unsigned int ndigits); 198*4882a593Smuzhiyun 199*4882a593Smuzhiyun /** 200*4882a593Smuzhiyun * vli_from_be64() - Load vli from big-endian u64 array 201*4882a593Smuzhiyun * 202*4882a593Smuzhiyun * @dest: destination vli 203*4882a593Smuzhiyun * @src: source array of u64 BE values 204*4882a593Smuzhiyun * @ndigits: length of both vli and array 205*4882a593Smuzhiyun */ 206*4882a593Smuzhiyun void vli_from_be64(u64 *dest, const void *src, unsigned int ndigits); 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun /** 209*4882a593Smuzhiyun * vli_from_le64() - Load vli from little-endian u64 array 210*4882a593Smuzhiyun * 211*4882a593Smuzhiyun * @dest: destination vli 212*4882a593Smuzhiyun * @src: source array of u64 LE values 213*4882a593Smuzhiyun * @ndigits: length of both vli and array 214*4882a593Smuzhiyun */ 215*4882a593Smuzhiyun void vli_from_le64(u64 *dest, const void *src, unsigned int ndigits); 216*4882a593Smuzhiyun 217*4882a593Smuzhiyun /** 218*4882a593Smuzhiyun * vli_mod_inv() - Modular inversion 219*4882a593Smuzhiyun * 220*4882a593Smuzhiyun * @result: where to write vli number 221*4882a593Smuzhiyun * @input: vli value to operate on 222*4882a593Smuzhiyun * @mod: modulus 223*4882a593Smuzhiyun * @ndigits: length of all vlis 224*4882a593Smuzhiyun */ 225*4882a593Smuzhiyun void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod, 226*4882a593Smuzhiyun unsigned int ndigits); 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun /** 229*4882a593Smuzhiyun * vli_mod_mult_slow() - Modular multiplication 230*4882a593Smuzhiyun * 231*4882a593Smuzhiyun * @result: where to write result value 232*4882a593Smuzhiyun * @left: vli number to multiply with @right 233*4882a593Smuzhiyun * @right: vli number to multiply with @left 234*4882a593Smuzhiyun * @mod: modulus 235*4882a593Smuzhiyun * @ndigits: length of all vlis 236*4882a593Smuzhiyun * 237*4882a593Smuzhiyun * Note: Assumes that mod is big enough curve order. 238*4882a593Smuzhiyun */ 239*4882a593Smuzhiyun void vli_mod_mult_slow(u64 *result, const u64 *left, const u64 *right, 240*4882a593Smuzhiyun const u64 *mod, unsigned int ndigits); 241*4882a593Smuzhiyun 242*4882a593Smuzhiyun /** 243*4882a593Smuzhiyun * ecc_point_mult_shamir() - Add two points multiplied by scalars 244*4882a593Smuzhiyun * 245*4882a593Smuzhiyun * @result: resulting point 246*4882a593Smuzhiyun * @x: scalar to multiply with @p 247*4882a593Smuzhiyun * @p: point to multiply with @x 248*4882a593Smuzhiyun * @y: scalar to multiply with @q 249*4882a593Smuzhiyun * @q: point to multiply with @y 250*4882a593Smuzhiyun * @curve: curve 251*4882a593Smuzhiyun * 252*4882a593Smuzhiyun * Returns result = x * p + x * q over the curve. 253*4882a593Smuzhiyun * This works faster than two multiplications and addition. 254*4882a593Smuzhiyun */ 255*4882a593Smuzhiyun void ecc_point_mult_shamir(const struct ecc_point *result, 256*4882a593Smuzhiyun const u64 *x, const struct ecc_point *p, 257*4882a593Smuzhiyun const u64 *y, const struct ecc_point *q, 258*4882a593Smuzhiyun const struct ecc_curve *curve); 259*4882a593Smuzhiyun #endif 260