chiark / gitweb /
Checkin, Debianized and more or less complete.
[catacomb-python] / share.c
1 /* -*-c-*-
2  *
3  * $Id$
4  *
5  * Secret sharing
6  *
7  * (c) 2005 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of the Python interface to Catacomb.
13  *
14  * Catacomb/Python is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  * 
19  * Catacomb/Python is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with Catacomb/Python; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Header files ------------------------------------------------------*/
30
31 #include "catacomb-python.h"
32
33 /*----- GF(2^8)-based secret-sharing --------------------------------------*/
34
35 typedef struct gfshare_pyobj {
36   PyObject_HEAD
37   gfshare s;
38 } gfshare_pyobj;
39
40 static PyTypeObject
41   *gfshare_pytype, *gfsharesplit_pytype, *gfsharejoin_pytype;
42 #define GFSHARE_PYCHECK(o) PyObject_TypeCheck((o), gfshare_pytype)
43 #define GFSHARESPLIT_PYCHECK(o) PyObject_TypeCheck((o), gfsharesplit_pytype)
44 #define GFSHAREJOIN_PYCHECK(o) PyObject_TypeCheck((o), gfsharejoin_pytype)
45 #define GFSHARE_S(o) (&((gfshare_pyobj *)(o))->s)
46
47 static void gfshare_pydealloc(PyObject *me)
48 {
49   gfshare_destroy(GFSHARE_S(me));
50   FREEOBJ(me);
51 }
52
53 static PyObject *gfsget_threshold(PyObject *me, void *hunoz)
54   { return (PyInt_FromLong(GFSHARE_S(me)->t)); }
55 static PyObject *gfsget_size(PyObject *me, void *hunoz)
56   { return (PyInt_FromLong(GFSHARE_S(me)->sz)); }
57
58 static PyGetSetDef gfshare_pygetset[]= {
59 #define GETSETNAME(op, name) gfs##op##_##name
60   GET   (threshold,     "S.threshold -> THRESHOLD")
61   GET   (size,          "S.size -> SECRETSZ")
62 #undef GETSETNAME
63   { 0 }
64 };
65
66 static PyTypeObject gfshare_pytype_skel = {
67   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
68   "catacomb.GFShare",                   /* @tp_name@ */
69   sizeof(gfshare_pyobj),                /* @tp_basicsize@ */
70   0,                                    /* @tp_itemsize@ */
71
72   gfshare_pydealloc,                    /* @tp_dealloc@ */
73   0,                                    /* @tp_print@ */
74   0,                                    /* @tp_getattr@ */
75   0,                                    /* @tp_setattr@ */
76   0,                                    /* @tp_compare@ */
77   0,                                    /* @tp_repr@ */
78   0,                                    /* @tp_as_number@ */
79   0,                                    /* @tp_as_sequence@ */
80   0,                                    /* @tp_as_mapping@ */
81   0,                                    /* @tp_hash@ */
82   0,                                    /* @tp_call@ */
83   0,                                    /* @tp_str@ */
84   0,                                    /* @tp_getattro@ */
85   0,                                    /* @tp_setattro@ */
86   0,                                    /* @tp_as_buffer@ */
87   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
88     Py_TPFLAGS_BASETYPE,
89
90   /* @tp_doc@ */
91 "Binary-field secret sharing base class.",
92
93   0,                                    /* @tp_traverse@ */
94   0,                                    /* @tp_clear@ */
95   0,                                    /* @tp_richcompare@ */
96   0,                                    /* @tp_weaklistoffset@ */
97   0,                                    /* @tp_iter@ */
98   0,                                    /* @tp_iternexr@ */
99   0,                                    /* @tp_methods@ */
100   0,                                    /* @tp_members@ */
101   gfshare_pygetset,                     /* @tp_getset@ */
102   0,                                    /* @tp_base@ */
103   0,                                    /* @tp_dict@ */
104   0,                                    /* @tp_descr_get@ */
105   0,                                    /* @tp_descr_set@ */
106   0,                                    /* @tp_dictoffset@ */
107   0,                                    /* @tp_init@ */
108   PyType_GenericAlloc,                  /* @tp_alloc@ */
109   abstract_pynew,                       /* @tp_new@ */
110   0,                                    /* @tp_free@ */
111   0                                     /* @tp_is_gc@ */
112 };
113
114 static PyObject *gfsharesplit_pynew(PyTypeObject *ty,
115                                     PyObject *arg, PyObject *kw)
116 {
117   char *p;
118   int n;
119   unsigned t;
120   grand *r = &rand_global;
121   gfshare_pyobj *s;
122   char *kwlist[] = { "threshold", "secret", "rng", 0 };
123   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&s#|O&:new", kwlist,
124                                    convuint, &t, &p, &n, convgrand, &r))
125     goto end;
126   if (!t || t > 255) VALERR("threshold must be nonzero and < 256");
127   s = (gfshare_pyobj *)ty->tp_alloc(ty, 0);
128   gfshare_create(&s->s, t, n);
129   gfshare_mkshares(&s->s, r, p);
130   return ((PyObject *)s);
131 end:
132   return (0);
133 }
134
135 static PyObject *gfsmeth_get(PyObject *me, PyObject *arg)
136 {
137   unsigned i;
138   PyObject *rc = 0;
139   if (!PyArg_ParseTuple(arg, "O&:get", convuint, &i)) goto end;
140   if (i >= 255) VALERR("index must be < 255");
141   rc = bytestring_pywrap(0, GFSHARE_S(me)->sz);
142   gfshare_get(GFSHARE_S(me), i, PyString_AS_STRING(rc));
143 end:
144   return (rc);
145 }
146
147 static PyMethodDef gfsharesplit_pymethods[] = {
148 #define METHNAME(name) gfsmeth_##name
149   METH  (get,           "S.get(I) -> SHARE")
150 #undef METHNAME
151   { 0 }
152 };
153
154 static PyTypeObject gfsharesplit_pytype_skel = {
155   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
156   "catacomb.GFShareSplit",              /* @tp_name@ */
157   sizeof(gfshare_pyobj),                /* @tp_basicsize@ */
158   0,                                    /* @tp_itemsize@ */
159
160   gfshare_pydealloc,                    /* @tp_dealloc@ */
161   0,                                    /* @tp_print@ */
162   0,                                    /* @tp_getattr@ */
163   0,                                    /* @tp_setattr@ */
164   0,                                    /* @tp_compare@ */
165   0,                                    /* @tp_repr@ */
166   0,                                    /* @tp_as_number@ */
167   0,                                    /* @tp_as_sequence@ */
168   0,                                    /* @tp_as_mapping@ */
169   0,                                    /* @tp_hash@ */
170   0,                                    /* @tp_call@ */
171   0,                                    /* @tp_str@ */
172   0,                                    /* @tp_getattro@ */
173   0,                                    /* @tp_setattro@ */
174   0,                                    /* @tp_as_buffer@ */
175   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
176     Py_TPFLAGS_BASETYPE,
177
178   /* @tp_doc@ */
179 "Binary field secret sharing: split secret into shares.",
180
181   0,                                    /* @tp_traverse@ */
182   0,                                    /* @tp_clear@ */
183   0,                                    /* @tp_richcompare@ */
184   0,                                    /* @tp_weaklistoffset@ */
185   0,                                    /* @tp_iter@ */
186   0,                                    /* @tp_iternexr@ */
187   gfsharesplit_pymethods,               /* @tp_methods@ */
188   0,                                    /* @tp_members@ */
189   0,                                    /* @tp_getset@ */
190   0,                                    /* @tp_base@ */
191   0,                                    /* @tp_dict@ */
192   0,                                    /* @tp_descr_get@ */
193   0,                                    /* @tp_descr_set@ */
194   0,                                    /* @tp_dictoffset@ */
195   0,                                    /* @tp_init@ */
196   PyType_GenericAlloc,                  /* @tp_alloc@ */
197   gfsharesplit_pynew,                   /* @tp_new@ */
198   0,                                    /* @tp_free@ */
199   0                                     /* @tp_is_gc@ */
200 };
201
202 static PyObject *gfsharejoin_pynew(PyTypeObject *ty,
203                                    PyObject *arg, PyObject *kw)
204 {
205   unsigned t, sz;
206   gfshare_pyobj *s;
207   char *kwlist[] = { "threshold", "size", 0 };
208   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", kwlist,
209                                    convuint, &t, convuint, &sz))
210     goto end;
211   if (!t || t > 255) VALERR("threshold must be nonzero and < 256");
212   s = (gfshare_pyobj *)ty->tp_alloc(ty, 0);
213   gfshare_create(&s->s, t, sz);
214   return ((PyObject *)s);
215 end:
216   return (0);
217 }
218
219 static PyObject *gfsmeth_addedp(PyObject *me, PyObject *arg)
220 {
221   unsigned i;
222   if (!PyArg_ParseTuple(arg, "O&:addedp", convuint, &i)) goto end;
223   if (i > 254) VALERR("index must be < 255");
224   return (getbool(gfshare_addedp(GFSHARE_S(me), i)));
225 end:
226   return (0);
227 }
228
229 static PyObject *gfsmeth_add(PyObject *me, PyObject *arg)
230 {
231   unsigned i;
232   char *p;
233   int n;
234   if (!PyArg_ParseTuple(arg, "O&s#:add", convuint, &i, &p, &n)) goto end;
235   if (i > 254) VALERR("index must be < 255");
236   if (n != GFSHARE_S(me)->sz) VALERR("bad share size");
237   if (gfshare_addedp(GFSHARE_S(me), i)) VALERR("this share already added");
238   if (GFSHARE_S(me)->i >= GFSHARE_S(me)->t) VALERR("enough shares already");
239   gfshare_add(GFSHARE_S(me), i, p);
240   return (PyInt_FromLong(GFSHARE_S(me)->t - GFSHARE_S(me)->i));
241 end:
242   return (0);
243 }
244
245 static PyObject *gfsmeth_combine(PyObject *me, PyObject *arg)
246 {
247   PyObject *rc = 0;
248   if (!PyArg_ParseTuple(arg, ":combine")) goto end;
249   if (GFSHARE_S(me)->i < GFSHARE_S(me)->t) VALERR("not enough shares yet");
250   rc = bytestring_pywrap(0, GFSHARE_S(me)->sz);
251   gfshare_combine(GFSHARE_S(me), PyString_AS_STRING(rc));
252 end:
253   return (rc);
254 }
255
256 static PyMethodDef gfsharejoin_pymethods[] = {
257 #define METHNAME(name) gfsmeth_##name
258   METH  (addedp,        "S.addedp(I) -> BOOL")
259   METH  (add,           "S.add(I, SHARE) -> REMAIN")
260   METH  (combine,       "S.combine() -> SECRET")
261 #undef METHNAME
262   { 0 }
263 };
264
265 static PyObject *gfsget_remain(PyObject *me, void *hunoz)
266   { return (PyInt_FromLong(GFSHARE_S(me)->t - GFSHARE_S(me)->i)); }
267
268 static PyGetSetDef gfsharejoin_pygetset[]= {
269 #define GETSETNAME(op, name) gfs##op##_##name
270   GET   (remain,        "S.remain -> REMAIN")
271 #undef GETSETNAME
272   { 0 }
273 };
274
275 static PyTypeObject gfsharejoin_pytype_skel = {
276   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
277   "catacomb.GFShareJoin",               /* @tp_name@ */
278   sizeof(gfshare_pyobj),                /* @tp_basicsize@ */
279   0,                                    /* @tp_itemsize@ */
280
281   gfshare_pydealloc,                    /* @tp_dealloc@ */
282   0,                                    /* @tp_print@ */
283   0,                                    /* @tp_getattr@ */
284   0,                                    /* @tp_setattr@ */
285   0,                                    /* @tp_compare@ */
286   0,                                    /* @tp_repr@ */
287   0,                                    /* @tp_as_number@ */
288   0,                                    /* @tp_as_sequence@ */
289   0,                                    /* @tp_as_mapping@ */
290   0,                                    /* @tp_hash@ */
291   0,                                    /* @tp_call@ */
292   0,                                    /* @tp_str@ */
293   0,                                    /* @tp_getattro@ */
294   0,                                    /* @tp_setattro@ */
295   0,                                    /* @tp_as_buffer@ */
296   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
297     Py_TPFLAGS_BASETYPE,
298
299   /* @tp_doc@ */
300 "Binary field secret sharing: 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_iternexr@ */
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   "catacomb.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_iternexr@ */
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&: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   "catacomb.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 "Prime field secret sharing: split secret into shares.",
473
474   0,                                    /* @tp_traverse@ */
475   0,                                    /* @tp_clear@ */
476   0,                                    /* @tp_richcompare@ */
477   0,                                    /* @tp_weaklistoffset@ */
478   0,                                    /* @tp_iter@ */
479   0,                                    /* @tp_iternexr@ */
480   sharesplit_pymethods,                 /* @tp_methods@ */
481   0,                                    /* @tp_members@ */
482   0,                                    /* @tp_getset@ */
483   0,                                    /* @tp_base@ */
484   0,                                    /* @tp_dict@ */
485   0,                                    /* @tp_descr_get@ */
486   0,                                    /* @tp_descr_set@ */
487   0,                                    /* @tp_dictoffset@ */
488   0,                                    /* @tp_init@ */
489   PyType_GenericAlloc,                  /* @tp_alloc@ */
490   sharesplit_pynew,                     /* @tp_new@ */
491   0,                                    /* @tp_free@ */
492   0                                     /* @tp_is_gc@ */
493 };
494
495 static PyObject *sharejoin_pynew(PyTypeObject *ty,
496                                  PyObject *arg, PyObject *kw)
497 {
498   unsigned t;
499   mp *m = 0;
500   share_pyobj *s;
501   char *kwlist[] = { "threshold", "modulus", 0 };
502   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", kwlist,
503                                    convuint, &t, convmp, &m))
504     goto end;
505   if (!t) VALERR("threshold must be nonzero");
506   s = (share_pyobj *)ty->tp_alloc(ty, 0);
507   share_create(&s->s, t);
508   s->s.p = m;
509   return ((PyObject *)s);
510 end:
511   mp_drop(m);
512   return (0);
513 }
514
515 static PyObject *smeth_addedp(PyObject *me, PyObject *arg)
516 {
517   unsigned i;
518   if (!PyArg_ParseTuple(arg, "O&:addedp", convuint, &i)) goto end;
519   return (getbool(share_addedp(SHARE_S(me), i)));
520 end:
521   return (0);
522 }
523
524 static PyObject *smeth_add(PyObject *me, PyObject *arg)
525 {
526   unsigned i;
527   mp *s = 0;
528   PyObject *rc = 0;
529   if (!PyArg_ParseTuple(arg, "O&O&:add", convuint, &i, convmp, &s)) goto end;
530   if (MP_NEGP(s) || MP_CMP(s, >=, SHARE_S(me)->p))
531     VALERR("share out of range");
532   if (share_addedp(SHARE_S(me), i)) VALERR("this share already added");
533   if (SHARE_S(me)->i >= SHARE_S(me)->t) VALERR("enough shares already");
534   share_add(SHARE_S(me), i, s);
535   rc = PyInt_FromLong(SHARE_S(me)->t - SHARE_S(me)->i);
536 end:
537   mp_drop(s);
538   return (rc);
539 }
540
541 static PyObject *smeth_combine(PyObject *me, PyObject *arg)
542 {
543   PyObject *rc = 0;
544   if (!PyArg_ParseTuple(arg, ":combine")) goto end;
545   if (SHARE_S(me)->i < SHARE_S(me)->t) VALERR("not enough shares yet");
546   rc = mp_pywrap(share_combine(SHARE_S(me)));
547 end:
548   return (rc);
549 }
550
551 static PyMethodDef sharejoin_pymethods[] = {
552 #define METHNAME(name) smeth_##name
553   METH  (addedp,        "S.addedp(I) -> BOOL")
554   METH  (add,           "S.add(I, SHARE) -> REMAIN")
555   METH  (combine,       "S.combine() -> SECRET")
556 #undef METHNAME
557   { 0 }
558 };
559
560 static PyObject *sget_remain(PyObject *me, void *hunoz)
561   { return (PyInt_FromLong(SHARE_S(me)->t - SHARE_S(me)->i)); }
562
563 static PyGetSetDef sharejoin_pygetset[]= {
564 #define GETSETNAME(op, name) s##op##_##name
565   GET   (remain,        "S.remain -> REMAIN")
566 #undef GETSETNAME
567   { 0 }
568 };
569
570 static PyTypeObject sharejoin_pytype_skel = {
571   PyObject_HEAD_INIT(&PyType_Type) 0,   /* Header */
572   "catacomb.ShareJoin",                 /* @tp_name@ */
573   sizeof(share_pyobj),                  /* @tp_basicsize@ */
574   0,                                    /* @tp_itemsize@ */
575
576   share_pydealloc,                      /* @tp_dealloc@ */
577   0,                                    /* @tp_print@ */
578   0,                                    /* @tp_getattr@ */
579   0,                                    /* @tp_setattr@ */
580   0,                                    /* @tp_compare@ */
581   0,                                    /* @tp_repr@ */
582   0,                                    /* @tp_as_number@ */
583   0,                                    /* @tp_as_sequence@ */
584   0,                                    /* @tp_as_mapping@ */
585   0,                                    /* @tp_hash@ */
586   0,                                    /* @tp_call@ */
587   0,                                    /* @tp_str@ */
588   0,                                    /* @tp_getattro@ */
589   0,                                    /* @tp_setattro@ */
590   0,                                    /* @tp_as_buffer@ */
591   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
592     Py_TPFLAGS_BASETYPE,
593
594   /* @tp_doc@ */
595 "Prime field secret sharing: join shares to recover secret.",
596
597   0,                                    /* @tp_traverse@ */
598   0,                                    /* @tp_clear@ */
599   0,                                    /* @tp_richcompare@ */
600   0,                                    /* @tp_weaklistoffset@ */
601   0,                                    /* @tp_iter@ */
602   0,                                    /* @tp_iternexr@ */
603   sharejoin_pymethods,                  /* @tp_methods@ */
604   0,                                    /* @tp_members@ */
605   sharejoin_pygetset,                   /* @tp_getset@ */
606   0,                                    /* @tp_base@ */
607   0,                                    /* @tp_dict@ */
608   0,                                    /* @tp_descr_get@ */
609   0,                                    /* @tp_descr_set@ */
610   0,                                    /* @tp_dictoffset@ */
611   0,                                    /* @tp_init@ */
612   PyType_GenericAlloc,                  /* @tp_alloc@ */
613   sharejoin_pynew,                      /* @tp_new@ */
614   0,                                    /* @tp_free@ */
615   0                                     /* @tp_is_gc@ */
616 };
617
618 /*----- Global stuff ------------------------------------------------------*/
619
620 void share_pyinit(void)
621 {
622   INITTYPE(gfshare, root);
623   INITTYPE(gfsharesplit, gfshare);
624   INITTYPE(gfsharejoin, gfshare);
625   INITTYPE(share, root);
626   INITTYPE(sharesplit, share);
627   INITTYPE(sharejoin, share);
628 }
629
630 void share_pyinsert(PyObject *mod)
631 {
632   INSERT("GFShare", gfshare_pytype);
633   INSERT("GFShareSplit", gfsharesplit_pytype);
634   INSERT("GFShareJoin", gfsharejoin_pytype);
635   INSERT("Share", share_pytype);
636   INSERT("ShareSplit", sharesplit_pytype);
637   INSERT("ShareJoin", sharejoin_pytype);
638 }
639
640 /*----- That's all, folks -------------------------------------------------*/