1use crate::{
7 codec::{CodecError, Decode, Encode},
8 field::{FieldElement, FieldElementVisitor, FieldError},
9};
10use fiat_crypto::curve25519_64::{
11 fiat_25519_add, fiat_25519_carry, fiat_25519_carry_mul, fiat_25519_from_bytes,
12 fiat_25519_loose_field_element, fiat_25519_opp, fiat_25519_relax, fiat_25519_selectznz,
13 fiat_25519_sub, fiat_25519_tight_field_element, fiat_25519_to_bytes,
14};
15use serde::{Deserialize, Deserializer, Serialize, Serializer};
16use std::{
17 convert::TryFrom,
18 fmt::{self, Debug, Display, Formatter},
19 io::{Cursor, Read},
20 marker::PhantomData,
21 mem::size_of,
22 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
23};
24use subtle::{
25 Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
26};
27
28const MODULUS_LITTLE_ENDIAN: [u8; 32] = [
30 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
31 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
32];
33
34#[derive(Clone, Copy)]
36#[cfg_attr(docsrs, doc(cfg(feature = "experimental")))]
37pub struct Field255(fiat_25519_tight_field_element);
38
39impl Field255 {
40 fn try_from_bytes(bytes: &[u8], mask_top_bit: bool) -> Result<Self, FieldError> {
48 if Self::ENCODED_SIZE > bytes.len() {
49 return Err(FieldError::ShortRead);
50 }
51
52 let mut value = [0u8; Self::ENCODED_SIZE];
53 value.copy_from_slice(&bytes[..Self::ENCODED_SIZE]);
54
55 if mask_top_bit {
56 value[31] &= 0b0111_1111;
57 }
58
59 let mut less_than_modulus = Choice::from(0u8);
64 let mut greater_than_modulus = Choice::from(0u8);
65 for (value_byte, modulus_byte) in value.iter().rev().zip(MODULUS_LITTLE_ENDIAN.iter().rev())
66 {
67 less_than_modulus |= value_byte.ct_lt(modulus_byte) & !greater_than_modulus;
68 greater_than_modulus |= value_byte.ct_gt(modulus_byte) & !less_than_modulus;
69 }
70
71 if bool::from(!less_than_modulus) {
72 return Err(FieldError::ModulusOverflow);
73 }
74
75 let mut output = fiat_25519_tight_field_element([0; 5]);
76 fiat_25519_from_bytes(&mut output, &value);
77
78 Ok(Field255(output))
79 }
80}
81
82impl ConstantTimeEq for Field255 {
83 fn ct_eq(&self, rhs: &Self) -> Choice {
84 let mut self_encoded = [0; 32];
88 fiat_25519_to_bytes(&mut self_encoded, &self.0);
89 let mut rhs_encoded = [0; 32];
90 fiat_25519_to_bytes(&mut rhs_encoded, &rhs.0);
91
92 self_encoded.ct_eq(&rhs_encoded)
93 }
94}
95
96impl ConditionallySelectable for Field255 {
97 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
98 let mut output = [0; 5];
99 fiat_25519_selectznz(&mut output, choice.unwrap_u8(), &(a.0).0, &(b.0).0);
100 Field255(fiat_25519_tight_field_element(output))
101 }
102}
103
104impl PartialEq for Field255 {
105 fn eq(&self, rhs: &Self) -> bool {
106 self.ct_eq(rhs).into()
107 }
108}
109
110impl Eq for Field255 {}
111
112impl Add for Field255 {
113 type Output = Field255;
114
115 fn add(self, rhs: Self) -> Field255 {
116 let mut loose_output = fiat_25519_loose_field_element([0; 5]);
117 fiat_25519_add(&mut loose_output, &self.0, &rhs.0);
118 let mut output = fiat_25519_tight_field_element([0; 5]);
119 fiat_25519_carry(&mut output, &loose_output);
120 Field255(output)
121 }
122}
123
124impl AddAssign for Field255 {
125 fn add_assign(&mut self, rhs: Self) {
126 let mut loose_output = fiat_25519_loose_field_element([0; 5]);
127 fiat_25519_add(&mut loose_output, &self.0, &rhs.0);
128 fiat_25519_carry(&mut self.0, &loose_output);
129 }
130}
131
132impl Sub for Field255 {
133 type Output = Field255;
134
135 fn sub(self, rhs: Self) -> Field255 {
136 let mut loose_output = fiat_25519_loose_field_element([0; 5]);
137 fiat_25519_sub(&mut loose_output, &self.0, &rhs.0);
138 let mut output = fiat_25519_tight_field_element([0; 5]);
139 fiat_25519_carry(&mut output, &loose_output);
140 Field255(output)
141 }
142}
143
144impl SubAssign for Field255 {
145 fn sub_assign(&mut self, rhs: Self) {
146 let mut loose_output = fiat_25519_loose_field_element([0; 5]);
147 fiat_25519_sub(&mut loose_output, &self.0, &rhs.0);
148 fiat_25519_carry(&mut self.0, &loose_output);
149 }
150}
151
152impl Mul for Field255 {
153 type Output = Field255;
154
155 fn mul(self, rhs: Self) -> Field255 {
156 let mut self_relaxed = fiat_25519_loose_field_element([0; 5]);
157 fiat_25519_relax(&mut self_relaxed, &self.0);
158 let mut rhs_relaxed = fiat_25519_loose_field_element([0; 5]);
159 fiat_25519_relax(&mut rhs_relaxed, &rhs.0);
160 let mut output = fiat_25519_tight_field_element([0; 5]);
161 fiat_25519_carry_mul(&mut output, &self_relaxed, &rhs_relaxed);
162 Field255(output)
163 }
164}
165
166impl MulAssign for Field255 {
167 fn mul_assign(&mut self, rhs: Self) {
168 let mut self_relaxed = fiat_25519_loose_field_element([0; 5]);
169 fiat_25519_relax(&mut self_relaxed, &self.0);
170 let mut rhs_relaxed = fiat_25519_loose_field_element([0; 5]);
171 fiat_25519_relax(&mut rhs_relaxed, &rhs.0);
172 fiat_25519_carry_mul(&mut self.0, &self_relaxed, &rhs_relaxed);
173 }
174}
175
176impl Div for Field255 {
177 type Output = Field255;
178
179 fn div(self, _rhs: Self) -> Self::Output {
180 unimplemented!("Div is not implemented for Field255 because it's not needed yet")
181 }
182}
183
184impl DivAssign for Field255 {
185 fn div_assign(&mut self, _rhs: Self) {
186 unimplemented!("DivAssign is not implemented for Field255 because it's not needed yet")
187 }
188}
189
190impl Neg for Field255 {
191 type Output = Field255;
192
193 fn neg(self) -> Field255 {
194 -&self
195 }
196}
197
198impl<'a> Neg for &'a Field255 {
199 type Output = Field255;
200
201 fn neg(self) -> Field255 {
202 let mut loose_output = fiat_25519_loose_field_element([0; 5]);
203 fiat_25519_opp(&mut loose_output, &self.0);
204 let mut output = fiat_25519_tight_field_element([0; 5]);
205 fiat_25519_carry(&mut output, &loose_output);
206 Field255(output)
207 }
208}
209
210impl From<u64> for Field255 {
211 fn from(value: u64) -> Self {
212 let input_bytes = value.to_le_bytes();
213 let mut field_bytes = [0u8; Self::ENCODED_SIZE];
214 field_bytes[..input_bytes.len()].copy_from_slice(&input_bytes);
215 Self::try_from_bytes(&field_bytes, false).unwrap()
216 }
217}
218
219impl<'a> TryFrom<&'a [u8]> for Field255 {
220 type Error = FieldError;
221
222 fn try_from(bytes: &[u8]) -> Result<Self, FieldError> {
223 Self::try_from_bytes(bytes, false)
224 }
225}
226
227impl From<Field255> for [u8; Field255::ENCODED_SIZE] {
228 fn from(element: Field255) -> Self {
229 let mut array = [0; Field255::ENCODED_SIZE];
230 fiat_25519_to_bytes(&mut array, &element.0);
231 array
232 }
233}
234
235impl From<Field255> for Vec<u8> {
236 fn from(elem: Field255) -> Vec<u8> {
237 <[u8; Field255::ENCODED_SIZE]>::from(elem).to_vec()
238 }
239}
240
241impl Display for Field255 {
242 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
243 let encoded: [u8; Self::ENCODED_SIZE] = (*self).into();
244 write!(f, "0x")?;
245 for byte in encoded {
246 write!(f, "{byte:02x}")?;
247 }
248 Ok(())
249 }
250}
251
252impl Debug for Field255 {
253 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
254 <Self as Display>::fmt(self, f)
255 }
256}
257
258impl Serialize for Field255 {
259 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
260 let bytes: [u8; Self::ENCODED_SIZE] = (*self).into();
261 serializer.serialize_bytes(&bytes)
262 }
263}
264
265impl<'de> Deserialize<'de> for Field255 {
266 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Field255, D::Error> {
267 deserializer.deserialize_bytes(FieldElementVisitor {
268 phantom: PhantomData,
269 })
270 }
271}
272
273impl Encode for Field255 {
274 fn encode(&self, bytes: &mut Vec<u8>) -> Result<(), CodecError> {
275 bytes.extend_from_slice(&<[u8; Self::ENCODED_SIZE]>::from(*self));
276 Ok(())
277 }
278
279 fn encoded_len(&self) -> Option<usize> {
280 Some(Self::ENCODED_SIZE)
281 }
282}
283
284impl Decode for Field255 {
285 fn decode(bytes: &mut Cursor<&[u8]>) -> Result<Self, CodecError> {
286 let mut value = [0u8; Self::ENCODED_SIZE];
287 bytes.read_exact(&mut value)?;
288 Field255::try_from_bytes(&value, false).map_err(|e| {
289 CodecError::Other(Box::new(e) as Box<dyn std::error::Error + 'static + Send + Sync>)
290 })
291 }
292}
293
294impl FieldElement for Field255 {
295 const ENCODED_SIZE: usize = 32;
296
297 fn inv(&self) -> Self {
298 unimplemented!("Field255::inv() is not implemented because it's not needed yet")
299 }
300
301 fn try_from_random(bytes: &[u8]) -> Result<Self, FieldError> {
302 Field255::try_from_bytes(bytes, true)
303 }
304
305 fn zero() -> Self {
306 Field255(fiat_25519_tight_field_element([0, 0, 0, 0, 0]))
307 }
308
309 fn one() -> Self {
310 Field255(fiat_25519_tight_field_element([1, 0, 0, 0, 0]))
311 }
312}
313
314impl Default for Field255 {
315 fn default() -> Self {
316 Field255::zero()
317 }
318}
319
320impl TryFrom<Field255> for u64 {
321 type Error = FieldError;
322
323 fn try_from(elem: Field255) -> Result<u64, FieldError> {
324 const PREFIX_LEN: usize = size_of::<u64>();
325 let mut le_bytes = [0; 32];
326
327 fiat_25519_to_bytes(&mut le_bytes, &elem.0);
328 if !bool::from(le_bytes[PREFIX_LEN..].ct_eq(&[0_u8; 32 - PREFIX_LEN])) {
329 return Err(FieldError::IntegerTryFrom);
330 }
331
332 Ok(u64::from_le_bytes(
333 le_bytes[..PREFIX_LEN].try_into().unwrap(),
334 ))
335 }
336}
337
338#[cfg(test)]
339mod tests {
340 use super::{Field255, MODULUS_LITTLE_ENDIAN};
341 use crate::{
342 codec::Encode,
343 field::{
344 test_utils::{field_element_test_common, TestFieldElementWithInteger},
345 FieldElement, FieldError, Integer,
346 },
347 };
348 use assert_matches::assert_matches;
349 use fiat_crypto::curve25519_64::{
350 fiat_25519_from_bytes, fiat_25519_tight_field_element, fiat_25519_to_bytes,
351 };
352 use num_bigint::BigUint;
353 use once_cell::sync::Lazy;
354 use std::convert::{TryFrom, TryInto};
355
356 static MODULUS: Lazy<BigUint> = Lazy::new(|| BigUint::from_bytes_le(&MODULUS_LITTLE_ENDIAN));
357
358 impl From<BigUint> for Field255 {
359 fn from(value: BigUint) -> Self {
360 let le_bytes_vec = (value % &*MODULUS).to_bytes_le();
361
362 let mut le_bytes_array = [0u8; 32];
363 le_bytes_array[..le_bytes_vec.len()].copy_from_slice(&le_bytes_vec);
364
365 let mut output = fiat_25519_tight_field_element([0; 5]);
366 fiat_25519_from_bytes(&mut output, &le_bytes_array);
367 Field255(output)
368 }
369 }
370
371 impl From<Field255> for BigUint {
372 fn from(value: Field255) -> Self {
373 let mut le_bytes = [0u8; 32];
374 fiat_25519_to_bytes(&mut le_bytes, &value.0);
375 BigUint::from_bytes_le(&le_bytes)
376 }
377 }
378
379 impl Integer for BigUint {
380 type TryFromUsizeError = <Self as TryFrom<usize>>::Error;
381
382 type TryIntoU64Error = <Self as TryInto<u64>>::Error;
383
384 fn zero() -> Self {
385 Self::new(Vec::new())
386 }
387
388 fn one() -> Self {
389 Self::new(Vec::from([1]))
390 }
391 }
392
393 impl TestFieldElementWithInteger for Field255 {
394 type TestInteger = BigUint;
395 type IntegerTryFromError = <Self::TestInteger as TryFrom<usize>>::Error;
396 type TryIntoU64Error = <Self::TestInteger as TryInto<u64>>::Error;
397
398 fn modulus() -> Self::TestInteger {
399 MODULUS.clone()
400 }
401 }
402
403 #[test]
404 fn check_modulus() {
405 let modulus = Field255::modulus();
406 let element = Field255::from(modulus);
407 assert_eq!(element, Field255::zero());
410 }
411
412 #[test]
413 fn check_identities() {
414 let zero_bytes: [u8; 32] = Field255::zero().into();
415 assert_eq!(zero_bytes, [0; 32]);
416 let one_bytes: [u8; 32] = Field255::one().into();
417 assert_eq!(
418 one_bytes,
419 [
420 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
421 0, 0, 0, 0
422 ]
423 );
424 }
425
426 #[test]
427 fn encode_endianness() {
428 let mut one_encoded = Vec::new();
429 Field255::one().encode(&mut one_encoded).unwrap();
430 assert_eq!(
431 one_encoded,
432 [
433 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
434 0, 0, 0, 0
435 ]
436 );
437 }
438
439 #[test]
440 fn test_field255() {
441 field_element_test_common::<Field255>();
442 }
443
444 #[test]
445 fn try_from_bytes() {
446 assert_matches!(
447 Field255::try_from_bytes(
448 &[
449 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
450 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
451 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
452 ],
453 false,
454 ),
455 Err(FieldError::ModulusOverflow)
456 );
457 assert_matches!(
458 Field255::try_from_bytes(
459 &[
460 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
461 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
462 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
463 ],
464 false,
465 ),
466 Ok(_)
467 );
468 assert_matches!(
469 Field255::try_from_bytes(
470 &[
471 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
472 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
473 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
474 ],
475 true,
476 ),
477 Ok(element) => assert_eq!(element + Field255::one(), Field255::zero())
478 );
479 assert_matches!(
480 Field255::try_from_bytes(
481 &[
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
484 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
485 ],
486 false
487 ),
488 Err(FieldError::ModulusOverflow)
489 );
490 assert_matches!(
491 Field255::try_from_bytes(
492 &[
493 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
496 ],
497 true
498 ),
499 Ok(element) => assert_eq!(element, Field255::zero())
500 );
501 }
502
503 #[test]
504 fn u64_conversion() {
505 assert_eq!(Field255::from(0u64), Field255::zero());
506 assert_eq!(Field255::from(1u64), Field255::one());
507
508 let max_bytes: [u8; 32] = Field255::from(u64::MAX).into();
509 assert_eq!(
510 max_bytes,
511 [
512 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
514 0x00, 0x00, 0x00, 0x00
515 ]
516 );
517
518 let want: u64 = 0xffffffffffffffff;
519 assert_eq!(u64::try_from(Field255::from(want)).unwrap(), want);
520
521 let want: u64 = 0x7000000000000001;
522 assert_eq!(u64::try_from(Field255::from(want)).unwrap(), want);
523
524 let want: u64 = 0x1234123412341234;
525 assert_eq!(u64::try_from(Field255::from(want)).unwrap(), want);
526
527 assert!(u64::try_from(Field255::try_from_bytes(&[1; 32], false).unwrap()).is_err());
528 assert!(u64::try_from(Field255::try_from_bytes(&[2; 32], false).unwrap()).is_err());
529 }
530
531 #[test]
532 fn formatting() {
533 assert_eq!(
534 format!("{}", Field255::zero()),
535 "0x0000000000000000000000000000000000000000000000000000000000000000"
536 );
537 assert_eq!(
538 format!("{}", Field255::one()),
539 "0x0100000000000000000000000000000000000000000000000000000000000000"
540 );
541 assert_eq!(
542 format!("{}", -Field255::one()),
543 "0xecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f"
544 );
545 assert_eq!(
546 format!("{:?}", Field255::zero()),
547 "0x0000000000000000000000000000000000000000000000000000000000000000"
548 );
549 assert_eq!(
550 format!("{:?}", Field255::one()),
551 "0x0100000000000000000000000000000000000000000000000000000000000000"
552 );
553 }
554}