1 /* 2 * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright 2015-2016 Cryptography Research, Inc. 4 * 5 * Licensed under the OpenSSL license (the "License"). You may not use 6 * this file except in compliance with the License. You can obtain a copy 7 * in the file LICENSE in the source distribution or at 8 * https://www.openssl.org/source/license.html 9 * 10 * Originally written by Mike Hamburg 11 */ 12 13 #ifndef OSSL_CRYPTO_EC_CURVE448_POINT_448_H 14 # define OSSL_CRYPTO_EC_CURVE448_POINT_448_H 15 16 # include "curve448utils.h" 17 # include "field.h" 18 19 /* Comb config: number of combs, n, t, s. */ 20 #define COMBS_N 5 21 #define COMBS_T 5 22 #define COMBS_S 18 23 24 /* Projective Niels coordinates */ 25 typedef struct { 26 gf a, b, c; 27 } niels_s, niels_t[1]; 28 typedef struct { 29 niels_t n; 30 gf z; 31 } pniels_t[1]; 32 33 /* Precomputed base */ 34 struct curve448_precomputed_s { 35 niels_t table[COMBS_N << (COMBS_T - 1)]; 36 }; 37 38 # define C448_SCALAR_LIMBS ((446-1)/C448_WORD_BITS+1) 39 40 /* The number of bits in a scalar */ 41 # define C448_SCALAR_BITS 446 42 43 /* Number of bytes in a serialized scalar. */ 44 # define C448_SCALAR_BYTES 56 45 46 /* X448 encoding ratio. */ 47 # define X448_ENCODE_RATIO 2 48 49 /* Number of bytes in an x448 public key */ 50 # define X448_PUBLIC_BYTES 56 51 52 /* Number of bytes in an x448 private key */ 53 # define X448_PRIVATE_BYTES 56 54 55 /* Twisted Edwards extended homogeneous coordinates */ 56 typedef struct curve448_point_s { 57 gf x, y, z, t; 58 } curve448_point_t[1]; 59 60 /* Precomputed table based on a point. Can be trivial implementation. */ 61 struct curve448_precomputed_s; 62 63 /* Precomputed table based on a point. Can be trivial implementation. */ 64 typedef struct curve448_precomputed_s curve448_precomputed_s; 65 66 /* Scalar is stored packed, because we don't need the speed. */ 67 typedef struct curve448_scalar_s { 68 c448_word_t limb[C448_SCALAR_LIMBS]; 69 } curve448_scalar_t[1]; 70 71 /* A scalar equal to 1. */ 72 extern const curve448_scalar_t curve448_scalar_one; 73 74 /* A scalar equal to 0. */ 75 extern const curve448_scalar_t curve448_scalar_zero; 76 77 /* The identity point on the curve. */ 78 extern const curve448_point_t curve448_point_identity; 79 80 /* Precomputed table for the base point on the curve. */ 81 extern const struct curve448_precomputed_s *curve448_precomputed_base; 82 extern const niels_t *curve448_wnaf_base; 83 84 /* 85 * Read a scalar from wire format or from bytes. 86 * 87 * ser (in): Serialized form of a scalar. 88 * out (out): Deserialized form. 89 * 90 * Returns: 91 * C448_SUCCESS: The scalar was correctly encoded. 92 * C448_FAILURE: The scalar was greater than the modulus, and has been reduced 93 * modulo that modulus. 94 */ 95 c448_error_t curve448_scalar_decode(curve448_scalar_t out, 96 const unsigned char ser[C448_SCALAR_BYTES]); 97 98 /* 99 * Read a scalar from wire format or from bytes. Reduces mod scalar prime. 100 * 101 * ser (in): Serialized form of a scalar. 102 * ser_len (in): Length of serialized form. 103 * out (out): Deserialized form. 104 */ 105 void curve448_scalar_decode_long(curve448_scalar_t out, 106 const unsigned char *ser, size_t ser_len); 107 108 /* 109 * Serialize a scalar to wire format. 110 * 111 * ser (out): Serialized form of a scalar. 112 * s (in): Deserialized scalar. 113 */ 114 void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], 115 const curve448_scalar_t s); 116 117 /* 118 * Add two scalars. |a|, |b| and |out| may alias each other. 119 * 120 * a (in): One scalar. 121 * b (in): Another scalar. 122 * out (out): a+b. 123 */ 124 void curve448_scalar_add(curve448_scalar_t out, 125 const curve448_scalar_t a, const curve448_scalar_t b); 126 127 /* 128 * Subtract two scalars. |a|, |b| and |out| may alias each other. 129 * a (in): One scalar. 130 * b (in): Another scalar. 131 * out (out): a-b. 132 */ 133 void curve448_scalar_sub(curve448_scalar_t out, 134 const curve448_scalar_t a, const curve448_scalar_t b); 135 136 /* 137 * Multiply two scalars. |a|, |b| and |out| may alias each other. 138 * 139 * a (in): One scalar. 140 * b (in): Another scalar. 141 * out (out): a*b. 142 */ 143 void curve448_scalar_mul(curve448_scalar_t out, 144 const curve448_scalar_t a, const curve448_scalar_t b); 145 146 /* 147 * Halve a scalar. |a| and |out| may alias each other. 148 * 149 * a (in): A scalar. 150 * out (out): a/2. 151 */ 152 void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a); 153 154 /* 155 * Copy a scalar. The scalars may alias each other, in which case this 156 * function does nothing. 157 * 158 * a (in): A scalar. 159 * out (out): Will become a copy of a. 160 */ 161 static ossl_inline void curve448_scalar_copy(curve448_scalar_t out, 162 const curve448_scalar_t a) 163 { 164 *out = *a; 165 } 166 167 /* 168 * Copy a point. The input and output may alias, in which case this function 169 * does nothing. 170 * 171 * a (out): A copy of the point. 172 * b (in): Any point. 173 */ 174 static ossl_inline void curve448_point_copy(curve448_point_t a, 175 const curve448_point_t b) 176 { 177 *a = *b; 178 } 179 180 /* 181 * Test whether two points are equal. If yes, return C448_TRUE, else return 182 * C448_FALSE. 183 * 184 * a (in): A point. 185 * b (in): Another point. 186 * 187 * Returns: 188 * C448_TRUE: The points are equal. 189 * C448_FALSE: The points are not equal. 190 */ 191 __owur c448_bool_t curve448_point_eq(const curve448_point_t a, 192 const curve448_point_t b); 193 194 /* 195 * Double a point. Equivalent to curve448_point_add(two_a,a,a), but potentially 196 * faster. 197 * 198 * two_a (out): The sum a+a. 199 * a (in): A point. 200 */ 201 void curve448_point_double(curve448_point_t two_a, const curve448_point_t a); 202 203 /* 204 * RFC 7748 Diffie-Hellman scalarmul. This function uses a different 205 * (non-Decaf) encoding. 206 * 207 * out (out): The scaled point base*scalar 208 * base (in): The point to be scaled. 209 * scalar (in): The scalar to multiply by. 210 * 211 * Returns: 212 * C448_SUCCESS: The scalarmul succeeded. 213 * C448_FAILURE: The scalarmul didn't succeed, because the base point is in a 214 * small subgroup. 215 */ 216 __owur c448_error_t x448_int(uint8_t out[X448_PUBLIC_BYTES], 217 const uint8_t base[X448_PUBLIC_BYTES], 218 const uint8_t scalar[X448_PRIVATE_BYTES]); 219 220 /* 221 * Multiply a point by X448_ENCODE_RATIO, then encode it like RFC 7748. 222 * 223 * This function is mainly used internally, but is exported in case 224 * it will be useful. 225 * 226 * The ratio is necessary because the internal representation doesn't 227 * track the cofactor information, so on output we must clear the cofactor. 228 * This would multiply by the cofactor, but in fact internally points are always 229 * even, so it multiplies by half the cofactor instead. 230 * 231 * As it happens, this aligns with the base point definitions; that is, 232 * if you pass the Decaf/Ristretto base point to this function, the result 233 * will be X448_ENCODE_RATIO times the X448 234 * base point. 235 * 236 * out (out): The scaled and encoded point. 237 * p (in): The point to be scaled and encoded. 238 */ 239 void curve448_point_mul_by_ratio_and_encode_like_x448( 240 uint8_t out[X448_PUBLIC_BYTES], 241 const curve448_point_t p); 242 243 /* 244 * RFC 7748 Diffie-Hellman base point scalarmul. This function uses a different 245 * (non-Decaf) encoding. 246 * 247 * out (out): The scaled point base*scalar 248 * scalar (in): The scalar to multiply by. 249 */ 250 void x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES], 251 const uint8_t scalar[X448_PRIVATE_BYTES]); 252 253 /* 254 * Multiply a precomputed base point by a scalar: out = scalar*base. 255 * 256 * scaled (out): The scaled point base*scalar 257 * base (in): The point to be scaled. 258 * scalar (in): The scalar to multiply by. 259 */ 260 void curve448_precomputed_scalarmul(curve448_point_t scaled, 261 const curve448_precomputed_s * base, 262 const curve448_scalar_t scalar); 263 264 /* 265 * Multiply two base points by two scalars: 266 * combo = scalar1*curve448_point_base + scalar2*base2. 267 * 268 * Otherwise equivalent to curve448_point_double_scalarmul, but may be 269 * faster at the expense of being variable time. 270 * 271 * combo (out): The linear combination scalar1*base + scalar2*base2. 272 * scalar1 (in): A first scalar to multiply by. 273 * base2 (in): A second point to be scaled. 274 * scalar2 (in) A second scalar to multiply by. 275 * 276 * Warning: This function takes variable time, and may leak the scalars used. 277 * It is designed for signature verification. 278 */ 279 void curve448_base_double_scalarmul_non_secret(curve448_point_t combo, 280 const curve448_scalar_t scalar1, 281 const curve448_point_t base2, 282 const curve448_scalar_t scalar2); 283 284 /* 285 * Test that a point is valid, for debugging purposes. 286 * 287 * to_test (in): The point to test. 288 * 289 * Returns: 290 * C448_TRUE The point is valid. 291 * C448_FALSE The point is invalid. 292 */ 293 __owur c448_bool_t curve448_point_valid(const curve448_point_t to_test); 294 295 /* Overwrite scalar with zeros. */ 296 void curve448_scalar_destroy(curve448_scalar_t scalar); 297 298 /* Overwrite point with zeros. */ 299 void curve448_point_destroy(curve448_point_t point); 300 301 #endif /* OSSL_CRYPTO_EC_CURVE448_POINT_448_H */ 302