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 use super::*;
436 use crate::test;
437 use alloc::{format, vec, vec::Vec};
438
439 const ZERO_SCALAR: Scalar = Scalar {
440 limbs: [0; MAX_LIMBS],
441 m: PhantomData,
442 encoding: PhantomData,
443 };
444
q_minus_n_plus_n_equals_0_test(ops: &PublicScalarOps)445 fn q_minus_n_plus_n_equals_0_test(ops: &PublicScalarOps) {
446 let cops = ops.scalar_ops.common;
447 let mut x = ops.q_minus_n;
448 cops.elem_add(&mut x, &cops.n);
449 assert!(cops.is_zero(&x));
450 }
451
452 #[test]
p256_q_minus_n_plus_n_equals_0_test()453 fn p256_q_minus_n_plus_n_equals_0_test() {
454 q_minus_n_plus_n_equals_0_test(&p256::PUBLIC_SCALAR_OPS);
455 }
456
457 #[test]
p384_q_minus_n_plus_n_equals_0_test()458 fn p384_q_minus_n_plus_n_equals_0_test() {
459 q_minus_n_plus_n_equals_0_test(&p384::PUBLIC_SCALAR_OPS);
460 }
461
462 #[test]
p256_elem_add_test()463 fn p256_elem_add_test() {
464 elem_add_test(
465 &p256::PUBLIC_SCALAR_OPS,
466 test_file!("ops/p256_elem_sum_tests.txt"),
467 );
468 }
469
470 #[test]
p384_elem_add_test()471 fn p384_elem_add_test() {
472 elem_add_test(
473 &p384::PUBLIC_SCALAR_OPS,
474 test_file!("ops/p384_elem_sum_tests.txt"),
475 );
476 }
477
elem_add_test(ops: &PublicScalarOps, test_file: test::File)478 fn elem_add_test(ops: &PublicScalarOps, test_file: test::File) {
479 test::run(test_file, |section, test_case| {
480 assert_eq!(section, "");
481
482 let cops = ops.public_key_ops.common;
483 let a = consume_elem(cops, test_case, "a");
484 let b = consume_elem(cops, test_case, "b");
485 let expected_sum = consume_elem(cops, test_case, "r");
486
487 let mut actual_sum = a;
488 ops.public_key_ops.common.elem_add(&mut actual_sum, &b);
489 assert_limbs_are_equal(cops, &actual_sum.limbs, &expected_sum.limbs);
490
491 let mut actual_sum = b;
492 ops.public_key_ops.common.elem_add(&mut actual_sum, &a);
493 assert_limbs_are_equal(cops, &actual_sum.limbs, &expected_sum.limbs);
494
495 Ok(())
496 })
497 }
498
499 // XXX: There's no `p256_sub` in *ring*; it's logic is inlined into
500 // the point arithmetic functions. Thus, we can't test it.
501
502 #[test]
p384_elem_sub_test()503 fn p384_elem_sub_test() {
504 prefixed_extern! {
505 fn p384_elem_sub(r: *mut Limb, a: *const Limb, b: *const Limb);
506 }
507 elem_sub_test(
508 &p384::COMMON_OPS,
509 p384_elem_sub,
510 test_file!("ops/p384_elem_sum_tests.txt"),
511 );
512 }
513
elem_sub_test( ops: &CommonOps, elem_sub: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb), test_file: test::File, )514 fn elem_sub_test(
515 ops: &CommonOps,
516 elem_sub: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, b: *const Limb),
517 test_file: test::File,
518 ) {
519 test::run(test_file, |section, test_case| {
520 assert_eq!(section, "");
521
522 let a = consume_elem(ops, test_case, "a");
523 let b = consume_elem(ops, test_case, "b");
524 let r = consume_elem(ops, test_case, "r");
525
526 let mut actual_difference = Elem::<R>::zero();
527 unsafe {
528 elem_sub(
529 actual_difference.limbs.as_mut_ptr(),
530 r.limbs.as_ptr(),
531 b.limbs.as_ptr(),
532 );
533 }
534 assert_limbs_are_equal(ops, &actual_difference.limbs, &a.limbs);
535
536 let mut actual_difference = Elem::<R>::zero();
537 unsafe {
538 elem_sub(
539 actual_difference.limbs.as_mut_ptr(),
540 r.limbs.as_ptr(),
541 a.limbs.as_ptr(),
542 );
543 }
544 assert_limbs_are_equal(ops, &actual_difference.limbs, &b.limbs);
545
546 Ok(())
547 })
548 }
549
550 // XXX: There's no `p256_div_by_2` in *ring*; it's logic is inlined
551 // into the point arithmetic functions. Thus, we can't test it.
552
553 #[test]
p384_elem_div_by_2_test()554 fn p384_elem_div_by_2_test() {
555 prefixed_extern! {
556 fn p384_elem_div_by_2(r: *mut Limb, a: *const Limb);
557 }
558 elem_div_by_2_test(
559 &p384::COMMON_OPS,
560 p384_elem_div_by_2,
561 test_file!("ops/p384_elem_div_by_2_tests.txt"),
562 );
563 }
564
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, )565 fn elem_div_by_2_test(
566 ops: &CommonOps,
567 elem_div_by_2: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
568 test_file: test::File,
569 ) {
570 test::run(test_file, |section, test_case| {
571 assert_eq!(section, "");
572
573 let a = consume_elem(ops, test_case, "a");
574 let r = consume_elem(ops, test_case, "r");
575
576 let mut actual_result = Elem::<R>::zero();
577 unsafe {
578 elem_div_by_2(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr());
579 }
580 assert_limbs_are_equal(ops, &actual_result.limbs, &r.limbs);
581
582 Ok(())
583 })
584 }
585
586 // There is no `nistz256_neg` on other targets.
587 #[cfg(target_arch = "x86_64")]
588 #[test]
p256_elem_neg_test()589 fn p256_elem_neg_test() {
590 prefixed_extern! {
591 fn nistz256_neg(r: *mut Limb, a: *const Limb);
592 }
593 elem_neg_test(
594 &p256::COMMON_OPS,
595 nistz256_neg,
596 test_file!("ops/p256_elem_neg_tests.txt"),
597 );
598 }
599
600 #[test]
p384_elem_neg_test()601 fn p384_elem_neg_test() {
602 prefixed_extern! {
603 fn p384_elem_neg(r: *mut Limb, a: *const Limb);
604 }
605 elem_neg_test(
606 &p384::COMMON_OPS,
607 p384_elem_neg,
608 test_file!("ops/p384_elem_neg_tests.txt"),
609 );
610 }
611
elem_neg_test( ops: &CommonOps, elem_neg: unsafe extern "C" fn(r: *mut Limb, a: *const Limb), test_file: test::File, )612 fn elem_neg_test(
613 ops: &CommonOps,
614 elem_neg: unsafe extern "C" fn(r: *mut Limb, a: *const Limb),
615 test_file: test::File,
616 ) {
617 test::run(test_file, |section, test_case| {
618 assert_eq!(section, "");
619
620 let a = consume_elem(ops, test_case, "a");
621 let b = consume_elem(ops, test_case, "b");
622
623 // Verify -a == b.
624 {
625 let mut actual_result = Elem::<R>::zero();
626 unsafe {
627 elem_neg(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr());
628 }
629 assert_limbs_are_equal(ops, &actual_result.limbs, &b.limbs);
630 }
631
632 // Verify -b == a.
633 {
634 let mut actual_result = Elem::<R>::zero();
635 unsafe {
636 elem_neg(actual_result.limbs.as_mut_ptr(), b.limbs.as_ptr());
637 }
638 assert_limbs_are_equal(ops, &actual_result.limbs, &a.limbs);
639 }
640
641 Ok(())
642 })
643 }
644
645 #[test]
p256_elem_mul_test()646 fn p256_elem_mul_test() {
647 elem_mul_test(&p256::COMMON_OPS, test_file!("ops/p256_elem_mul_tests.txt"));
648 }
649
650 #[test]
p384_elem_mul_test()651 fn p384_elem_mul_test() {
652 elem_mul_test(&p384::COMMON_OPS, test_file!("ops/p384_elem_mul_tests.txt"));
653 }
654
elem_mul_test(ops: &CommonOps, test_file: test::File)655 fn elem_mul_test(ops: &CommonOps, test_file: test::File) {
656 test::run(test_file, |section, test_case| {
657 assert_eq!(section, "");
658
659 let mut a = consume_elem(ops, test_case, "a");
660 let b = consume_elem(ops, test_case, "b");
661 let r = consume_elem(ops, test_case, "r");
662 ops.elem_mul(&mut a, &b);
663 assert_limbs_are_equal(ops, &a.limbs, &r.limbs);
664
665 Ok(())
666 })
667 }
668
669 #[test]
p256_scalar_mul_test()670 fn p256_scalar_mul_test() {
671 scalar_mul_test(
672 &p256::SCALAR_OPS,
673 test_file!("ops/p256_scalar_mul_tests.txt"),
674 );
675 }
676
677 #[test]
p384_scalar_mul_test()678 fn p384_scalar_mul_test() {
679 scalar_mul_test(
680 &p384::SCALAR_OPS,
681 test_file!("ops/p384_scalar_mul_tests.txt"),
682 );
683 }
684
scalar_mul_test(ops: &ScalarOps, test_file: test::File)685 fn scalar_mul_test(ops: &ScalarOps, test_file: test::File) {
686 test::run(test_file, |section, test_case| {
687 assert_eq!(section, "");
688 let cops = ops.common;
689 let a = consume_scalar(cops, test_case, "a");
690 let b = consume_scalar_mont(cops, test_case, "b");
691 let expected_result = consume_scalar(cops, test_case, "r");
692 let actual_result = ops.scalar_product(&a, &b);
693 assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
694
695 Ok(())
696 })
697 }
698
699 #[test]
p256_scalar_square_test()700 fn p256_scalar_square_test() {
701 prefixed_extern! {
702 fn p256_scalar_sqr_rep_mont(r: *mut Limb, a: *const Limb, rep: Limb);
703 }
704 scalar_square_test(
705 &p256::SCALAR_OPS,
706 p256_scalar_sqr_rep_mont,
707 test_file!("ops/p256_scalar_square_tests.txt"),
708 );
709 }
710
711 // XXX: There's no `p384_scalar_square_test()` because there's no dedicated
712 // `p384_scalar_sqr_rep_mont()`.
713
scalar_square_test( ops: &ScalarOps, sqr_rep: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, rep: Limb), test_file: test::File, )714 fn scalar_square_test(
715 ops: &ScalarOps,
716 sqr_rep: unsafe extern "C" fn(r: *mut Limb, a: *const Limb, rep: Limb),
717 test_file: test::File,
718 ) {
719 test::run(test_file, |section, test_case| {
720 assert_eq!(section, "");
721 let cops = &ops.common;
722 let a = consume_scalar(cops, test_case, "a");
723 let expected_result = consume_scalar(cops, test_case, "r");
724
725 {
726 let mut actual_result: Scalar<R> = Scalar {
727 limbs: [0; MAX_LIMBS],
728 m: PhantomData,
729 encoding: PhantomData,
730 };
731 unsafe {
732 sqr_rep(actual_result.limbs.as_mut_ptr(), a.limbs.as_ptr(), 1);
733 }
734 assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
735 }
736
737 {
738 let actual_result = ops.scalar_product(&a, &a);
739 assert_limbs_are_equal(cops, &actual_result.limbs, &expected_result.limbs);
740 }
741
742 Ok(())
743 })
744 }
745
746 #[test]
747 #[should_panic(expected = "!self.common.is_zero(a)")]
p256_scalar_inv_to_mont_zero_panic_test()748 fn p256_scalar_inv_to_mont_zero_panic_test() {
749 let _ = p256::SCALAR_OPS.scalar_inv_to_mont(&ZERO_SCALAR);
750 }
751
752 #[test]
753 #[should_panic(expected = "!self.common.is_zero(a)")]
p384_scalar_inv_to_mont_zero_panic_test()754 fn p384_scalar_inv_to_mont_zero_panic_test() {
755 let _ = p384::SCALAR_OPS.scalar_inv_to_mont(&ZERO_SCALAR);
756 }
757
758 #[test]
p256_point_sum_test()759 fn p256_point_sum_test() {
760 point_sum_test(
761 &p256::PRIVATE_KEY_OPS,
762 test_file!("ops/p256_point_sum_tests.txt"),
763 );
764 }
765
766 #[test]
p384_point_sum_test()767 fn p384_point_sum_test() {
768 point_sum_test(
769 &p384::PRIVATE_KEY_OPS,
770 test_file!("ops/p384_point_sum_tests.txt"),
771 );
772 }
773
point_sum_test(ops: &PrivateKeyOps, test_file: test::File)774 fn point_sum_test(ops: &PrivateKeyOps, test_file: test::File) {
775 test::run(test_file, |section, test_case| {
776 assert_eq!(section, "");
777
778 let a = consume_jacobian_point(ops, test_case, "a");
779 let b = consume_jacobian_point(ops, test_case, "b");
780 let r_expected = consume_point(ops, test_case, "r");
781
782 let r_actual = ops.common.point_sum(&a, &b);
783 assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
784
785 Ok(())
786 });
787 }
788
789 #[test]
p256_point_sum_mixed_test()790 fn p256_point_sum_mixed_test() {
791 prefixed_extern! {
792 fn p256_point_add_affine(
793 r: *mut Limb, // [p256::COMMON_OPS.num_limbs*3]
794 a: *const Limb, // [p256::COMMON_OPS.num_limbs*3]
795 b: *const Limb, // [p256::COMMON_OPS.num_limbs*2]
796 );
797 }
798 point_sum_mixed_test(
799 &p256::PRIVATE_KEY_OPS,
800 p256_point_add_affine,
801 test_file!("ops/p256_point_sum_mixed_tests.txt"),
802 );
803 }
804
805 // XXX: There is no `nistz384_point_add_affine()`.
806
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, )807 fn point_sum_mixed_test(
808 ops: &PrivateKeyOps,
809 point_add_affine: unsafe extern "C" fn(
810 r: *mut Limb, // [ops.num_limbs*3]
811 a: *const Limb, // [ops.num_limbs*3]
812 b: *const Limb, // [ops.num_limbs*2]
813 ),
814 test_file: test::File,
815 ) {
816 test::run(test_file, |section, test_case| {
817 assert_eq!(section, "");
818
819 let a = consume_jacobian_point(ops, test_case, "a");
820 let b = consume_affine_point(ops, test_case, "b");
821 let r_expected = consume_point(ops, test_case, "r");
822
823 let mut r_actual = Point::new_at_infinity();
824 unsafe {
825 point_add_affine(r_actual.xyz.as_mut_ptr(), a.xyz.as_ptr(), b.xy.as_ptr());
826 }
827
828 assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
829
830 Ok(())
831 });
832 }
833
834 #[test]
p256_point_double_test()835 fn p256_point_double_test() {
836 prefixed_extern! {
837 fn p256_point_double(
838 r: *mut Limb, // [p256::COMMON_OPS.num_limbs*3]
839 a: *const Limb, // [p256::COMMON_OPS.num_limbs*3]
840 );
841 }
842 point_double_test(
843 &p256::PRIVATE_KEY_OPS,
844 p256_point_double,
845 test_file!("ops/p256_point_double_tests.txt"),
846 );
847 }
848
849 #[test]
p384_point_double_test()850 fn p384_point_double_test() {
851 prefixed_extern! {
852 fn nistz384_point_double(
853 r: *mut Limb, // [p384::COMMON_OPS.num_limbs*3]
854 a: *const Limb, // [p384::COMMON_OPS.num_limbs*3]
855 );
856 }
857 point_double_test(
858 &p384::PRIVATE_KEY_OPS,
859 nistz384_point_double,
860 test_file!("ops/p384_point_double_tests.txt"),
861 );
862 }
863
point_double_test( ops: &PrivateKeyOps, point_double: unsafe extern "C" fn( r: *mut Limb, a: *const Limb, ), test_file: test::File, )864 fn point_double_test(
865 ops: &PrivateKeyOps,
866 point_double: unsafe extern "C" fn(
867 r: *mut Limb, // [ops.num_limbs*3]
868 a: *const Limb, // [ops.num_limbs*3]
869 ),
870 test_file: test::File,
871 ) {
872 test::run(test_file, |section, test_case| {
873 assert_eq!(section, "");
874
875 let a = consume_jacobian_point(ops, test_case, "a");
876 let r_expected = consume_point(ops, test_case, "r");
877
878 let mut r_actual = Point::new_at_infinity();
879 unsafe {
880 point_double(r_actual.xyz.as_mut_ptr(), a.xyz.as_ptr());
881 }
882
883 assert_point_actual_equals_expected(ops, &r_actual, &r_expected);
884
885 Ok(())
886 });
887 }
888
889 #[test]
p256_point_mul_test()890 fn p256_point_mul_test() {
891 point_mul_tests(
892 &p256::PRIVATE_KEY_OPS,
893 test_file!("ops/p256_point_mul_tests.txt"),
894 );
895 }
896
897 #[test]
p384_point_mul_test()898 fn p384_point_mul_test() {
899 point_mul_tests(
900 &p384::PRIVATE_KEY_OPS,
901 test_file!("ops/p384_point_mul_tests.txt"),
902 );
903 }
904
point_mul_tests(ops: &PrivateKeyOps, test_file: test::File)905 fn point_mul_tests(ops: &PrivateKeyOps, test_file: test::File) {
906 test::run(test_file, |section, test_case| {
907 assert_eq!(section, "");
908 let p_scalar = consume_scalar(ops.common, test_case, "p_scalar");
909 let (x, y) = match consume_point(ops, test_case, "p") {
910 TestPoint::Infinity => {
911 panic!("can't be inf.");
912 }
913 TestPoint::Affine(x, y) => (x, y),
914 };
915 let expected_result = consume_point(ops, test_case, "r");
916 let actual_result = ops.point_mul(&p_scalar, &(x, y));
917 assert_point_actual_equals_expected(ops, &actual_result, &expected_result);
918 Ok(())
919 })
920 }
921
922 #[test]
p256_point_mul_serialized_test()923 fn p256_point_mul_serialized_test() {
924 point_mul_serialized_test(
925 &p256::PRIVATE_KEY_OPS,
926 &p256::PUBLIC_KEY_OPS,
927 test_file!("ops/p256_point_mul_serialized_tests.txt"),
928 );
929 }
930
point_mul_serialized_test( priv_ops: &PrivateKeyOps, pub_ops: &PublicKeyOps, test_file: test::File, )931 fn point_mul_serialized_test(
932 priv_ops: &PrivateKeyOps,
933 pub_ops: &PublicKeyOps,
934 test_file: test::File,
935 ) {
936 let cops = pub_ops.common;
937
938 test::run(test_file, |section, test_case| {
939 assert_eq!(section, "");
940 let p_scalar = consume_scalar(cops, test_case, "p_scalar");
941
942 let p = test_case.consume_bytes("p");
943 let p = super::super::public_key::parse_uncompressed_point(
944 pub_ops,
945 untrusted::Input::from(&p),
946 )
947 .expect("valid point");
948
949 let expected_result = test_case.consume_bytes("r");
950
951 let product = priv_ops.point_mul(&p_scalar, &p);
952
953 let mut actual_result = vec![4u8; 1 + (2 * (cops.num_limbs * LIMB_BYTES))];
954 {
955 let (x, y) = actual_result[1..].split_at_mut(cops.num_limbs * LIMB_BYTES);
956 super::super::private_key::big_endian_affine_from_jacobian(
957 priv_ops,
958 Some(x),
959 Some(y),
960 &product,
961 )
962 .expect("successful encoding");
963 }
964
965 assert_eq!(expected_result, actual_result);
966
967 Ok(())
968 })
969 }
970
971 #[test]
p256_point_mul_base_test()972 fn p256_point_mul_base_test() {
973 point_mul_base_tests(
974 &p256::PRIVATE_KEY_OPS,
975 test_file!("ops/p256_point_mul_base_tests.txt"),
976 );
977 }
978
979 #[test]
p384_point_mul_base_test()980 fn p384_point_mul_base_test() {
981 point_mul_base_tests(
982 &p384::PRIVATE_KEY_OPS,
983 test_file!("ops/p384_point_mul_base_tests.txt"),
984 );
985 }
986
point_mul_base_tests(ops: &PrivateKeyOps, test_file: test::File)987 fn point_mul_base_tests(ops: &PrivateKeyOps, test_file: test::File) {
988 test::run(test_file, |section, test_case| {
989 assert_eq!(section, "");
990 let g_scalar = consume_scalar(ops.common, test_case, "g_scalar");
991 let expected_result = consume_point(ops, test_case, "r");
992 let actual_result = ops.point_mul_base(&g_scalar);
993 assert_point_actual_equals_expected(ops, &actual_result, &expected_result);
994 Ok(())
995 })
996 }
997
assert_point_actual_equals_expected( ops: &PrivateKeyOps, actual_point: &Point, expected_point: &TestPoint, )998 fn assert_point_actual_equals_expected(
999 ops: &PrivateKeyOps,
1000 actual_point: &Point,
1001 expected_point: &TestPoint,
1002 ) {
1003 let cops = ops.common;
1004 let actual_x = &cops.point_x(&actual_point);
1005 let actual_y = &cops.point_y(&actual_point);
1006 let actual_z = &cops.point_z(&actual_point);
1007 match expected_point {
1008 TestPoint::Infinity => {
1009 let zero = Elem::zero();
1010 assert_elems_are_equal(cops, &actual_z, &zero);
1011 }
1012 TestPoint::Affine(expected_x, expected_y) => {
1013 let zz_inv = ops.elem_inverse_squared(&actual_z);
1014 let x_aff = cops.elem_product(&actual_x, &zz_inv);
1015 let y_aff = {
1016 let zzzz_inv = cops.elem_squared(&zz_inv);
1017 let zzz_inv = cops.elem_product(&actual_z, &zzzz_inv);
1018 cops.elem_product(&actual_y, &zzz_inv)
1019 };
1020
1021 assert_elems_are_equal(cops, &x_aff, &expected_x);
1022 assert_elems_are_equal(cops, &y_aff, &expected_y);
1023 }
1024 }
1025 }
1026
consume_jacobian_point( ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str, ) -> Point1027 fn consume_jacobian_point(
1028 ops: &PrivateKeyOps,
1029 test_case: &mut test::TestCase,
1030 name: &str,
1031 ) -> Point {
1032 let input = test_case.consume_string(name);
1033 let elems = input.split(", ").collect::<Vec<&str>>();
1034 assert_eq!(elems.len(), 3);
1035 let mut p = Point::new_at_infinity();
1036 consume_point_elem(ops.common, &mut p.xyz, &elems, 0);
1037 consume_point_elem(ops.common, &mut p.xyz, &elems, 1);
1038 consume_point_elem(ops.common, &mut p.xyz, &elems, 2);
1039 p
1040 }
1041
1042 struct AffinePoint {
1043 xy: [Limb; 2 * MAX_LIMBS],
1044 }
1045
consume_affine_point( ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str, ) -> AffinePoint1046 fn consume_affine_point(
1047 ops: &PrivateKeyOps,
1048 test_case: &mut test::TestCase,
1049 name: &str,
1050 ) -> AffinePoint {
1051 let input = test_case.consume_string(name);
1052 let elems = input.split(", ").collect::<Vec<&str>>();
1053 assert_eq!(elems.len(), 2);
1054 let mut p = AffinePoint {
1055 xy: [0; 2 * MAX_LIMBS],
1056 };
1057 consume_point_elem(ops.common, &mut p.xy, &elems, 0);
1058 consume_point_elem(ops.common, &mut p.xy, &elems, 1);
1059 p
1060 }
1061
consume_point_elem(ops: &CommonOps, limbs_out: &mut [Limb], elems: &[&str], i: usize)1062 fn consume_point_elem(ops: &CommonOps, limbs_out: &mut [Limb], elems: &[&str], i: usize) {
1063 let bytes = test::from_hex(elems[i]).unwrap();
1064 let bytes = untrusted::Input::from(&bytes);
1065 let r: Elem<Unencoded> = elem_parse_big_endian_fixed_consttime(ops, bytes).unwrap();
1066 // XXX: “Transmute” this to `Elem<R>` limbs.
1067 limbs_out[(i * ops.num_limbs)..((i + 1) * ops.num_limbs)]
1068 .copy_from_slice(&r.limbs[..ops.num_limbs]);
1069 }
1070
1071 enum TestPoint {
1072 Infinity,
1073 Affine(Elem<R>, Elem<R>),
1074 }
1075
consume_point(ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str) -> TestPoint1076 fn consume_point(ops: &PrivateKeyOps, test_case: &mut test::TestCase, name: &str) -> TestPoint {
1077 fn consume_point_elem(ops: &CommonOps, elems: &[&str], i: usize) -> Elem<R> {
1078 let bytes = test::from_hex(elems[i]).unwrap();
1079 let bytes = untrusted::Input::from(&bytes);
1080 let unencoded: Elem<Unencoded> =
1081 elem_parse_big_endian_fixed_consttime(ops, bytes).unwrap();
1082 // XXX: “Transmute” this to `Elem<R>` limbs.
1083 Elem {
1084 limbs: unencoded.limbs,
1085 m: PhantomData,
1086 encoding: PhantomData,
1087 }
1088 }
1089
1090 let input = test_case.consume_string(name);
1091 if input == "inf" {
1092 return TestPoint::Infinity;
1093 }
1094 let elems = input.split(", ").collect::<Vec<&str>>();
1095 assert_eq!(elems.len(), 2);
1096 let x = consume_point_elem(ops.common, &elems, 0);
1097 let y = consume_point_elem(ops.common, &elems, 1);
1098 TestPoint::Affine(x, y)
1099 }
1100
assert_elems_are_equal(ops: &CommonOps, a: &Elem<R>, b: &Elem<R>)1101 fn assert_elems_are_equal(ops: &CommonOps, a: &Elem<R>, b: &Elem<R>) {
1102 assert_limbs_are_equal(ops, &a.limbs, &b.limbs)
1103 }
1104
assert_limbs_are_equal( ops: &CommonOps, actual: &[Limb; MAX_LIMBS], expected: &[Limb; MAX_LIMBS], )1105 fn assert_limbs_are_equal(
1106 ops: &CommonOps,
1107 actual: &[Limb; MAX_LIMBS],
1108 expected: &[Limb; MAX_LIMBS],
1109 ) {
1110 if actual[..ops.num_limbs] != expected[..ops.num_limbs] {
1111 let mut actual_s = alloc::string::String::new();
1112 let mut expected_s = alloc::string::String::new();
1113 for j in 0..ops.num_limbs {
1114 let formatted = format!("{:016x}", actual[ops.num_limbs - j - 1]);
1115 actual_s.push_str(&formatted);
1116 let formatted = format!("{:016x}", expected[ops.num_limbs - j - 1]);
1117 expected_s.push_str(&formatted);
1118 }
1119 panic!(
1120 "Actual != Expected,\nActual = {}, Expected = {}",
1121 actual_s, expected_s
1122 );
1123 }
1124 }
1125
consume_elem(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Elem<R>1126 fn consume_elem(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Elem<R> {
1127 let bytes = consume_padded_bytes(ops, test_case, name);
1128 let bytes = untrusted::Input::from(&bytes);
1129 let r: Elem<Unencoded> = elem_parse_big_endian_fixed_consttime(ops, bytes).unwrap();
1130 // XXX: “Transmute” this to an `Elem<R>`.
1131 Elem {
1132 limbs: r.limbs,
1133 m: PhantomData,
1134 encoding: PhantomData,
1135 }
1136 }
1137
consume_scalar(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Scalar1138 fn consume_scalar(ops: &CommonOps, test_case: &mut test::TestCase, name: &str) -> Scalar {
1139 let bytes = test_case.consume_bytes(name);
1140 let bytes = untrusted::Input::from(&bytes);
1141 scalar_parse_big_endian_variable(ops, AllowZero::Yes, bytes).unwrap()
1142 }
1143
consume_scalar_mont( ops: &CommonOps, test_case: &mut test::TestCase, name: &str, ) -> Scalar<R>1144 fn consume_scalar_mont(
1145 ops: &CommonOps,
1146 test_case: &mut test::TestCase,
1147 name: &str,
1148 ) -> Scalar<R> {
1149 let bytes = test_case.consume_bytes(name);
1150 let bytes = untrusted::Input::from(&bytes);
1151 let s = scalar_parse_big_endian_variable(ops, AllowZero::Yes, bytes).unwrap();
1152 // “Transmute” it to a `Scalar<R>`.
1153 Scalar {
1154 limbs: s.limbs,
1155 m: PhantomData,
1156 encoding: PhantomData,
1157 }
1158 }
1159
consume_padded_bytes( ops: &CommonOps, test_case: &mut test::TestCase, name: &str, ) -> Vec<u8>1160 fn consume_padded_bytes(
1161 ops: &CommonOps,
1162 test_case: &mut test::TestCase,
1163 name: &str,
1164 ) -> Vec<u8> {
1165 let unpadded_bytes = test_case.consume_bytes(name);
1166 let mut bytes = vec![0; (ops.num_limbs * LIMB_BYTES) - unpadded_bytes.len()];
1167 bytes.extend(&unpadded_bytes);
1168 bytes
1169 }
1170 }
1171
1172 mod elem;
1173 pub mod p256;
1174 pub mod p384;
1175