1 /* 2 * NIST curve reduction 3 * 4 * Copyright: 5 * (C) 2014 Jack LLoyd 6 * (C) 2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 12 module botan.math.ec_gfp.curve_nistp; 13 14 import botan.constants; 15 static if (BOTAN_HAS_PUBLIC_KEY_CRYPTO): 16 17 import botan.math.ec_gfp.curve_gfp; 18 import botan.math.bigint.bigint; 19 import botan.math.mp.mp_core; 20 import botan.codec.hex; 21 import botan.utils.types; 22 import botan.utils.mem_ops; 23 24 abstract class CurveGFpNIST : CurveGFpRepr 25 { 26 this()(size_t p_bits, BigInt* a, BigInt* b) 27 { 28 m_a = a.dup; 29 m_b = b.dup; 30 m_p_words = (p_bits + BOTAN_MP_WORD_BITS - 1) / BOTAN_MP_WORD_BITS; 31 } 32 33 override ref const(BigInt) getA() const { return m_a; } 34 35 override ref const(BigInt) getB() const { return m_b; } 36 37 override ref const(BigInt) getARep() const { return m_a; } 38 39 override ref const(BigInt) getBRep() const { return m_b; } 40 41 override size_t getPWords() const { return m_p_words; } 42 43 override void toCurveRep(BigInt* x, ref SecureVector!word ws) const 44 { 45 redc(x, ws); 46 } 47 48 override void fromCurveRep(BigInt* x, ref SecureVector!word ws) const 49 { 50 redc(x, ws); 51 } 52 53 /** 54 * Montgomery multiplication/reduction 55 * Notes: z cannot alias x or y 56 * Params: 57 * z = output 58 * x = first multiplicand 59 * y = second multiplicand 60 */ 61 override void curveMul(BigInt* z, const(BigInt)* x, const(BigInt)* y, ref SecureVector!word ws) const 62 { 63 if (x.isZero() || y.isZero()) 64 { 65 BigInt zero = BigInt(0); 66 z.swap(&zero); 67 return; 68 } 69 70 const size_t p_words = getPWords(); 71 const size_t output_size = 2*p_words + 1; 72 ws.resize(2*(p_words+2)); 73 74 z.growTo(output_size); 75 z.clear(); 76 77 bigint_mul(z.mutablePtr(), output_size, ws.ptr, 78 x.ptr, x.length, x.sigWords(), 79 y.ptr, y.length, y.sigWords()); 80 81 this.redc(z, ws); 82 } 83 84 /** 85 * Montgomery squaring/reduction 86 * Notes: z cannot alias x 87 * Params: 88 * z = output 89 * x = multiplicand 90 */ 91 override void curveSqr(BigInt* z, const(BigInt)* x, ref SecureVector!word ws) const 92 { 93 if (x.isZero()) 94 { 95 BigInt zero = BigInt(0); 96 z.swap(&zero); 97 return; 98 } 99 100 const size_t p_words = getPWords(); 101 const size_t output_size = 2*p_words + 1; 102 103 ws.resize(2*(p_words+2)); 104 105 z.growTo(output_size); 106 z.clear(); 107 108 bigint_sqr(z.mutablePtr(), output_size, ws.ptr, 109 x.ptr, x.length, x.sigWords()); 110 111 this.redc(z, ws); 112 } 113 114 override Vector!char toVector() const 115 { 116 Vector!char ret; 117 ret ~= "\nm_a: "; 118 ret ~= m_a.toString(); 119 ret ~= "\nm_b: "; 120 ret ~= m_b.toString(); 121 ret ~= "\nm_p_words: "; 122 ret ~= m_p_words.to!string; 123 ret ~= "\n"; 124 return ret.move(); 125 } 126 127 override void swap(CurveGFpRepr other_) { 128 auto other = cast(CurveGFpNIST) other_; 129 m_a.swap(&other.m_a); 130 m_b.swap(&other.m_b); 131 import std.algorithm.mutation : swap; 132 swap(m_p_words, other.m_p_words); 133 } 134 135 protected: 136 abstract void redc(BigInt* x, ref SecureVector!word ws) const; 137 138 abstract size_t maxRedcSubstractions() const; 139 private: 140 // Curve parameters 141 BigInt m_a, m_b; 142 143 size_t m_p_words; // cache of m_p.sigWords() 144 } 145 146 /** 147 * The NIST P-521 curve 148 */ 149 class CurveGFpP521 : CurveGFpNIST 150 { 151 public: 152 this()(BigInt* a, BigInt* b) 153 { 154 if (prime is BigInt.init) 155 prime = BigInt("0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); 156 157 super(521, a, b); 158 } 159 160 override ref const(BigInt) getP() const { return prime; } 161 162 override void redc(BigInt* x, ref SecureVector!word ws) const 163 { 164 const size_t p_words = getPWords(); 165 166 const size_t shift_words = 521 / MP_WORD_BITS, 167 shift_bits = 521 % MP_WORD_BITS; 168 169 const size_t x_sw = x.sigWords(); 170 171 if (x_sw < p_words) 172 return; // already smaller 173 174 if (ws.length < p_words + 1) 175 ws.resize(p_words + 1); 176 177 clearMem(ws.ptr, ws.length); 178 bigint_shr2(ws.ptr, x.ptr, x_sw, shift_words, shift_bits); 179 180 x.maskBits(521); 181 182 bigint_add3(x.mutablePtr(), x.ptr, p_words, ws.ptr, p_words); 183 184 normalize(x, ws, maxRedcSubstractions()); 185 } 186 187 override size_t maxRedcSubstractions() const 188 { 189 return 1; 190 } 191 192 __gshared BigInt prime; 193 } 194