1 // Copyright 2016 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 use crate::{arithmetic::montgomery::*, c, error, limb::*};
16 use core::marker::PhantomData;
17 use untrusted;
18
19 pub use self::elem::*;
20
21 /// A field element, i.e. an element of ℤ/qℤ for the curve's field modulus
22 /// *q*.
23 pub type Elem<E> = elem::Elem<Q, E>;
24
25 /// Represents the (prime) order *q* of the curve's prime field.
26 #[derive(Clone, Copy)]
27 pub enum Q {}
28
29 /// A scalar. Its value is in [0, n). Zero-valued scalars are forbidden in most
30 /// contexts.
31 pub type Scalar<E = Unencoded> = elem::Elem<N, E>;
32
33 /// Represents the prime order *n* of the curve's group.
34 #[derive(Clone, Copy)]
35 pub enum N {}
36
37 pub struct Point {
38 // The coordinates are stored in a contiguous array, where the first
39 // `ops.num_limbs` elements are the X coordinate, the next
40 // `ops.num_limbs` elements are the Y coordinate, and the next
41 // `ops.num_limbs` elements are the Z coordinate. This layout is dictated
42 // by the requirements of the GFp_nistz256 code.
43 xyz: [Limb; 3 * MAX_LIMBS],
44 }
45
46 impl Point {
new_at_infinity() -> Point47 pub fn new_at_infinity() -> Point {
48 Point {
49 xyz: [0; 3 * MAX_LIMBS],
50 }
51 }
52 }
53
54 static ONE: Elem<Unencoded> = Elem {
55 limbs: limbs![1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
56 m: PhantomData,
57 encoding: PhantomData,
58 };
59
60 /// Operations and values needed by all curve operations.
61 pub struct CommonOps {
62 pub num_limbs: usize,
63 q: Modulus,
64 pub n: Elem<Unencoded>,
65
66 pub a: Elem<R>, // Must be -3 mod q
67 pub b: Elem<R>,
68
69 // In all cases, `r`, `a`, and `b` may all alias each other.
70 elem_add_impl: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
71 elem_mul_mont: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
72 elem_sqr_mont: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
73
74 point_add_jacobian_impl: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
75 }
76
77 impl CommonOps {
78 #[inline]
elem_add<E: Encoding>(&self, a: &mut Elem<E>, b: &Elem<E>)79 pub fn elem_add<E: Encoding>(&self, a: &mut Elem<E>, b: &Elem<E>) {
80 binary_op_assign(self.elem_add_impl, a, b)
81 }
82
83 #[inline]
elems_are_equal(&self, a: &Elem<R>, b: &Elem<R>) -> LimbMask84 pub fn elems_are_equal(&self, a: &Elem<R>, b: &Elem<R>) -> LimbMask {
85 limbs_equal_limbs_consttime(&a.limbs[..self.num_limbs], &b.limbs[..self.num_limbs])
86 }
87
88 #[inline]
elem_unencoded(&self, a: &Elem<R>) -> Elem<Unencoded>89 pub fn elem_unencoded(&self, a: &Elem<R>) -> Elem<Unencoded> {
90 self.elem_product(a, &ONE)
91 }
92
93 #[inline]
elem_mul(&self, a: &mut Elem<R>, b: &Elem<R>)94 pub fn elem_mul(&self, a: &mut Elem<R>, b: &Elem<R>) {
95 binary_op_assign(self.elem_mul_mont, a, b)
96 }
97
98 #[inline]
elem_product<EA: Encoding, EB: Encoding>( &self, a: &Elem<EA>, b: &Elem<EB>, ) -> Elem<<(EA, EB) as ProductEncoding>::Output> where (EA, EB): ProductEncoding,99 pub fn elem_product<EA: Encoding, EB: Encoding>(
100 &self,
101 a: &Elem<EA>,
102 b: &Elem<EB>,
103 ) -> Elem<<(EA, EB) as ProductEncoding>::Output>
104 where
105 (EA, EB): ProductEncoding,
106 {
107 mul_mont(self.elem_mul_mont, a, b)
108 }
109
110 #[inline]
elem_square(&self, a: &mut Elem<R>)111 pub fn elem_square(&self, a: &mut Elem<R>) {
112 unary_op_assign(self.elem_sqr_mont, a);
113 }
114
115 #[inline]
elem_squared(&self, a: &Elem<R>) -> Elem<R>116 pub fn elem_squared(&self, a: &Elem<R>) -> Elem<R> {
117 unary_op(self.elem_sqr_mont, a)
118 }
119
120 #[inline]
is_zero<M, E: Encoding>(&self, a: &elem::Elem<M, E>) -> bool121 pub fn is_zero<M, E: Encoding>(&self, a: &elem::Elem<M, E>) -> bool {
122 limbs_are_zero_constant_time(&a.limbs[..self.num_limbs]) == LimbMask::True
123 }
124
elem_verify_is_not_zero(&self, a: &Elem<R>) -> Result<(), error::Unspecified>125 pub fn elem_verify_is_not_zero(&self, a: &Elem<R>) -> Result<(), error::Unspecified> {
126 if self.is_zero(a) {
127 Err(error::Unspecified)
128 } else {
129 Ok(())
130 }
131 }
132
point_sum(&self, a: &Point, b: &Point) -> Point133 pub fn point_sum(&self, a: &Point, b: &Point) -> Point {
134 let mut r = Point::new_at_infinity();
135 unsafe {
136 (self.point_add_jacobian_impl)(r.xyz.as_mut_ptr(), a.xyz.as_ptr(), b.xyz.as_ptr())
137 }
138 r
139 }
140
point_x(&self, p: &Point) -> Elem<R>141 pub fn point_x(&self, p: &Point) -> Elem<R> {
142 let mut r = Elem::zero();
143 r.limbs[..self.num_limbs].copy_from_slice(&p.xyz[0..self.num_limbs]);
144 r
145 }
146
point_y(&self, p: &Point) -> Elem<R>147 pub fn point_y(&self, p: &Point) -> Elem<R> {
148 let mut r = Elem::zero();
149 r.limbs[..self.num_limbs].copy_from_slice(&p.xyz[self.num_limbs..(2 * self.num_limbs)]);
150 r
151 }
152
point_z(&self, p: &Point) -> Elem<R>153 pub fn point_z(&self, p: &Point) -> Elem<R> {
154 let mut r = Elem::zero();
155 r.limbs[..self.num_limbs]
156 .copy_from_slice(&p.xyz[(2 * self.num_limbs)..(3 * self.num_limbs)]);
157 r
158 }
159 }
160
161 struct Modulus {
162 p: [Limb; MAX_LIMBS],
163 rr: [Limb; MAX_LIMBS],
164 }
165
166 /// Operations on private keys, for ECDH and ECDSA signing.
167 pub struct PrivateKeyOps {
168 pub common: &'static CommonOps,
169 elem_inv_squared: fn(a: &Elem<R>) -> Elem<R>,
170 point_mul_base_impl: fn(a: &Scalar) -> Point,
171 point_mul_impl: unsafe extern "C" fn(
172 r: *mut Limb, // [3][num_limbs]
173 p_scalar: *const Limb, // [num_limbs]
174 p_x: *const Limb, // [num_limbs]
175 p_y: *const Limb, // [num_limbs]
176 ),
177 }
178
179 impl PrivateKeyOps {
180 #[inline(always)]
point_mul_base(&self, a: &Scalar) -> Point181 pub fn point_mul_base(&self, a: &Scalar) -> Point {
182 (self.point_mul_base_impl)(a)
183 }
184
185 #[inline(always)]
point_mul(&self, p_scalar: &Scalar, (p_x, p_y): &(Elem<R>, Elem<R>)) -> Point186 pub fn point_mul(&self, p_scalar: &Scalar, (p_x, p_y): &(Elem<R>, Elem<R>)) -> Point {
187 let mut r = Point::new_at_infinity();
188 unsafe {
189 (self.point_mul_impl)(
190 r.xyz.as_mut_ptr(),
191 p_scalar.limbs.as_ptr(),
192 p_x.limbs.as_ptr(),
193 p_y.limbs.as_ptr(),
194 );
195 }
196 r
197 }
198
199 #[inline]
elem_inverse_squared(&self, a: &Elem<R>) -> Elem<R>200 pub fn elem_inverse_squared(&self, a: &Elem<R>) -> Elem<R> {
201 (self.elem_inv_squared)(a)
202 }
203 }
204
205 /// Operations and values needed by all operations on public keys (ECDH
206 /// agreement and ECDSA verification).
207 pub struct PublicKeyOps {
208 pub common: &'static CommonOps,
209 }
210
211 impl PublicKeyOps {
212 // The serialized bytes are in big-endian order, zero-padded. The limbs
213 // of `Elem` are in the native endianness, least significant limb to
214 // most significant limb. Besides the parsing, conversion, this also
215 // implements NIST SP 800-56A Step 2: "Verify that xQ and yQ are integers
216 // in the interval [0, p-1] in the case that q is an odd prime p[.]"
elem_parse(&self, input: &mut untrusted::Reader) -> Result<Elem<R>, error::Unspecified>217 pub fn elem_parse(&self, input: &mut untrusted::Reader) -> Result<Elem<R>, error::Unspecified> {
218 let encoded_value = input.read_bytes(self.common.num_limbs * LIMB_BYTES)?;
219 let parsed = elem_parse_big_endian_fixed_consttime(self.common, encoded_value)?;
220 let mut r = Elem::zero();
221 // Montgomery encode (elem_to_mont).
222 // TODO: do something about this.
223 unsafe {
224 (self.common.elem_mul_mont)(
225 r.limbs.as_mut_ptr(),
226 parsed.limbs.as_ptr(),
227 self.common.q.rr.as_ptr(),
228 )
229 }
230 Ok(r)
231 }
232 }
233
234 // Operations used by both ECDSA signing and ECDSA verification. In general
235 // these must be side-channel resistant.
236 pub struct ScalarOps {
237 pub common: &'static CommonOps,
238
239 scalar_inv_to_mont_impl: fn(a: &Scalar) -> Scalar<R>,
240 scalar_mul_mont: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
241 }
242
243 impl ScalarOps {
244 // The (maximum) length of a scalar, not including any padding.
scalar_bytes_len(&self) -> usize245 pub fn scalar_bytes_len(&self) -> usize {
246 self.common.num_limbs * LIMB_BYTES
247 }
248
249 /// Returns the modular inverse of `a` (mod `n`). Panics of `a` is zero,
250 /// because zero isn't invertible.
scalar_inv_to_mont(&self, a: &Scalar) -> Scalar<R>251 pub fn scalar_inv_to_mont(&self, a: &Scalar) -> Scalar<R> {
252 assert!(!self.common.is_zero(a));
253 (self.scalar_inv_to_mont_impl)(a)
254 }
255
256 #[inline]
scalar_product<EA: Encoding, EB: Encoding>( &self, a: &Scalar<EA>, b: &Scalar<EB>, ) -> Scalar<<(EA, EB) as ProductEncoding>::Output> where (EA, EB): ProductEncoding,257 pub fn scalar_product<EA: Encoding, EB: Encoding>(
258 &self,
259 a: &Scalar<EA>,
260 b: &Scalar<EB>,
261 ) -> Scalar<<(EA, EB) as ProductEncoding>::Output>
262 where
263 (EA, EB): ProductEncoding,
264 {
265 mul_mont(self.scalar_mul_mont, a, b)
266 }
267 }
268
269 /// Operations on public scalars needed by ECDSA signature verification.
270 pub struct PublicScalarOps {
271 pub scalar_ops: &'static ScalarOps,
272 pub public_key_ops: &'static PublicKeyOps,
273
274 // XXX: `PublicScalarOps` shouldn't depend on `PrivateKeyOps`, but it does
275 // temporarily until `twin_mul` is rewritten.
276 pub private_key_ops: &'static PrivateKeyOps,
277
278 pub q_minus_n: Elem<Unencoded>,
279 }
280
281 impl PublicScalarOps {
282 #[inline]
scalar_as_elem(&self, a: &Scalar) -> Elem<Unencoded>283 pub fn scalar_as_elem(&self, a: &Scalar) -> Elem<Unencoded> {
284 Elem {
285 limbs: a.limbs,
286 m: PhantomData,
287 encoding: PhantomData,
288 }
289 }
290
elem_equals(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> bool291 pub fn elem_equals(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> bool {
292 for i in 0..self.public_key_ops.common.num_limbs {
293 if a.limbs[i] != b.limbs[i] {
294 return false;
295 }
296 }
297 true
298 }
299
elem_less_than(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> bool300 pub fn elem_less_than(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> bool {
301 let num_limbs = self.public_key_ops.common.num_limbs;
302 limbs_less_than_limbs_vartime(&a.limbs[..num_limbs], &b.limbs[..num_limbs])
303 }
304
305 #[inline]
elem_sum(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> Elem<Unencoded>306 pub fn elem_sum(&self, a: &Elem<Unencoded>, b: &Elem<Unencoded>) -> Elem<Unencoded> {
307 binary_op(self.public_key_ops.common.elem_add_impl, a, b)
308 }
309 }
310
311 #[allow(non_snake_case)]
312 pub struct PrivateScalarOps {
313 pub scalar_ops: &'static ScalarOps,
314
315 pub oneRR_mod_n: Scalar<RR>, // 1 * R**2 (mod n). TOOD: Use One<RR>.
316 }
317
318 // This assumes n < q < 2*n.
elem_reduced_to_scalar(ops: &CommonOps, elem: &Elem<Unencoded>) -> Scalar<Unencoded>319 pub fn elem_reduced_to_scalar(ops: &CommonOps, elem: &Elem<Unencoded>) -> Scalar<Unencoded> {
320 let num_limbs = ops.num_limbs;
321 let mut r_limbs = elem.limbs;
322 limbs_reduce_once_constant_time(&mut r_limbs[..num_limbs], &ops.n.limbs[..num_limbs]);
323 Scalar {
324 limbs: r_limbs,
325 m: PhantomData,
326 encoding: PhantomData,
327 }
328 }
329
scalar_sum(ops: &CommonOps, a: &Scalar, b: &Scalar) -> Scalar330 pub fn scalar_sum(ops: &CommonOps, a: &Scalar, b: &Scalar) -> Scalar {
331 let mut r = Scalar::zero();
332 unsafe {
333 LIMBS_add_mod(
334 r.limbs.as_mut_ptr(),
335 a.limbs.as_ptr(),
336 b.limbs.as_ptr(),
337 ops.n.limbs.as_ptr(),
338 ops.num_limbs,
339 )
340 }
341 r
342 }
343
344 // Returns (`a` squared `squarings` times) * `b`.
elem_sqr_mul(ops: &CommonOps, a: &Elem<R>, squarings: usize, b: &Elem<R>) -> Elem<R>345 fn elem_sqr_mul(ops: &CommonOps, a: &Elem<R>, squarings: usize, b: &Elem<R>) -> Elem<R> {
346 debug_assert!(squarings >= 1);
347 let mut tmp = ops.elem_squared(a);
348 for _ in 1..squarings {
349 ops.elem_square(&mut tmp);
350 }
351 ops.elem_product(&tmp, b)
352 }
353
354 // Sets `acc` = (`acc` squared `squarings` times) * `b`.
elem_sqr_mul_acc(ops: &CommonOps, acc: &mut Elem<R>, squarings: usize, b: &Elem<R>)355 fn elem_sqr_mul_acc(ops: &CommonOps, acc: &mut Elem<R>, squarings: usize, b: &Elem<R>) {
356 debug_assert!(squarings >= 1);
357 for _ in 0..squarings {
358 ops.elem_square(acc);
359 }
360 ops.elem_mul(acc, b)
361 }
362
363 #[inline]
elem_parse_big_endian_fixed_consttime( ops: &CommonOps, bytes: untrusted::Input, ) -> Result<Elem<Unencoded>, error::Unspecified>364 pub fn elem_parse_big_endian_fixed_consttime(
365 ops: &CommonOps,
366 bytes: untrusted::Input,
367 ) -> Result<Elem<Unencoded>, error::Unspecified> {
368 parse_big_endian_fixed_consttime(ops, bytes, AllowZero::Yes, &ops.q.p[..ops.num_limbs])
369 }
370
371 #[inline]
scalar_parse_big_endian_fixed_consttime( ops: &CommonOps, bytes: untrusted::Input, ) -> Result<Scalar, error::Unspecified>372 pub fn scalar_parse_big_endian_fixed_consttime(
373 ops: &CommonOps,
374 bytes: untrusted::Input,
375 ) -> Result<Scalar, error::Unspecified> {
376 parse_big_endian_fixed_consttime(ops, bytes, AllowZero::No, &ops.n.limbs[..ops.num_limbs])
377 }
378
379 #[inline]
scalar_parse_big_endian_variable( ops: &CommonOps, allow_zero: AllowZero, bytes: untrusted::Input, ) -> Result<Scalar, error::Unspecified>380 pub fn scalar_parse_big_endian_variable(
381 ops: &CommonOps,
382 allow_zero: AllowZero,
383 bytes: untrusted::Input,
384 ) -> Result<Scalar, error::Unspecified> {
385 let mut r = Scalar::zero();
386 parse_big_endian_in_range_and_pad_consttime(
387 bytes,
388 allow_zero,
389 &ops.n.limbs[..ops.num_limbs],
390 &mut r.limbs[..ops.num_limbs],
391 )?;
392 Ok(r)
393 }
394
scalar_parse_big_endian_partially_reduced_variable_consttime( ops: &CommonOps, allow_zero: AllowZero, bytes: untrusted::Input, ) -> Result<Scalar, error::Unspecified>395 pub fn scalar_parse_big_endian_partially_reduced_variable_consttime(
396 ops: &CommonOps,
397 allow_zero: AllowZero,
398 bytes: untrusted::Input,
399 ) -> Result<Scalar, error::Unspecified> {
400 let mut r = Scalar::zero();
401 parse_big_endian_in_range_partially_reduced_and_pad_consttime(
402 bytes,
403 allow_zero,
404 &ops.n.limbs[..ops.num_limbs],
405 &mut r.limbs[..ops.num_limbs],
406 )?;
407 Ok(r)
408 }
409
parse_big_endian_fixed_consttime<M>( ops: &CommonOps, bytes: untrusted::Input, allow_zero: AllowZero, max_exclusive: &[Limb], ) -> Result<elem::Elem<M, Unencoded>, error::Unspecified>410 fn parse_big_endian_fixed_consttime<M>(
411 ops: &CommonOps,
412 bytes: untrusted::Input,
413 allow_zero: AllowZero,
414 max_exclusive: &[Limb],
415 ) -> Result<elem::Elem<M, Unencoded>, error::Unspecified> {
416 if bytes.len() != ops.num_limbs * LIMB_BYTES {
417 return Err(error::Unspecified);
418 }
419 let mut r = elem::Elem::zero();
420 parse_big_endian_in_range_and_pad_consttime(
421 bytes,
422 allow_zero,
423 max_exclusive,
424 &mut r.limbs[..ops.num_limbs],
425 )?;
426 Ok(r)
427 }
428
429 extern "C" {
LIMBS_add_mod( r: *mut Limb, a: *const Limb, b: *const Limb, m: *const Limb, num_limbs: c::size_t, )430 fn LIMBS_add_mod(
431 r: *mut Limb,
432 a: *const Limb,
433 b: *const Limb,
434 m: *const Limb,
435 num_limbs: c::size_t,
436 );
437 }
438
439 #[cfg(test)]
440 mod tests {
441 use super::*;
442 use crate::test;
443 use alloc::{format, vec, vec::Vec};
444 use untrusted;
445
446 const ZERO_SCALAR: Scalar = Scalar {
447 limbs: [0; MAX_LIMBS],
448 m: PhantomData,
449 encoding: PhantomData,
450 };
451
q_minus_n_plus_n_equals_0_test(ops: &PublicScalarOps)452 fn q_minus_n_plus_n_equals_0_test(ops: &PublicScalarOps) {
453 let cops = ops.scalar_ops.common;
454 let mut x = ops.q_minus_n;
455 cops.elem_add(&mut x, &cops.n);
456 assert!(cops.is_zero(&x));
457 }
458
459 #[test]
p256_q_minus_n_plus_n_equals_0_test()460 fn p256_q_minus_n_plus_n_equals_0_test() {
461 q_minus_n_plus_n_equals_0_test(&p256::PUBLIC_SCALAR_OPS);
462 }
463
464 #[test]
p384_q_minus_n_plus_n_equals_0_test()465 fn p384_q_minus_n_plus_n_equals_0_test() {
466 q_minus_n_plus_n_equals_0_test(&p384::PUBLIC_SCALAR_OPS);
467 }
468
469 #[test]
p256_elem_add_test()470 fn p256_elem_add_test() {
471 elem_add_test(
472 &p256::PUBLIC_SCALAR_OPS,
473 test_file!("ops/p256_elem_sum_tests.txt"),
474 );
475 }
476
477 #[test]
p384_elem_add_test()478 fn p384_elem_add_test() {
479 elem_add_test(
480 &p384::PUBLIC_SCALAR_OPS,
481 test_file!("ops/p384_elem_sum_tests.txt"),
482 );
483 }
484
elem_add_test(ops: &PublicScalarOps, test_file: test::File)485 fn elem_add_test(ops: &PublicScalarOps, test_file: test::File) {
486 test::run(test_file, |section, test_case| {
487 assert_eq!(section, "");
488
489 let cops = ops.public_key_ops.common;
490 let a = consume_elem(cops, test_case, "a");
491 let b = consume_elem(cops, test_case, "b");
492 let expected_sum = consume_elem(cops, test_case, "r");
493
494 let mut actual_sum = a.clone();
495 ops.public_key_ops.common.elem_add(&mut actual_sum, &b);
496 assert_limbs_are_equal(cops, &actual_sum.limbs, &expected_sum.limbs);
497
498 let mut actual_sum = b.clone();
499 ops.public_key_ops.common.elem_add(&mut actual_sum, &a);
500 assert_limbs_are_equal(cops, &actual_sum.limbs, &expected_sum.limbs);
501
502 Ok(())
503 })
504 }
505
506 // XXX: There's no `GFp_nistz256_sub` in *ring*; it's logic is inlined into
507 // the point arithmetic functions. Thus, we can't test it.
508
509 #[test]
p384_elem_sub_test()510 fn p384_elem_sub_test() {
511 extern "C" {
512 fn GFp_p384_elem_sub(r: *mut Limb, a: *const Limb, b: *const Limb);
513 }
514 elem_sub_test(
515 &p384::COMMON_OPS,
516 GFp_p384_elem_sub,
517 test_file!("ops/p384_elem_sum_tests.txt"),
518 );
519 }
520
elem_sub_test( ops: &CommonOps, elem_sub: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), test_file: test::File, )521 fn elem_sub_test(
522 ops: &CommonOps,
523 elem_sub: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
524 test_file: test::File,
525 ) {
526 test::run(test_file, |section, test_case| {
527 assert_eq!(section, "");
528
529 let a = consume_elem(ops, test_case, "a");
530 let b = consume_elem(ops, test_case, "b");
531 let r = consume_elem(ops, test_case, "r");
532
533 let mut actual_difference = Elem::<R>::zero();
534 unsafe {
535 elem_sub(
536 actual_difference.limbs.as_mut_ptr(),
537 r.limbs.as_ptr(),
538 b.limbs.as_ptr(),
539 );
540 }
541 assert_limbs_are_equal(ops, &actual_difference.limbs, &a.limbs);
542
543 let mut actual_difference = Elem::<R>::zero();
544 unsafe {
545 elem_sub(
546 actual_difference.limbs.as_mut_ptr(),
547 r.limbs.as_ptr(),
548 a.limbs.as_ptr(),
549 );
550 }
551 assert_limbs_are_equal(ops, &actual_difference.limbs, &b.limbs);
552
553 Ok(())
554 })
555 }
556
557 // XXX: There's no `GFp_nistz256_div_by_2` in *ring*; it's logic is inlined
558 // into the point arithmetic functions. Thus, we can't test it.
559
560 #[test]
p384_elem_div_by_2_test()561 fn p384_elem_div_by_2_test() {
562 extern "C" {
563 fn GFp_p384_elem_div_by_2(r: *mut Limb, a: *const Limb);
564 }
565 elem_div_by_2_test(
566 &p384::COMMON_OPS,
567 GFp_p384_elem_div_by_2,
568 test_file!("ops/p384_elem_div_by_2_tests.txt"),
569 );
570 }
571
elem_div_by_2_test( ops: &CommonOps, elem_div_by_2: unsafe extern "C" fn(r: *mut Limb, a: *const Limb), test_file: test::File, )572 fn elem_div_by_2_test(
573 ops: &CommonOps,
574 elem_div_by_2: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
575 test_file: test::File,
576 ) {
577 test::run(test_file, |section, test_case| {
578 assert_eq!(section, "");
579
580 let a = consume_elem(ops, test_case, "a");
581 let r = consume_elem(ops, test_case, "r");
582
583 let mut actual_result = Elem::<R>::zero();
584 unsafe {
585 elem_div_by_2(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr());
586 }
587 assert_limbs_are_equal(ops, &actual_result.limbs, &r.limbs);
588
589 Ok(())
590 })
591 }
592
593 // TODO: Add test vectors that test the range of values above `q`.
594 #[test]
p256_elem_neg_test()595 fn p256_elem_neg_test() {
596 extern "C" {
597 fn GFp_nistz256_neg(r: *mut Limb, a: *const Limb);
598 }
599 elem_neg_test(
600 &p256::COMMON_OPS,
601 GFp_nistz256_neg,
602 test_file!("ops/p256_elem_neg_tests.txt"),
603 );
604 }
605
606 #[test]
p384_elem_neg_test()607 fn p384_elem_neg_test() {
608 extern "C" {
609 fn GFp_p384_elem_neg(r: *mut Limb, a: *const Limb);
610 }
611 elem_neg_test(
612 &p384::COMMON_OPS,
613 GFp_p384_elem_neg,
614 test_file!("ops/p384_elem_neg_tests.txt"),
615 );
616 }
617
elem_neg_test( ops: &CommonOps, elem_neg: unsafe extern "C" fn(r: *mut Limb, a: *const Limb), test_file: test::File, )618 fn elem_neg_test(
619 ops: &CommonOps,
620 elem_neg: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
621 test_file: test::File,
622 ) {
623 test::run(test_file, |section, test_case| {
624 assert_eq!(section, "");
625
626 let a = consume_elem(ops, test_case, "a");
627 let b = consume_elem(ops, test_case, "b");
628
629 // Verify -a == b.
630 {
631 let mut actual_result = Elem::<R>::zero();
632 unsafe {
633 elem_neg(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr());
634 }
635 assert_limbs_are_equal(ops, &actual_result.limbs, &b.limbs);
636 }
637
638 // Verify -b == a.
639 {
640 let mut actual_result = Elem::<R>::zero();
641 unsafe {
642 elem_neg(actual_result.limbs.as_mut_ptr(), b.limbs.as_ptr());
643 }
644 assert_limbs_are_equal(ops, &actual_result.limbs, &a.limbs);
645 }
646
647 Ok(())
648 })
649 }
650
651 #[test]
p256_elem_mul_test()652 fn p256_elem_mul_test() {
653 elem_mul_test(&p256::COMMON_OPS, test_file!("ops/p256_elem_mul_tests.txt"));
654 }
655
656 #[test]
p384_elem_mul_test()657 fn p384_elem_mul_test() {
658 elem_mul_test(&p384::COMMON_OPS, test_file!("ops/p384_elem_mul_tests.txt"));
659 }
660
elem_mul_test(ops: &CommonOps, test_file: test::File)661 fn elem_mul_test(ops: &CommonOps, test_file: test::File) {
662 test::run(test_file, |section, test_case| {
663 assert_eq!(section, "");
664
665 let mut a = consume_elem(ops, test_case, "a");
666 let b = consume_elem(ops, test_case, "b");
667 let r = consume_elem(ops, test_case, "r");
668 ops.elem_mul(&mut a, &b);
669 assert_limbs_are_equal(ops, &a.limbs, &r.limbs);
670
671 Ok(())
672 })
673 }
674
675 #[test]
p256_scalar_mul_test()676 fn p256_scalar_mul_test() {
677 scalar_mul_test(
678 &p256::SCALAR_OPS,
679 test_file!("ops/p256_scalar_mul_tests.txt"),
680 );
681 }
682
683 #[test]
p384_scalar_mul_test()684 fn p384_scalar_mul_test() {
685 scalar_mul_test(
686 &p384::SCALAR_OPS,
687 test_file!("ops/p384_scalar_mul_tests.txt"),
688 );
689 }
690
scalar_mul_test(ops: &ScalarOps, test_file: test::File)691 fn scalar_mul_test(ops: &ScalarOps, test_file: test::File) {
692 test::run(test_file, |section, test_case| {
693 assert_eq!(section, "");
694 let cops = ops.common;
695 let mut a = consume_scalar(cops, test_case, "a");
696 let b = consume_scalar_mont(cops, test_case, "b");
697 let expected_result = consume_scalar(cops, test_case, "r");
698 let actual_result = ops.scalar_product(&mut a, &b);
699 assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
700
701 Ok(())
702 })
703 }
704
705 #[test]
p256_scalar_square_test()706 fn p256_scalar_square_test() {
707 extern "C" {
708 fn GFp_p256_scalar_sqr_rep_mont(r: *mut Limb, a: *const Limb, rep: Limb);
709 }
710 scalar_square_test(
711 &p256::SCALAR_OPS,
712 GFp_p256_scalar_sqr_rep_mont,
713 test_file!("ops/p256_scalar_square_tests.txt"),
714 );
715 }
716
717 // XXX: There's no `p384_scalar_square_test()` because there's no dedicated
718 // `GFp_p384_scalar_sqr_rep_mont()`.
719
scalar_square_test( ops: &ScalarOps, sqr_rep: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, rep: Limb), test_file: test::File, )720 fn scalar_square_test(
721 ops: &ScalarOps,
722 sqr_rep: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, rep: Limb),
723 test_file: test::File,
724 ) {
725 test::run(test_file, |section, test_case| {
726 assert_eq!(section, "");
727 let cops = &ops.common;
728 let a = consume_scalar(cops, test_case, "a");
729 let expected_result = consume_scalar(cops, test_case, "r");
730
731 {
732 let mut actual_result: Scalar<R> = Scalar {
733 limbs: [0; MAX_LIMBS],
734 m: PhantomData,
735 encoding: PhantomData,
736 };
737 unsafe {
738 sqr_rep(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr(), 1);
739 }
740 assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
741 }
742
743 {
744 let actual_result = ops.scalar_product(&a, &a);
745 assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
746 }
747
748 Ok(())
749 })
750 }
751
752 #[test]
753 #[should_panic(expected = "!self.common.is_zero(a)")]
p256_scalar_inv_to_mont_zero_panic_test()754 fn p256_scalar_inv_to_mont_zero_panic_test() {
755 let _ = p256::SCALAR_OPS.scalar_inv_to_mont(&ZERO_SCALAR);
756 }
757
758 #[test]
759 #[should_panic(expected = "!self.common.is_zero(a)")]
p384_scalar_inv_to_mont_zero_panic_test()760 fn p384_scalar_inv_to_mont_zero_panic_test() {
761 let _ = p384::SCALAR_OPS.scalar_inv_to_mont(&ZERO_SCALAR);
762 }
763
764 #[test]
p256_point_sum_test()765 fn p256_point_sum_test() {
766 point_sum_test(
767 &p256::PRIVATE_KEY_OPS,
768 test_file!("ops/p256_point_sum_tests.txt"),
769 );
770 }
771
772 #[test]
p384_point_sum_test()773 fn p384_point_sum_test() {
774 point_sum_test(
775 &p384::PRIVATE_KEY_OPS,
776 test_file!("ops/p384_point_sum_tests.txt"),
777 );
778 }
779
point_sum_test(ops: &PrivateKeyOps, test_file: test::File)780 fn point_sum_test(ops: &PrivateKeyOps, test_file: test::File) {
781 test::run(test_file, |section, test_case| {
782 assert_eq!(section, "");
783
784 let a = consume_jacobian_point(ops, test_case, "a");
785 let b = consume_jacobian_point(ops, test_case, "b");
786 let r_expected = consume_point(ops, test_case, "r");
787
788 let r_actual = ops.common.point_sum(&a, &b);
789 assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
790
791 Ok(())
792 });
793 }
794
795 #[test]
p256_point_sum_mixed_test()796 fn p256_point_sum_mixed_test() {
797 extern "C" {
798 fn GFp_nistz256_point_add_affine(
799 r: *mut Limb, // [p256::COMMON_OPS.num_limbs*3]
800 a: *const Limb, // [p256::COMMON_OPS.num_limbs*3]
801 b: *const Limb, // [p256::COMMON_OPS.num_limbs*2]
802 );
803 }
804 point_sum_mixed_test(
805 &p256::PRIVATE_KEY_OPS,
806 GFp_nistz256_point_add_affine,
807 test_file!("ops/p256_point_sum_mixed_tests.txt"),
808 );
809 }
810
811 // XXX: There is no `GFp_nistz384_point_add_affine()`.
812
point_sum_mixed_test( ops: &PrivateKeyOps, point_add_affine: unsafe extern "C" fn( r: *mut Limb, a: *const Limb, b: *const Limb, ), test_file: test::File, )813 fn point_sum_mixed_test(
814 ops: &PrivateKeyOps,
815 point_add_affine: unsafe extern "C" fn(
816 r: *mut Limb, // [ops.num_limbs*3]
817 a: *const Limb, // [ops.num_limbs*3]
818 b: *const Limb, // [ops.num_limbs*2]
819 ),
820 test_file: test::File,
821 ) {
822 test::run(test_file, |section, test_case| {
823 assert_eq!(section, "");
824
825 let a = consume_jacobian_point(ops, test_case, "a");
826 let b = consume_affine_point(ops, test_case, "b");
827 let r_expected = consume_point(ops, test_case, "r");
828
829 let mut r_actual = Point::new_at_infinity();
830 unsafe {
831 point_add_affine(r_actual.xyz.as_mut_ptr(), a.xyz.as_ptr(), b.xy.as_ptr());
832 }
833
834 assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
835
836 Ok(())
837 });
838 }
839
840 #[test]
p256_point_double_test()841 fn p256_point_double_test() {
842 extern "C" {
843 fn GFp_nistz256_point_double(
844 r: *mut Limb, // [p256::COMMON_OPS.num_limbs*3]
845 a: *const Limb, // [p256::COMMON_OPS.num_limbs*3]
846 );
847 }
848 point_double_test(
849 &p256::PRIVATE_KEY_OPS,
850 GFp_nistz256_point_double,
851 test_file!("ops/p256_point_double_tests.txt"),
852 );
853 }
854
855 #[test]
p384_point_double_test()856 fn p384_point_double_test() {
857 extern "C" {
858 fn GFp_nistz384_point_double(
859 r: *mut Limb, // [p384::COMMON_OPS.num_limbs*3]
860 a: *const Limb, // [p384::COMMON_OPS.num_limbs*3]
861 );
862 }
863 point_double_test(
864 &p384::PRIVATE_KEY_OPS,
865 GFp_nistz384_point_double,
866 test_file!("ops/p384_point_double_tests.txt"),
867 );
868 }
869
point_double_test( ops: &PrivateKeyOps, point_double: unsafe extern "C" fn( r: *mut Limb, a: *const Limb, ), test_file: test::File, )870 fn point_double_test(
871 ops: &PrivateKeyOps,
872 point_double: unsafe extern "C" fn(
873 r: *mut Limb, // [ops.num_limbs*3]
874 a: *const Limb, // [ops.num_limbs*3]
875 ),
876 test_file: test::File,
877 ) {
878 test::run(test_file, |section, test_case| {
879 assert_eq!(section, "");
880
881 let a = consume_jacobian_point(ops, test_case, "a");
882 let r_expected = consume_point(ops, test_case, "r");
883
884 let mut r_actual = Point::new_at_infinity();
885 unsafe {
886 point_double(r_actual.xyz.as_mut_ptr(), a.xyz.as_ptr());
887 }
888
889 assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
890
891 Ok(())
892 });
893 }
894
895 #[test]
p256_point_mul_test()896 fn p256_point_mul_test() {
897 point_mul_tests(
898 &p256::PRIVATE_KEY_OPS,
899 test_file!("ops/p256_point_mul_tests.txt"),
900 );
901 }
902
903 #[test]
p384_point_mul_test()904 fn p384_point_mul_test() {
905 point_mul_tests(
906 &p384::PRIVATE_KEY_OPS,
907 test_file!("ops/p384_point_mul_tests.txt"),
908 );
909 }
910
point_mul_tests(ops: &PrivateKeyOps, test_file: test::File)911 fn point_mul_tests(ops: &PrivateKeyOps, test_file: test::File) {
912 test::run(test_file, |section, test_case| {
913 assert_eq!(section, "");
914 let p_scalar = consume_scalar(ops.common, test_case, "p_scalar");
915 let (x, y) = match consume_point(ops, test_case, "p") {
916 TestPoint::Infinity => {
917 panic!("can't be inf.");
918 }
919 TestPoint::Affine(x, y) => (x, y),
920 };
921 let expected_result = consume_point(ops, test_case, "r");
922 let actual_result = ops.point_mul(&p_scalar, &(x, y));
923 assert_point_actual_equals_expected(ops, &actual_result, &expected_result);
924 Ok(())
925 })
926 }
927
928 #[test]
p256_point_mul_serialized_test()929 fn p256_point_mul_serialized_test() {
930 point_mul_serialized_test(
931 &p256::PRIVATE_KEY_OPS,
932 &p256::PUBLIC_KEY_OPS,
933 test_file!("ops/p256_point_mul_serialized_tests.txt"),
934 );
935 }
936
point_mul_serialized_test( priv_ops: &PrivateKeyOps, pub_ops: &PublicKeyOps, test_file: test::File, )937 fn point_mul_serialized_test(
938 priv_ops: &PrivateKeyOps,
939 pub_ops: &PublicKeyOps,
940 test_file: test::File,
941 ) {
942 let cops = pub_ops.common;
943
944 test::run(test_file, |section, test_case| {
945 assert_eq!(section, "");
946 let p_scalar = consume_scalar(cops, test_case, "p_scalar");
947
948 let p = test_case.consume_bytes("p");
949 let p = super::super::public_key::parse_uncompressed_point(
950 pub_ops,
951 untrusted::Input::from(&p),
952 )
953 .expect("valid point");
954
955 let expected_result = test_case.consume_bytes("r");
956
957 let product = priv_ops.point_mul(&p_scalar, &p);
958
959 let mut actual_result = vec![4u8; 1 + (2 * (cops.num_limbs * LIMB_BYTES))];
960 {
961 let (x, y) = actual_result[1..].split_at_mut(cops.num_limbs * LIMB_BYTES);
962 super::super::private_key::big_endian_affine_from_jacobian(
963 priv_ops,
964 Some(x),
965 Some(y),
966 &product,
967 )
968 .expect("successful encoding");
969 }
970
971 assert_eq!(expected_result, actual_result);
972
973 Ok(())
974 })
975 }
976
977 #[test]
p256_point_mul_base_test()978 fn p256_point_mul_base_test() {
979 point_mul_base_tests(
980 &p256::PRIVATE_KEY_OPS,
981 test_file!("ops/p256_point_mul_base_tests.txt"),
982 );
983 }
984
985 #[test]
p384_point_mul_base_test()986 fn p384_point_mul_base_test() {
987 point_mul_base_tests(
988 &p384::PRIVATE_KEY_OPS,
989 test_file!("ops/p384_point_mul_base_tests.txt"),
990 );
991 }
992
point_mul_base_tests(ops: &PrivateKeyOps, test_file: test::File)993 fn point_mul_base_tests(ops: &PrivateKeyOps, test_file: test::File) {
994 test::run(test_file, |section, test_case| {
995 assert_eq!(section, "");
996 let g_scalar = consume_scalar(ops.common, test_case, "g_scalar");
997 let expected_result = consume_point(ops, test_case, "r");
998 let actual_result = ops.point_mul_base(&g_scalar);
999 assert_point_actual_equals_expected(ops, &actual_result, &expected_result);
1000 Ok(())
1001 })
1002 }
1003
assert_point_actual_equals_expected( ops: &PrivateKeyOps, actual_point: &Point, expected_point: &TestPoint, )1004 fn assert_point_actual_equals_expected(
1005 ops: &PrivateKeyOps,
1006 actual_point: &Point,
1007 expected_point: &TestPoint,
1008 ) {
1009 let cops = ops.common;
1010 let actual_x = &cops.point_x(&actual_point);
1011 let actual_y = &cops.point_y(&actual_point);
1012 let actual_z = &cops.point_z(&actual_point);
1013 match expected_point {
1014 TestPoint::Infinity => {
1015 let zero = Elem::zero();
1016 assert_elems_are_equal(cops, &actual_z, &zero);
1017 }
1018 TestPoint::Affine(expected_x, expected_y) => {
1019 let zz_inv = ops.elem_inverse_squared(&actual_z);
1020 let x_aff = cops.elem_product(&actual_x, &zz_inv);
1021 let y_aff = {
1022 let zzzz_inv = cops.elem_squared(&zz_inv);
1023 let zzz_inv = cops.elem_product(&actual_z, &zzzz_inv);
1024 cops.elem_product(&actual_y, &zzz_inv)
1025 };
1026
1027 assert_elems_are_equal(cops, &x_aff, &expected_x);
1028 assert_elems_are_equal(cops, &y_aff, &expected_y);
1029 }
1030 }
1031 }
1032
consume_jacobian_point( ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str, ) -> Point1033 fn consume_jacobian_point(
1034 ops: &PrivateKeyOps,
1035 test_case: &mut test::TestCase,
1036 name: &str,
1037 ) -> Point {
1038 let input = test_case.consume_string(name);
1039 let elems = input.split(", ").collect::<Vec<&str>>();
1040 assert_eq!(elems.len(), 3);
1041 let mut p = Point::new_at_infinity();
1042 consume_point_elem(ops.common, &mut p.xyz, &elems, 0);
1043 consume_point_elem(ops.common, &mut p.xyz, &elems, 1);
1044 consume_point_elem(ops.common, &mut p.xyz, &elems, 2);
1045 p
1046 }
1047
1048 struct AffinePoint {
1049 xy: [Limb; 2 * MAX_LIMBS],
1050 }
1051
consume_affine_point( ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str, ) -> AffinePoint1052 fn consume_affine_point(
1053 ops: &PrivateKeyOps,
1054 test_case: &mut test::TestCase,
1055 name: &str,
1056 ) -> AffinePoint {
1057 let input = test_case.consume_string(name);
1058 let elems = input.split(", ").collect::<Vec<&str>>();
1059 assert_eq!(elems.len(), 2);
1060 let mut p = AffinePoint {
1061 xy: [0; 2 * MAX_LIMBS],
1062 };
1063 consume_point_elem(ops.common, &mut p.xy, &elems, 0);
1064 consume_point_elem(ops.common, &mut p.xy, &elems, 1);
1065 p
1066 }
1067
consume_point_elem(ops: &CommonOps, limbs_out: &mut [Limb], elems: &Vec<&str>, i: usize)1068 fn consume_point_elem(ops: &CommonOps, limbs_out: &mut [Limb], elems: &Vec<&str>, i: usize) {
1069 let bytes = test::from_hex(elems[i]).unwrap();
1070 let bytes = untrusted::Input::from(&bytes);
1071 let r: Elem<Unencoded> = elem_parse_big_endian_fixed_consttime(ops, bytes).unwrap();
1072 // XXX: “Transmute” this to `Elem<R>` limbs.
1073 limbs_out[(i * ops.num_limbs)..((i + 1) * ops.num_limbs)]
1074 .copy_from_slice(&r.limbs[..ops.num_limbs]);
1075 }
1076
1077 enum TestPoint {
1078 Infinity,
1079 Affine(Elem<R>, Elem<R>),
1080 }
1081
consume_point(ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str) -> TestPoint1082 fn consume_point(ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str) -> TestPoint {
1083 fn consume_point_elem(ops: &CommonOps, elems: &Vec<&str>, i: usize) -> Elem<R> {
1084 let bytes = test::from_hex(elems[i]).unwrap();
1085 let bytes = untrusted::Input::from(&bytes);
1086 let unencoded: Elem<Unencoded> =
1087 elem_parse_big_endian_fixed_consttime(ops, bytes).unwrap();
1088 // XXX: “Transmute” this to `Elem<R>` limbs.
1089 Elem {
1090 limbs: unencoded.limbs,
1091 m: PhantomData,
1092 encoding: PhantomData,
1093 }
1094 }
1095
1096 let input = test_case.consume_string(name);
1097 if input == "inf" {
1098 return TestPoint::Infinity;
1099 }
1100 let elems = input.split(", ").collect::<Vec<&str>>();
1101 assert_eq!(elems.len(), 2);
1102 let x = consume_point_elem(ops.common, &elems, 0);
1103 let y = consume_point_elem(ops.common, &elems, 1);
1104 TestPoint::Affine(x, y)
1105 }
1106
assert_elems_are_equal(ops: &CommonOps, a: &Elem<R>, b: &Elem<R>)1107 fn assert_elems_are_equal(ops: &CommonOps, a: &Elem<R>, b: &Elem<R>) {
1108 assert_limbs_are_equal(ops, &a.limbs, &b.limbs)
1109 }
1110
assert_limbs_are_equal( ops: &CommonOps, actual: &[Limb; MAX_LIMBS], expected: &[Limb; MAX_LIMBS], )1111 fn assert_limbs_are_equal(
1112 ops: &CommonOps,
1113 actual: &[Limb; MAX_LIMBS],
1114 expected: &[Limb; MAX_LIMBS],
1115 ) {
1116 for i in 0..ops.num_limbs {
1117 if actual[i] != expected[i] {
1118 let mut s = alloc::string::String::new();
1119 for j in 0..ops.num_limbs {
1120 let formatted = format!("{:016x}", actual[ops.num_limbs - j - 1]);
1121 s.push_str(&formatted);
1122 }
1123 panic!("Actual != Expected,\nActual = {}", s);
1124 }
1125 }
1126 }
1127
consume_elem(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Elem<R>1128 fn consume_elem(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Elem<R> {
1129 let bytes = consume_padded_bytes(ops, test_case, name);
1130 let bytes = untrusted::Input::from(&bytes);
1131 let r: Elem<Unencoded> = elem_parse_big_endian_fixed_consttime(ops, bytes).unwrap();
1132 // XXX: “Transmute” this to an `Elem<R>`.
1133 Elem {
1134 limbs: r.limbs,
1135 m: PhantomData,
1136 encoding: PhantomData,
1137 }
1138 }
1139
consume_scalar(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Scalar1140 fn consume_scalar(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Scalar {
1141 let bytes = test_case.consume_bytes(name);
1142 let bytes = untrusted::Input::from(&bytes);
1143 scalar_parse_big_endian_variable(ops, AllowZero::Yes, bytes).unwrap()
1144 }
1145
consume_scalar_mont( ops: &CommonOps, test_case: &mut test::TestCase, name: &str, ) -> Scalar<R>1146 fn consume_scalar_mont(
1147 ops: &CommonOps,
1148 test_case: &mut test::TestCase,
1149 name: &str,
1150 ) -> Scalar<R> {
1151 let bytes = test_case.consume_bytes(name);
1152 let bytes = untrusted::Input::from(&bytes);
1153 let s = scalar_parse_big_endian_variable(ops, AllowZero::Yes, bytes).unwrap();
1154 // “Transmute” it to a `Scalar<R>`.
1155 Scalar {
1156 limbs: s.limbs,
1157 m: PhantomData,
1158 encoding: PhantomData,
1159 }
1160 }
1161
consume_padded_bytes( ops: &CommonOps, test_case: &mut test::TestCase, name: &str, ) -> Vec<u8>1162 fn consume_padded_bytes(
1163 ops: &CommonOps,
1164 test_case: &mut test::TestCase,
1165 name: &str,
1166 ) -> Vec<u8> {
1167 let unpadded_bytes = test_case.consume_bytes(name);
1168 let mut bytes = vec![0; (ops.num_limbs * LIMB_BYTES) - unpadded_bytes.len()];
1169 bytes.extend(&unpadded_bytes);
1170 bytes
1171 }
1172 }
1173
1174 #[cfg(feature = "internal_benches")]
1175 mod internal_benches {
1176 use super::{Limb, MAX_LIMBS};
1177
1178 pub const LIMBS_1: [Limb; MAX_LIMBS] = limbs![1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
1179
1180 pub const LIMBS_ALTERNATING_10: [Limb; MAX_LIMBS] = limbs![
1181 0b10101010_10101010_10101010_10101010,
1182 0b10101010_10101010_10101010_10101010,
1183 0b10101010_10101010_10101010_10101010,
1184 0b10101010_10101010_10101010_10101010,
1185 0b10101010_10101010_10101010_10101010,
1186 0b10101010_10101010_10101010_10101010,
1187 0b10101010_10101010_10101010_10101010,
1188 0b10101010_10101010_10101010_10101010,
1189 0b10101010_10101010_10101010_10101010,
1190 0b10101010_10101010_10101010_10101010,
1191 0b10101010_10101010_10101010_10101010,
1192 0b10101010_10101010_10101010_10101010
1193 ];
1194 }
1195
1196 #[cfg(feature = "internal_benches")]
1197 macro_rules! bench_curve {
1198 ( $vectors:expr ) => {
1199 use super::super::{Elem, Scalar};
1200 extern crate test;
1201
1202 #[bench]
1203 fn elem_inverse_squared_bench(bench: &mut test::Bencher) {
1204 // This benchmark assumes that `elem_inverse_squared()` is
1205 // constant-time so inverting 1 mod q is as good of a choice as
1206 // anything.
1207 let mut a = Elem::zero();
1208 a.limbs[0] = 1;
1209 bench.iter(|| {
1210 let _ = PRIVATE_KEY_OPS.elem_inverse_squared(&a);
1211 });
1212 }
1213
1214 #[bench]
1215 fn elem_product_bench(bench: &mut test::Bencher) {
1216 // This benchmark assumes that the multiplication is constant-time
1217 // so 0 * 0 is as good of a choice as anything.
1218 let a: Elem<R> = Elem::zero();
1219 let b: Elem<R> = Elem::zero();
1220 bench.iter(|| {
1221 let _ = COMMON_OPS.elem_product(&a, &b);
1222 });
1223 }
1224
1225 #[bench]
1226 fn elem_squared_bench(bench: &mut test::Bencher) {
1227 // This benchmark assumes that the squaring is constant-time so
1228 // 0**2 * 0 is as good of a choice as anything.
1229 let a = Elem::zero();
1230 bench.iter(|| {
1231 let _ = COMMON_OPS.elem_squared(&a);
1232 });
1233 }
1234
1235 #[bench]
1236 fn scalar_inv_to_mont_bench(bench: &mut test::Bencher) {
1237 const VECTORS: &[Scalar] = $vectors;
1238 let vectors_len = VECTORS.len();
1239 let mut i = 0;
1240 bench.iter(|| {
1241 let _ = SCALAR_OPS.scalar_inv_to_mont(&VECTORS[i]);
1242
1243 i += 1;
1244 if i == vectors_len {
1245 i = 0;
1246 }
1247 });
1248 }
1249 };
1250 }
1251
1252 mod elem;
1253 pub mod p256;
1254 pub mod p384;
1255