7 * (c) 2005 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of the Python interface to Catacomb.
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.
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.
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.
29 /*----- Header files ------------------------------------------------------*/
31 #include "catacomb-python.h"
33 /*----- GF(2^8)-based secret-sharing --------------------------------------*/
35 typedef struct gfshare_pyobj
{
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)
47 static void gfshare_pydealloc(PyObject
*me
)
49 gfshare_destroy(GFSHARE_S(me
));
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
)); }
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")
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@ */
72 gfshare_pydealloc
, /* @tp_dealloc@ */
78 0, /* @tp_as_number@ */
79 0, /* @tp_as_sequence@ */
80 0, /* @tp_as_mapping@ */
84 0, /* @tp_getattro@ */
85 0, /* @tp_setattro@ */
86 0, /* @tp_as_buffer@ */
87 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
91 "Binary-field secret sharing base class.",
93 0, /* @tp_traverse@ */
95 0, /* @tp_richcompare@ */
96 0, /* @tp_weaklistoffset@ */
98 0, /* @tp_iternext@ */
100 0, /* @tp_members@ */
101 gfshare_pygetset
, /* @tp_getset@ */
104 0, /* @tp_descr_get@ */
105 0, /* @tp_descr_set@ */
106 0, /* @tp_dictoffset@ */
108 PyType_GenericAlloc
, /* @tp_alloc@ */
109 abstract_pynew
, /* @tp_new@ */
114 static PyObject
*gfsharesplit_pynew(PyTypeObject
*ty
,
115 PyObject
*arg
, PyObject
*kw
)
120 grand
*r
= &rand_global
;
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
))
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
);
135 static PyObject
*gfsmeth_get(PyObject
*me
, PyObject
*arg
)
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
));
147 static PyMethodDef gfsharesplit_pymethods
[] = {
148 #define METHNAME(name) gfsmeth_##name
149 METH (get
, "S.get(I) -> SHARE")
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@ */
160 gfshare_pydealloc
, /* @tp_dealloc@ */
162 0, /* @tp_getattr@ */
163 0, /* @tp_setattr@ */
164 0, /* @tp_compare@ */
166 0, /* @tp_as_number@ */
167 0, /* @tp_as_sequence@ */
168 0, /* @tp_as_mapping@ */
172 0, /* @tp_getattro@ */
173 0, /* @tp_setattro@ */
174 0, /* @tp_as_buffer@ */
175 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
179 "Binary field secret sharing: split secret into shares.",
181 0, /* @tp_traverse@ */
183 0, /* @tp_richcompare@ */
184 0, /* @tp_weaklistoffset@ */
186 0, /* @tp_iternext@ */
187 gfsharesplit_pymethods
, /* @tp_methods@ */
188 0, /* @tp_members@ */
192 0, /* @tp_descr_get@ */
193 0, /* @tp_descr_set@ */
194 0, /* @tp_dictoffset@ */
196 PyType_GenericAlloc
, /* @tp_alloc@ */
197 gfsharesplit_pynew
, /* @tp_new@ */
202 static PyObject
*gfsharejoin_pynew(PyTypeObject
*ty
,
203 PyObject
*arg
, PyObject
*kw
)
207 char *kwlist
[] = { "threshold", "size", 0 };
208 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "O&O&:new", kwlist
,
209 convuint
, &t
, convuint
, &sz
))
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
);
219 static PyObject
*gfsmeth_addedp(PyObject
*me
, PyObject
*arg
)
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
)));
229 static PyObject
*gfsmeth_add(PyObject
*me
, PyObject
*arg
)
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
));
245 static PyObject
*gfsmeth_combine(PyObject
*me
, PyObject
*arg
)
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
));
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")
265 static PyObject
*gfsget_remain(PyObject
*me
, void *hunoz
)
266 { return (PyInt_FromLong(GFSHARE_S(me
)->t
- GFSHARE_S(me
)->i
)); }
268 static PyGetSetDef gfsharejoin_pygetset
[]= {
269 #define GETSETNAME(op, name) gfs##op##_##name
270 GET (remain
, "S.remain -> REMAIN")
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@ */
281 gfshare_pydealloc
, /* @tp_dealloc@ */
283 0, /* @tp_getattr@ */
284 0, /* @tp_setattr@ */
285 0, /* @tp_compare@ */
287 0, /* @tp_as_number@ */
288 0, /* @tp_as_sequence@ */
289 0, /* @tp_as_mapping@ */
293 0, /* @tp_getattro@ */
294 0, /* @tp_setattro@ */
295 0, /* @tp_as_buffer@ */
296 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
300 "Binary field secret sharing: join shares to recover secret.",
302 0, /* @tp_traverse@ */
304 0, /* @tp_richcompare@ */
305 0, /* @tp_weaklistoffset@ */
307 0, /* @tp_iternext@ */
308 gfsharejoin_pymethods
, /* @tp_methods@ */
309 0, /* @tp_members@ */
310 gfsharejoin_pygetset
, /* @tp_getset@ */
313 0, /* @tp_descr_get@ */
314 0, /* @tp_descr_set@ */
315 0, /* @tp_dictoffset@ */
317 PyType_GenericAlloc
, /* @tp_alloc@ */
318 gfsharejoin_pynew
, /* @tp_new@ */
323 /*----- Prime-field secret-sharing ----------------------------------------*/
325 typedef struct share_pyobj
{
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)
337 static void share_pydealloc(PyObject
*me
)
339 share_destroy(SHARE_S(me
));
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
)); }
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")
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@ */
362 share_pydealloc
, /* @tp_dealloc@ */
364 0, /* @tp_getattr@ */
365 0, /* @tp_setattr@ */
366 0, /* @tp_compare@ */
368 0, /* @tp_as_number@ */
369 0, /* @tp_as_sequence@ */
370 0, /* @tp_as_mapping@ */
374 0, /* @tp_getattro@ */
375 0, /* @tp_setattro@ */
376 0, /* @tp_as_buffer@ */
377 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
381 "Prime-field secret sharing base class.",
383 0, /* @tp_traverse@ */
385 0, /* @tp_richcompare@ */
386 0, /* @tp_weaklistoffset@ */
388 0, /* @tp_iternext@ */
389 0, /* @tp_methods@ */
390 0, /* @tp_members@ */
391 share_pygetset
, /* @tp_getset@ */
394 0, /* @tp_descr_get@ */
395 0, /* @tp_descr_set@ */
396 0, /* @tp_dictoffset@ */
398 PyType_GenericAlloc
, /* @tp_alloc@ */
399 abstract_pynew
, /* @tp_new@ */
404 static PyObject
*sharesplit_pynew(PyTypeObject
*ty
,
405 PyObject
*arg
, PyObject
*kw
)
409 grand
*r
= &rand_global
;
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
))
417 if (!t
) VALERR("threshold must be nonzero");
418 s
= (share_pyobj
*)ty
->tp_alloc(ty
, 0);
419 share_create(&s
->s
, t
);
421 share_mkshares(&s
->s
, r
, sec
);
423 return ((PyObject
*)s
);
430 static PyObject
*smeth_get(PyObject
*me
, PyObject
*arg
)
434 if (!PyArg_ParseTuple(arg
, "O&:get", convuint
, &i
)) goto end
;
435 rc
= mp_pywrap(share_get(SHARE_S(me
), MP_NEW
, i
));
440 static PyMethodDef sharesplit_pymethods
[] = {
441 #define METHNAME(name) smeth_##name
442 METH (get
, "S.get(I) -> SHARE")
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@ */
453 share_pydealloc
, /* @tp_dealloc@ */
455 0, /* @tp_getattr@ */
456 0, /* @tp_setattr@ */
457 0, /* @tp_compare@ */
459 0, /* @tp_as_number@ */
460 0, /* @tp_as_sequence@ */
461 0, /* @tp_as_mapping@ */
465 0, /* @tp_getattro@ */
466 0, /* @tp_setattro@ */
467 0, /* @tp_as_buffer@ */
468 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
472 "Prime field secret sharing: split secret into shares.",
474 0, /* @tp_traverse@ */
476 0, /* @tp_richcompare@ */
477 0, /* @tp_weaklistoffset@ */
479 0, /* @tp_iternext@ */
480 sharesplit_pymethods
, /* @tp_methods@ */
481 0, /* @tp_members@ */
485 0, /* @tp_descr_get@ */
486 0, /* @tp_descr_set@ */
487 0, /* @tp_dictoffset@ */
489 PyType_GenericAlloc
, /* @tp_alloc@ */
490 sharesplit_pynew
, /* @tp_new@ */
495 static PyObject
*sharejoin_pynew(PyTypeObject
*ty
,
496 PyObject
*arg
, PyObject
*kw
)
501 char *kwlist
[] = { "threshold", "modulus", 0 };
502 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "O&O&:new", kwlist
,
503 convuint
, &t
, convmp
, &m
))
505 if (!t
) VALERR("threshold must be nonzero");
506 s
= (share_pyobj
*)ty
->tp_alloc(ty
, 0);
507 share_create(&s
->s
, t
);
509 return ((PyObject
*)s
);
515 static PyObject
*smeth_addedp(PyObject
*me
, PyObject
*arg
)
518 if (!PyArg_ParseTuple(arg
, "O&:addedp", convuint
, &i
)) goto end
;
519 return (getbool(share_addedp(SHARE_S(me
), i
)));
524 static PyObject
*smeth_add(PyObject
*me
, PyObject
*arg
)
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
);
541 static PyObject
*smeth_combine(PyObject
*me
, PyObject
*arg
)
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
)));
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")
560 static PyObject
*sget_remain(PyObject
*me
, void *hunoz
)
561 { return (PyInt_FromLong(SHARE_S(me
)->t
- SHARE_S(me
)->i
)); }
563 static PyGetSetDef sharejoin_pygetset
[]= {
564 #define GETSETNAME(op, name) s##op##_##name
565 GET (remain
, "S.remain -> REMAIN")
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@ */
576 share_pydealloc
, /* @tp_dealloc@ */
578 0, /* @tp_getattr@ */
579 0, /* @tp_setattr@ */
580 0, /* @tp_compare@ */
582 0, /* @tp_as_number@ */
583 0, /* @tp_as_sequence@ */
584 0, /* @tp_as_mapping@ */
588 0, /* @tp_getattro@ */
589 0, /* @tp_setattro@ */
590 0, /* @tp_as_buffer@ */
591 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
595 "Prime field secret sharing: join shares to recover secret.",
597 0, /* @tp_traverse@ */
599 0, /* @tp_richcompare@ */
600 0, /* @tp_weaklistoffset@ */
602 0, /* @tp_iternext@ */
603 sharejoin_pymethods
, /* @tp_methods@ */
604 0, /* @tp_members@ */
605 sharejoin_pygetset
, /* @tp_getset@ */
608 0, /* @tp_descr_get@ */
609 0, /* @tp_descr_set@ */
610 0, /* @tp_dictoffset@ */
612 PyType_GenericAlloc
, /* @tp_alloc@ */
613 sharejoin_pynew
, /* @tp_new@ */
618 /*----- Global stuff ------------------------------------------------------*/
620 void share_pyinit(void)
622 INITTYPE(gfshare
, root
);
623 INITTYPE(gfsharesplit
, gfshare
);
624 INITTYPE(gfsharejoin
, gfshare
);
625 INITTYPE(share
, root
);
626 INITTYPE(sharesplit
, share
);
627 INITTYPE(sharejoin
, share
);
630 void share_pyinsert(PyObject
*mod
)
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
);
640 /*----- That's all, folks -------------------------------------------------*/