chiark / gitweb /
key.c: Factor out populating a `KeyDataStructured' from a mapping.
[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 const 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 const PyTypeObject gfshare_pytype_skel = {
65   PyVarObject_HEAD_INIT(0, 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   PYGETSET(gfshare),                    /* @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   struct bin in;
116   unsigned t;
117   grand *r = &rand_global;
118   gfshare_pyobj *s;
119   static const char *const kwlist[] = { "threshold", "secret", "rng", 0 };
120   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&:new", KWLIST,
121                                    convuint, &t, convbin, &in,
122                                    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, in.sz);
127   gfshare_mkshares(&s->s, r, in.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, BIN_PTR(rc));
141 end:
142   return (rc);
143 }
144
145 static const 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 const PyTypeObject gfsharesplit_pytype_skel = {
153   PyVarObject_HEAD_INIT(0, 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   PYMETHODS(gfsharesplit),              /* @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   struct bin s;
232   if (!PyArg_ParseTuple(arg, "O&O&:add", convuint, &i, convbin, &s))
233     goto end;
234   if (i > 254) VALERR("index must be < 255");
235   if (s.sz != 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, s.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)
245 {
246   PyObject *rc = 0;
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), BIN_PTR(rc));
250 end:
251   return (rc);
252 }
253
254 static const 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   NAMETH(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 const 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 const PyTypeObject gfsharejoin_pytype_skel = {
274   PyVarObject_HEAD_INIT(0, 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   "GFShareJoin(THRESHOLD, SIZE): binary field sharing:\n"
299   "  join shares to recover secret.",
300
301   0,                                    /* @tp_traverse@ */
302   0,                                    /* @tp_clear@ */
303   0,                                    /* @tp_richcompare@ */
304   0,                                    /* @tp_weaklistoffset@ */
305   0,                                    /* @tp_iter@ */
306   0,                                    /* @tp_iternext@ */
307   PYMETHODS(gfsharejoin),               /* @tp_methods@ */
308   0,                                    /* @tp_members@ */
309   PYGETSET(gfsharejoin),                /* @tp_getset@ */
310   0,                                    /* @tp_base@ */
311   0,                                    /* @tp_dict@ */
312   0,                                    /* @tp_descr_get@ */
313   0,                                    /* @tp_descr_set@ */
314   0,                                    /* @tp_dictoffset@ */
315   0,                                    /* @tp_init@ */
316   PyType_GenericAlloc,                  /* @tp_alloc@ */
317   gfsharejoin_pynew,                    /* @tp_new@ */
318   0,                                    /* @tp_free@ */
319   0                                     /* @tp_is_gc@ */
320 };
321
322 /*----- Prime-field secret-sharing ----------------------------------------*/
323
324 typedef struct share_pyobj {
325   PyObject_HEAD
326   share s;
327 } share_pyobj;
328
329 static PyTypeObject
330   *share_pytype, *sharesplit_pytype, *sharejoin_pytype;
331 #define SHARE_PYCHECK(o) PyObject_TypeCheck((o), share_pytype)
332 #define SHARESPLIT_PYCHECK(o) PyObject_TypeCheck((o), sharesplit_pytype)
333 #define SHAREJOIN_PYCHECK(o) PyObject_TypeCheck((o), sharejoin_pytype)
334 #define SHARE_S(o) (&((share_pyobj *)(o))->s)
335
336 static void share_pydealloc(PyObject *me)
337 {
338   share_destroy(SHARE_S(me));
339   FREEOBJ(me);
340 }
341
342 static PyObject *sget_threshold(PyObject *me, void *hunoz)
343   { return (PyInt_FromLong(SHARE_S(me)->t)); }
344 static PyObject *sget_modulus(PyObject *me, void *hunoz)
345   { return (mp_pywrap(SHARE_S(me)->p)); }
346
347 static const PyGetSetDef share_pygetset[]= {
348 #define GETSETNAME(op, name) s##op##_##name
349   GET   (threshold,     "S.threshold -> THRESHOLD")
350   GET   (modulus,       "S.modulus -> MODULUS")
351 #undef GETSETNAME
352   { 0 }
353 };
354
355 static const PyTypeObject share_pytype_skel = {
356   PyVarObject_HEAD_INIT(0, 0)           /* Header */
357   "Share",                              /* @tp_name@ */
358   sizeof(share_pyobj),                  /* @tp_basicsize@ */
359   0,                                    /* @tp_itemsize@ */
360
361   share_pydealloc,                      /* @tp_dealloc@ */
362   0,                                    /* @tp_print@ */
363   0,                                    /* @tp_getattr@ */
364   0,                                    /* @tp_setattr@ */
365   0,                                    /* @tp_compare@ */
366   0,                                    /* @tp_repr@ */
367   0,                                    /* @tp_as_number@ */
368   0,                                    /* @tp_as_sequence@ */
369   0,                                    /* @tp_as_mapping@ */
370   0,                                    /* @tp_hash@ */
371   0,                                    /* @tp_call@ */
372   0,                                    /* @tp_str@ */
373   0,                                    /* @tp_getattro@ */
374   0,                                    /* @tp_setattro@ */
375   0,                                    /* @tp_as_buffer@ */
376   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
377     Py_TPFLAGS_BASETYPE,
378
379   /* @tp_doc@ */
380   "Prime-field secret sharing base class.",
381
382   0,                                    /* @tp_traverse@ */
383   0,                                    /* @tp_clear@ */
384   0,                                    /* @tp_richcompare@ */
385   0,                                    /* @tp_weaklistoffset@ */
386   0,                                    /* @tp_iter@ */
387   0,                                    /* @tp_iternext@ */
388   0,                                    /* @tp_methods@ */
389   0,                                    /* @tp_members@ */
390   PYGETSET(share),                      /* @tp_getset@ */
391   0,                                    /* @tp_base@ */
392   0,                                    /* @tp_dict@ */
393   0,                                    /* @tp_descr_get@ */
394   0,                                    /* @tp_descr_set@ */
395   0,                                    /* @tp_dictoffset@ */
396   0,                                    /* @tp_init@ */
397   PyType_GenericAlloc,                  /* @tp_alloc@ */
398   abstract_pynew,                       /* @tp_new@ */
399   0,                                    /* @tp_free@ */
400   0                                     /* @tp_is_gc@ */
401 };
402
403 static PyObject *sharesplit_pynew(PyTypeObject *ty,
404                                   PyObject *arg, PyObject *kw)
405 {
406   mp *sec = 0;
407   unsigned t;
408   grand *r = &rand_global;
409   mp *m = 0;
410   share_pyobj *s;
411   static const char *const kwlist[] =
412     { "threshold", "secret", "modulus", "rng", 0 };
413
414   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:new", KWLIST,
415                                    convuint, &t, convmp, &sec,
416                                    convmp, &m, convgrand, &r))
417     goto end;
418   if (!t) VALERR("threshold must be nonzero");
419   s = (share_pyobj *)ty->tp_alloc(ty, 0);
420   share_create(&s->s, t);
421   s->s.p = m;
422   share_mkshares(&s->s, r, sec);
423   mp_drop(sec);
424   return ((PyObject *)s);
425 end:
426   mp_drop(m);
427   mp_drop(sec);
428   return (0);
429 }
430
431 static PyObject *smeth_get(PyObject *me, PyObject *arg)
432 {
433   unsigned i;
434   PyObject *rc = 0;
435   if (!PyArg_ParseTuple(arg, "O&:get", convuint, &i)) goto end;
436   rc = mp_pywrap(share_get(SHARE_S(me), MP_NEW, i));
437 end:
438   return (rc);
439 }
440
441 static const PyMethodDef sharesplit_pymethods[] = {
442 #define METHNAME(name) smeth_##name
443   METH  (get,           "S.get(I) -> SHARE")
444 #undef METHNAME
445   { 0 }
446 };
447
448 static const PyTypeObject sharesplit_pytype_skel = {
449   PyVarObject_HEAD_INIT(0, 0)           /* Header */
450   "ShareSplit",                         /* @tp_name@ */
451   sizeof(share_pyobj),                  /* @tp_basicsize@ */
452   0,                                    /* @tp_itemsize@ */
453
454   share_pydealloc,                      /* @tp_dealloc@ */
455   0,                                    /* @tp_print@ */
456   0,                                    /* @tp_getattr@ */
457   0,                                    /* @tp_setattr@ */
458   0,                                    /* @tp_compare@ */
459   0,                                    /* @tp_repr@ */
460   0,                                    /* @tp_as_number@ */
461   0,                                    /* @tp_as_sequence@ */
462   0,                                    /* @tp_as_mapping@ */
463   0,                                    /* @tp_hash@ */
464   0,                                    /* @tp_call@ */
465   0,                                    /* @tp_str@ */
466   0,                                    /* @tp_getattro@ */
467   0,                                    /* @tp_setattro@ */
468   0,                                    /* @tp_as_buffer@ */
469   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
470     Py_TPFLAGS_BASETYPE,
471
472   /* @tp_doc@ */
473   "ShareSplit(THRESHOLD, SECRET, [modulus = ?], [rng = rand]):\n"
474   "  prime field secret sharing: split secret into shares.",
475
476   0,                                    /* @tp_traverse@ */
477   0,                                    /* @tp_clear@ */
478   0,                                    /* @tp_richcompare@ */
479   0,                                    /* @tp_weaklistoffset@ */
480   0,                                    /* @tp_iter@ */
481   0,                                    /* @tp_iternext@ */
482   PYMETHODS(sharesplit),                /* @tp_methods@ */
483   0,                                    /* @tp_members@ */
484   0,                                    /* @tp_getset@ */
485   0,                                    /* @tp_base@ */
486   0,                                    /* @tp_dict@ */
487   0,                                    /* @tp_descr_get@ */
488   0,                                    /* @tp_descr_set@ */
489   0,                                    /* @tp_dictoffset@ */
490   0,                                    /* @tp_init@ */
491   PyType_GenericAlloc,                  /* @tp_alloc@ */
492   sharesplit_pynew,                     /* @tp_new@ */
493   0,                                    /* @tp_free@ */
494   0                                     /* @tp_is_gc@ */
495 };
496
497 static PyObject *sharejoin_pynew(PyTypeObject *ty,
498                                  PyObject *arg, PyObject *kw)
499 {
500   unsigned t;
501   mp *m = 0;
502   share_pyobj *s;
503   static const char *const kwlist[] = { "threshold", "modulus", 0 };
504   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST,
505                                    convuint, &t, convmp, &m))
506     goto end;
507   if (!t) VALERR("threshold must be nonzero");
508   s = (share_pyobj *)ty->tp_alloc(ty, 0);
509   share_create(&s->s, t);
510   s->s.p = m;
511   return ((PyObject *)s);
512 end:
513   mp_drop(m);
514   return (0);
515 }
516
517 static PyObject *smeth_addedp(PyObject *me, PyObject *arg)
518 {
519   unsigned i;
520   if (!PyArg_ParseTuple(arg, "O&:addedp", convuint, &i)) goto end;
521   return (getbool(share_addedp(SHARE_S(me), i)));
522 end:
523   return (0);
524 }
525
526 static PyObject *smeth_add(PyObject *me, PyObject *arg)
527 {
528   unsigned i;
529   mp *s = 0;
530   PyObject *rc = 0;
531   if (!PyArg_ParseTuple(arg, "O&O&:add", convuint, &i, convmp, &s)) goto end;
532   if (MP_NEGP(s) || MP_CMP(s, >=, SHARE_S(me)->p))
533     VALERR("share out of range");
534   if (share_addedp(SHARE_S(me), i)) VALERR("this share already added");
535   if (SHARE_S(me)->i >= SHARE_S(me)->t) VALERR("enough shares already");
536   share_add(SHARE_S(me), i, s);
537   rc = PyInt_FromLong(SHARE_S(me)->t - SHARE_S(me)->i);
538 end:
539   mp_drop(s);
540   return (rc);
541 }
542
543 static PyObject *smeth_combine(PyObject *me)
544 {
545   PyObject *rc = 0;
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 const 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   NAMETH(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 const 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 const PyTypeObject sharejoin_pytype_skel = {
572   PyVarObject_HEAD_INIT(0, 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   PYMETHODS(sharejoin),                 /* @tp_methods@ */
606   0,                                    /* @tp_members@ */
607   PYGETSET(sharejoin),                  /* @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 -------------------------------------------------*/