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