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, auto const ref BigInt a, auto const ref 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(ref BigInt x, ref SecureVector!word ws) const
44     {
45         redc(x, ws);
46     }
47     
48     override void fromCurveRep(ref 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(ref BigInt z, const ref BigInt x, const ref BigInt y, ref SecureVector!word ws) const
62     {
63         if (x.isZero() || y.isZero())
64         {
65             z = 0;
66             return;
67         }
68         
69         const size_t p_words = getPWords();
70         const size_t output_size = 2*p_words + 1;
71         ws.resize(2*(p_words+2));
72         
73         z.growTo(output_size);
74         z.clear();
75         
76         bigint_mul(z.mutablePtr(), output_size, ws.ptr,
77             x.ptr, x.length, x.sigWords(),
78             y.ptr, y.length, y.sigWords());
79         
80         this.redc(z, ws);
81     }
82     
83     /**
84     * Montgomery squaring/reduction
85     * Notes: z cannot alias x
86     * Params:
87     *  z = output
88     *  x = multiplicand
89     */
90     override void curveSqr(ref BigInt z, const ref BigInt x, ref SecureVector!word ws) const
91     {
92         if (x.isZero())
93         {
94             z = 0;
95             return;
96         }
97         
98         const size_t p_words = getPWords();
99         const size_t output_size = 2*p_words + 1;
100         
101         ws.resize(2*(p_words+2));
102         
103         z.growTo(output_size);
104         z.clear();
105         
106         bigint_sqr(z.mutablePtr(), output_size, ws.ptr,
107             x.ptr, x.length, x.sigWords());
108         
109         this.redc(z, ws);
110     }
111     
112     override Vector!char toVector() const
113     {
114         Vector!char ret;
115         ret ~= "\nm_a: ";
116         ret ~= m_a.toString();
117         ret ~= "\nm_b: ";
118         ret ~= m_b.toString();
119         ret ~= "\nm_p_words: ";
120         ret ~= m_p_words.to!string;
121         ret ~= "\n";
122         return ret.move();
123     }
124     
125 protected:
126     abstract void redc(ref BigInt x, ref SecureVector!word ws) const;
127 
128     abstract size_t maxRedcSubstractions() const;
129 private:
130     // Curve parameters
131     BigInt m_a, m_b;
132     
133     size_t m_p_words; // cache of m_p.sigWords()    
134 }
135 
136 /**
137 * The NIST P-521 curve
138 */
139 class CurveGFpP521 : CurveGFpNIST
140 {
141 public:
142     this()(auto const ref BigInt a, auto const ref BigInt b)
143     {
144 		if (prime is BigInt.init)
145 			prime = BigInt("0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
146 
147         super(521, a, b);
148     }
149 
150     override ref const(BigInt) getP() const { return prime; }
151 
152     override void redc(ref BigInt x, ref SecureVector!word ws) const
153     {
154         const size_t p_words = getPWords();
155         
156         const size_t shift_words = 521 / MP_WORD_BITS,
157             shift_bits  = 521 % MP_WORD_BITS;
158         
159         const size_t x_sw = x.sigWords();
160         
161         if (x_sw < p_words)
162             return; // already smaller
163         
164         if (ws.length < p_words + 1)
165             ws.resize(p_words + 1);
166         
167         clearMem(ws.ptr, ws.length);
168         bigint_shr2(ws.ptr, x.ptr, x_sw, shift_words, shift_bits);
169         
170         x.maskBits(521);
171         
172         bigint_add3(x.mutablePtr(), x.ptr, p_words, ws.ptr, p_words);
173         
174         normalize(x, ws, maxRedcSubstractions());
175     }
176 
177     override size_t maxRedcSubstractions() const
178     {
179         return 1;
180     }
181 
182     __gshared BigInt prime; 
183 }
184