ring/ec/curve25519/
ops.rs1pub use super::scalar::{MaskedScalar, Scalar, SCALAR_LEN};
19use crate::{
20 bssl, error,
21 limb::{Limb, LIMB_BITS},
22};
23use core::marker::PhantomData;
24
25#[repr(C)]
29pub struct Elem<E: Encoding> {
30 limbs: [Limb; ELEM_LIMBS], encoding: PhantomData<E>,
32}
33
34pub trait Encoding {}
35pub struct T;
36impl Encoding for T {}
37
38const ELEM_LIMBS: usize = 5 * 64 / LIMB_BITS;
39
40impl<E: Encoding> Elem<E> {
41 fn zero() -> Self {
42 Self {
43 limbs: Default::default(),
44 encoding: PhantomData,
45 }
46 }
47}
48
49impl Elem<T> {
50 fn negate(&mut self) {
51 unsafe {
52 GFp_x25519_fe_neg(self);
53 }
54 }
55}
56
57pub type EncodedPoint = [u8; ELEM_LEN];
64pub const ELEM_LEN: usize = 32;
65
66#[repr(C)]
68pub struct ExtPoint {
69 x: Elem<T>,
70 y: Elem<T>,
71 z: Elem<T>,
72 t: Elem<T>,
73}
74
75impl ExtPoint {
76 pub fn new_at_infinity() -> Self {
77 Self {
78 x: Elem::zero(),
79 y: Elem::zero(),
80 z: Elem::zero(),
81 t: Elem::zero(),
82 }
83 }
84
85 pub fn from_encoded_point_vartime(encoded: &EncodedPoint) -> Result<Self, error::Unspecified> {
86 let mut point = Self::new_at_infinity();
87
88 Result::from(unsafe { GFp_x25519_ge_frombytes_vartime(&mut point, encoded) })
89 .map(|()| point)
90 }
91
92 pub fn into_encoded_point(self) -> EncodedPoint {
93 encode_point(self.x, self.y, self.z)
94 }
95
96 pub fn invert_vartime(&mut self) {
97 self.x.negate();
98 self.t.negate();
99 }
100}
101
102#[repr(C)]
104pub struct Point {
105 x: Elem<T>,
106 y: Elem<T>,
107 z: Elem<T>,
108}
109
110impl Point {
111 pub fn new_at_infinity() -> Self {
112 Self {
113 x: Elem::zero(),
114 y: Elem::zero(),
115 z: Elem::zero(),
116 }
117 }
118
119 pub fn into_encoded_point(self) -> EncodedPoint {
120 encode_point(self.x, self.y, self.z)
121 }
122}
123
124fn encode_point(x: Elem<T>, y: Elem<T>, z: Elem<T>) -> EncodedPoint {
125 let mut bytes = [0; ELEM_LEN];
126
127 let sign_bit: u8 = unsafe {
128 let mut recip = Elem::zero();
129 GFp_x25519_fe_invert(&mut recip, &z);
130
131 let mut x_over_z = Elem::zero();
132 GFp_x25519_fe_mul_ttt(&mut x_over_z, &x, &recip);
133
134 let mut y_over_z = Elem::zero();
135 GFp_x25519_fe_mul_ttt(&mut y_over_z, &y, &recip);
136 GFp_x25519_fe_tobytes(&mut bytes, &y_over_z);
137
138 GFp_x25519_fe_isnegative(&x_over_z)
139 };
140
141 bytes[ELEM_LEN - 1] ^= sign_bit << 7;
144
145 bytes
146}
147
148extern "C" {
149 fn GFp_x25519_fe_invert(out: &mut Elem<T>, z: &Elem<T>);
150 fn GFp_x25519_fe_isnegative(elem: &Elem<T>) -> u8;
151 fn GFp_x25519_fe_mul_ttt(h: &mut Elem<T>, f: &Elem<T>, g: &Elem<T>);
152 fn GFp_x25519_fe_neg(f: &mut Elem<T>);
153 fn GFp_x25519_fe_tobytes(bytes: &mut EncodedPoint, elem: &Elem<T>);
154 fn GFp_x25519_ge_frombytes_vartime(h: &mut ExtPoint, s: &EncodedPoint) -> bssl::Result;
155}