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