efficient_sm2/jacobian/
exchange.rs

1// Copyright 2020 Yao Pengfei.
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
15use crate::elem::{
16    elem_add, elem_inv_sqr_to_mont, elem_mul, elem_to_unencoded, point_x, point_y, point_z, Elem, R,
17};
18use crate::err::KeyRejectedError;
19use crate::limb::{Limb, LIMB_BYTES, LIMB_LENGTH};
20use crate::norop::big_endian_from_limbs;
21use crate::sm2p256::CURVE_PARAMS;
22
23pub fn big_endian_affine_from_jacobian(
24    x_out: &mut [u8; LIMB_LENGTH * LIMB_BYTES],
25    y_out: &mut [u8; LIMB_LENGTH * LIMB_BYTES],
26    point: &[Limb; LIMB_LENGTH * 3],
27) -> Result<(), KeyRejectedError> {
28    let (x_aff, y_aff) = affine_from_jacobian(point)?;
29    let x = elem_to_unencoded(&x_aff);
30    big_endian_from_limbs(&x.limbs, x_out);
31    let y = elem_to_unencoded(&y_aff);
32    big_endian_from_limbs(&y.limbs, y_out);
33
34    Ok(())
35}
36
37pub fn affine_from_jacobian(
38    point: &[Limb; LIMB_LENGTH * 3],
39) -> Result<(Elem<R>, Elem<R>), KeyRejectedError> {
40    let x = point_x(point);
41    let y = point_y(point);
42    let z = point_z(point);
43
44    let zz_inv = elem_inv_sqr_to_mont(&z);
45
46    let x_aff = elem_mul(&x, &zz_inv);
47
48    let y_aff = {
49        let zzzz_inv = elem_mul(&zz_inv, &zz_inv);
50        let zzz_inv = elem_mul(&z, &zzzz_inv);
51        elem_mul(&y, &zzz_inv)
52    };
53
54    verify_affine_point_is_on_the_curve((&x_aff, &y_aff), &CURVE_PARAMS.a, &CURVE_PARAMS.b)?;
55
56    Ok((x_aff, y_aff))
57}
58
59pub fn verify_jacobian_point_is_on_the_curve(
60    point: &[Limb; LIMB_LENGTH * 3],
61) -> Result<(), KeyRejectedError> {
62    let z = point_z(point);
63
64    if z.is_zero() {
65        return Err(KeyRejectedError::ZeroError);
66    }
67
68    let x = point_x(point);
69    let y = point_y(point);
70
71    let z2 = elem_mul(&z, &z);
72    let z4 = elem_mul(&z2, &z2);
73    let z4_a = elem_mul(&z4, &CURVE_PARAMS.a);
74    let z6 = elem_mul(&z4, &z2);
75    let z6_b = elem_mul(&z6, &CURVE_PARAMS.b);
76
77    verify_affine_point_is_on_the_curve((&x, &y), &z4_a, &z6_b)
78}
79
80pub fn verify_affine_point_is_on_the_curve(
81    (x, y): (&Elem<R>, &Elem<R>),
82    a: &Elem<R>,
83    b: &Elem<R>,
84) -> Result<(), KeyRejectedError> {
85    let lhs = elem_mul(y, y);
86
87    let x2 = elem_mul(x, x);
88    let x2_a = elem_add(&x2, a);
89    let x2_a_x = elem_mul(&x2_a, x);
90    let rhs = elem_add(&x2_a_x, b);
91
92    if !lhs.is_equal(&rhs) {
93        return Err(KeyRejectedError::NotOnCurveError);
94    }
95    Ok(())
96}