Clearmatics Libff  0.1
C++ library for Finite Fields and Elliptic Curves
ffi_serialization.tcc
Go to the documentation of this file.
1 #ifndef __LIBFF_FFI_FFI_SERIALIZATION_TCC__
2 #define __LIBFF_FFI_FFI_SERIALIZATION_TCC__
3 
4 #include "ffi_serialization.hpp"
5 
6 #include <libff/algebra/fields/fp.hpp>
7 
8 namespace libff
9 {
10 
11 namespace ffi
12 {
13 
14 namespace internal
15 {
16 
17 // Generic big-endian field_serializer for multi-component field
18 // elements.
19 template<typename FieldT> class field_serializer
20 {
21 public:
22  static bool read_from_buffer(
23  FieldT &f, const void *buffer, size_t buffer_size)
24  {
25  constexpr size_t component_size = sizeof(f.coeffs[0]);
26  size_t i = FieldT::extension_degree() - 1;
27  do {
28  if (buffer_size < component_size ||
29  !field_element_read(f.coeffs[i], buffer, component_size)) {
30  return false;
31  }
32  buffer = ((const char *)buffer) + component_size;
33  buffer_size -= component_size;
34  } while (i-- > 0);
35 
36  return true;
37  }
38 
39  static bool write_to_buffer(
40  const FieldT &f, void *buffer, size_t buffer_size)
41  {
42  constexpr size_t component_size = sizeof(f.coeffs[0]);
43  size_t i = FieldT::extension_degree() - 1;
44  do {
45  if (buffer_size < component_size ||
46  !field_element_write(f.coeffs[i], buffer, component_size)) {
47  return false;
48  }
49  buffer = ((char *)buffer) + component_size;
50  buffer_size -= component_size;
51  } while (i-- > 0);
52 
53  return true;
54  }
55 };
56 
57 // Specialized version of field_serializer, for the base-case of base
58 // fields.
59 template<mp_size_t n, const libff::bigint<n> &modulus>
60 class field_serializer<libff::Fp_model<n, modulus>>
61 {
62 public:
63  using FieldT = libff::Fp_model<n, modulus>;
64 
65  static bool read_from_buffer(
66  FieldT &f, const void *buffer, size_t buffer_size)
67  {
68  libff::bigint<n> bigint;
69  if (object_read_from_buffer(bigint, buffer, buffer_size) &&
70  mpn_cmp(modulus.data, bigint.data, n) > 0) {
71  f = libff::Fp_model<n, modulus>(bigint);
72  return true;
73  }
74 
75  return false;
76  }
77 
78  static bool write_to_buffer(
79  const FieldT &f, void *buffer, size_t buffer_size)
80  {
81  const libff::bigint<n> bigint = f.as_bigint();
82  return object_write_to_buffer(bigint, buffer, buffer_size);
83  }
84 };
85 
86 template<typename FieldT> bool field_element_equals_zero(const FieldT &f)
87 {
88  return f == FieldT::zero();
89 }
90 
91 template<typename FieldT> bool field_element_equals_one(const FieldT &f)
92 {
93  return f == FieldT::one();
94 }
95 
96 } // namespace internal
97 
98 template<typename T>
99 bool object_read_from_buffer(T &object, const void *buffer, size_t buffer_size)
100 {
101  constexpr size_t object_size = sizeof(T);
102  if (buffer_size != object_size) {
103  return false;
104  }
105 
106  char *dest = (char *)&object;
107  const char *src = ((const char *)buffer) + buffer_size;
108  const char *end = src - object_size;
109  while (src > end) {
110  *(dest++) = *(--src);
111  }
112 
113  return true;
114 }
115 
116 // Ensure there is enough data in the buffer, copy in reverse-byte
117 // order from the right of the buffer into an array of element_size.
118 template<typename T>
119 bool object_write_to_buffer(const T &object, void *buffer, size_t buffer_size)
120 {
121  constexpr size_t object_size = sizeof(T);
122  if (buffer_size != object_size) {
123  return false;
124  }
125 
126  char *dest = (char *)buffer;
127  const char *const end = ((const char *)&object);
128  const char *src = end + object_size;
129  while (src > end) {
130  *(dest++) = *(--src);
131  }
132 
133  return true;
134 }
135 
136 template<typename FieldT>
137 bool field_element_read(FieldT &f, const void *buffer, size_t buffer_size)
138 {
139  return internal::field_serializer<FieldT>::read_from_buffer(
140  f, buffer, buffer_size);
141 }
142 
143 template<typename FieldT>
144 bool field_element_write(const FieldT &f, void *buffer, size_t buffer_size)
145 {
146  return internal::field_serializer<FieldT>::write_to_buffer(
147  f, buffer, buffer_size);
148 }
149 
150 template<typename GroupT>
151 bool group_element_read(GroupT &g, const void *buffer, size_t buffer_size)
152 {
153  constexpr size_t coordinate_size = sizeof(g.X);
154  if (buffer_size == 2 * coordinate_size) {
155  if (field_element_read(g.X, buffer, coordinate_size)) {
156  buffer = ((const char *)buffer) + coordinate_size;
157  if (field_element_read(g.Y, buffer, coordinate_size)) {
158  if (internal::field_element_equals_zero(g.X) &&
159  internal::field_element_equals_one(g.Y)) {
160  g.Z = g.Z.zero();
161  } else {
162  g.Z = g.Z.one();
163  }
164 
165  return g.is_well_formed() && g.is_in_safe_subgroup();
166  }
167  }
168  }
169 
170  return false;
171 }
172 
173 template<typename GroupT>
174 bool group_element_write(const GroupT &g, void *buffer, size_t buffer_size)
175 {
176  constexpr size_t coordinate_size = sizeof(g.X);
177  if (buffer_size == 2 * coordinate_size) {
178  GroupT affine_p = g;
179  affine_p.to_affine_coordinates();
180  if (field_element_write(affine_p.X, buffer, coordinate_size)) {
181  buffer = ((char *)buffer) + coordinate_size;
182  return field_element_write(affine_p.Y, buffer, coordinate_size);
183  }
184  }
185 
186  return false;
187 }
188 
189 } // namespace ffi
190 
191 } // namespace libff
192 
193 #endif // __LIBFF_FFI_FFI_SERIALIZATION_HPP__