Percy++
A C++ implementation of Private Information Retrieval (PIR) protocols
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Pages
gf2e.h
1 // Percy++ Copyright 2007,2012,2013,2014
2 // Ian Goldberg <iang@cs.uwaterloo.ca>,
3 // Paul Hendry <pshendry@uwaterloo.ca>,
4 // Casey Devet <cjdevet@uwaterloo.ca>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of version 2 of the GNU General Public License as
8 // published by the Free Software Foundation.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // There is a copy of the GNU General Public License in the COPYING file
16 // packaged with this plugin; if you cannot find it, write to the Free
17 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 
20 #ifndef __GF2E_H__
21 #define __GF2E_H__
22 
23 #include <stdint.h>
24 
25 typedef unsigned char GF28_Element;
26 
27 typedef uint16_t GF216_Element;
28 
29 /* Use the same representation as AES */
30 static const unsigned char GF28_Generator = 0x1b;
31 
32 extern const GF28_Element GF28_mult_table[256][256];
33 
34 extern const GF28_Element GF28_inv_table[256];
35 
36 extern const GF216_Element GF216_exp_table[131070];
37 
38 extern const GF216_Element GF216_log_table[65536];
39 
40 //Multiply two GF(2^E) elements
41 //
42 template <typename E>
43 inline E multiply_GF2E(E x, E y);
44 // specialization for GF(2^8)
45 template <>
46 inline GF28_Element multiply_GF2E<GF28_Element>(GF28_Element x, GF28_Element y) {
47  return GF28_mult_table[x][y];
48 }
49 // specialization for GF(2^16)
50 template <>
51 inline GF216_Element multiply_GF2E<GF216_Element>(GF216_Element x, GF216_Element y) {
52  if(x == 0 || y == 0) return 0;
53 
54  GF216_Element log_x = GF216_log_table[x];
55  GF216_Element log_y = GF216_log_table[y];
56 
57  return GF216_exp_table[log_x+log_y];
58 }
59 
60 //Compute the inverse of a GF(2^E) element
61 //
62 template <typename E>
63 inline E inverse_GF2E(E x);
64 // specialization for GF(2^8)
65 template <>
66 inline GF28_Element inverse_GF2E<GF28_Element>(GF28_Element x) {
67  return GF28_inv_table[x];
68 }
69 // specialization for GF(2^16)
70 template <>
71 inline GF216_Element inverse_GF2E<GF216_Element>(GF216_Element x) {
72  if (x == 0) return 0;
73  GF216_Element log_x = GF216_log_table[x];
74  return GF216_exp_table[65535-log_x];
75 }
76 
77 // Evaluate a given polynomial over GF(2^E) at the given index
78 template <typename E>
79 E evalpoly_GF2E(E *coeffs, unsigned short degree,
80  E index)
81 {
82  E res = 0;
83 
84  int i = degree + 1;
85 
86  while (i > 0) {
87  --i;
88  res = multiply_GF2E<E>(res, index);
89  res ^= coeffs[i];
90  }
91 
92  return res;
93 }
94 
95 // return f(alpha), where f is the polynomial of degree numpoints-1 such
96 // that f(indices[i]) = values[i] for i=0..(numpoints-1)
97 template <typename E>
98 E interpolate_GF2E(const E *indices, const E *values,
99  unsigned short numpoints, const E alpha) {
100  E res;
101 
102  E *lagrange = new E[numpoints];
103  unsigned short i,j;
104 
105  for (i=0;i<numpoints;++i) {
106  E numer = 1, denom = 1;
107  for (j=0;j<numpoints;++j) {
108  if (j==i) continue;
109  E numerdiff = indices[j] ^ alpha;
110  E denomdiff = indices[j] ^ indices[i];
111  numer = multiply_GF2E<E>(numer, numerdiff);
112  denom = multiply_GF2E<E>(denom, denomdiff);
113  }
114  lagrange[i] = multiply_GF2E<E>(numer, inverse_GF2E<E>(denom));
115  }
116 
117  res = 0;
118  for (i=0;i<numpoints;++i) {
119  res ^= multiply_GF2E<E>(lagrange[i], values[i]);
120  }
121 
122  delete[] lagrange;
123  return res;
124 }
125 
126 // Multiply the polynomial in1 of degree deg1 (a pointer to
127 // deg1+1 coefficients) by the polynomial in2 of degree deg2
128 // (a pointer to deg2+1 coefficients) and put the output
129 // into result (a pointer to deg1+deg2+1 coefficients).
130 // Note that you cannot multiply "in place"; that is, the
131 // memory regions pointed to by result and in1 (and result
132 // and in2) cannot overlap. in1 and in2 may overlap, however.
133 // This function requires that deg1 and deg2 each be >= 0 (so you
134 // can't multiply by the zero polynomial with no coefficients; you
135 // can of course multiply by the constant (degree 0) polynomial whose
136 // only coefficient is 0, however).
137 template <typename E>
138 inline void multpoly_GF2E(E *result, const E *in1, unsigned short deg1,
139  const E *in2, unsigned short deg2)
140 {
141  unsigned short resdeg = deg1 + deg2;
142 
143  for (unsigned short d=0; d<=resdeg; ++d) {
144  result[d] = 0;
145 
146  /* lower = max(0,d-deg2) */
147  unsigned short lower = 0;
148  if (d > deg2) lower = d-deg2;
149 
150  /* upper = min(d,deg1) */
151  unsigned short upper = d;
152  if (deg1 < d) upper = deg1;
153 
154  for (unsigned short i=lower; i<=upper; ++i) {
155  result[d] ^= multiply_GF2E<E>(in1[i],in2[d-i]);
156  }
157  }
158 }
159 
160 // Create the polynomial whose roots are the ones in the given array
161 // The output pointer must point to pre-allocated memory of size
162 // (numroots+1)*sizeof(E)
163 template <typename E>
164 inline void polyfromroots_GF2E(E *result, const E *roots,
165  unsigned short numroots)
166 {
167  result[numroots] = 1;
168  for (unsigned short r=0; r<numroots; ++r) {
169  result[numroots-r-1] = 0;
170  for (unsigned short i=0; i<=r; ++i) {
171  result[numroots-r+i-1] ^=
172  multiply_GF2E<E>(result[numroots-r+i],roots[r]);
173  }
174  }
175 }
176 
177 #endif