1 /* 2 * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright 2015-2016 Cryptography Research, Inc. 4 * 5 * Licensed under the Apache License 2.0 (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 ossl_curve448_scalar_one; 73 74 /* A scalar equal to 0. */ 75 extern const curve448_scalar_t ossl_curve448_scalar_zero; 76 77 /* The identity point on the curve. */ 78 extern const curve448_point_t ossl_curve448_point_identity; 79 80 /* Precomputed table for the base point on the curve. */ 81 extern const struct curve448_precomputed_s *ossl_curve448_precomputed_base; 82 extern const niels_t *ossl_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 96 ossl_curve448_scalar_decode(curve448_scalar_t out, 97 const unsigned char ser[C448_SCALAR_BYTES]); 98 99 /* 100 * Read a scalar from wire format or from bytes. Reduces mod scalar prime. 101 * 102 * ser (in): Serialized form of a scalar. 103 * ser_len (in): Length of serialized form. 104 * out (out): Deserialized form. 105 */ 106 void 107 ossl_curve448_scalar_decode_long(curve448_scalar_t out, 108 const unsigned char *ser, size_t ser_len); 109 110 /* 111 * Serialize a scalar to wire format. 112 * 113 * ser (out): Serialized form of a scalar. 114 * s (in): Deserialized scalar. 115 */ 116 void 117 ossl_curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES], 118 const curve448_scalar_t s); 119 120 /* 121 * Add two scalars. |a|, |b| and |out| may alias each other. 122 * 123 * a (in): One scalar. 124 * b (in): Another scalar. 125 * out (out): a+b. 126 */ 127 void 128 ossl_curve448_scalar_add(curve448_scalar_t out, 129 const curve448_scalar_t a, const curve448_scalar_t b); 130 131 /* 132 * Subtract two scalars. |a|, |b| and |out| may alias each other. 133 * a (in): One scalar. 134 * b (in): Another scalar. 135 * out (out): a-b. 136 */ 137 void 138 ossl_curve448_scalar_sub(curve448_scalar_t out, 139 const curve448_scalar_t a, const curve448_scalar_t b); 140 141 /* 142 * Multiply two scalars. |a|, |b| and |out| may alias each other. 143 * 144 * a (in): One scalar. 145 * b (in): Another scalar. 146 * out (out): a*b. 147 */ 148 void 149 ossl_curve448_scalar_mul(curve448_scalar_t out, 150 const curve448_scalar_t a, const curve448_scalar_t b); 151 152 /* 153 * Halve a scalar. |a| and |out| may alias each other. 154 * 155 * a (in): A scalar. 156 * out (out): a/2. 157 */ 158 void 159 ossl_curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a); 160 161 /* 162 * Copy a scalar. The scalars may alias each other, in which case this 163 * function does nothing. 164 * 165 * a (in): A scalar. 166 * out (out): Will become a copy of a. 167 */ 168 static ossl_inline void curve448_scalar_copy(curve448_scalar_t out, 169 const curve448_scalar_t a) 170 { 171 *out = *a; 172 } 173 174 /* 175 * Copy a point. The input and output may alias, in which case this function 176 * does nothing. 177 * 178 * a (out): A copy of the point. 179 * b (in): Any point. 180 */ 181 static ossl_inline void curve448_point_copy(curve448_point_t a, 182 const curve448_point_t b) 183 { 184 *a = *b; 185 } 186 187 /* 188 * Test whether two points are equal. If yes, return C448_TRUE, else return 189 * C448_FALSE. 190 * 191 * a (in): A point. 192 * b (in): Another point. 193 * 194 * Returns: 195 * C448_TRUE: The points are equal. 196 * C448_FALSE: The points are not equal. 197 */ 198 __owur c448_bool_t 199 ossl_curve448_point_eq(const curve448_point_t a, 200 const curve448_point_t b); 201 202 /* 203 * Double a point. Equivalent to curve448_point_add(two_a,a,a), but potentially 204 * faster. 205 * 206 * two_a (out): The sum a+a. 207 * a (in): A point. 208 */ 209 void 210 ossl_curve448_point_double(curve448_point_t two_a, const curve448_point_t a); 211 212 /* 213 * RFC 7748 Diffie-Hellman scalarmul. This function uses a different 214 * (non-Decaf) encoding. 215 * 216 * out (out): The scaled point base*scalar 217 * base (in): The point to be scaled. 218 * scalar (in): The scalar to multiply by. 219 * 220 * Returns: 221 * C448_SUCCESS: The scalarmul succeeded. 222 * C448_FAILURE: The scalarmul didn't succeed, because the base point is in a 223 * small subgroup. 224 */ 225 __owur c448_error_t 226 ossl_x448_int(uint8_t out[X448_PUBLIC_BYTES], 227 const uint8_t base[X448_PUBLIC_BYTES], 228 const uint8_t scalar[X448_PRIVATE_BYTES]); 229 230 /* 231 * Multiply a point by X448_ENCODE_RATIO, then encode it like RFC 7748. 232 * 233 * This function is mainly used internally, but is exported in case 234 * it will be useful. 235 * 236 * The ratio is necessary because the internal representation doesn't 237 * track the cofactor information, so on output we must clear the cofactor. 238 * This would multiply by the cofactor, but in fact internally points are always 239 * even, so it multiplies by half the cofactor instead. 240 * 241 * As it happens, this aligns with the base point definitions; that is, 242 * if you pass the Decaf/Ristretto base point to this function, the result 243 * will be X448_ENCODE_RATIO times the X448 244 * base point. 245 * 246 * out (out): The scaled and encoded point. 247 * p (in): The point to be scaled and encoded. 248 */ 249 void 250 ossl_curve448_point_mul_by_ratio_and_encode_like_x448( 251 uint8_t out[X448_PUBLIC_BYTES], 252 const curve448_point_t p); 253 254 /* 255 * RFC 7748 Diffie-Hellman base point scalarmul. This function uses a different 256 * (non-Decaf) encoding. 257 * 258 * out (out): The scaled point base*scalar 259 * scalar (in): The scalar to multiply by. 260 */ 261 void 262 ossl_x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES], 263 const uint8_t scalar[X448_PRIVATE_BYTES]); 264 265 /* 266 * Multiply a precomputed base point by a scalar: out = scalar*base. 267 * 268 * scaled (out): The scaled point base*scalar 269 * base (in): The point to be scaled. 270 * scalar (in): The scalar to multiply by. 271 */ 272 void 273 ossl_curve448_precomputed_scalarmul(curve448_point_t scaled, 274 const curve448_precomputed_s * base, 275 const curve448_scalar_t scalar); 276 277 /* 278 * Multiply two base points by two scalars: 279 * combo = scalar1*curve448_point_base + scalar2*base2. 280 * 281 * Otherwise equivalent to curve448_point_double_scalarmul, but may be 282 * faster at the expense of being variable time. 283 * 284 * combo (out): The linear combination scalar1*base + scalar2*base2. 285 * scalar1 (in): A first scalar to multiply by. 286 * base2 (in): A second point to be scaled. 287 * scalar2 (in) A second scalar to multiply by. 288 * 289 * Warning: This function takes variable time, and may leak the scalars used. 290 * It is designed for signature verification. 291 */ 292 void 293 ossl_curve448_base_double_scalarmul_non_secret(curve448_point_t combo, 294 const curve448_scalar_t scalar1, 295 const curve448_point_t base2, 296 const curve448_scalar_t scalar2); 297 298 /* 299 * Test that a point is valid, for debugging purposes. 300 * 301 * to_test (in): The point to test. 302 * 303 * Returns: 304 * C448_TRUE The point is valid. 305 * C448_FALSE The point is invalid. 306 */ 307 __owur c448_bool_t 308 ossl_curve448_point_valid(const curve448_point_t to_test); 309 310 /* Overwrite scalar with zeros. */ 311 void ossl_curve448_scalar_destroy(curve448_scalar_t scalar); 312 313 /* Overwrite point with zeros. */ 314 void ossl_curve448_point_destroy(curve448_point_t point); 315 316 #endif /* OSSL_CRYPTO_EC_CURVE448_POINT_448_H */ 317