chiark / gitweb /
t/t-algorithms.py: Add tests for other HSalsa20 and HChaCha key sizes.
[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   static const char *const 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 "GFShareSplit(THRESHOLD, SECRET, [rng = rand]): binary-field sharing:\n\
178    split secret into shares.",
179
180   0,                                    /* @tp_traverse@ */
181   0,                                    /* @tp_clear@ */
182   0,                                    /* @tp_richcompare@ */
183   0,                                    /* @tp_weaklistoffset@ */
184   0,                                    /* @tp_iter@ */
185   0,                                    /* @tp_iternext@ */
186   gfsharesplit_pymethods,               /* @tp_methods@ */
187   0,                                    /* @tp_members@ */
188   0,                                    /* @tp_getset@ */
189   0,                                    /* @tp_base@ */
190   0,                                    /* @tp_dict@ */
191   0,                                    /* @tp_descr_get@ */
192   0,                                    /* @tp_descr_set@ */
193   0,                                    /* @tp_dictoffset@ */
194   0,                                    /* @tp_init@ */
195   PyType_GenericAlloc,                  /* @tp_alloc@ */
196   gfsharesplit_pynew,                   /* @tp_new@ */
197   0,                                    /* @tp_free@ */
198   0                                     /* @tp_is_gc@ */
199 };
200
201 static PyObject *gfsharejoin_pynew(PyTypeObject *ty,
202                                    PyObject *arg, PyObject *kw)
203 {
204   unsigned t, sz;
205   gfshare_pyobj *s;
206   static const char *const kwlist[] = { "threshold", "size", 0 };
207   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST,
208                                    convuint, &t, convuint, &sz))
209     goto end;
210   if (!t || t > 255) VALERR("threshold must be nonzero and < 256");
211   s = (gfshare_pyobj *)ty->tp_alloc(ty, 0);
212   gfshare_create(&s->s, t, sz);
213   return ((PyObject *)s);
214 end:
215   return (0);
216 }
217
218 static PyObject *gfsmeth_addedp(PyObject *me, PyObject *arg)
219 {
220   unsigned i;
221   if (!PyArg_ParseTuple(arg, "O&:addedp", convuint, &i)) goto end;
222   if (i > 254) VALERR("index must be < 255");
223   return (getbool(gfshare_addedp(GFSHARE_S(me), i)));
224 end:
225   return (0);
226 }
227
228 static PyObject *gfsmeth_add(PyObject *me, PyObject *arg)
229 {
230   unsigned i;
231   char *p;
232   Py_ssize_t n;
233   if (!PyArg_ParseTuple(arg, "O&s#:add", convuint, &i, &p, &n)) goto end;
234   if (i > 254) VALERR("index must be < 255");
235   if (n != GFSHARE_S(me)->sz) VALERR("bad share size");
236   if (gfshare_addedp(GFSHARE_S(me), i)) VALERR("this share already added");
237   if (GFSHARE_S(me)->i >= GFSHARE_S(me)->t) VALERR("enough shares already");
238   gfshare_add(GFSHARE_S(me), i, p);
239   return (PyInt_FromLong(GFSHARE_S(me)->t - GFSHARE_S(me)->i));
240 end:
241   return (0);
242 }
243
244 static PyObject *gfsmeth_combine(PyObject *me, PyObject *arg)
245 {
246   PyObject *rc = 0;
247   if (!PyArg_ParseTuple(arg, ":combine")) goto end;
248   if (GFSHARE_S(me)->i < GFSHARE_S(me)->t) VALERR("not enough shares yet");
249   rc = bytestring_pywrap(0, GFSHARE_S(me)->sz);
250   gfshare_combine(GFSHARE_S(me), PyString_AS_STRING(rc));
251 end:
252   return (rc);
253 }
254
255 static PyMethodDef gfsharejoin_pymethods[] = {
256 #define METHNAME(name) gfsmeth_##name
257   METH  (addedp,        "S.addedp(I) -> BOOL")
258   METH  (add,           "S.add(I, SHARE) -> REMAIN")
259   METH  (combine,       "S.combine() -> SECRET")
260 #undef METHNAME
261   { 0 }
262 };
263
264 static PyObject *gfsget_remain(PyObject *me, void *hunoz)
265   { return (PyInt_FromLong(GFSHARE_S(me)->t - GFSHARE_S(me)->i)); }
266
267 static PyGetSetDef gfsharejoin_pygetset[]= {
268 #define GETSETNAME(op, name) gfs##op##_##name
269   GET   (remain,        "S.remain -> REMAIN")
270 #undef GETSETNAME
271   { 0 }
272 };
273
274 static PyTypeObject gfsharejoin_pytype_skel = {
275   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
276   "GFShareJoin",                        /* @tp_name@ */
277   sizeof(gfshare_pyobj),                /* @tp_basicsize@ */
278   0,                                    /* @tp_itemsize@ */
279
280   gfshare_pydealloc,                    /* @tp_dealloc@ */
281   0,                                    /* @tp_print@ */
282   0,                                    /* @tp_getattr@ */
283   0,                                    /* @tp_setattr@ */
284   0,                                    /* @tp_compare@ */
285   0,                                    /* @tp_repr@ */
286   0,                                    /* @tp_as_number@ */
287   0,                                    /* @tp_as_sequence@ */
288   0,                                    /* @tp_as_mapping@ */
289   0,                                    /* @tp_hash@ */
290   0,                                    /* @tp_call@ */
291   0,                                    /* @tp_str@ */
292   0,                                    /* @tp_getattro@ */
293   0,                                    /* @tp_setattro@ */
294   0,                                    /* @tp_as_buffer@ */
295   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
296     Py_TPFLAGS_BASETYPE,
297
298   /* @tp_doc@ */
299 "GFShareJoin(THRESHOLD, SIZE): binary field sharing:\n\
300   join shares to recover secret.",
301
302   0,                                    /* @tp_traverse@ */
303   0,                                    /* @tp_clear@ */
304   0,                                    /* @tp_richcompare@ */
305   0,                                    /* @tp_weaklistoffset@ */
306   0,                                    /* @tp_iter@ */
307   0,                                    /* @tp_iternext@ */
308   gfsharejoin_pymethods,                /* @tp_methods@ */
309   0,                                    /* @tp_members@ */
310   gfsharejoin_pygetset,                 /* @tp_getset@ */
311   0,                                    /* @tp_base@ */
312   0,                                    /* @tp_dict@ */
313   0,                                    /* @tp_descr_get@ */
314   0,                                    /* @tp_descr_set@ */
315   0,                                    /* @tp_dictoffset@ */
316   0,                                    /* @tp_init@ */
317   PyType_GenericAlloc,                  /* @tp_alloc@ */
318   gfsharejoin_pynew,                    /* @tp_new@ */
319   0,                                    /* @tp_free@ */
320   0                                     /* @tp_is_gc@ */
321 };
322
323 /*----- Prime-field secret-sharing ----------------------------------------*/
324
325 typedef struct share_pyobj {
326   PyObject_HEAD
327   share s;
328 } share_pyobj;
329
330 static PyTypeObject
331   *share_pytype, *sharesplit_pytype, *sharejoin_pytype;
332 #define SHARE_PYCHECK(o) PyObject_TypeCheck((o), share_pytype)
333 #define SHARESPLIT_PYCHECK(o) PyObject_TypeCheck((o), sharesplit_pytype)
334 #define SHAREJOIN_PYCHECK(o) PyObject_TypeCheck((o), sharejoin_pytype)
335 #define SHARE_S(o) (&((share_pyobj *)(o))->s)
336
337 static void share_pydealloc(PyObject *me)
338 {
339   share_destroy(SHARE_S(me));
340   FREEOBJ(me);
341 }
342
343 static PyObject *sget_threshold(PyObject *me, void *hunoz)
344   { return (PyInt_FromLong(SHARE_S(me)->t)); }
345 static PyObject *sget_modulus(PyObject *me, void *hunoz)
346   { return (mp_pywrap(SHARE_S(me)->p)); }
347
348 static PyGetSetDef share_pygetset[]= {
349 #define GETSETNAME(op, name) s##op##_##name
350   GET   (threshold,     "S.threshold -> THRESHOLD")
351   GET   (modulus,       "S.modulus -> MODULUS")
352 #undef GETSETNAME
353   { 0 }
354 };
355
356 static PyTypeObject share_pytype_skel = {
357   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
358   "Share",                              /* @tp_name@ */
359   sizeof(share_pyobj),                  /* @tp_basicsize@ */
360   0,                                    /* @tp_itemsize@ */
361
362   share_pydealloc,                      /* @tp_dealloc@ */
363   0,                                    /* @tp_print@ */
364   0,                                    /* @tp_getattr@ */
365   0,                                    /* @tp_setattr@ */
366   0,                                    /* @tp_compare@ */
367   0,                                    /* @tp_repr@ */
368   0,                                    /* @tp_as_number@ */
369   0,                                    /* @tp_as_sequence@ */
370   0,                                    /* @tp_as_mapping@ */
371   0,                                    /* @tp_hash@ */
372   0,                                    /* @tp_call@ */
373   0,                                    /* @tp_str@ */
374   0,                                    /* @tp_getattro@ */
375   0,                                    /* @tp_setattro@ */
376   0,                                    /* @tp_as_buffer@ */
377   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
378     Py_TPFLAGS_BASETYPE,
379
380   /* @tp_doc@ */
381 "Prime-field secret sharing base class.",
382
383   0,                                    /* @tp_traverse@ */
384   0,                                    /* @tp_clear@ */
385   0,                                    /* @tp_richcompare@ */
386   0,                                    /* @tp_weaklistoffset@ */
387   0,                                    /* @tp_iter@ */
388   0,                                    /* @tp_iternext@ */
389   0,                                    /* @tp_methods@ */
390   0,                                    /* @tp_members@ */
391   share_pygetset,                       /* @tp_getset@ */
392   0,                                    /* @tp_base@ */
393   0,                                    /* @tp_dict@ */
394   0,                                    /* @tp_descr_get@ */
395   0,                                    /* @tp_descr_set@ */
396   0,                                    /* @tp_dictoffset@ */
397   0,                                    /* @tp_init@ */
398   PyType_GenericAlloc,                  /* @tp_alloc@ */
399   abstract_pynew,                       /* @tp_new@ */
400   0,                                    /* @tp_free@ */
401   0                                     /* @tp_is_gc@ */
402 };
403
404 static PyObject *sharesplit_pynew(PyTypeObject *ty,
405                                   PyObject *arg, PyObject *kw)
406 {
407   mp *sec = 0;
408   unsigned t;
409   grand *r = &rand_global;
410   mp *m = 0;
411   share_pyobj *s;
412   static const char *const kwlist[] =
413     { "threshold", "secret", "modulus", "rng", 0 };
414
415   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:new", KWLIST,
416                                    convuint, &t, convmp, &sec,
417                                    convmp, &m, convgrand, &r))
418     goto end;
419   if (!t) VALERR("threshold must be nonzero");
420   s = (share_pyobj *)ty->tp_alloc(ty, 0);
421   share_create(&s->s, t);
422   s->s.p = m;
423   share_mkshares(&s->s, r, sec);
424   mp_drop(sec);
425   return ((PyObject *)s);
426 end:
427   mp_drop(m);
428   mp_drop(sec);
429   return (0);
430 }
431
432 static PyObject *smeth_get(PyObject *me, PyObject *arg)
433 {
434   unsigned i;
435   PyObject *rc = 0;
436   if (!PyArg_ParseTuple(arg, "O&:get", convuint, &i)) goto end;
437   rc = mp_pywrap(share_get(SHARE_S(me), MP_NEW, i));
438 end:
439   return (rc);
440 }
441
442 static PyMethodDef sharesplit_pymethods[] = {
443 #define METHNAME(name) smeth_##name
444   METH  (get,           "S.get(I) -> SHARE")
445 #undef METHNAME
446   { 0 }
447 };
448
449 static PyTypeObject sharesplit_pytype_skel = {
450   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
451   "ShareSplit",                         /* @tp_name@ */
452   sizeof(share_pyobj),                  /* @tp_basicsize@ */
453   0,                                    /* @tp_itemsize@ */
454
455   share_pydealloc,                      /* @tp_dealloc@ */
456   0,                                    /* @tp_print@ */
457   0,                                    /* @tp_getattr@ */
458   0,                                    /* @tp_setattr@ */
459   0,                                    /* @tp_compare@ */
460   0,                                    /* @tp_repr@ */
461   0,                                    /* @tp_as_number@ */
462   0,                                    /* @tp_as_sequence@ */
463   0,                                    /* @tp_as_mapping@ */
464   0,                                    /* @tp_hash@ */
465   0,                                    /* @tp_call@ */
466   0,                                    /* @tp_str@ */
467   0,                                    /* @tp_getattro@ */
468   0,                                    /* @tp_setattro@ */
469   0,                                    /* @tp_as_buffer@ */
470   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
471     Py_TPFLAGS_BASETYPE,
472
473   /* @tp_doc@ */
474 "ShareSplit(THRESHOLD, SECRET, [modulus = ?], [rng = rand]):\n\
475   prime field secret sharing: split secret into shares.",
476
477   0,                                    /* @tp_traverse@ */
478   0,                                    /* @tp_clear@ */
479   0,                                    /* @tp_richcompare@ */
480   0,                                    /* @tp_weaklistoffset@ */
481   0,                                    /* @tp_iter@ */
482   0,                                    /* @tp_iternext@ */
483   sharesplit_pymethods,                 /* @tp_methods@ */
484   0,                                    /* @tp_members@ */
485   0,                                    /* @tp_getset@ */
486   0,                                    /* @tp_base@ */
487   0,                                    /* @tp_dict@ */
488   0,                                    /* @tp_descr_get@ */
489   0,                                    /* @tp_descr_set@ */
490   0,                                    /* @tp_dictoffset@ */
491   0,                                    /* @tp_init@ */
492   PyType_GenericAlloc,                  /* @tp_alloc@ */
493   sharesplit_pynew,                     /* @tp_new@ */
494   0,                                    /* @tp_free@ */
495   0                                     /* @tp_is_gc@ */
496 };
497
498 static PyObject *sharejoin_pynew(PyTypeObject *ty,
499                                  PyObject *arg, PyObject *kw)
500 {
501   unsigned t;
502   mp *m = 0;
503   share_pyobj *s;
504   static const char *const kwlist[] = { "threshold", "modulus", 0 };
505   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST,
506                                    convuint, &t, convmp, &m))
507     goto end;
508   if (!t) VALERR("threshold must be nonzero");
509   s = (share_pyobj *)ty->tp_alloc(ty, 0);
510   share_create(&s->s, t);
511   s->s.p = m;
512   return ((PyObject *)s);
513 end:
514   mp_drop(m);
515   return (0);
516 }
517
518 static PyObject *smeth_addedp(PyObject *me, PyObject *arg)
519 {
520   unsigned i;
521   if (!PyArg_ParseTuple(arg, "O&:addedp", convuint, &i)) goto end;
522   return (getbool(share_addedp(SHARE_S(me), i)));
523 end:
524   return (0);
525 }
526
527 static PyObject *smeth_add(PyObject *me, PyObject *arg)
528 {
529   unsigned i;
530   mp *s = 0;
531   PyObject *rc = 0;
532   if (!PyArg_ParseTuple(arg, "O&O&:add", convuint, &i, convmp, &s)) goto end;
533   if (MP_NEGP(s) || MP_CMP(s, >=, SHARE_S(me)->p))
534     VALERR("share out of range");
535   if (share_addedp(SHARE_S(me), i)) VALERR("this share already added");
536   if (SHARE_S(me)->i >= SHARE_S(me)->t) VALERR("enough shares already");
537   share_add(SHARE_S(me), i, s);
538   rc = PyInt_FromLong(SHARE_S(me)->t - SHARE_S(me)->i);
539 end:
540   mp_drop(s);
541   return (rc);
542 }
543
544 static PyObject *smeth_combine(PyObject *me, PyObject *arg)
545 {
546   PyObject *rc = 0;
547   if (!PyArg_ParseTuple(arg, ":combine")) goto end;
548   if (SHARE_S(me)->i < SHARE_S(me)->t) VALERR("not enough shares yet");
549   rc = mp_pywrap(share_combine(SHARE_S(me)));
550 end:
551   return (rc);
552 }
553
554 static PyMethodDef sharejoin_pymethods[] = {
555 #define METHNAME(name) smeth_##name
556   METH  (addedp,        "S.addedp(I) -> BOOL")
557   METH  (add,           "S.add(I, SHARE) -> REMAIN")
558   METH  (combine,       "S.combine() -> SECRET")
559 #undef METHNAME
560   { 0 }
561 };
562
563 static PyObject *sget_remain(PyObject *me, void *hunoz)
564   { return (PyInt_FromLong(SHARE_S(me)->t - SHARE_S(me)->i)); }
565
566 static PyGetSetDef sharejoin_pygetset[]= {
567 #define GETSETNAME(op, name) s##op##_##name
568   GET   (remain,        "S.remain -> REMAIN")
569 #undef GETSETNAME
570   { 0 }
571 };
572
573 static PyTypeObject sharejoin_pytype_skel = {
574   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
575   "ShareJoin",                          /* @tp_name@ */
576   sizeof(share_pyobj),                  /* @tp_basicsize@ */
577   0,                                    /* @tp_itemsize@ */
578
579   share_pydealloc,                      /* @tp_dealloc@ */
580   0,                                    /* @tp_print@ */
581   0,                                    /* @tp_getattr@ */
582   0,                                    /* @tp_setattr@ */
583   0,                                    /* @tp_compare@ */
584   0,                                    /* @tp_repr@ */
585   0,                                    /* @tp_as_number@ */
586   0,                                    /* @tp_as_sequence@ */
587   0,                                    /* @tp_as_mapping@ */
588   0,                                    /* @tp_hash@ */
589   0,                                    /* @tp_call@ */
590   0,                                    /* @tp_str@ */
591   0,                                    /* @tp_getattro@ */
592   0,                                    /* @tp_setattro@ */
593   0,                                    /* @tp_as_buffer@ */
594   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
595     Py_TPFLAGS_BASETYPE,
596
597   /* @tp_doc@ */
598 "ShareJoin(THRESHOLD, MODULUS): prime field secret sharing:\n\
599   join shares to recover secret.",
600
601   0,                                    /* @tp_traverse@ */
602   0,                                    /* @tp_clear@ */
603   0,                                    /* @tp_richcompare@ */
604   0,                                    /* @tp_weaklistoffset@ */
605   0,                                    /* @tp_iter@ */
606   0,                                    /* @tp_iternext@ */
607   sharejoin_pymethods,                  /* @tp_methods@ */
608   0,                                    /* @tp_members@ */
609   sharejoin_pygetset,                   /* @tp_getset@ */
610   0,                                    /* @tp_base@ */
611   0,                                    /* @tp_dict@ */
612   0,                                    /* @tp_descr_get@ */
613   0,                                    /* @tp_descr_set@ */
614   0,                                    /* @tp_dictoffset@ */
615   0,                                    /* @tp_init@ */
616   PyType_GenericAlloc,                  /* @tp_alloc@ */
617   sharejoin_pynew,                      /* @tp_new@ */
618   0,                                    /* @tp_free@ */
619   0                                     /* @tp_is_gc@ */
620 };
621
622 /*----- Global stuff ------------------------------------------------------*/
623
624 void share_pyinit(void)
625 {
626   INITTYPE(gfshare, root);
627   INITTYPE(gfsharesplit, gfshare);
628   INITTYPE(gfsharejoin, gfshare);
629   INITTYPE(share, root);
630   INITTYPE(sharesplit, share);
631   INITTYPE(sharejoin, share);
632 }
633
634 void share_pyinsert(PyObject *mod)
635 {
636   INSERT("GFShare", gfshare_pytype);
637   INSERT("GFShareSplit", gfsharesplit_pytype);
638   INSERT("GFShareJoin", gfsharejoin_pytype);
639   INSERT("Share", share_pytype);
640   INSERT("ShareSplit", sharesplit_pytype);
641   INSERT("ShareJoin", sharejoin_pytype);
642 }
643
644 /*----- That's all, folks -------------------------------------------------*/