chiark / gitweb /
Merge remote-tracking branch 'origin/HEAD'
[catacomb-python] / share.c
1 /* -*-c-*-
2  *
3  * Secret sharing
4  *
5  * (c) 2005 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the Python interface to Catacomb.
11  *
12  * Catacomb/Python is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Catacomb/Python is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Catacomb/Python; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /*----- Header files ------------------------------------------------------*/
28
29 #include "catacomb-python.h"
30
31 /*----- GF(2^8)-based secret-sharing --------------------------------------*/
32
33 typedef struct gfshare_pyobj {
34   PyObject_HEAD
35   gfshare s;
36 } gfshare_pyobj;
37
38 static PyTypeObject
39   *gfshare_pytype, *gfsharesplit_pytype, *gfsharejoin_pytype;
40 #define GFSHARE_PYCHECK(o) PyObject_TypeCheck((o), gfshare_pytype)
41 #define GFSHARESPLIT_PYCHECK(o) PyObject_TypeCheck((o), gfsharesplit_pytype)
42 #define GFSHAREJOIN_PYCHECK(o) PyObject_TypeCheck((o), gfsharejoin_pytype)
43 #define GFSHARE_S(o) (&((gfshare_pyobj *)(o))->s)
44
45 static void gfshare_pydealloc(PyObject *me)
46 {
47   gfshare_destroy(GFSHARE_S(me));
48   FREEOBJ(me);
49 }
50
51 static PyObject *gfsget_threshold(PyObject *me, void *hunoz)
52   { return (PyInt_FromLong(GFSHARE_S(me)->t)); }
53 static PyObject *gfsget_size(PyObject *me, void *hunoz)
54   { return (PyInt_FromLong(GFSHARE_S(me)->sz)); }
55
56 static PyGetSetDef gfshare_pygetset[]= {
57 #define GETSETNAME(op, name) gfs##op##_##name
58   GET   (threshold,     "S.threshold -> THRESHOLD")
59   GET   (size,          "S.size -> SECRETSZ")
60 #undef GETSETNAME
61   { 0 }
62 };
63
64 static PyTypeObject gfshare_pytype_skel = {
65   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
66   "GFShare",                            /* @tp_name@ */
67   sizeof(gfshare_pyobj),                /* @tp_basicsize@ */
68   0,                                    /* @tp_itemsize@ */
69
70   gfshare_pydealloc,                    /* @tp_dealloc@ */
71   0,                                    /* @tp_print@ */
72   0,                                    /* @tp_getattr@ */
73   0,                                    /* @tp_setattr@ */
74   0,                                    /* @tp_compare@ */
75   0,                                    /* @tp_repr@ */
76   0,                                    /* @tp_as_number@ */
77   0,                                    /* @tp_as_sequence@ */
78   0,                                    /* @tp_as_mapping@ */
79   0,                                    /* @tp_hash@ */
80   0,                                    /* @tp_call@ */
81   0,                                    /* @tp_str@ */
82   0,                                    /* @tp_getattro@ */
83   0,                                    /* @tp_setattro@ */
84   0,                                    /* @tp_as_buffer@ */
85   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
86     Py_TPFLAGS_BASETYPE,
87
88   /* @tp_doc@ */
89 "Binary-field secret sharing base class.",
90
91   0,                                    /* @tp_traverse@ */
92   0,                                    /* @tp_clear@ */
93   0,                                    /* @tp_richcompare@ */
94   0,                                    /* @tp_weaklistoffset@ */
95   0,                                    /* @tp_iter@ */
96   0,                                    /* @tp_iternext@ */
97   0,                                    /* @tp_methods@ */
98   0,                                    /* @tp_members@ */
99   gfshare_pygetset,                     /* @tp_getset@ */
100   0,                                    /* @tp_base@ */
101   0,                                    /* @tp_dict@ */
102   0,                                    /* @tp_descr_get@ */
103   0,                                    /* @tp_descr_set@ */
104   0,                                    /* @tp_dictoffset@ */
105   0,                                    /* @tp_init@ */
106   PyType_GenericAlloc,                  /* @tp_alloc@ */
107   abstract_pynew,                       /* @tp_new@ */
108   0,                                    /* @tp_free@ */
109   0                                     /* @tp_is_gc@ */
110 };
111
112 static PyObject *gfsharesplit_pynew(PyTypeObject *ty,
113                                     PyObject *arg, PyObject *kw)
114 {
115   char *p;
116   Py_ssize_t n;
117   unsigned t;
118   grand *r = &rand_global;
119   gfshare_pyobj *s;
120   char *kwlist[] = { "threshold", "secret", "rng", 0 };
121   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&s#|O&:new", kwlist,
122                                    convuint, &t, &p, &n, convgrand, &r))
123     goto end;
124   if (!t || t > 255) VALERR("threshold must be nonzero and < 256");
125   s = (gfshare_pyobj *)ty->tp_alloc(ty, 0);
126   gfshare_create(&s->s, t, n);
127   gfshare_mkshares(&s->s, r, p);
128   return ((PyObject *)s);
129 end:
130   return (0);
131 }
132
133 static PyObject *gfsmeth_get(PyObject *me, PyObject *arg)
134 {
135   unsigned i;
136   PyObject *rc = 0;
137   if (!PyArg_ParseTuple(arg, "O&:get", convuint, &i)) goto end;
138   if (i >= 255) VALERR("index must be < 255");
139   rc = bytestring_pywrap(0, GFSHARE_S(me)->sz);
140   gfshare_get(GFSHARE_S(me), i, PyString_AS_STRING(rc));
141 end:
142   return (rc);
143 }
144
145 static PyMethodDef gfsharesplit_pymethods[] = {
146 #define METHNAME(name) gfsmeth_##name
147   METH  (get,           "S.get(I) -> SHARE")
148 #undef METHNAME
149   { 0 }
150 };
151
152 static PyTypeObject gfsharesplit_pytype_skel = {
153   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
154   "GFShareSplit",                       /* @tp_name@ */
155   sizeof(gfshare_pyobj),                /* @tp_basicsize@ */
156   0,                                    /* @tp_itemsize@ */
157
158   gfshare_pydealloc,                    /* @tp_dealloc@ */
159   0,                                    /* @tp_print@ */
160   0,                                    /* @tp_getattr@ */
161   0,                                    /* @tp_setattr@ */
162   0,                                    /* @tp_compare@ */
163   0,                                    /* @tp_repr@ */
164   0,                                    /* @tp_as_number@ */
165   0,                                    /* @tp_as_sequence@ */
166   0,                                    /* @tp_as_mapping@ */
167   0,                                    /* @tp_hash@ */
168   0,                                    /* @tp_call@ */
169   0,                                    /* @tp_str@ */
170   0,                                    /* @tp_getattro@ */
171   0,                                    /* @tp_setattro@ */
172   0,                                    /* @tp_as_buffer@ */
173   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
174     Py_TPFLAGS_BASETYPE,
175
176   /* @tp_doc@ */
177 "Binary field secret sharing: split secret into shares.",
178
179   0,                                    /* @tp_traverse@ */
180   0,                                    /* @tp_clear@ */
181   0,                                    /* @tp_richcompare@ */
182   0,                                    /* @tp_weaklistoffset@ */
183   0,                                    /* @tp_iter@ */
184   0,                                    /* @tp_iternext@ */
185   gfsharesplit_pymethods,               /* @tp_methods@ */
186   0,                                    /* @tp_members@ */
187   0,                                    /* @tp_getset@ */
188   0,                                    /* @tp_base@ */
189   0,                                    /* @tp_dict@ */
190   0,                                    /* @tp_descr_get@ */
191   0,                                    /* @tp_descr_set@ */
192   0,                                    /* @tp_dictoffset@ */
193   0,                                    /* @tp_init@ */
194   PyType_GenericAlloc,                  /* @tp_alloc@ */
195   gfsharesplit_pynew,                   /* @tp_new@ */
196   0,                                    /* @tp_free@ */
197   0                                     /* @tp_is_gc@ */
198 };
199
200 static PyObject *gfsharejoin_pynew(PyTypeObject *ty,
201                                    PyObject *arg, PyObject *kw)
202 {
203   unsigned t, sz;
204   gfshare_pyobj *s;
205   char *kwlist[] = { "threshold", "size", 0 };
206   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", kwlist,
207                                    convuint, &t, convuint, &sz))
208     goto end;
209   if (!t || t > 255) VALERR("threshold must be nonzero and < 256");
210   s = (gfshare_pyobj *)ty->tp_alloc(ty, 0);
211   gfshare_create(&s->s, t, sz);
212   return ((PyObject *)s);
213 end:
214   return (0);
215 }
216
217 static PyObject *gfsmeth_addedp(PyObject *me, PyObject *arg)
218 {
219   unsigned i;
220   if (!PyArg_ParseTuple(arg, "O&:addedp", convuint, &i)) goto end;
221   if (i > 254) VALERR("index must be < 255");
222   return (getbool(gfshare_addedp(GFSHARE_S(me), i)));
223 end:
224   return (0);
225 }
226
227 static PyObject *gfsmeth_add(PyObject *me, PyObject *arg)
228 {
229   unsigned i;
230   char *p;
231   Py_ssize_t n;
232   if (!PyArg_ParseTuple(arg, "O&s#:add", convuint, &i, &p, &n)) goto end;
233   if (i > 254) VALERR("index must be < 255");
234   if (n != GFSHARE_S(me)->sz) VALERR("bad share size");
235   if (gfshare_addedp(GFSHARE_S(me), i)) VALERR("this share already added");
236   if (GFSHARE_S(me)->i >= GFSHARE_S(me)->t) VALERR("enough shares already");
237   gfshare_add(GFSHARE_S(me), i, p);
238   return (PyInt_FromLong(GFSHARE_S(me)->t - GFSHARE_S(me)->i));
239 end:
240   return (0);
241 }
242
243 static PyObject *gfsmeth_combine(PyObject *me, PyObject *arg)
244 {
245   PyObject *rc = 0;
246   if (!PyArg_ParseTuple(arg, ":combine")) goto end;
247   if (GFSHARE_S(me)->i < GFSHARE_S(me)->t) VALERR("not enough shares yet");
248   rc = bytestring_pywrap(0, GFSHARE_S(me)->sz);
249   gfshare_combine(GFSHARE_S(me), PyString_AS_STRING(rc));
250 end:
251   return (rc);
252 }
253
254 static PyMethodDef gfsharejoin_pymethods[] = {
255 #define METHNAME(name) gfsmeth_##name
256   METH  (addedp,        "S.addedp(I) -> BOOL")
257   METH  (add,           "S.add(I, SHARE) -> REMAIN")
258   METH  (combine,       "S.combine() -> SECRET")
259 #undef METHNAME
260   { 0 }
261 };
262
263 static PyObject *gfsget_remain(PyObject *me, void *hunoz)
264   { return (PyInt_FromLong(GFSHARE_S(me)->t - GFSHARE_S(me)->i)); }
265
266 static PyGetSetDef gfsharejoin_pygetset[]= {
267 #define GETSETNAME(op, name) gfs##op##_##name
268   GET   (remain,        "S.remain -> REMAIN")
269 #undef GETSETNAME
270   { 0 }
271 };
272
273 static PyTypeObject gfsharejoin_pytype_skel = {
274   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
275   "GFShareJoin",                        /* @tp_name@ */
276   sizeof(gfshare_pyobj),                /* @tp_basicsize@ */
277   0,                                    /* @tp_itemsize@ */
278
279   gfshare_pydealloc,                    /* @tp_dealloc@ */
280   0,                                    /* @tp_print@ */
281   0,                                    /* @tp_getattr@ */
282   0,                                    /* @tp_setattr@ */
283   0,                                    /* @tp_compare@ */
284   0,                                    /* @tp_repr@ */
285   0,                                    /* @tp_as_number@ */
286   0,                                    /* @tp_as_sequence@ */
287   0,                                    /* @tp_as_mapping@ */
288   0,                                    /* @tp_hash@ */
289   0,                                    /* @tp_call@ */
290   0,                                    /* @tp_str@ */
291   0,                                    /* @tp_getattro@ */
292   0,                                    /* @tp_setattro@ */
293   0,                                    /* @tp_as_buffer@ */
294   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
295     Py_TPFLAGS_BASETYPE,
296
297   /* @tp_doc@ */
298 "Binary field secret sharing: join shares to recover secret.",
299
300   0,                                    /* @tp_traverse@ */
301   0,                                    /* @tp_clear@ */
302   0,                                    /* @tp_richcompare@ */
303   0,                                    /* @tp_weaklistoffset@ */
304   0,                                    /* @tp_iter@ */
305   0,                                    /* @tp_iternext@ */
306   gfsharejoin_pymethods,                /* @tp_methods@ */
307   0,                                    /* @tp_members@ */
308   gfsharejoin_pygetset,                 /* @tp_getset@ */
309   0,                                    /* @tp_base@ */
310   0,                                    /* @tp_dict@ */
311   0,                                    /* @tp_descr_get@ */
312   0,                                    /* @tp_descr_set@ */
313   0,                                    /* @tp_dictoffset@ */
314   0,                                    /* @tp_init@ */
315   PyType_GenericAlloc,                  /* @tp_alloc@ */
316   gfsharejoin_pynew,                    /* @tp_new@ */
317   0,                                    /* @tp_free@ */
318   0                                     /* @tp_is_gc@ */
319 };
320
321 /*----- Prime-field secret-sharing ----------------------------------------*/
322
323 typedef struct share_pyobj {
324   PyObject_HEAD
325   share s;
326 } share_pyobj;
327
328 static PyTypeObject
329   *share_pytype, *sharesplit_pytype, *sharejoin_pytype;
330 #define SHARE_PYCHECK(o) PyObject_TypeCheck((o), share_pytype)
331 #define SHARESPLIT_PYCHECK(o) PyObject_TypeCheck((o), sharesplit_pytype)
332 #define SHAREJOIN_PYCHECK(o) PyObject_TypeCheck((o), sharejoin_pytype)
333 #define SHARE_S(o) (&((share_pyobj *)(o))->s)
334
335 static void share_pydealloc(PyObject *me)
336 {
337   share_destroy(SHARE_S(me));
338   FREEOBJ(me);
339 }
340
341 static PyObject *sget_threshold(PyObject *me, void *hunoz)
342   { return (PyInt_FromLong(SHARE_S(me)->t)); }
343 static PyObject *sget_modulus(PyObject *me, void *hunoz)
344   { return (mp_pywrap(SHARE_S(me)->p)); }
345
346 static PyGetSetDef share_pygetset[]= {
347 #define GETSETNAME(op, name) s##op##_##name
348   GET   (threshold,     "S.threshold -> THRESHOLD")
349   GET   (modulus,       "S.modulus -> MODULUS")
350 #undef GETSETNAME
351   { 0 }
352 };
353
354 static PyTypeObject share_pytype_skel = {
355   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
356   "Share",                              /* @tp_name@ */
357   sizeof(share_pyobj),                  /* @tp_basicsize@ */
358   0,                                    /* @tp_itemsize@ */
359
360   share_pydealloc,                      /* @tp_dealloc@ */
361   0,                                    /* @tp_print@ */
362   0,                                    /* @tp_getattr@ */
363   0,                                    /* @tp_setattr@ */
364   0,                                    /* @tp_compare@ */
365   0,                                    /* @tp_repr@ */
366   0,                                    /* @tp_as_number@ */
367   0,                                    /* @tp_as_sequence@ */
368   0,                                    /* @tp_as_mapping@ */
369   0,                                    /* @tp_hash@ */
370   0,                                    /* @tp_call@ */
371   0,                                    /* @tp_str@ */
372   0,                                    /* @tp_getattro@ */
373   0,                                    /* @tp_setattro@ */
374   0,                                    /* @tp_as_buffer@ */
375   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
376     Py_TPFLAGS_BASETYPE,
377
378   /* @tp_doc@ */
379 "Prime-field secret sharing base class.",
380
381   0,                                    /* @tp_traverse@ */
382   0,                                    /* @tp_clear@ */
383   0,                                    /* @tp_richcompare@ */
384   0,                                    /* @tp_weaklistoffset@ */
385   0,                                    /* @tp_iter@ */
386   0,                                    /* @tp_iternext@ */
387   0,                                    /* @tp_methods@ */
388   0,                                    /* @tp_members@ */
389   share_pygetset,                       /* @tp_getset@ */
390   0,                                    /* @tp_base@ */
391   0,                                    /* @tp_dict@ */
392   0,                                    /* @tp_descr_get@ */
393   0,                                    /* @tp_descr_set@ */
394   0,                                    /* @tp_dictoffset@ */
395   0,                                    /* @tp_init@ */
396   PyType_GenericAlloc,                  /* @tp_alloc@ */
397   abstract_pynew,                       /* @tp_new@ */
398   0,                                    /* @tp_free@ */
399   0                                     /* @tp_is_gc@ */
400 };
401
402 static PyObject *sharesplit_pynew(PyTypeObject *ty,
403                                   PyObject *arg, PyObject *kw)
404 {
405   mp *sec = 0;
406   unsigned t;
407   grand *r = &rand_global;
408   mp *m = 0;
409   share_pyobj *s;
410   char *kwlist[] = { "threshold", "secret", "modulus", "rng", 0 };
411   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:new", kwlist,
412                                    convuint, &t, convmp, &sec,
413                                    convmp, &m, convgrand, &r))
414     goto end;
415   if (!t) VALERR("threshold must be nonzero");
416   s = (share_pyobj *)ty->tp_alloc(ty, 0);
417   share_create(&s->s, t);
418   s->s.p = m;
419   share_mkshares(&s->s, r, sec);
420   mp_drop(sec);
421   return ((PyObject *)s);
422 end:
423   mp_drop(m);
424   mp_drop(sec);
425   return (0);
426 }
427
428 static PyObject *smeth_get(PyObject *me, PyObject *arg)
429 {
430   unsigned i;
431   PyObject *rc = 0;
432   if (!PyArg_ParseTuple(arg, "O&:get", convuint, &i)) goto end;
433   rc = mp_pywrap(share_get(SHARE_S(me), MP_NEW, i));
434 end:
435   return (rc);
436 }
437
438 static PyMethodDef sharesplit_pymethods[] = {
439 #define METHNAME(name) smeth_##name
440   METH  (get,           "S.get(I) -> SHARE")
441 #undef METHNAME
442   { 0 }
443 };
444
445 static PyTypeObject sharesplit_pytype_skel = {
446   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
447   "ShareSplit",                         /* @tp_name@ */
448   sizeof(share_pyobj),                  /* @tp_basicsize@ */
449   0,                                    /* @tp_itemsize@ */
450
451   share_pydealloc,                      /* @tp_dealloc@ */
452   0,                                    /* @tp_print@ */
453   0,                                    /* @tp_getattr@ */
454   0,                                    /* @tp_setattr@ */
455   0,                                    /* @tp_compare@ */
456   0,                                    /* @tp_repr@ */
457   0,                                    /* @tp_as_number@ */
458   0,                                    /* @tp_as_sequence@ */
459   0,                                    /* @tp_as_mapping@ */
460   0,                                    /* @tp_hash@ */
461   0,                                    /* @tp_call@ */
462   0,                                    /* @tp_str@ */
463   0,                                    /* @tp_getattro@ */
464   0,                                    /* @tp_setattro@ */
465   0,                                    /* @tp_as_buffer@ */
466   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
467     Py_TPFLAGS_BASETYPE,
468
469   /* @tp_doc@ */
470 "Prime field secret sharing: split secret into shares.",
471
472   0,                                    /* @tp_traverse@ */
473   0,                                    /* @tp_clear@ */
474   0,                                    /* @tp_richcompare@ */
475   0,                                    /* @tp_weaklistoffset@ */
476   0,                                    /* @tp_iter@ */
477   0,                                    /* @tp_iternext@ */
478   sharesplit_pymethods,                 /* @tp_methods@ */
479   0,                                    /* @tp_members@ */
480   0,                                    /* @tp_getset@ */
481   0,                                    /* @tp_base@ */
482   0,                                    /* @tp_dict@ */
483   0,                                    /* @tp_descr_get@ */
484   0,                                    /* @tp_descr_set@ */
485   0,                                    /* @tp_dictoffset@ */
486   0,                                    /* @tp_init@ */
487   PyType_GenericAlloc,                  /* @tp_alloc@ */
488   sharesplit_pynew,                     /* @tp_new@ */
489   0,                                    /* @tp_free@ */
490   0                                     /* @tp_is_gc@ */
491 };
492
493 static PyObject *sharejoin_pynew(PyTypeObject *ty,
494                                  PyObject *arg, PyObject *kw)
495 {
496   unsigned t;
497   mp *m = 0;
498   share_pyobj *s;
499   char *kwlist[] = { "threshold", "modulus", 0 };
500   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", kwlist,
501                                    convuint, &t, convmp, &m))
502     goto end;
503   if (!t) VALERR("threshold must be nonzero");
504   s = (share_pyobj *)ty->tp_alloc(ty, 0);
505   share_create(&s->s, t);
506   s->s.p = m;
507   return ((PyObject *)s);
508 end:
509   mp_drop(m);
510   return (0);
511 }
512
513 static PyObject *smeth_addedp(PyObject *me, PyObject *arg)
514 {
515   unsigned i;
516   if (!PyArg_ParseTuple(arg, "O&:addedp", convuint, &i)) goto end;
517   return (getbool(share_addedp(SHARE_S(me), i)));
518 end:
519   return (0);
520 }
521
522 static PyObject *smeth_add(PyObject *me, PyObject *arg)
523 {
524   unsigned i;
525   mp *s = 0;
526   PyObject *rc = 0;
527   if (!PyArg_ParseTuple(arg, "O&O&:add", convuint, &i, convmp, &s)) goto end;
528   if (MP_NEGP(s) || MP_CMP(s, >=, SHARE_S(me)->p))
529     VALERR("share out of range");
530   if (share_addedp(SHARE_S(me), i)) VALERR("this share already added");
531   if (SHARE_S(me)->i >= SHARE_S(me)->t) VALERR("enough shares already");
532   share_add(SHARE_S(me), i, s);
533   rc = PyInt_FromLong(SHARE_S(me)->t - SHARE_S(me)->i);
534 end:
535   mp_drop(s);
536   return (rc);
537 }
538
539 static PyObject *smeth_combine(PyObject *me, PyObject *arg)
540 {
541   PyObject *rc = 0;
542   if (!PyArg_ParseTuple(arg, ":combine")) goto end;
543   if (SHARE_S(me)->i < SHARE_S(me)->t) VALERR("not enough shares yet");
544   rc = mp_pywrap(share_combine(SHARE_S(me)));
545 end:
546   return (rc);
547 }
548
549 static PyMethodDef sharejoin_pymethods[] = {
550 #define METHNAME(name) smeth_##name
551   METH  (addedp,        "S.addedp(I) -> BOOL")
552   METH  (add,           "S.add(I, SHARE) -> REMAIN")
553   METH  (combine,       "S.combine() -> SECRET")
554 #undef METHNAME
555   { 0 }
556 };
557
558 static PyObject *sget_remain(PyObject *me, void *hunoz)
559   { return (PyInt_FromLong(SHARE_S(me)->t - SHARE_S(me)->i)); }
560
561 static PyGetSetDef sharejoin_pygetset[]= {
562 #define GETSETNAME(op, name) s##op##_##name
563   GET   (remain,        "S.remain -> REMAIN")
564 #undef GETSETNAME
565   { 0 }
566 };
567
568 static PyTypeObject sharejoin_pytype_skel = {
569   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
570   "ShareJoin",                          /* @tp_name@ */
571   sizeof(share_pyobj),                  /* @tp_basicsize@ */
572   0,                                    /* @tp_itemsize@ */
573
574   share_pydealloc,                      /* @tp_dealloc@ */
575   0,                                    /* @tp_print@ */
576   0,                                    /* @tp_getattr@ */
577   0,                                    /* @tp_setattr@ */
578   0,                                    /* @tp_compare@ */
579   0,                                    /* @tp_repr@ */
580   0,                                    /* @tp_as_number@ */
581   0,                                    /* @tp_as_sequence@ */
582   0,                                    /* @tp_as_mapping@ */
583   0,                                    /* @tp_hash@ */
584   0,                                    /* @tp_call@ */
585   0,                                    /* @tp_str@ */
586   0,                                    /* @tp_getattro@ */
587   0,                                    /* @tp_setattro@ */
588   0,                                    /* @tp_as_buffer@ */
589   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
590     Py_TPFLAGS_BASETYPE,
591
592   /* @tp_doc@ */
593 "Prime field secret sharing: join shares to recover secret.",
594
595   0,                                    /* @tp_traverse@ */
596   0,                                    /* @tp_clear@ */
597   0,                                    /* @tp_richcompare@ */
598   0,                                    /* @tp_weaklistoffset@ */
599   0,                                    /* @tp_iter@ */
600   0,                                    /* @tp_iternext@ */
601   sharejoin_pymethods,                  /* @tp_methods@ */
602   0,                                    /* @tp_members@ */
603   sharejoin_pygetset,                   /* @tp_getset@ */
604   0,                                    /* @tp_base@ */
605   0,                                    /* @tp_dict@ */
606   0,                                    /* @tp_descr_get@ */
607   0,                                    /* @tp_descr_set@ */
608   0,                                    /* @tp_dictoffset@ */
609   0,                                    /* @tp_init@ */
610   PyType_GenericAlloc,                  /* @tp_alloc@ */
611   sharejoin_pynew,                      /* @tp_new@ */
612   0,                                    /* @tp_free@ */
613   0                                     /* @tp_is_gc@ */
614 };
615
616 /*----- Global stuff ------------------------------------------------------*/
617
618 void share_pyinit(void)
619 {
620   INITTYPE(gfshare, root);
621   INITTYPE(gfsharesplit, gfshare);
622   INITTYPE(gfsharejoin, gfshare);
623   INITTYPE(share, root);
624   INITTYPE(sharesplit, share);
625   INITTYPE(sharejoin, share);
626 }
627
628 void share_pyinsert(PyObject *mod)
629 {
630   INSERT("GFShare", gfshare_pytype);
631   INSERT("GFShareSplit", gfsharesplit_pytype);
632   INSERT("GFShareJoin", gfsharejoin_pytype);
633   INSERT("Share", share_pytype);
634   INSERT("ShareSplit", sharesplit_pytype);
635   INSERT("ShareJoin", sharejoin_pytype);
636 }
637
638 /*----- That's all, folks -------------------------------------------------*/