1 // Requires:
2 // * stdio.h
3 // * gmp.h
4 // * utils.h
5 // * field.h
6 // * param.h
7 #ifndef __PBC_PAIRING_H__
8 #define __PBC_PAIRING_H__
9 
10 struct pairing_pp_s {
11   struct pairing_s *pairing;
12   void *data;
13 };
14 typedef struct pairing_pp_s pairing_pp_t[1];
15 typedef struct pairing_pp_s *pairing_pp_ptr;
16 
17 struct pairing_s {
18   mpz_t r; // order of G1, G2, GT
19   field_t Zr; // the field Z_r
20   field_ptr G1, G2;
21   field_t GT; // group of rth roots of unity
22 
23   mpz_t phikonr;
24   // Phi_k(q)/r where Phi_k is the kth cyclotomic polynomial,
25   // q as in F_q, is the base field
26 
27   void (*phi)(element_ptr out, element_ptr in, struct pairing_s *pairing); //isomorphism G2 --> G1
28   void (*map)(element_ptr out, element_ptr in1, element_ptr in2,
29       struct pairing_s *p);
30   void (*prod_pairings)(element_ptr out, element_t in1[], element_t in2[], int n_prod,
31             struct pairing_s *p);  //calculate a product of pairings at one time.
32   // is_almost coddh returns true given (g, g^x, h, h^x) or (g, g^x, h, h^-x)
33   // order is important: a, b are from G1, c, d are from G2
34   int (*is_almost_coddh)(element_ptr a, element_ptr b,
35       element_ptr c, element_ptr d,
36       struct pairing_s *p);
37   void (*clear_func)(struct pairing_s *);
38   void (*pp_init)(pairing_pp_t p, element_t in1, struct pairing_s *);
39   void (*pp_clear)(pairing_pp_t p);
40   void (*pp_apply)(element_t out, element_t in2, pairing_pp_t p);
41   void (*finalpow)(element_t e);
42   void (*option_set)(struct pairing_s *, char *key, char *value);
43   void *data;
44 };
45 
46 typedef struct pairing_s pairing_t[1];
47 typedef struct pairing_s *pairing_ptr;
48 
49 // TODO: The 'pairing' argument is redundant.
50 /*@manual pairing_apply
51 Get ready to perform a pairing whose first input is 'in1',
52 and store the results of time-saving precomputation in 'p'.
53 */
pairing_pp_init(pairing_pp_t p,element_t in1,pairing_t pairing)54 static inline void pairing_pp_init(pairing_pp_t p, element_t in1, pairing_t pairing) {
55   if (element_is0(in1)) {
56     p->pairing = NULL;
57     return;
58   }
59   p->pairing = pairing;
60   pairing->pp_init(p, in1, pairing);
61 }
62 
63 /*@manual pairing_apply
64 Clear 'p'. This should be called after 'p' is no longer needed.
65 */
pairing_pp_clear(pairing_pp_t p)66 static inline void pairing_pp_clear(pairing_pp_t p) {
67   if (!p->pairing) {
68     // happens when p was initialized with identity
69     return;
70   }
71   p->pairing->pp_clear(p);
72 }
73 
74 /*@manual pairing_apply
75 Compute a pairing using 'in2' and the preprocessed information stored in 'p'
76 and store the output in 'out'. The inputs to the pairing are the element
77 previously used to initialize 'p' and the element 'in2'.
78 */
pairing_pp_apply(element_t out,element_t in2,pairing_pp_t p)79 static inline void pairing_pp_apply(element_t out, element_t in2, pairing_pp_t p) {
80   if (!p->pairing) {
81     element_set0(out);
82     return;
83   }
84   if (element_is0(in2)) {
85     element_set0(out);
86     return;
87   }
88   p->pairing->pp_apply((element_ptr) out->data, in2, p);
89 }
90 
91 /*@manual pairing_init
92 Initialize pairing from parameters in a ASCIIZ string 'str'
93 Returns 0 on success, 1 on failure.
94 */
95 int pairing_init_set_str(pairing_t pairing, const char *s);
96 
97 /*@manual pairing_init
98 Same, but read at most 'len' bytes.
99 If 'len' is 0, it behaves as the previous function.
100 Returns 0 on success, 1 on failure.
101 */
102 int pairing_init_set_buf(pairing_t pairing, const char *s, size_t len);
103 
104 /*@manual pairing_init
105 Initialize a pairing with pairing parameters 'p'.
106 */
107 void pairing_init_pbc_param(struct pairing_s *pairing, pbc_param_ptr p);
108 
109 /*@manual pairing_init
110 Free the space occupied by 'pairing'. Call
111 whenever a +pairing_t+ variable is no longer needed.
112 Only call this after all elements associated with 'pairing'
113 have been cleared, as they need information stored in the 'pairing'
114 structure.
115 */
116 void pairing_clear(pairing_t pairing);
117 
pairing_apply(element_t out,element_t in1,element_t in2,pairing_t pairing)118 static inline void pairing_apply(element_t out, element_t in1, element_t in2,
119     pairing_t pairing) {
120   PBC_ASSERT(pairing->GT == out->field, "pairing output mismatch");
121   PBC_ASSERT(pairing->G1 == in1->field, "pairing 1st input mismatch");
122   PBC_ASSERT(pairing->G2 == in2->field, "pairing 2nd input mismatch");
123   if (element_is0(in1)) {
124     element_set0(out);
125     return;
126   }
127   if (element_is0(in2)) {
128     element_set0(out);
129     return;
130   }
131   // TODO: 'out' is an element of a multiplicative subgroup, but the
132   // pairing routine expects it to be an element of the full group, hence
133   // the 'out->data'. I should make this clearer.
134   pairing->map((element_ptr) out->data, in1, in2, pairing);
135 }
136 
137 /*@manual pairing_apply
138 Computes a pairing: 'out' = 'e'('in1', 'in2'),
139 where 'in1', 'in2', 'out' must be in the groups G1, G2, GT.
140 */
element_pairing(element_t out,element_t in1,element_t in2)141 static inline void element_pairing(element_t out, element_t in1, element_t in2) {
142   pairing_ptr pairing = out->field->pairing;
143   PBC_ASSERT(pairing != NULL, "pairing output mismatch");
144   pairing_apply(out, in1, in2, pairing);
145 }
146 
147 /*@manual pairing_apply
148 Computes the product of pairings, that is
149 'out' = 'e'('in1'[0], 'in2'[0]) ... 'e'('in1'[n-1], 'in2'[n-1]).
150 The arrays 'in1', 'in2' must have at least 'n' elements belonging to
151 the groups G1, G2 respectively, and 'out' must belong to the group GT.
152 */
element_prod_pairing(element_t out,element_t in1[],element_t in2[],int n)153 static inline void element_prod_pairing(
154     element_t out, element_t in1[], element_t in2[], int n) {
155   pairing_ptr pairing = out->field->pairing;
156   int i;
157   PBC_ASSERT(pairing->GT == out->field, "pairing output mismatch");
158   for(i = 0; i < n; i++) {
159     PBC_ASSERT(pairing->G1 == in1[i]->field, "pairing 1st input mismatch");
160     PBC_ASSERT(pairing->G2 == in2[i]->field, "pairing 2nd input mismatch");
161     if (element_is0(in1[i])) {
162       element_set0(out);
163       return;
164     }
165     if (element_is0(in2[i])) {
166       element_set0(out);
167       return;
168     }
169   }
170   pairing->prod_pairings((element_ptr) out->data, in1, in2, n, pairing);
171 }
172 
173 /*@manual pairing_op
174 Returns true if G1 and G2 are the same group.
175 */
pairing_is_symmetric(pairing_t pairing)176 static inline int pairing_is_symmetric(pairing_t pairing) {
177   return pairing->G1 == pairing->G2;
178 }
179 
180 /*@manual pairing_op
181 Returns the length in bytes needed to represent an element of G1.
182 */
pairing_length_in_bytes_G1(pairing_t pairing)183 static inline int pairing_length_in_bytes_G1(pairing_t pairing) {
184   return pairing->G1->fixed_length_in_bytes;
185 }
186 
187 /*@manual pairing_op
188 Returns the length in bytes needed to represent the x-coordinate of
189 an element of G1.
190 */
pairing_length_in_bytes_x_only_G1(pairing_t pairing)191 static inline int pairing_length_in_bytes_x_only_G1(pairing_t pairing) {
192   return pairing->G1->fixed_length_in_bytes / 2;
193 }
194 
195 /*@manual pairing_op
196 Returns the length in bytes needed to represent a compressed form of
197 an element of G1. There is some overhead in decompressing.
198 */
pairing_length_in_bytes_compressed_G1(pairing_t pairing)199 static inline int pairing_length_in_bytes_compressed_G1(pairing_t pairing) {
200   return pairing->G1->fixed_length_in_bytes / 2 + 1;
201 }
202 
203 /*@manual pairing_op
204 Returns the length in bytes needed to represent an element of G2.
205 */
pairing_length_in_bytes_G2(pairing_t pairing)206 static inline int pairing_length_in_bytes_G2(pairing_t pairing) {
207   return pairing->G2->fixed_length_in_bytes;
208 }
209 
210 /*@manual pairing_op
211 Returns the length in bytes needed to represent a compressed form of
212 an element of G2. There is some overhead in decompressing.
213 */
pairing_length_in_bytes_compressed_G2(pairing_t pairing)214 static inline int pairing_length_in_bytes_compressed_G2(pairing_t pairing) {
215   return pairing->G2->fixed_length_in_bytes / 2 + 1;
216 }
217 
218 /*@manual pairing_op
219 Returns the length in bytes needed to represent the x-coordinate of
220 an element of G2.
221 */
pairing_length_in_bytes_x_only_G2(pairing_t pairing)222 static inline int pairing_length_in_bytes_x_only_G2(pairing_t pairing) {
223   return pairing->G2->fixed_length_in_bytes / 2;
224 }
225 
226 /*@manual pairing_op
227 Returns the length in bytes needed to represent an element of GT.
228 */
pairing_length_in_bytes_GT(pairing_t pairing)229 static inline int pairing_length_in_bytes_GT(pairing_t pairing) {
230   return pairing->GT->fixed_length_in_bytes;
231 }
232 
233 /*@manual pairing_op
234 Returns the length in bytes needed to represent an element of Zr.
235 */
pairing_length_in_bytes_Zr(pairing_t pairing)236 static inline int pairing_length_in_bytes_Zr(pairing_t pairing) {
237   return pairing->Zr->fixed_length_in_bytes;
238 }
239 
is_almost_coddh(element_t a,element_t b,element_t c,element_t d,pairing_t pairing)240 static inline int is_almost_coddh(element_t a, element_t b,
241     element_t c, element_t d, pairing_t pairing) {
242   return pairing->is_almost_coddh(a, b, c, d, pairing);
243 }
244 
245 /*@manual einit.1
246 */
element_init_G1(element_t e,pairing_t pairing)247 static inline void element_init_G1(element_t e, pairing_t pairing) {
248   element_init(e, pairing->G1);
249 }
250 
251 /*@manual einit.1
252 */
element_init_G2(element_t e,pairing_t pairing)253 static inline void element_init_G2(element_t e, pairing_t pairing) {
254   element_init(e, pairing->G2);
255 }
256 
257 /*@manual einit.1
258 Initialize 'e' to be an element of the group G1, G2 or GT of 'pairing'.
259 */
element_init_GT(element_t e,pairing_t pairing)260 static inline void element_init_GT(element_t e, pairing_t pairing) {
261   element_init(e, pairing->GT);
262 }
263 
264 /*@manual einit.1
265 Initialize 'e' to be an element of the ring Z_r of 'pairing'.
266 r is the order of the groups G1, G2 and GT that are involved in the pairing.
267 */
element_init_Zr(element_t e,pairing_t pairing)268 static inline void element_init_Zr(element_t e, pairing_t pairing) {
269   element_init(e, pairing->Zr);
270 }
271 
pairing_option_set(pairing_t pairing,char * key,char * value)272 static inline void pairing_option_set(pairing_t pairing, char *key, char *value) {
273   pairing->option_set(pairing, key, value);
274 }
275 
276 // Initialize GT = group of rth roots of unity in f.
277 // Requires pairing->r has been set.
278 void pairing_GT_init(pairing_ptr pairing, field_t f);
279 
280 #endif //__PBC_PAIRING_H__
281