Initial commit.
[BoarSSL] / Crypto / MutableECPoint.cs
1 /*
2 * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 using System;
26
27 namespace Crypto {
28
29 /*
30 * A MutableECPoint instance contains an elliptic curve point, in a
31 * given curve. It may be modified to contain another point, but not
32 * on another curve.
33 *
34 * Constant-time guarantees: IsInfinityCT, DoubleCT(), NegCT() and
35 * AddCT() are constant-time with regards to the represented curve
36 * point. Execution time may vary depending on the sequence of calls,
37 * but not on the point data. In particular, points may be internally
38 * "normalized" or not, and operations involving normalized points can
39 * be faster; however, normalization happens only upon an explicit call.
40 * The normalization process itself (Normalize()) is constant-time.
41 */
42
43 internal abstract class MutableECPoint {
44
45 internal MutableECPoint()
46 {
47 }
48
49 internal abstract ECCurve Curve {
50 get;
51 }
52
53 /*
54 * Test whether this point is the point at infinity.
55 */
56 internal bool IsInfinity {
57 get {
58 return IsInfinityCT != 0;
59 }
60 }
61
62 /*
63 * Test whether this point is the point at infinity (returns
64 * 0xFFFFFFFF or 0x00000000).
65 */
66 internal abstract uint IsInfinityCT {
67 get;
68 }
69
70 /*
71 * Normalize this instance. What this entails depends on the
72 * curve type, but it will typically means computing affine
73 * coordinates in case this instance was using some sort of
74 * projective system.
75 */
76 internal abstract void Normalize();
77
78 /*
79 * Encode this point into some bytes. If "compressed" is true,
80 * then a compressed format will be used.
81 *
82 * This call may entail normalization. If the point is not the
83 * infinity point, then this method is constant-time.
84 */
85 internal abstract byte[] Encode(bool compressed);
86
87 /*
88 * Encode this point into some bytes. If "compressed is true,
89 * then a compressed format will be used. The destination array
90 * must have the proper length for the requested point format.
91 *
92 * This call may entail normalization. If the point is invalid
93 * or is the point at infinity, then the returned value is 0
94 * and what gets written in the array is indeterminate. Otherwise,
95 * the encoded point is written and -1 is returned. Either way,
96 * this call is constant-time.
97 */
98 internal abstract uint Encode(byte[] dst, bool compressed);
99
100 /*
101 * Set this point by decoding the provided value. An invalid
102 * encoding sets this point to 0 (infinity) and triggers an
103 * exception.
104 */
105 internal void Decode(byte[] enc)
106 {
107 if (DecodeCT(enc) == 0) {
108 throw new CryptoException("Invalid encoded point");
109 }
110 }
111
112 /*
113 * Set this point by decoding the provided value. This is
114 * constant-time (up to the encoded point length). Returned
115 * value is 0xFFFFFFFF if the encoded point was valid,
116 * 0x00000000 otherwise. If the decoding failed, then this
117 * value is set to 0 (infinity).
118 */
119 internal abstract uint DecodeCT(byte[] enc);
120
121 /*
122 * Get the X coordinate for this point. This implies
123 * normalization. If the point is the point at infinity,
124 * then the returned array contains the encoding of 0.
125 * This is constant-time.
126 */
127 internal abstract byte[] X {
128 get;
129 }
130
131 /*
132 * Get the Y coordinate for this point. This implies
133 * normalization. If the point is the point at infinity,
134 * then the returned array contains the encoding of 0.
135 * This is constant-time.
136 */
137 internal abstract byte[] Y {
138 get;
139 }
140
141 /*
142 * Create a new instance that starts with the same contents as
143 * this point.
144 */
145 internal abstract MutableECPoint Dup();
146
147 /*
148 * Set this instance to the point at infinity.
149 */
150 internal abstract void SetZero();
151
152 /*
153 * Set this instance to the same contents as the provided point.
154 * The operand Q must be part of the same curve.
155 */
156 internal abstract void Set(MutableECPoint Q);
157
158 /*
159 * Set this instance to the same contents as the provided point,
160 * but only if ctl == 0xFFFFFFFFF. If ctl == 0x00000000, then
161 * this instance is unmodified. The operand Q must be part of
162 * the same curve.
163 */
164 internal abstract void Set(MutableECPoint Q, uint ctl);
165
166 /*
167 * Set this instance to the same contents as point P1 if
168 * ctl == 0xFFFFFFFF, or point P2 if ctl == 0x00000000.
169 * Both operands must use the same curve as this instance.
170 */
171 internal abstract void SetMux(uint ctl,
172 MutableECPoint P1, MutableECPoint P2);
173
174 /*
175 * DoubleCT() is constant-time. It works for all points
176 * (including points of order 2 and the infinity point).
177 */
178 internal abstract void DoubleCT();
179
180 /*
181 * AddCT() computes P+Q (P is this instance, Q is the operand).
182 * It may assume that P != Q. If P = Q and the method could not
183 * compute the correct result, then it shall set this instance to
184 * 0 (infinity) and return 0x00000000. In all other cases, it must
185 * compute the correct point and return 0xFFFFFFFF. In particular,
186 * it should properly handle cases where P = 0 or Q = 0. This
187 * function is allowed to handle doubling cases as well, if it
188 * can.
189 *
190 * This method may be more efficient if the operand is
191 * normalized. Execution time and memory access may depend on
192 * whether this instance or the other operand is normalized,
193 * but not on the actual point values (including if the points
194 * do not fulfill the properties above).
195 */
196 internal abstract uint AddCT(MutableECPoint Q);
197
198 /*
199 * Negate this point. It also works on the point at infinity,
200 * and it is constant-time.
201 */
202 internal abstract void NegCT();
203
204 /*
205 * Multiply this point by the provided integer (unsigned
206 * big-endian representation). This is constant-time. This
207 * method assumes that:
208 * -- the point on which we are operating is part of the curve
209 * defined subgroup;
210 * -- the defined subgroup has a prime order which is no less
211 * than 17;
212 * -- the point is not the point at infinity;
213 * -- the multiplier operand is no more than the subgroup order.
214 * If these conditions are met, then the resulting point will
215 * be the proper element of the defined subgroup (it will be
216 * the point at infinity only if the multiplier is 0 or is
217 * equal to the subgroup order). If they are NOT met, then the
218 * resulting point is undefined (but will still be part of the
219 * curve).
220 *
221 * This method is constant-time.
222 *
223 * Returned value is 0xFFFFFFFF if none of the internal
224 * operations reached a problematic state (i.e. that we tried to
225 * perform an addition and the two operands turned out to be
226 * equal to each other). If the conditions above are met, then
227 * this is always the case. If a problematic state was reached,
228 * then the returned value is 0x00000000. Callers MUST be very
229 * cautious about using that reported error state, since it is
230 * not guaranteed that all invalid points would be reported as
231 * such. There thus is potential for leakage of secret data.
232 */
233 internal abstract uint MulSpecCT(byte[] n);
234
235 /*
236 * Compare this point to another. This method throws an
237 * exception if the provided point is not on the same curve as
238 * this instance. It otherwise returns 0xFFFFFFFF if both points
239 * are equal, 0x00000000 otherwise. This method is constant-time
240 * (its execution time may depend on whether this and/or the
241 * other point is normalized or not, but not on the actual
242 * values).
243 */
244 internal abstract uint EqCT(MutableECPoint Q);
245
246 internal bool Eq(MutableECPoint Q)
247 {
248 return EqCT(Q) != 0;
249 }
250 }
251
252 }