5 * Random-number generators
7 * (c) 2004 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 /*----- Main code ---------------------------------------------------------*/
35 PyTypeObject
*grand_pytype
, *truerand_pytype
;
36 PyTypeObject
*lcrand_pytype
, *fibrand_pytype
;
37 PyTypeObject
*dsarand_pytype
, *bbs_pytype
, *bbspriv_pytype
;
38 PyTypeObject
*sslprf_pytype
, *tlsdx_pytype
, *tlsprf_pytype
;
41 static PyObject
*grand_dopywrap(PyTypeObject
*ty
, grand
*r
, unsigned f
)
45 g
= (grand_pyobj
*)ty
->tp_alloc(ty
, 0);
48 return ((PyObject
*)g
);
51 PyObject
*grand_pywrap(grand
*r
, unsigned f
)
53 PyTypeObject
*ty
= grand_pytype
;
55 if (strcmp(r
->ops
->name
, "rand") == 0) ty
= truerand_pytype
;
56 else if (strcmp(r
->ops
->name
, "lcrand") == 0) ty
= lcrand_pytype
;
57 else if (strcmp(r
->ops
->name
, "fibrand") == 0) ty
= fibrand_pytype
;
58 else if (strcmp(r
->ops
->name
, "dsarand") == 0) ty
= dsarand_pytype
;
59 else if (strcmp(r
->ops
->name
, "bbs") == 0) ty
= bbs_pytype
;
60 return (grand_dopywrap(ty
, r
, f
));
63 CONVFUNC(grand
, grand
*, GRAND_R
)
65 static PyObject
*grmeth_byte(PyObject
*me
, PyObject
*arg
)
67 if (!PyArg_ParseTuple(arg
, ":byte")) return (0);
68 return (PyInt_FromLong(grand_byte(GRAND_R(me
))));
71 static PyObject
*grmeth_word(PyObject
*me
, PyObject
*arg
)
73 if (!PyArg_ParseTuple(arg
, ":word")) return (0);
74 return (getu32(grand_word(GRAND_R(me
))));
77 static PyObject
*grmeth_range(PyObject
*me
, PyObject
*arg
)
83 if (!PyArg_ParseTuple(arg
, "O:range", &m
)) return (0);
85 long mm
= PyInt_AS_LONG(m
);
89 return (PyInt_FromLong(grand_range(GRAND_R(me
), mm
)));
91 if ((x
= getmp(m
)) == 0)
95 y
= mprand_range(MP_NEW
, x
, GRAND_R(me
), 0);
97 return (mp_pywrap(y
));
99 TYERR("range must be nonnegative");
105 static PyObject
*grmeth_mp(PyObject
*me
, PyObject
*arg
, PyObject
*kw
)
109 char *kwlist
[] = { "bits", "or", 0 };
111 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "O&|O&:mp", kwlist
,
112 convszt
, &l
, convmpw
, &o
))
114 return (mp_pywrap(mprand(MP_NEW
, l
, GRAND_R(me
), o
)));
119 static PyObject
*grmeth_block(PyObject
*me
, PyObject
*arg
)
124 if (!PyArg_ParseTuple(arg
, "O&:block", convulong
, &n
)) goto end
;
125 rc
= bytestring_pywrap(0, n
);
126 grand_fill(GRAND_R(me
), PyString_AS_STRING(rc
), n
);
131 static int checkop(grand
*r
, unsigned op
, const char *what
)
133 if (r
->ops
->misc(r
, GRAND_CHECK
, op
))
135 PyErr_Format(PyExc_TypeError
, "operation %s not supported", what
);
139 static PyObject
*grmeth_seedint(PyObject
*me
, PyObject
*arg
)
142 grand
*r
= GRAND_R(me
);
143 if (!PyArg_ParseTuple(arg
, "i:seedint", &i
) ||
144 checkop(r
, GRAND_SEEDINT
, "seedint"))
146 r
->ops
->misc(r
, GRAND_SEEDINT
, i
);
152 static PyObject
*grmeth_seedword(PyObject
*me
, PyObject
*arg
)
155 grand
*r
= GRAND_R(me
);
156 if (!PyArg_ParseTuple(arg
, "O&:seedword", convu32
, &u
) ||
157 checkop(r
, GRAND_SEEDUINT32
, "seedword"))
159 r
->ops
->misc(r
, GRAND_SEEDUINT32
, u
);
165 static PyObject
*grmeth_seedblock(PyObject
*me
, PyObject
*arg
)
169 grand
*r
= GRAND_R(me
);
170 if (!PyArg_ParseTuple(arg
, "s#:seedblock", &p
, &n
) ||
171 checkop(r
, GRAND_SEEDBLOCK
, "seedblock"))
173 r
->ops
->misc(r
, GRAND_SEEDBLOCK
, p
, (size_t)n
);
179 static PyObject
*grmeth_seedmp(PyObject
*me
, PyObject
*arg
)
183 grand
*r
= GRAND_R(me
);
184 if (!PyArg_ParseTuple(arg
, "O:seedmp", &x
) ||
185 checkop(r
, GRAND_SEEDMP
, "seedmp") ||
186 (xx
= getmp(x
)) == 0)
188 r
->ops
->misc(r
, GRAND_SEEDMP
, xx
);
195 static PyObject
*grmeth_seedrand(PyObject
*me
, PyObject
*arg
, PyObject
*kw
)
197 char *kwlist
[] = { "rng", 0 };
198 grand
*r
= GRAND_R(me
);
199 grand
*rr
= &rand_global
;
200 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "|O&:seedrand", kwlist
,
202 checkop(r
, GRAND_SEEDRAND
, "seedrand"))
204 r
->ops
->misc(r
, GRAND_SEEDRAND
, rr
);
210 static PyObject
*grmeth_mask(PyObject
*me
, PyObject
*arg
)
212 grand
*r
= GRAND_R(me
);
217 if (!PyArg_ParseTuple(arg
, "s#:mask", &p
, &sz
)) return (0);
218 rc
= bytestring_pywrap(0, sz
);
219 q
= PyString_AS_STRING(rc
);
221 while (sz
--) *q
++ ^= *p
++;
225 static void grand_pydealloc(PyObject
*me
)
227 grand_pyobj
*g
= (grand_pyobj
*)me
;
233 static PyObject
*grget_name(PyObject
*me
, void *hunoz
)
234 { return (PyString_FromString(GRAND_R(me
)->ops
->name
)); }
236 static PyObject
*grget_cryptop(PyObject
*me
, void *hunoz
)
237 { return (getbool(GRAND_R(me
)->ops
->f
& GRAND_CRYPTO
)); }
239 static PyGetSetDef grand_pygetset
[] = {
240 #define GETSETNAME(op, name) gr##op##_##name
241 GET (name
, "R.name -> name of this kind of generator")
242 GET (cryptop
, "R.cryptop -> flag: cryptographically strong?")
247 static PyMethodDef grand_pymethods
[] = {
248 #define METHNAME(name) grmeth_##name
249 METH (byte
, "R.byte() -> BYTE")
250 METH (word
, "R.word() -> WORD")
251 METH (block
, "R.block(N) -> STRING")
252 KWMETH(mp
, "R.mp(bits, or = 0) -> MP")
253 METH (range
, "R.range(MAX) -> INT")
254 METH (mask
, "R.mask(STR) -> STR")
255 METH (seedint
, "R.seedint(I)")
256 METH (seedword
, "R.seedword(I)")
257 METH (seedblock
, "R.seedblock(BYTES)")
258 METH (seedmp
, "R.seedmp(X)")
259 KWMETH(seedrand
, "R.seedrand(RR)")
264 static PyTypeObject grand_pytype_skel
= {
265 PyObject_HEAD_INIT(0) 0, /* Header */
266 "catacomb.GRand", /* @tp_name@ */
267 sizeof(grand_pyobj
), /* @tp_basicsize@ */
268 0, /* @tp_itemsize@ */
270 grand_pydealloc
, /* @tp_dealloc@ */
272 0, /* @tp_getattr@ */
273 0, /* @tp_setattr@ */
274 0, /* @tp_compare@ */
276 0, /* @tp_as_number@ */
277 0, /* @tp_as_sequence@ */
278 0, /* @tp_as_mapping@ */
282 0, /* @tp_getattro@ */
283 0, /* @tp_setattro@ */
284 0, /* @tp_as_buffer@ */
285 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
289 "Generic random number source.",
291 0, /* @tp_traverse@ */
293 0, /* @tp_richcompare@ */
294 0, /* @tp_weaklistoffset@ */
296 0, /* @tp_iternexr@ */
297 grand_pymethods
, /* @tp_methods@ */
298 0, /* @tp_members@ */
299 grand_pygetset
, /* @tp_getset@ */
302 0, /* @tp_descr_get@ */
303 0, /* @tp_descr_set@ */
304 0, /* @tp_dictoffset@ */
306 PyType_GenericAlloc
, /* @tp_alloc@ */
307 abstract_pynew
, /* @tp_new@ */
312 static PyObject
*lcrand_pynew(PyTypeObject
*me
, PyObject
*arg
, PyObject
*kw
)
315 char *kwlist
[] = { "seed", 0 };
316 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "|O&:new", kwlist
, convu32
, &n
))
318 return (grand_dopywrap(lcrand_pytype
, lcrand_create(n
), f_freeme
));
321 static PyTypeObject lcrand_pytype_skel
= {
322 PyObject_HEAD_INIT(0) 0, /* Header */
323 "catacomb.LCRand", /* @tp_name@ */
324 sizeof(grand_pyobj
), /* @tp_basicsize@ */
325 0, /* @tp_itemsize@ */
327 grand_pydealloc
, /* @tp_dealloc@ */
329 0, /* @tp_getattr@ */
330 0, /* @tp_setattr@ */
331 0, /* @tp_compare@ */
333 0, /* @tp_as_number@ */
334 0, /* @tp_as_sequence@ */
335 0, /* @tp_as_mapping@ */
339 0, /* @tp_getattro@ */
340 0, /* @tp_setattro@ */
341 0, /* @tp_as_buffer@ */
342 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
346 "Linear congruential generator.",
348 0, /* @tp_traverse@ */
350 0, /* @tp_richcompare@ */
351 0, /* @tp_weaklistoffset@ */
353 0, /* @tp_iternexr@ */
354 0, /* @tp_methods@ */
355 0, /* @tp_members@ */
359 0, /* @tp_descr_get@ */
360 0, /* @tp_descr_set@ */
361 0, /* @tp_dictoffset@ */
363 PyType_GenericAlloc
, /* @tp_alloc@ */
364 lcrand_pynew
, /* @tp_new@ */
369 static PyObject
*fibrand_pynew(PyTypeObject
*me
, PyObject
*arg
, PyObject
*kw
)
372 char *kwlist
[] = { "seed", 0 };
373 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "|O&:new", kwlist
, convu32
, &n
))
375 return (grand_dopywrap(fibrand_pytype
, fibrand_create(n
), f_freeme
));
378 static PyTypeObject fibrand_pytype_skel
= {
379 PyObject_HEAD_INIT(0) 0, /* Header */
380 "catacomb.FibRand", /* @tp_name@ */
381 sizeof(grand_pyobj
), /* @tp_basicsize@ */
382 0, /* @tp_itemsize@ */
384 grand_pydealloc
, /* @tp_dealloc@ */
386 0, /* @tp_getattr@ */
387 0, /* @tp_setattr@ */
388 0, /* @tp_compare@ */
390 0, /* @tp_as_number@ */
391 0, /* @tp_as_sequence@ */
392 0, /* @tp_as_mapping@ */
396 0, /* @tp_getattro@ */
397 0, /* @tp_setattro@ */
398 0, /* @tp_as_buffer@ */
399 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
403 "Fibonacci generator.",
405 0, /* @tp_traverse@ */
407 0, /* @tp_richcompare@ */
408 0, /* @tp_weaklistoffset@ */
410 0, /* @tp_iternexr@ */
411 0, /* @tp_methods@ */
412 0, /* @tp_members@ */
416 0, /* @tp_descr_get@ */
417 0, /* @tp_descr_set@ */
418 0, /* @tp_dictoffset@ */
420 PyType_GenericAlloc
, /* @tp_alloc@ */
421 fibrand_pynew
, /* @tp_new@ */
426 /*----- True random generator ---------------------------------------------*/
428 static PyObject
*trmeth_gate(PyObject
*me
, PyObject
*arg
)
430 grand
*r
= GRAND_R(me
);
431 if (!PyArg_ParseTuple(arg
, ":gate")) return (0);
432 r
->ops
->misc(r
, RAND_GATE
);
436 static PyObject
*trmeth_stretch(PyObject
*me
, PyObject
*arg
)
438 grand
*r
= GRAND_R(me
);
439 if (!PyArg_ParseTuple(arg
, ":stretch")) return (0);
440 r
->ops
->misc(r
, RAND_STRETCH
);
444 static PyObject
*trmeth_key(PyObject
*me
, PyObject
*arg
)
446 grand
*r
= GRAND_R(me
);
448 if (!PyArg_ParseTuple(arg
, "s#:key", &p
, &n
)) return (0);
449 r
->ops
->misc(r
, RAND_KEY
, p
, n
);
453 static PyObject
*trmeth_seed(PyObject
*me
, PyObject
*arg
)
455 grand
*r
= GRAND_R(me
);
457 if (!PyArg_ParseTuple(arg
, "O&:seed", convuint
, &u
)) return (0);
458 if (u
> RAND_IBITS
) VALERR("pointlessly large");
459 r
->ops
->misc(r
, RAND_SEED
, u
);
465 static PyObject
*trmeth_timer(PyObject
*me
, PyObject
*arg
)
467 grand
*r
= GRAND_R(me
);
468 if (!PyArg_ParseTuple(arg
, ":timer")) return (0);
469 r
->ops
->misc(r
, RAND_TIMER
);
473 static PyObject
*truerand_pynew(PyTypeObject
*ty
,
474 PyObject
*arg
, PyObject
*kw
)
476 char *kwlist
[] = { 0 };
479 if (PyArg_ParseTupleAndKeywords(arg
, kw
, ":new", kwlist
)) goto end
;
481 r
->ops
->misc(r
, RAND_NOISESRC
, &noise_source
);
482 r
->ops
->misc(r
, RAND_SEED
, 160);
483 rc
= grand_dopywrap(ty
, r
, f_freeme
);
488 static PyMethodDef truerand_pymethods
[] = {
489 #define METHNAME(name) trmeth_##name
490 METH (gate
, "R.gate()")
491 METH (stretch
, "R.stretch()")
492 METH (key
, "R.key(BYTES)")
493 METH (seed
, "R.seed(NBITS)")
494 METH (timer
, "R.timer()")
499 static PyObject
*trget_goodbits(PyObject
*me
, void *hunoz
)
501 grand
*r
= GRAND_R(me
);
502 return (PyInt_FromLong(r
->ops
->misc(r
, RAND_GOODBITS
)));
505 static PyGetSetDef truerand_pygetset
[] = {
506 #define GETSETNAME(op, name) tr##op##_##name
507 GET (goodbits
, "R.goodbits -> good bits of entropy remaining")
512 static PyTypeObject truerand_pytype_skel
= {
513 PyObject_HEAD_INIT(0) 0, /* Header */
514 "catacomb.TrueRand", /* @tp_name@ */
515 sizeof(grand_pyobj
), /* @tp_basicsize@ */
516 0, /* @tp_itemsize@ */
518 grand_pydealloc
, /* @tp_dealloc@ */
520 0, /* @tp_getattr@ */
521 0, /* @tp_setattr@ */
522 0, /* @tp_compare@ */
524 0, /* @tp_as_number@ */
525 0, /* @tp_as_sequence@ */
526 0, /* @tp_as_mapping@ */
530 0, /* @tp_getattro@ */
531 0, /* @tp_setattro@ */
532 0, /* @tp_as_buffer@ */
533 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
537 "True random number source.",
539 0, /* @tp_traverse@ */
541 0, /* @tp_richcompare@ */
542 0, /* @tp_weaklistoffset@ */
544 0, /* @tp_iternexr@ */
545 truerand_pymethods
, /* @tp_methods@ */
546 0, /* @tp_members@ */
547 truerand_pygetset
, /* @tp_getset@ */
550 0, /* @tp_descr_get@ */
551 0, /* @tp_descr_set@ */
552 0, /* @tp_dictoffset@ */
554 PyType_GenericAlloc
, /* @tp_alloc@ */
555 truerand_pynew
, /* @tp_new@ */
560 /*----- SSL and TLS generators --------------------------------------------*/
562 static PyObject
*sslprf_pynew(PyTypeObject
*ty
, PyObject
*arg
, PyObject
*kw
)
566 const gchash
*hco
= &md5
, *hci
= &sha
;
568 char *kwlist
[] = { "key", "seed", "ohash", "ihash", 0 };
570 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "s#s#|O&O&:new", kwlist
,
572 convgchash
, &hco
, convgchash
, &hci
))
574 rc
= grand_dopywrap(ty
, sslprf_rand(hco
, hci
, k
, ksz
, s
, ssz
), f_freeme
);
579 static PyObject
*tlsdx_pynew(PyTypeObject
*ty
, PyObject
*arg
, PyObject
*kw
)
583 const gcmac
*mc
= &sha_hmac
;
585 char *kwlist
[] = { "key", "seed", "mac", 0 };
587 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "s#s#|O&:new", kwlist
,
591 rc
= grand_dopywrap(ty
, tlsdx_rand(mc
, k
, ksz
, s
, ssz
), f_freeme
);
596 static PyObject
*tlsprf_pynew(PyTypeObject
*ty
, PyObject
*arg
, PyObject
*kw
)
600 const gcmac
*mcl
= &md5_hmac
, *mcr
= &sha_hmac
;
602 char *kwlist
[] = { "key", "seed", "lmac", "rmac", 0 };
604 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "s#s#|O&O&:new", kwlist
,
606 convgcmac
, &mcl
, convgcmac
, &mcr
))
608 rc
= grand_dopywrap(ty
, tlsprf_rand(mcl
, mcr
, k
, ksz
, s
, ssz
), f_freeme
);
613 static PyTypeObject sslprf_pytype_skel
= {
614 PyObject_HEAD_INIT(0) 0, /* Header */
615 "catacomb.SSLRand", /* @tp_name@ */
616 sizeof(grand_pyobj
), /* @tp_basicsize@ */
617 0, /* @tp_itemsize@ */
619 grand_pydealloc
, /* @tp_dealloc@ */
621 0, /* @tp_getattr@ */
622 0, /* @tp_setattr@ */
623 0, /* @tp_compare@ */
625 0, /* @tp_as_number@ */
626 0, /* @tp_as_sequence@ */
627 0, /* @tp_as_mapping@ */
631 0, /* @tp_getattro@ */
632 0, /* @tp_setattro@ */
633 0, /* @tp_as_buffer@ */
634 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
638 "Random number generator for SSL master secret.",
640 0, /* @tp_traverse@ */
642 0, /* @tp_richcompare@ */
643 0, /* @tp_weaklistoffset@ */
645 0, /* @tp_iternexr@ */
646 0, /* @tp_methods@ */
647 0, /* @tp_members@ */
651 0, /* @tp_descr_get@ */
652 0, /* @tp_descr_set@ */
653 0, /* @tp_dictoffset@ */
655 PyType_GenericAlloc
, /* @tp_alloc@ */
656 sslprf_pynew
, /* @tp_new@ */
661 static PyTypeObject tlsdx_pytype_skel
= {
662 PyObject_HEAD_INIT(0) 0, /* Header */
663 "catacomb.TLSDataExpansion", /* @tp_name@ */
664 sizeof(grand_pyobj
), /* @tp_basicsize@ */
665 0, /* @tp_itemsize@ */
667 grand_pydealloc
, /* @tp_dealloc@ */
669 0, /* @tp_getattr@ */
670 0, /* @tp_setattr@ */
671 0, /* @tp_compare@ */
673 0, /* @tp_as_number@ */
674 0, /* @tp_as_sequence@ */
675 0, /* @tp_as_mapping@ */
679 0, /* @tp_getattro@ */
680 0, /* @tp_setattro@ */
681 0, /* @tp_as_buffer@ */
682 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
686 "TLS data expansion function.",
688 0, /* @tp_traverse@ */
690 0, /* @tp_richcompare@ */
691 0, /* @tp_weaklistoffset@ */
693 0, /* @tp_iternexr@ */
694 0, /* @tp_methods@ */
695 0, /* @tp_members@ */
699 0, /* @tp_descr_get@ */
700 0, /* @tp_descr_set@ */
701 0, /* @tp_dictoffset@ */
703 PyType_GenericAlloc
, /* @tp_alloc@ */
704 tlsdx_pynew
, /* @tp_new@ */
709 static PyTypeObject tlsprf_pytype_skel
= {
710 PyObject_HEAD_INIT(0) 0, /* Header */
711 "catacomb.TLSPRF", /* @tp_name@ */
712 sizeof(grand_pyobj
), /* @tp_basicsize@ */
713 0, /* @tp_itemsize@ */
715 grand_pydealloc
, /* @tp_dealloc@ */
717 0, /* @tp_getattr@ */
718 0, /* @tp_setattr@ */
719 0, /* @tp_compare@ */
721 0, /* @tp_as_number@ */
722 0, /* @tp_as_sequence@ */
723 0, /* @tp_as_mapping@ */
727 0, /* @tp_getattro@ */
728 0, /* @tp_setattro@ */
729 0, /* @tp_as_buffer@ */
730 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
734 "TLS pseudorandom function.",
736 0, /* @tp_traverse@ */
738 0, /* @tp_richcompare@ */
739 0, /* @tp_weaklistoffset@ */
741 0, /* @tp_iternexr@ */
742 0, /* @tp_methods@ */
743 0, /* @tp_members@ */
747 0, /* @tp_descr_get@ */
748 0, /* @tp_descr_set@ */
749 0, /* @tp_dictoffset@ */
751 PyType_GenericAlloc
, /* @tp_alloc@ */
752 tlsprf_pynew
, /* @tp_new@ */
757 /*----- DSA generator -----------------------------------------------------*/
759 static PyObject
*dsarand_pynew(PyTypeObject
*ty
, PyObject
*arg
, PyObject
*kw
)
764 char *kwlist
[] = { "seed", 0 };
766 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "s#:new", kwlist
, &p
, &sz
))
768 rc
= grand_dopywrap(ty
, dsarand_create(p
, sz
), f_freeme
);
773 static PyObject
*drget_seed(PyObject
*me
, void *hunoz
)
775 grand
*r
= GRAND_R(me
);
776 int n
= r
->ops
->misc(r
, DSARAND_SEEDSZ
);
777 PyObject
*rc
= bytestring_pywrap(0, n
);
778 r
->ops
->misc(r
, DSARAND_GETSEED
, PyString_AS_STRING(rc
));
782 static PyGetSetDef dsarand_pygetset
[] = {
783 #define GETSETNAME(op, name) dr##op##_##name
784 GET (seed
, "R.seed -> current generator seed")
789 static PyTypeObject dsarand_pytype_skel
= {
790 PyObject_HEAD_INIT(0) 0, /* Header */
791 "catacomb.DSARand", /* @tp_name@ */
792 sizeof(grand_pyobj
), /* @tp_basicsize@ */
793 0, /* @tp_itemsize@ */
795 grand_pydealloc
, /* @tp_dealloc@ */
797 0, /* @tp_getattr@ */
798 0, /* @tp_setattr@ */
799 0, /* @tp_compare@ */
801 0, /* @tp_as_number@ */
802 0, /* @tp_as_sequence@ */
803 0, /* @tp_as_mapping@ */
807 0, /* @tp_getattro@ */
808 0, /* @tp_setattro@ */
809 0, /* @tp_as_buffer@ */
810 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
814 "Pseudorandom number generator for constructing DSA parameters.",
816 0, /* @tp_traverse@ */
818 0, /* @tp_richcompare@ */
819 0, /* @tp_weaklistoffset@ */
821 0, /* @tp_iternexr@ */
822 0, /* @tp_methods@ */
823 0, /* @tp_members@ */
824 dsarand_pygetset
, /* @tp_getset@ */
827 0, /* @tp_descr_get@ */
828 0, /* @tp_descr_set@ */
829 0, /* @tp_dictoffset@ */
831 PyType_GenericAlloc
, /* @tp_alloc@ */
832 dsarand_pynew
, /* @tp_new@ */
837 /*----- Blum-Blum-Shub generator ------------------------------------------*/
839 static PyObject
*bbs_pynew(PyTypeObject
*ty
, PyObject
*arg
, PyObject
*kw
)
841 mp
*n
= 0, *x
= MP_TWO
;
843 char *kwlist
[] = { "n", "x", 0 };
845 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "O&|O&:new", kwlist
,
846 convmp
, &n
, convmp
, &x
))
848 rc
= grand_dopywrap(ty
, bbs_rand(n
, x
), f_freeme
);
855 static PyObject
*bbsmeth_step(PyObject
*me
, PyObject
*arg
)
857 grand
*r
= GRAND_R(me
); if (!PyArg_ParseTuple(arg
, ":step")) return (0);
858 r
->ops
->misc(r
, BBS_STEP
); RETURN_ME
;
861 static PyObject
*bbsmeth_bits(PyObject
*me
, PyObject
*arg
)
863 grand
*r
= GRAND_R(me
); unsigned n
; uint32 w
;
864 if (!PyArg_ParseTuple(arg
, "O&:bits", convuint
, &n
)) goto end
;
865 if (n
> 32) VALERR("can't get more than 32 bits");
866 r
->ops
->misc(r
, BBS_BITS
, n
, &w
); return (getu32(w
));
871 static PyObject
*bbsmeth_wrap(PyObject
*me
, PyObject
*arg
)
873 grand
*r
= GRAND_R(me
); if (!PyArg_ParseTuple(arg
, ":wrap")) return (0);
874 r
->ops
->misc(r
, BBS_WRAP
); RETURN_ME
;
877 static PyObject
*bbsget_n(PyObject
*me
, void *hunoz
)
879 mp
*x
= MP_NEW
; grand
*r
= GRAND_R(me
);
880 r
->ops
->misc(r
, BBS_MOD
, &x
); return (mp_pywrap(x
));
883 static PyObject
*bbsget_x(PyObject
*me
, void *hunoz
)
885 mp
*x
= MP_NEW
; grand
*r
= GRAND_R(me
);
886 r
->ops
->misc(r
, BBS_STATE
, &x
); return (mp_pywrap(x
));
889 static int bbsset_x(PyObject
*me
, PyObject
*val
, void *hunoz
)
891 mp
*x
= 0; grand
*r
= GRAND_R(me
); int rc
= -1;
892 if ((x
= getmp(val
)) == 0) goto end
; r
->ops
->misc(r
, BBS_SET
, x
); rc
= 0;
893 end
: mp_drop(x
); return (rc
);
896 static PyObject
*bbsget_stepsz(PyObject
*me
, void *hunoz
)
898 grand
*r
= GRAND_R(me
);
899 return (PyInt_FromLong(r
->ops
->misc(r
, BBS_STEPSZ
)));
902 static PyMethodDef bbs_pymethods
[] = {
903 #define METHNAME(name) bbsmeth_##name
904 METH (step
, "R.step(): steps the generator (not useful)")
905 METH (bits
, "R.bits(N) -> W: returns N bits (<= 32) from the generator")
906 METH (wrap
, "R.wrap(): flushes unused bits in internal buffer")
911 static PyGetSetDef bbs_pygetset
[] = {
912 #define GETSETNAME(op, name) bbs##op##_##name
913 GET (n
, "R.n -> Blum modulus")
914 GETSET(x
, "R.x -> current seed value")
915 GET (stepsz
, "R.stepsz -> number of bits generated per step")
920 static PyTypeObject bbs_pytype_skel
= {
921 PyObject_HEAD_INIT(0) 0, /* Header */
922 "catacomb.BlumBlumShub", /* @tp_name@ */
923 sizeof(grand_pyobj
), /* @tp_basicsize@ */
924 0, /* @tp_itemsize@ */
926 grand_pydealloc
, /* @tp_dealloc@ */
928 0, /* @tp_getattr@ */
929 0, /* @tp_setattr@ */
930 0, /* @tp_compare@ */
932 0, /* @tp_as_number@ */
933 0, /* @tp_as_sequence@ */
934 0, /* @tp_as_mapping@ */
938 0, /* @tp_getattro@ */
939 0, /* @tp_setattro@ */
940 0, /* @tp_as_buffer@ */
941 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
945 "Blum-Blum-Shub strong pseudorandom number generator.",
947 0, /* @tp_traverse@ */
949 0, /* @tp_richcompare@ */
950 0, /* @tp_weaklistoffset@ */
952 0, /* @tp_iternexr@ */
953 bbs_pymethods
, /* @tp_methods@ */
954 0, /* @tp_members@ */
955 bbs_pygetset
, /* @tp_getset@ */
958 0, /* @tp_descr_get@ */
959 0, /* @tp_descr_set@ */
960 0, /* @tp_dictoffset@ */
962 PyType_GenericAlloc
, /* @tp_alloc@ */
963 bbs_pynew
, /* @tp_new@ */
968 typedef struct bbspriv_pyobj
{
973 #define BBSPRIV_BP(o) (&((bbspriv_pyobj *)(o))->bp)
975 static PyObject
*bbspriv_pynew(PyTypeObject
*ty
,
976 PyObject
*arg
, PyObject
*kw
)
978 mp
*p
= 0, *q
= 0, *n
= 0, *x
= MP_TWO
;
979 bbspriv_pyobj
*rc
= 0;
980 char *kwlist
[] = { "n", "p", "q", "seed", 0 };
982 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "|O&O&O&O&:new", kwlist
,
983 convmp
, &n
, convmp
, &p
, convmp
, &q
,
986 if (!n
+ !p
+ !q
> 1) VALERR("must specify at least two of n, p, q");
987 if (!n
) n
= mp_mul(MP_NEW
, p
, q
);
988 else if (!p
) mp_div(&p
, 0, n
, q
);
989 else if (!q
) mp_div(&q
, 0, n
, p
);
990 rc
= (bbspriv_pyobj
*)ty
->tp_alloc(ty
, 0);
991 rc
->gr
.r
= bbs_rand(n
, x
);
993 rc
->bp
.p
= MP_COPY(p
);
994 rc
->bp
.q
= MP_COPY(q
);
995 rc
->bp
.n
= MP_COPY(n
);
997 mp_drop(p
); mp_drop(q
); mp_drop(n
); mp_drop(x
);
998 return ((PyObject
*)rc
);
1001 static PyObject
*meth__BBSPriv_generate(PyObject
*me
,
1002 PyObject
*arg
, PyObject
*kw
)
1004 bbs_priv bp
= { 0 };
1007 unsigned nbits
, n
= 0;
1008 grand
*r
= &rand_global
;
1009 char *kwlist
[] = { "class", "nbits", "event", "rng", "nsteps", "seed", 0 };
1010 bbspriv_pyobj
*rc
= 0;
1012 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "OO&|O&O&O&O&:generate", kwlist
,
1013 &me
, convuint
, &nbits
, convpgev
, &evt
,
1014 convgrand
, &r
, convuint
, &n
, convmp
, &x
))
1016 if (bbs_gen(&bp
, nbits
, r
, n
, evt
.proc
, evt
.ctx
))
1017 VALERR("prime genration failed");
1018 rc
= PyObject_New(bbspriv_pyobj
, bbspriv_pytype
);
1019 rc
->gr
.r
= bbs_rand(bp
.n
, x
);
1020 rc
->gr
.f
= f_freeme
;
1021 rc
->bp
.p
= MP_COPY(bp
.p
);
1022 rc
->bp
.q
= MP_COPY(bp
.q
);
1023 rc
->bp
.n
= MP_COPY(bp
.n
);
1025 mp_drop(bp
.p
); mp_drop(bp
.q
); mp_drop(bp
.n
); mp_drop(x
);
1026 return ((PyObject
*)rc
);
1029 static void bbspriv_pydealloc(PyObject
*me
)
1031 bbs_priv
*bp
= BBSPRIV_BP(me
);
1035 grand_pydealloc(me
);
1038 static PyObject
*bpmeth_ff(PyObject
*me
, PyObject
*arg
)
1040 mp
*n
= 0; grand
*r
= GRAND_R(me
); bbs_priv
*bp
= BBSPRIV_BP(me
);
1041 if (!PyArg_ParseTuple(arg
, "O&:ff", convmp
, &n
)) return (0);
1042 r
->ops
->misc(r
, BBS_FF
, bp
, n
); RETURN_ME
;
1045 static PyObject
*bpmeth_rew(PyObject
*me
, PyObject
*arg
)
1047 mp
*n
= 0; grand
*r
= GRAND_R(me
); bbs_priv
*bp
= BBSPRIV_BP(me
);
1048 if (!PyArg_ParseTuple(arg
, "O&:rew", convmp
, &n
)) return (0);
1049 r
->ops
->misc(r
, BBS_REW
, bp
, n
); RETURN_ME
;
1052 static PyObject
*bpget_n(PyObject
*me
, void *hunoz
)
1053 { return (mp_pywrap(MP_COPY(BBSPRIV_BP(me
)->n
))); }
1055 static PyObject
*bpget_p(PyObject
*me
, void *hunoz
)
1056 { return (mp_pywrap(MP_COPY(BBSPRIV_BP(me
)->p
))); }
1058 static PyObject
*bpget_q(PyObject
*me
, void *hunoz
)
1059 { return (mp_pywrap(MP_COPY(BBSPRIV_BP(me
)->q
))); }
1061 static PyMethodDef bbspriv_pymethods
[] = {
1062 #define METHNAME(name) bpmeth_##name
1063 METH (ff
, "R.ff(N): fast-forward N places")
1064 METH (rew
, "R.rew(N): rewind N places")
1069 static PyGetSetDef bbspriv_pygetset
[] = {
1070 #define GETSETNAME(op, name) bp##op##_##name
1071 GET (n
, "R.n -> Blum modulus")
1072 GET (p
, "R.p -> one of the factors of the modulus")
1073 GET (q
, "R.q -> one of the factors of the modulus")
1078 static PyTypeObject bbspriv_pytype_skel
= {
1079 PyObject_HEAD_INIT(0) 0, /* Header */
1080 "catacomb.BBSPriv", /* @tp_name@ */
1081 sizeof(bbspriv_pyobj
), /* @tp_basicsize@ */
1082 0, /* @tp_itemsize@ */
1084 bbspriv_pydealloc
, /* @tp_dealloc@ */
1086 0, /* @tp_getattr@ */
1087 0, /* @tp_setattr@ */
1088 0, /* @tp_compare@ */
1090 0, /* @tp_as_number@ */
1091 0, /* @tp_as_sequence@ */
1092 0, /* @tp_as_mapping@ */
1096 0, /* @tp_getattro@ */
1097 0, /* @tp_setattro@ */
1098 0, /* @tp_as_buffer@ */
1099 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
1100 Py_TPFLAGS_BASETYPE
,
1103 "Blum-Blum-Shub strong pseudorandom generator, with private key.",
1105 0, /* @tp_traverse@ */
1107 0, /* @tp_richcompare@ */
1108 0, /* @tp_weaklistoffset@ */
1110 0, /* @tp_iternexr@ */
1111 bbspriv_pymethods
, /* @tp_methods@ */
1112 0, /* @tp_members@ */
1113 bbspriv_pygetset
, /* @tp_getset@ */
1116 0, /* @tp_descr_get@ */
1117 0, /* @tp_descr_set@ */
1118 0, /* @tp_dictoffset@ */
1120 PyType_GenericAlloc
, /* @tp_alloc@ */
1121 bbspriv_pynew
, /* @tp_new@ */
1126 /*----- Global stuff ------------------------------------------------------*/
1128 static PyMethodDef methods
[] = {
1129 #define METHNAME(name) meth_##name
1130 KWMETH(_BBSPriv_generate
, "\
1131 generate(NBITS, [event = pgen_nullev, rng = rand, nsteps = 0, seed = 2])")
1136 void rand_pyinit(void)
1138 INITTYPE(grand
, root
);
1139 INITTYPE(truerand
, grand
);
1140 INITTYPE(fibrand
, grand
);
1141 INITTYPE(lcrand
, grand
);
1142 INITTYPE(dsarand
, grand
);
1143 INITTYPE(bbs
, grand
);
1144 INITTYPE(bbspriv
, bbs
);
1145 INITTYPE(sslprf
, grand
);
1146 INITTYPE(tlsdx
, grand
);
1147 INITTYPE(tlsprf
, grand
);
1148 rand_noisesrc(RAND_GLOBAL
, &noise_source
);
1149 rand_seed(RAND_GLOBAL
, 160);
1150 addmethods(methods
);
1153 void rand_pyinsert(PyObject
*mod
)
1155 INSERT("GRand", grand_pytype
);
1156 INSERT("TrueRand", truerand_pytype
);
1157 INSERT("LCRand", lcrand_pytype
);
1158 INSERT("FibRand", fibrand_pytype
);
1159 INSERT("SSLRand", sslprf_pytype
);
1160 INSERT("TLSDataExpansion", tlsdx_pytype
);
1161 INSERT("TLSPRF", tlsprf_pytype
);
1162 INSERT("DSARand", dsarand_pytype
);
1163 INSERT("BlumBlumShub", bbs_pytype
);
1164 INSERT("BBSPriv", bbspriv_pytype
);
1165 rand_pyobj
= grand_pywrap(&rand_global
, 0); Py_INCREF(rand_pyobj
);
1166 INSERT("rand", rand_pyobj
);
1169 /*----- That's all, folks -------------------------------------------------*/