chiark / gitweb /
debian/: Use `dh_python2' for packaging.
[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 "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   char *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   char *kwlist[] = { "threshold", "secret", "modulus", "rng", 0 };
413   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:new", kwlist,
414                                    convuint, &t, convmp, &sec,
415                                    convmp, &m, convgrand, &r))
416     goto end;
417   if (!t) VALERR("threshold must be nonzero");
418   s = (share_pyobj *)ty->tp_alloc(ty, 0);
419   share_create(&s->s, t);
420   s->s.p = m;
421   share_mkshares(&s->s, r, sec);
422   mp_drop(sec);
423   return ((PyObject *)s);
424 end:
425   mp_drop(m);
426   mp_drop(sec);
427   return (0);
428 }
429
430 static PyObject *smeth_get(PyObject *me, PyObject *arg)
431 {
432   unsigned i;
433   PyObject *rc = 0;
434   if (!PyArg_ParseTuple(arg, "O&:get", convuint, &i)) goto end;
435   rc = mp_pywrap(share_get(SHARE_S(me), MP_NEW, i));
436 end:
437   return (rc);
438 }
439
440 static PyMethodDef sharesplit_pymethods[] = {
441 #define METHNAME(name) smeth_##name
442   METH  (get,           "S.get(I) -> SHARE")
443 #undef METHNAME
444   { 0 }
445 };
446
447 static PyTypeObject sharesplit_pytype_skel = {
448   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
449   "ShareSplit",                         /* @tp_name@ */
450   sizeof(share_pyobj),                  /* @tp_basicsize@ */
451   0,                                    /* @tp_itemsize@ */
452
453   share_pydealloc,                      /* @tp_dealloc@ */
454   0,                                    /* @tp_print@ */
455   0,                                    /* @tp_getattr@ */
456   0,                                    /* @tp_setattr@ */
457   0,                                    /* @tp_compare@ */
458   0,                                    /* @tp_repr@ */
459   0,                                    /* @tp_as_number@ */
460   0,                                    /* @tp_as_sequence@ */
461   0,                                    /* @tp_as_mapping@ */
462   0,                                    /* @tp_hash@ */
463   0,                                    /* @tp_call@ */
464   0,                                    /* @tp_str@ */
465   0,                                    /* @tp_getattro@ */
466   0,                                    /* @tp_setattro@ */
467   0,                                    /* @tp_as_buffer@ */
468   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
469     Py_TPFLAGS_BASETYPE,
470
471   /* @tp_doc@ */
472 "ShareSplit(THRESHOLD, SECRET, [modulus = ?], [rng = rand]):\n\
473   prime field secret sharing: split secret into shares.",
474
475   0,                                    /* @tp_traverse@ */
476   0,                                    /* @tp_clear@ */
477   0,                                    /* @tp_richcompare@ */
478   0,                                    /* @tp_weaklistoffset@ */
479   0,                                    /* @tp_iter@ */
480   0,                                    /* @tp_iternext@ */
481   sharesplit_pymethods,                 /* @tp_methods@ */
482   0,                                    /* @tp_members@ */
483   0,                                    /* @tp_getset@ */
484   0,                                    /* @tp_base@ */
485   0,                                    /* @tp_dict@ */
486   0,                                    /* @tp_descr_get@ */
487   0,                                    /* @tp_descr_set@ */
488   0,                                    /* @tp_dictoffset@ */
489   0,                                    /* @tp_init@ */
490   PyType_GenericAlloc,                  /* @tp_alloc@ */
491   sharesplit_pynew,                     /* @tp_new@ */
492   0,                                    /* @tp_free@ */
493   0                                     /* @tp_is_gc@ */
494 };
495
496 static PyObject *sharejoin_pynew(PyTypeObject *ty,
497                                  PyObject *arg, PyObject *kw)
498 {
499   unsigned t;
500   mp *m = 0;
501   share_pyobj *s;
502   char *kwlist[] = { "threshold", "modulus", 0 };
503   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", kwlist,
504                                    convuint, &t, convmp, &m))
505     goto end;
506   if (!t) VALERR("threshold must be nonzero");
507   s = (share_pyobj *)ty->tp_alloc(ty, 0);
508   share_create(&s->s, t);
509   s->s.p = m;
510   return ((PyObject *)s);
511 end:
512   mp_drop(m);
513   return (0);
514 }
515
516 static PyObject *smeth_addedp(PyObject *me, PyObject *arg)
517 {
518   unsigned i;
519   if (!PyArg_ParseTuple(arg, "O&:addedp", convuint, &i)) goto end;
520   return (getbool(share_addedp(SHARE_S(me), i)));
521 end:
522   return (0);
523 }
524
525 static PyObject *smeth_add(PyObject *me, PyObject *arg)
526 {
527   unsigned i;
528   mp *s = 0;
529   PyObject *rc = 0;
530   if (!PyArg_ParseTuple(arg, "O&O&:add", convuint, &i, convmp, &s)) goto end;
531   if (MP_NEGP(s) || MP_CMP(s, >=, SHARE_S(me)->p))
532     VALERR("share out of range");
533   if (share_addedp(SHARE_S(me), i)) VALERR("this share already added");
534   if (SHARE_S(me)->i >= SHARE_S(me)->t) VALERR("enough shares already");
535   share_add(SHARE_S(me), i, s);
536   rc = PyInt_FromLong(SHARE_S(me)->t - SHARE_S(me)->i);
537 end:
538   mp_drop(s);
539   return (rc);
540 }
541
542 static PyObject *smeth_combine(PyObject *me, PyObject *arg)
543 {
544   PyObject *rc = 0;
545   if (!PyArg_ParseTuple(arg, ":combine")) goto end;
546   if (SHARE_S(me)->i < SHARE_S(me)->t) VALERR("not enough shares yet");
547   rc = mp_pywrap(share_combine(SHARE_S(me)));
548 end:
549   return (rc);
550 }
551
552 static PyMethodDef sharejoin_pymethods[] = {
553 #define METHNAME(name) smeth_##name
554   METH  (addedp,        "S.addedp(I) -> BOOL")
555   METH  (add,           "S.add(I, SHARE) -> REMAIN")
556   METH  (combine,       "S.combine() -> SECRET")
557 #undef METHNAME
558   { 0 }
559 };
560
561 static PyObject *sget_remain(PyObject *me, void *hunoz)
562   { return (PyInt_FromLong(SHARE_S(me)->t - SHARE_S(me)->i)); }
563
564 static PyGetSetDef sharejoin_pygetset[]= {
565 #define GETSETNAME(op, name) s##op##_##name
566   GET   (remain,        "S.remain -> REMAIN")
567 #undef GETSETNAME
568   { 0 }
569 };
570
571 static PyTypeObject sharejoin_pytype_skel = {
572   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
573   "ShareJoin",                          /* @tp_name@ */
574   sizeof(share_pyobj),                  /* @tp_basicsize@ */
575   0,                                    /* @tp_itemsize@ */
576
577   share_pydealloc,                      /* @tp_dealloc@ */
578   0,                                    /* @tp_print@ */
579   0,                                    /* @tp_getattr@ */
580   0,                                    /* @tp_setattr@ */
581   0,                                    /* @tp_compare@ */
582   0,                                    /* @tp_repr@ */
583   0,                                    /* @tp_as_number@ */
584   0,                                    /* @tp_as_sequence@ */
585   0,                                    /* @tp_as_mapping@ */
586   0,                                    /* @tp_hash@ */
587   0,                                    /* @tp_call@ */
588   0,                                    /* @tp_str@ */
589   0,                                    /* @tp_getattro@ */
590   0,                                    /* @tp_setattro@ */
591   0,                                    /* @tp_as_buffer@ */
592   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
593     Py_TPFLAGS_BASETYPE,
594
595   /* @tp_doc@ */
596 "ShareJoin(THRESHOLD, MODULUS): prime field secret sharing:\n\
597   join shares to recover secret.",
598
599   0,                                    /* @tp_traverse@ */
600   0,                                    /* @tp_clear@ */
601   0,                                    /* @tp_richcompare@ */
602   0,                                    /* @tp_weaklistoffset@ */
603   0,                                    /* @tp_iter@ */
604   0,                                    /* @tp_iternext@ */
605   sharejoin_pymethods,                  /* @tp_methods@ */
606   0,                                    /* @tp_members@ */
607   sharejoin_pygetset,                   /* @tp_getset@ */
608   0,                                    /* @tp_base@ */
609   0,                                    /* @tp_dict@ */
610   0,                                    /* @tp_descr_get@ */
611   0,                                    /* @tp_descr_set@ */
612   0,                                    /* @tp_dictoffset@ */
613   0,                                    /* @tp_init@ */
614   PyType_GenericAlloc,                  /* @tp_alloc@ */
615   sharejoin_pynew,                      /* @tp_new@ */
616   0,                                    /* @tp_free@ */
617   0                                     /* @tp_is_gc@ */
618 };
619
620 /*----- Global stuff ------------------------------------------------------*/
621
622 void share_pyinit(void)
623 {
624   INITTYPE(gfshare, root);
625   INITTYPE(gfsharesplit, gfshare);
626   INITTYPE(gfsharejoin, gfshare);
627   INITTYPE(share, root);
628   INITTYPE(sharesplit, share);
629   INITTYPE(sharejoin, share);
630 }
631
632 void share_pyinsert(PyObject *mod)
633 {
634   INSERT("GFShare", gfshare_pytype);
635   INSERT("GFShareSplit", gfsharesplit_pytype);
636   INSERT("GFShareJoin", gfsharejoin_pytype);
637   INSERT("Share", share_pytype);
638   INSERT("ShareSplit", sharesplit_pytype);
639   INSERT("ShareJoin", sharejoin_pytype);
640 }
641
642 /*----- That's all, folks -------------------------------------------------*/