chiark / gitweb /
Fix for Cygwin.
[catacomb-python] / rand.c
1 /* -*-c-*-
2  *
3  * $Id$
4  *
5  * Random-number generators
6  *
7  * (c) 2004 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 /*----- Main code ---------------------------------------------------------*/
34
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;
39 PyObject *rand_pyobj;
40
41 static PyObject *grand_dopywrap(PyTypeObject *ty, grand *r, unsigned f)
42 {
43   grand_pyobj *g;
44
45   g = (grand_pyobj *)ty->tp_alloc(ty, 0);
46   g->r = r;
47   g->f = f;
48   return ((PyObject *)g);
49 }
50
51 PyObject *grand_pywrap(grand *r, unsigned f)
52 {
53   PyTypeObject *ty = grand_pytype;
54
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));
61 }
62
63 CONVFUNC(grand, grand *, GRAND_R)
64
65 static PyObject *grmeth_byte(PyObject *me, PyObject *arg)
66 {
67   if (!PyArg_ParseTuple(arg, ":byte")) return (0);
68   return (PyInt_FromLong(grand_byte(GRAND_R(me))));
69 }
70
71 static PyObject *grmeth_word(PyObject *me, PyObject *arg)
72 {
73   if (!PyArg_ParseTuple(arg, ":word")) return (0);
74   return (getu32(grand_word(GRAND_R(me))));
75 }
76
77 static PyObject *grmeth_range(PyObject *me, PyObject *arg)
78 {
79   PyObject *m;
80   mp *x = 0;
81   mp *y = 0;
82
83   if (!PyArg_ParseTuple(arg, "O:range", &m)) return (0);
84   if (PyInt_Check(m)) {
85     long mm = PyInt_AS_LONG(m);
86     if (mm < 0)
87       goto negative;
88     if (mm <= 0xffffffff)
89       return (PyInt_FromLong(grand_range(GRAND_R(me), mm)));
90   }
91   if ((x = getmp(m)) == 0)
92     goto end;
93   if (MP_NEGP(x))
94     goto negative;
95   y = mprand_range(MP_NEW, x, GRAND_R(me), 0);
96   MP_DROP(x);
97   return (mp_pywrap(y));
98 negative:
99   TYERR("range must be nonnegative");
100 end:
101   if (x) MP_DROP(x);
102   return (0);
103 }
104
105 static PyObject *grmeth_mp(PyObject *me, PyObject *arg, PyObject *kw)
106 {
107   size_t l;
108   mpw o;
109   char *kwlist[] = { "bits", "or", 0 };
110
111   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:mp", kwlist,
112                                    convszt, &l, convmpw, &o))
113     goto end;
114   return (mp_pywrap(mprand(MP_NEW, l, GRAND_R(me), o)));
115 end:
116   return (0);
117 }
118
119 static PyObject *grmeth_block(PyObject *me, PyObject *arg)
120 {
121   unsigned long n;
122   PyObject *rc = 0;
123
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);
127 end:
128   return (rc);
129 }
130
131 static int checkop(grand *r, unsigned op, const char *what)
132 {
133   if (r->ops->misc(r, GRAND_CHECK, op))
134     return (0);
135   PyErr_Format(PyExc_TypeError, "operation %s not supported", what);
136   return (-1);
137 }
138
139 static PyObject *grmeth_seedint(PyObject *me, PyObject *arg)
140 {
141   int i;
142   grand *r = GRAND_R(me);
143   if (!PyArg_ParseTuple(arg, "i:seedint", &i) ||
144       checkop(r, GRAND_SEEDINT, "seedint"))
145     goto end;
146   r->ops->misc(r, GRAND_SEEDINT, i);
147   RETURN_ME;
148 end:
149   return (0);
150 }
151
152 static PyObject *grmeth_seedword(PyObject *me, PyObject *arg)
153 {
154   uint32 u;
155   grand *r = GRAND_R(me);
156   if (!PyArg_ParseTuple(arg, "O&:seedword", convu32, &u) ||
157       checkop(r, GRAND_SEEDUINT32, "seedword"))
158     goto end;
159   r->ops->misc(r, GRAND_SEEDUINT32, u);
160   RETURN_ME;
161 end:
162   return (0);
163 }
164
165 static PyObject *grmeth_seedblock(PyObject *me, PyObject *arg)
166 {
167   char *p;
168   int n;
169   grand *r = GRAND_R(me);
170   if (!PyArg_ParseTuple(arg, "s#:seedblock", &p, &n) ||
171       checkop(r, GRAND_SEEDBLOCK, "seedblock"))
172     goto end;
173   r->ops->misc(r, GRAND_SEEDBLOCK, p, (size_t)n);
174   RETURN_ME;
175 end:
176   return (0);
177 }
178
179 static PyObject *grmeth_seedmp(PyObject *me, PyObject *arg)
180 {
181   PyObject *x;
182   mp *xx;
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)
187     goto end;
188   r->ops->misc(r, GRAND_SEEDMP, xx);
189   MP_DROP(xx);
190   RETURN_ME;
191 end:
192   return (0);
193 }
194
195 static PyObject *grmeth_seedrand(PyObject *me, PyObject *arg, PyObject *kw)
196 {
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,
201                                    convgrand, &rr) ||
202       checkop(r, GRAND_SEEDRAND, "seedrand"))
203     goto end;
204   r->ops->misc(r, GRAND_SEEDRAND, rr);
205   RETURN_ME;
206 end:
207   return (0);
208 }
209
210 static PyObject *grmeth_mask(PyObject *me, PyObject *arg)
211 {
212   grand *r = GRAND_R(me);
213   char *p, *q;
214   int sz;
215   PyObject *rc;
216
217   if (!PyArg_ParseTuple(arg, "s#:mask", &p, &sz)) return (0);
218   rc = bytestring_pywrap(0, sz);
219   q = PyString_AS_STRING(rc);
220   GR_FILL(r, q, sz);
221   while (sz--) *q++ ^= *p++;
222   return (rc);
223 }
224
225 static void grand_pydealloc(PyObject *me)
226 {
227   grand_pyobj *g = (grand_pyobj *)me;
228   if (g->f & f_freeme)
229     GR_DESTROY(g->r);
230   FREEOBJ(me);
231 }
232
233 static PyObject *grget_name(PyObject *me, void *hunoz)
234   { return (PyString_FromString(GRAND_R(me)->ops->name)); }
235
236 static PyObject *grget_cryptop(PyObject *me, void *hunoz)
237   { return (getbool(GRAND_R(me)->ops->f & GRAND_CRYPTO)); }
238
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?")
243 #undef GETSETNAME
244   { 0 }
245 };
246
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)")
260 #undef METHNAME
261   { 0 }
262 };
263
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@ */
269
270   grand_pydealloc,                      /* @tp_dealloc@ */
271   0,                                    /* @tp_print@ */
272   0,                                    /* @tp_getattr@ */
273   0,                                    /* @tp_setattr@ */
274   0,                                    /* @tp_compare@ */
275   0,                                    /* @tp_repr@ */
276   0,                                    /* @tp_as_number@ */
277   0,                                    /* @tp_as_sequence@ */
278   0,                                    /* @tp_as_mapping@ */
279   0,                                    /* @tp_hash@ */
280   0,                                    /* @tp_call@ */
281   0,                                    /* @tp_str@ */
282   0,                                    /* @tp_getattro@ */
283   0,                                    /* @tp_setattro@ */
284   0,                                    /* @tp_as_buffer@ */
285   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
286     Py_TPFLAGS_BASETYPE,
287
288   /* @tp_doc@ */
289 "Generic random number source.",
290
291   0,                                    /* @tp_traverse@ */
292   0,                                    /* @tp_clear@ */
293   0,                                    /* @tp_richcompare@ */
294   0,                                    /* @tp_weaklistoffset@ */
295   0,                                    /* @tp_iter@ */
296   0,                                    /* @tp_iternexr@ */
297   grand_pymethods,                      /* @tp_methods@ */
298   0,                                    /* @tp_members@ */
299   grand_pygetset,                       /* @tp_getset@ */
300   0,                                    /* @tp_base@ */
301   0,                                    /* @tp_dict@ */
302   0,                                    /* @tp_descr_get@ */
303   0,                                    /* @tp_descr_set@ */
304   0,                                    /* @tp_dictoffset@ */
305   0,                                    /* @tp_init@ */
306   PyType_GenericAlloc,                  /* @tp_alloc@ */
307   abstract_pynew,                       /* @tp_new@ */
308   0,                                    /* @tp_free@ */
309   0                                     /* @tp_is_gc@ */
310 };
311
312 static PyObject *lcrand_pynew(PyTypeObject *me, PyObject *arg, PyObject *kw)
313 {
314   uint32 n = 0;
315   char *kwlist[] = { "seed", 0 };
316   if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", kwlist, convu32, &n))
317     return (0);
318   return (grand_dopywrap(lcrand_pytype, lcrand_create(n), f_freeme));
319 }
320
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@ */
326
327   grand_pydealloc,                      /* @tp_dealloc@ */
328   0,                                    /* @tp_print@ */
329   0,                                    /* @tp_getattr@ */
330   0,                                    /* @tp_setattr@ */
331   0,                                    /* @tp_compare@ */
332   0,                                    /* @tp_repr@ */
333   0,                                    /* @tp_as_number@ */
334   0,                                    /* @tp_as_sequence@ */
335   0,                                    /* @tp_as_mapping@ */
336   0,                                    /* @tp_hash@ */
337   0,                                    /* @tp_call@ */
338   0,                                    /* @tp_str@ */
339   0,                                    /* @tp_getattro@ */
340   0,                                    /* @tp_setattro@ */
341   0,                                    /* @tp_as_buffer@ */
342   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
343     Py_TPFLAGS_BASETYPE,
344
345   /* @tp_doc@ */
346 "Linear congruential generator.",
347
348   0,                                    /* @tp_traverse@ */
349   0,                                    /* @tp_clear@ */
350   0,                                    /* @tp_richcompare@ */
351   0,                                    /* @tp_weaklistoffset@ */
352   0,                                    /* @tp_iter@ */
353   0,                                    /* @tp_iternexr@ */
354   0,                                    /* @tp_methods@ */
355   0,                                    /* @tp_members@ */
356   0,                                    /* @tp_getset@ */
357   0,                                    /* @tp_base@ */
358   0,                                    /* @tp_dict@ */
359   0,                                    /* @tp_descr_get@ */
360   0,                                    /* @tp_descr_set@ */
361   0,                                    /* @tp_dictoffset@ */
362   0,                                    /* @tp_init@ */
363   PyType_GenericAlloc,                  /* @tp_alloc@ */
364   lcrand_pynew,                         /* @tp_new@ */
365   0,                                    /* @tp_free@ */
366   0                                     /* @tp_is_gc@ */
367 };
368
369 static PyObject *fibrand_pynew(PyTypeObject *me, PyObject *arg, PyObject *kw)
370 {
371   uint32 n = 0;
372   char *kwlist[] = { "seed", 0 };
373   if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", kwlist, convu32, &n))
374     return (0);
375   return (grand_dopywrap(fibrand_pytype, fibrand_create(n), f_freeme));
376 }
377
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@ */
383
384   grand_pydealloc,                      /* @tp_dealloc@ */
385   0,                                    /* @tp_print@ */
386   0,                                    /* @tp_getattr@ */
387   0,                                    /* @tp_setattr@ */
388   0,                                    /* @tp_compare@ */
389   0,                                    /* @tp_repr@ */
390   0,                                    /* @tp_as_number@ */
391   0,                                    /* @tp_as_sequence@ */
392   0,                                    /* @tp_as_mapping@ */
393   0,                                    /* @tp_hash@ */
394   0,                                    /* @tp_call@ */
395   0,                                    /* @tp_str@ */
396   0,                                    /* @tp_getattro@ */
397   0,                                    /* @tp_setattro@ */
398   0,                                    /* @tp_as_buffer@ */
399   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
400     Py_TPFLAGS_BASETYPE,
401
402   /* @tp_doc@ */
403 "Fibonacci generator.",
404
405   0,                                    /* @tp_traverse@ */
406   0,                                    /* @tp_clear@ */
407   0,                                    /* @tp_richcompare@ */
408   0,                                    /* @tp_weaklistoffset@ */
409   0,                                    /* @tp_iter@ */
410   0,                                    /* @tp_iternexr@ */
411   0,                                    /* @tp_methods@ */
412   0,                                    /* @tp_members@ */
413   0,                                    /* @tp_getset@ */
414   0,                                    /* @tp_base@ */
415   0,                                    /* @tp_dict@ */
416   0,                                    /* @tp_descr_get@ */
417   0,                                    /* @tp_descr_set@ */
418   0,                                    /* @tp_dictoffset@ */
419   0,                                    /* @tp_init@ */
420   PyType_GenericAlloc,                  /* @tp_alloc@ */
421   fibrand_pynew,                        /* @tp_new@ */
422   0,                                    /* @tp_free@ */
423   0                                     /* @tp_is_gc@ */
424 };
425
426 /*----- True random generator ---------------------------------------------*/
427
428 static PyObject *trmeth_gate(PyObject *me, PyObject *arg)
429 {
430   grand *r = GRAND_R(me);
431   if (!PyArg_ParseTuple(arg, ":gate")) return (0);
432   r->ops->misc(r, RAND_GATE);
433   RETURN_ME;
434 }
435
436 static PyObject *trmeth_stretch(PyObject *me, PyObject *arg)
437 {
438   grand *r = GRAND_R(me);
439   if (!PyArg_ParseTuple(arg, ":stretch")) return (0);
440   r->ops->misc(r, RAND_STRETCH);
441   RETURN_ME;
442 }
443
444 static PyObject *trmeth_key(PyObject *me, PyObject *arg)
445 {
446   grand *r = GRAND_R(me);
447   char *p; int n;
448   if (!PyArg_ParseTuple(arg, "s#:key", &p, &n)) return (0);
449   r->ops->misc(r, RAND_KEY, p, n);
450   RETURN_ME;
451 }
452
453 static PyObject *trmeth_seed(PyObject *me, PyObject *arg)
454 {
455   grand *r = GRAND_R(me);
456   unsigned u;
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);
460   RETURN_ME;
461 end:
462   return (0);
463 }
464
465 static PyObject *trmeth_timer(PyObject *me, PyObject *arg)
466 {
467   grand *r = GRAND_R(me);
468   if (!PyArg_ParseTuple(arg, ":timer")) return (0);
469   r->ops->misc(r, RAND_TIMER);
470   RETURN_ME;
471 }
472
473 static PyObject *truerand_pynew(PyTypeObject *ty,
474                                 PyObject *arg, PyObject *kw)
475 {
476   char *kwlist[] = { 0 };
477   grand *r;
478   PyObject *rc = 0;
479   if (PyArg_ParseTupleAndKeywords(arg, kw, ":new", kwlist)) goto end;
480   r = rand_create();
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);
484 end:
485   return (rc);
486 }
487
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()")
495 #undef METHNAME
496   { 0 }
497 };
498
499 static PyObject *trget_goodbits(PyObject *me, void *hunoz)
500 {
501   grand *r = GRAND_R(me);
502   return (PyInt_FromLong(r->ops->misc(r, RAND_GOODBITS)));
503 }
504
505 static PyGetSetDef truerand_pygetset[] = {
506 #define GETSETNAME(op, name) tr##op##_##name
507   GET   (goodbits,      "R.goodbits -> good bits of entropy remaining")
508 #undef GETSETNAME
509   { 0 }
510 };
511
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@ */
517
518   grand_pydealloc,                      /* @tp_dealloc@ */
519   0,                                    /* @tp_print@ */
520   0,                                    /* @tp_getattr@ */
521   0,                                    /* @tp_setattr@ */
522   0,                                    /* @tp_compare@ */
523   0,                                    /* @tp_repr@ */
524   0,                                    /* @tp_as_number@ */
525   0,                                    /* @tp_as_sequence@ */
526   0,                                    /* @tp_as_mapping@ */
527   0,                                    /* @tp_hash@ */
528   0,                                    /* @tp_call@ */
529   0,                                    /* @tp_str@ */
530   0,                                    /* @tp_getattro@ */
531   0,                                    /* @tp_setattro@ */
532   0,                                    /* @tp_as_buffer@ */
533   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
534     Py_TPFLAGS_BASETYPE,
535
536   /* @tp_doc@ */
537 "True random number source.",
538
539   0,                                    /* @tp_traverse@ */
540   0,                                    /* @tp_clear@ */
541   0,                                    /* @tp_richcompare@ */
542   0,                                    /* @tp_weaklistoffset@ */
543   0,                                    /* @tp_iter@ */
544   0,                                    /* @tp_iternexr@ */
545   truerand_pymethods,                   /* @tp_methods@ */
546   0,                                    /* @tp_members@ */
547   truerand_pygetset,                    /* @tp_getset@ */
548   0,                                    /* @tp_base@ */
549   0,                                    /* @tp_dict@ */
550   0,                                    /* @tp_descr_get@ */
551   0,                                    /* @tp_descr_set@ */
552   0,                                    /* @tp_dictoffset@ */
553   0,                                    /* @tp_init@ */
554   PyType_GenericAlloc,                  /* @tp_alloc@ */
555   truerand_pynew,                       /* @tp_new@ */
556   0,                                    /* @tp_free@ */
557   0                                     /* @tp_is_gc@ */
558 };
559
560 /*----- SSL and TLS generators --------------------------------------------*/
561
562 static PyObject *sslprf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
563 {
564   char *k, *s;
565   int ksz, ssz;
566   const gchash *hco = &md5, *hci = &sha;
567   PyObject *rc = 0;
568   char *kwlist[] = { "key", "seed", "ohash", "ihash", 0 };
569
570   if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&O&:new", kwlist,
571                                    &k, &ksz, &s, &ssz,
572                                    convgchash, &hco, convgchash, &hci))
573     goto end;
574   rc = grand_dopywrap(ty, sslprf_rand(hco, hci, k, ksz, s, ssz), f_freeme);
575 end:
576   return (rc);
577 }
578
579 static PyObject *tlsdx_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
580 {
581   char *k, *s;
582   int ksz, ssz;
583   const gcmac *mc = &sha_hmac;
584   PyObject *rc = 0;
585   char *kwlist[] = { "key", "seed", "mac", 0 };
586
587   if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&:new", kwlist,
588                                    &k, &ksz, &s, &ssz,
589                                    convgcmac, &mc))
590     goto end;
591   rc = grand_dopywrap(ty, tlsdx_rand(mc, k, ksz, s, ssz), f_freeme);
592 end:
593   return (rc);
594 }
595
596 static PyObject *tlsprf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
597 {
598   char *k, *s;
599   int ksz, ssz;
600   const gcmac *mcl = &md5_hmac, *mcr = &sha_hmac;
601   PyObject *rc = 0;
602   char *kwlist[] = { "key", "seed", "lmac", "rmac", 0 };
603
604   if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&O&:new", kwlist,
605                                    &k, &ksz, &s, &ssz,
606                                    convgcmac, &mcl, convgcmac, &mcr))
607     goto end;
608   rc = grand_dopywrap(ty, tlsprf_rand(mcl, mcr, k, ksz, s, ssz), f_freeme);
609 end:
610   return (rc);
611 }
612
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@ */
618
619   grand_pydealloc,                      /* @tp_dealloc@ */
620   0,                                    /* @tp_print@ */
621   0,                                    /* @tp_getattr@ */
622   0,                                    /* @tp_setattr@ */
623   0,                                    /* @tp_compare@ */
624   0,                                    /* @tp_repr@ */
625   0,                                    /* @tp_as_number@ */
626   0,                                    /* @tp_as_sequence@ */
627   0,                                    /* @tp_as_mapping@ */
628   0,                                    /* @tp_hash@ */
629   0,                                    /* @tp_call@ */
630   0,                                    /* @tp_str@ */
631   0,                                    /* @tp_getattro@ */
632   0,                                    /* @tp_setattro@ */
633   0,                                    /* @tp_as_buffer@ */
634   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
635     Py_TPFLAGS_BASETYPE,
636
637   /* @tp_doc@ */
638 "Random number generator for SSL master secret.",
639
640   0,                                    /* @tp_traverse@ */
641   0,                                    /* @tp_clear@ */
642   0,                                    /* @tp_richcompare@ */
643   0,                                    /* @tp_weaklistoffset@ */
644   0,                                    /* @tp_iter@ */
645   0,                                    /* @tp_iternexr@ */
646   0,                                    /* @tp_methods@ */
647   0,                                    /* @tp_members@ */
648   0,                                    /* @tp_getset@ */
649   0,                                    /* @tp_base@ */
650   0,                                    /* @tp_dict@ */
651   0,                                    /* @tp_descr_get@ */
652   0,                                    /* @tp_descr_set@ */
653   0,                                    /* @tp_dictoffset@ */
654   0,                                    /* @tp_init@ */
655   PyType_GenericAlloc,                  /* @tp_alloc@ */
656   sslprf_pynew,                         /* @tp_new@ */
657   0,                                    /* @tp_free@ */
658   0                                     /* @tp_is_gc@ */
659 };
660
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@ */
666
667   grand_pydealloc,                      /* @tp_dealloc@ */
668   0,                                    /* @tp_print@ */
669   0,                                    /* @tp_getattr@ */
670   0,                                    /* @tp_setattr@ */
671   0,                                    /* @tp_compare@ */
672   0,                                    /* @tp_repr@ */
673   0,                                    /* @tp_as_number@ */
674   0,                                    /* @tp_as_sequence@ */
675   0,                                    /* @tp_as_mapping@ */
676   0,                                    /* @tp_hash@ */
677   0,                                    /* @tp_call@ */
678   0,                                    /* @tp_str@ */
679   0,                                    /* @tp_getattro@ */
680   0,                                    /* @tp_setattro@ */
681   0,                                    /* @tp_as_buffer@ */
682   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
683     Py_TPFLAGS_BASETYPE,
684
685   /* @tp_doc@ */
686 "TLS data expansion function.",
687
688   0,                                    /* @tp_traverse@ */
689   0,                                    /* @tp_clear@ */
690   0,                                    /* @tp_richcompare@ */
691   0,                                    /* @tp_weaklistoffset@ */
692   0,                                    /* @tp_iter@ */
693   0,                                    /* @tp_iternexr@ */
694   0,                                    /* @tp_methods@ */
695   0,                                    /* @tp_members@ */
696   0,                                    /* @tp_getset@ */
697   0,                                    /* @tp_base@ */
698   0,                                    /* @tp_dict@ */
699   0,                                    /* @tp_descr_get@ */
700   0,                                    /* @tp_descr_set@ */
701   0,                                    /* @tp_dictoffset@ */
702   0,                                    /* @tp_init@ */
703   PyType_GenericAlloc,                  /* @tp_alloc@ */
704   tlsdx_pynew,                          /* @tp_new@ */
705   0,                                    /* @tp_free@ */
706   0                                     /* @tp_is_gc@ */
707 };
708
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@ */
714
715   grand_pydealloc,                      /* @tp_dealloc@ */
716   0,                                    /* @tp_print@ */
717   0,                                    /* @tp_getattr@ */
718   0,                                    /* @tp_setattr@ */
719   0,                                    /* @tp_compare@ */
720   0,                                    /* @tp_repr@ */
721   0,                                    /* @tp_as_number@ */
722   0,                                    /* @tp_as_sequence@ */
723   0,                                    /* @tp_as_mapping@ */
724   0,                                    /* @tp_hash@ */
725   0,                                    /* @tp_call@ */
726   0,                                    /* @tp_str@ */
727   0,                                    /* @tp_getattro@ */
728   0,                                    /* @tp_setattro@ */
729   0,                                    /* @tp_as_buffer@ */
730   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
731     Py_TPFLAGS_BASETYPE,
732
733   /* @tp_doc@ */
734 "TLS pseudorandom function.",
735
736   0,                                    /* @tp_traverse@ */
737   0,                                    /* @tp_clear@ */
738   0,                                    /* @tp_richcompare@ */
739   0,                                    /* @tp_weaklistoffset@ */
740   0,                                    /* @tp_iter@ */
741   0,                                    /* @tp_iternexr@ */
742   0,                                    /* @tp_methods@ */
743   0,                                    /* @tp_members@ */
744   0,                                    /* @tp_getset@ */
745   0,                                    /* @tp_base@ */
746   0,                                    /* @tp_dict@ */
747   0,                                    /* @tp_descr_get@ */
748   0,                                    /* @tp_descr_set@ */
749   0,                                    /* @tp_dictoffset@ */
750   0,                                    /* @tp_init@ */
751   PyType_GenericAlloc,                  /* @tp_alloc@ */
752   tlsprf_pynew,                         /* @tp_new@ */
753   0,                                    /* @tp_free@ */
754   0                                     /* @tp_is_gc@ */
755 };
756
757 /*----- DSA generator -----------------------------------------------------*/
758
759 static PyObject *dsarand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
760 {
761   char *p;
762   int sz;
763   PyObject *rc = 0;
764   char *kwlist[] = { "seed", 0 };
765
766   if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &p, &sz))
767     goto end;
768   rc = grand_dopywrap(ty, dsarand_create(p, sz), f_freeme);
769 end:
770   return (0);
771 }
772
773 static PyObject *drget_seed(PyObject *me, void *hunoz)
774 {
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));
779   return (rc);
780 }
781
782 static PyGetSetDef dsarand_pygetset[] = {
783 #define GETSETNAME(op, name) dr##op##_##name
784   GET   (seed,          "R.seed -> current generator seed")
785 #undef GETSETNAME
786   { 0 }
787 };
788
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@ */
794
795   grand_pydealloc,                      /* @tp_dealloc@ */
796   0,                                    /* @tp_print@ */
797   0,                                    /* @tp_getattr@ */
798   0,                                    /* @tp_setattr@ */
799   0,                                    /* @tp_compare@ */
800   0,                                    /* @tp_repr@ */
801   0,                                    /* @tp_as_number@ */
802   0,                                    /* @tp_as_sequence@ */
803   0,                                    /* @tp_as_mapping@ */
804   0,                                    /* @tp_hash@ */
805   0,                                    /* @tp_call@ */
806   0,                                    /* @tp_str@ */
807   0,                                    /* @tp_getattro@ */
808   0,                                    /* @tp_setattro@ */
809   0,                                    /* @tp_as_buffer@ */
810   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
811     Py_TPFLAGS_BASETYPE,
812
813   /* @tp_doc@ */
814 "Pseudorandom number generator for constructing DSA parameters.",
815
816   0,                                    /* @tp_traverse@ */
817   0,                                    /* @tp_clear@ */
818   0,                                    /* @tp_richcompare@ */
819   0,                                    /* @tp_weaklistoffset@ */
820   0,                                    /* @tp_iter@ */
821   0,                                    /* @tp_iternexr@ */
822   0,                                    /* @tp_methods@ */
823   0,                                    /* @tp_members@ */
824   dsarand_pygetset,                     /* @tp_getset@ */
825   0,                                    /* @tp_base@ */
826   0,                                    /* @tp_dict@ */
827   0,                                    /* @tp_descr_get@ */
828   0,                                    /* @tp_descr_set@ */
829   0,                                    /* @tp_dictoffset@ */
830   0,                                    /* @tp_init@ */
831   PyType_GenericAlloc,                  /* @tp_alloc@ */
832   dsarand_pynew,                        /* @tp_new@ */
833   0,                                    /* @tp_free@ */
834   0                                     /* @tp_is_gc@ */
835 };
836
837 /*----- Blum-Blum-Shub generator ------------------------------------------*/
838
839 static PyObject *bbs_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
840 {
841   mp *n = 0, *x = MP_TWO;
842   PyObject *rc = 0;
843   char *kwlist[] = { "n", "x", 0 };
844
845   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", kwlist,
846                                    convmp, &n, convmp, &x))
847     goto end;
848   rc = grand_dopywrap(ty, bbs_rand(n, x), f_freeme);
849 end:
850   mp_drop(n);
851   mp_drop(x);
852   return (rc);
853 }
854
855 static PyObject *bbsmeth_step(PyObject *me, PyObject *arg)
856 {
857   grand *r = GRAND_R(me); if (!PyArg_ParseTuple(arg, ":step")) return (0);
858   r->ops->misc(r, BBS_STEP); RETURN_ME;
859 }
860
861 static PyObject *bbsmeth_bits(PyObject *me, PyObject *arg)
862 {
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));
867 end:
868   return (0);
869 }
870
871 static PyObject *bbsmeth_wrap(PyObject *me, PyObject *arg)
872 {
873   grand *r = GRAND_R(me); if (!PyArg_ParseTuple(arg, ":wrap")) return (0);
874   r->ops->misc(r, BBS_WRAP); RETURN_ME;
875 }
876
877 static PyObject *bbsget_n(PyObject *me, void *hunoz)
878 {
879   mp *x = MP_NEW; grand *r = GRAND_R(me);
880   r->ops->misc(r, BBS_MOD, &x); return (mp_pywrap(x));
881 }
882
883 static PyObject *bbsget_x(PyObject *me, void *hunoz)
884 {
885   mp *x = MP_NEW; grand *r = GRAND_R(me);
886   r->ops->misc(r, BBS_STATE, &x); return (mp_pywrap(x));
887 }
888
889 static int bbsset_x(PyObject *me, PyObject *val, void *hunoz)
890 {
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);
894 }
895
896 static PyObject *bbsget_stepsz(PyObject *me, void *hunoz)
897 {
898   grand *r = GRAND_R(me);
899   return (PyInt_FromLong(r->ops->misc(r, BBS_STEPSZ)));
900 }
901
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")
907 #undef METHNAME
908   { 0 }
909 };
910
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")
916 #undef GETSETNAME
917   { 0 }
918 };
919
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@ */
925
926   grand_pydealloc,                      /* @tp_dealloc@ */
927   0,                                    /* @tp_print@ */
928   0,                                    /* @tp_getattr@ */
929   0,                                    /* @tp_setattr@ */
930   0,                                    /* @tp_compare@ */
931   0,                                    /* @tp_repr@ */
932   0,                                    /* @tp_as_number@ */
933   0,                                    /* @tp_as_sequence@ */
934   0,                                    /* @tp_as_mapping@ */
935   0,                                    /* @tp_hash@ */
936   0,                                    /* @tp_call@ */
937   0,                                    /* @tp_str@ */
938   0,                                    /* @tp_getattro@ */
939   0,                                    /* @tp_setattro@ */
940   0,                                    /* @tp_as_buffer@ */
941   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
942     Py_TPFLAGS_BASETYPE,
943
944   /* @tp_doc@ */
945 "Blum-Blum-Shub strong pseudorandom number generator.",
946
947   0,                                    /* @tp_traverse@ */
948   0,                                    /* @tp_clear@ */
949   0,                                    /* @tp_richcompare@ */
950   0,                                    /* @tp_weaklistoffset@ */
951   0,                                    /* @tp_iter@ */
952   0,                                    /* @tp_iternexr@ */
953   bbs_pymethods,                        /* @tp_methods@ */
954   0,                                    /* @tp_members@ */
955   bbs_pygetset,                         /* @tp_getset@ */
956   0,                                    /* @tp_base@ */
957   0,                                    /* @tp_dict@ */
958   0,                                    /* @tp_descr_get@ */
959   0,                                    /* @tp_descr_set@ */
960   0,                                    /* @tp_dictoffset@ */
961   0,                                    /* @tp_init@ */
962   PyType_GenericAlloc,                  /* @tp_alloc@ */
963   bbs_pynew,                            /* @tp_new@ */
964   0,                                    /* @tp_free@ */
965   0                                     /* @tp_is_gc@ */
966 };
967
968 typedef struct bbspriv_pyobj {
969   grand_pyobj gr;
970   bbs_priv bp;
971 } bbspriv_pyobj;
972
973 #define BBSPRIV_BP(o) (&((bbspriv_pyobj *)(o))->bp)
974
975 static PyObject *bbspriv_pynew(PyTypeObject *ty,
976                                PyObject *arg, PyObject *kw)
977 {
978   mp *p = 0, *q = 0, *n = 0, *x = MP_TWO;
979   bbspriv_pyobj *rc = 0;
980   char *kwlist[] = { "n", "p", "q", "seed", 0 };
981
982   if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&O&O&O&:new", kwlist,
983                                    convmp, &n, convmp, &p, convmp, &q,
984                                    convmp, &x))
985     goto end;
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);
992   rc->gr.f = f_freeme;
993   rc->bp.p = MP_COPY(p);
994   rc->bp.q = MP_COPY(q);
995   rc->bp.n = MP_COPY(n);
996 end:
997   mp_drop(p); mp_drop(q); mp_drop(n); mp_drop(x);
998   return ((PyObject *)rc);
999 }
1000
1001 static PyObject *meth__BBSPriv_generate(PyObject *me,
1002                                         PyObject *arg, PyObject *kw)
1003 {
1004   bbs_priv bp = { 0 };
1005   mp *x = MP_TWO;
1006   pgev evt = { 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;
1011
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))
1015     goto end;
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);
1024 end:
1025   mp_drop(bp.p); mp_drop(bp.q); mp_drop(bp.n); mp_drop(x);
1026   return ((PyObject *)rc); 
1027 }
1028
1029 static void bbspriv_pydealloc(PyObject *me)
1030 {
1031   bbs_priv *bp = BBSPRIV_BP(me);
1032   mp_drop(bp->n);
1033   mp_drop(bp->p);
1034   mp_drop(bp->q);
1035   grand_pydealloc(me);
1036 }
1037
1038 static PyObject *bpmeth_ff(PyObject *me, PyObject *arg)
1039 {
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;
1043 }
1044
1045 static PyObject *bpmeth_rew(PyObject *me, PyObject *arg)
1046 {
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;
1050 }
1051
1052 static PyObject *bpget_n(PyObject *me, void *hunoz)
1053   { return (mp_pywrap(MP_COPY(BBSPRIV_BP(me)->n))); }
1054
1055 static PyObject *bpget_p(PyObject *me, void *hunoz)
1056   { return (mp_pywrap(MP_COPY(BBSPRIV_BP(me)->p))); }
1057
1058 static PyObject *bpget_q(PyObject *me, void *hunoz)
1059   { return (mp_pywrap(MP_COPY(BBSPRIV_BP(me)->q))); }
1060
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")
1065 #undef METHNAME
1066   { 0 }
1067 };
1068
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")
1074 #undef GETSETNAME
1075   { 0 }
1076 };
1077
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@ */
1083
1084   bbspriv_pydealloc,                    /* @tp_dealloc@ */
1085   0,                                    /* @tp_print@ */
1086   0,                                    /* @tp_getattr@ */
1087   0,                                    /* @tp_setattr@ */
1088   0,                                    /* @tp_compare@ */
1089   0,                                    /* @tp_repr@ */
1090   0,                                    /* @tp_as_number@ */
1091   0,                                    /* @tp_as_sequence@ */
1092   0,                                    /* @tp_as_mapping@ */
1093   0,                                    /* @tp_hash@ */
1094   0,                                    /* @tp_call@ */
1095   0,                                    /* @tp_str@ */
1096   0,                                    /* @tp_getattro@ */
1097   0,                                    /* @tp_setattro@ */
1098   0,                                    /* @tp_as_buffer@ */
1099   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
1100     Py_TPFLAGS_BASETYPE,
1101
1102   /* @tp_doc@ */
1103 "Blum-Blum-Shub strong pseudorandom generator, with private key.",
1104
1105   0,                                    /* @tp_traverse@ */
1106   0,                                    /* @tp_clear@ */
1107   0,                                    /* @tp_richcompare@ */
1108   0,                                    /* @tp_weaklistoffset@ */
1109   0,                                    /* @tp_iter@ */
1110   0,                                    /* @tp_iternexr@ */
1111   bbspriv_pymethods,                    /* @tp_methods@ */
1112   0,                                    /* @tp_members@ */
1113   bbspriv_pygetset,                     /* @tp_getset@ */
1114   0,                                    /* @tp_base@ */
1115   0,                                    /* @tp_dict@ */
1116   0,                                    /* @tp_descr_get@ */
1117   0,                                    /* @tp_descr_set@ */
1118   0,                                    /* @tp_dictoffset@ */
1119   0,                                    /* @tp_init@ */
1120   PyType_GenericAlloc,                  /* @tp_alloc@ */
1121   bbspriv_pynew,                        /* @tp_new@ */
1122   0,                                    /* @tp_free@ */
1123   0                                     /* @tp_is_gc@ */
1124 };
1125
1126 /*----- Global stuff ------------------------------------------------------*/
1127
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])")
1132 #undef METHNAME
1133   { 0 }
1134 };
1135
1136 void rand_pyinit(void)
1137 {
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);
1151 }
1152
1153 void rand_pyinsert(PyObject *mod)
1154 {
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);
1167 }
1168
1169 /*----- That's all, folks -------------------------------------------------*/