1 /** \ingroup py_c
2  * \file python/rng-py.c
3  */
4 
5 #define	_REENTRANT	1	/* XXX config.h collides with pyconfig.h */
6 #include "config.h"
7 
8 #include "Python.h"
9 #ifdef __LCLINT__
10 #undef  PyObject_HEAD
11 #define PyObject_HEAD   int _PyObjectHead;
12 #endif
13 
14 #include "beecrypt/python/rng-py.h"
15 
16 #include "debug-py.c"
17 
18 /*@unchecked@*/
19 static int _rng_debug = 0;
20 
21 /*@unchecked@*/ /*@observer@*/
22 static const char initialiser_name[] = "_bc.rng";
23 
24 /* ---------- */
25 
26 static void
rng_dealloc(rngObject * s)27 rng_dealloc(rngObject * s)
28 	/*@modifies s @*/
29 {
30 if (_rng_debug < -1)
31 fprintf(stderr, "*** rng_dealloc(%p)\n", s);
32 
33 /*@-modobserver@*/
34     randomGeneratorContextFree(&s->rngc);
35 /*@=modobserver@*/
36     mpbfree(&s->b);
37     PyObject_Del(s);
38 }
39 
40 static int
rng_print(rngObject * s,FILE * fp,int flags)41 rng_print(rngObject * s, FILE * fp, /*@unused@*/ int flags)
42 	/*@globals fileSystem @*/
43 	/*@modifies fileSystem @*/
44 {
45 if (_rng_debug < -1)
46 fprintf(stderr, "*** rng_print(%p)\n", s);
47     return 0;
48 }
49 
50 /** \ingroup py_c
51  */
rng_init(rngObject * s,PyObject * args,PyObject * kwds)52 static int rng_init(rngObject * s, PyObject *args, PyObject *kwds)
53 	/*@modifies s @*/
54 {
55     PyObject * o = NULL;
56     const randomGenerator* rng = NULL;
57 
58     if (!PyArg_ParseTuple(args, "|O:Cvt", &o)) return -1;
59 
60     if (o) {
61 	/* XXX "FIPS 186" or "Mersenne Twister" */
62 	if (PyString_Check(o))
63 	    rng = randomGeneratorFind(PyString_AsString(o));
64     }
65 
66     if (rng == NULL)
67 	rng = randomGeneratorDefault();
68 
69 /*@-modobserver@*/
70     if (randomGeneratorContextInit(&s->rngc, rng) != 0)
71 	return -1;
72 /*@=modobserver@*/
73     mpbzero(&s->b);
74 
75 if (_rng_debug)
76 fprintf(stderr, "*** rng_init(%p[%s],%p[%s],%p[%s])\n", s, lbl(s), args, lbl(args), kwds, lbl(kwds));
77 
78     return 0;
79 }
80 
81 /** \ingroup py_c
82  */
rng_free(rngObject * s)83 static void rng_free(/*@only@*/ rngObject * s)
84 	/*@modifies s @*/
85 {
86 if (_rng_debug)
87 fprintf(stderr, "*** rng_free(%p[%s])\n", s, lbl(s));
88 /*@-modobserver@*/
89     randomGeneratorContextFree(&s->rngc);
90 /*@=modobserver@*/
91     mpbfree(&s->b);
92     PyObject_Del(s);
93 }
94 
95 /** \ingroup py_c
96  */
rng_alloc(PyTypeObject * subtype,int nitems)97 static PyObject * rng_alloc(PyTypeObject * subtype, int nitems)
98 	/*@*/
99 {
100     PyObject * ns = PyType_GenericAlloc(subtype, nitems);
101 
102 if (_rng_debug)
103 fprintf(stderr, "*** rng_alloc(%p[%s},%d) ret %p[%s]\n", subtype, lbl(subtype), nitems, ns, lbl(ns));
104     return (PyObject *) ns;
105 }
106 
107 static PyObject *
rng_new(PyTypeObject * subtype,PyObject * args,PyObject * kwds)108 rng_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
109 	/*@*/
110 {
111     PyObject * ns = (PyObject *) PyObject_New(rngObject, &rng_Type);
112 
113 if (_rng_debug < -1)
114 fprintf(stderr, "*** rng_new(%p[%s],%p[%s],%p[%s]) ret %p[%s]\n", subtype, lbl(subtype), args, lbl(args), kwds, lbl(kwds), ns, lbl(ns));
115     return ns;
116 }
117 
118 static rngObject *
rng_New(void)119 rng_New(void)
120 {
121     rngObject * ns = PyObject_New(rngObject, &rng_Type);
122 
123     return ns;
124 }
125 
126 /* ---------- */
127 
128 /** \ingroup py_c
129  */
130 static PyObject *
rng_Debug(rngObject * s,PyObject * args)131 rng_Debug(/*@unused@*/ rngObject * s, PyObject * args)
132         /*@globals _Py_NoneStruct @*/
133         /*@modifies _Py_NoneStruct @*/
134 {
135     if (!PyArg_ParseTuple(args, "i:Debug", &_rng_debug)) return NULL;
136 
137 if (_rng_debug < 0)
138 fprintf(stderr, "*** rng_Debug(%p)\n", s);
139 
140     Py_INCREF(Py_None);
141     return Py_None;
142 }
143 
144 /** \ingroup py_c
145  */
146 static PyObject *
rng_Seed(rngObject * s,PyObject * args)147 rng_Seed(rngObject * s, PyObject * args)
148         /*@globals _Py_NoneStruct @*/
149         /*@modifies _Py_NoneStruct @*/
150 {
151     PyObject * o;
152     randomGeneratorContext* rc = &s->rngc;
153     mpwObject *z;
154 
155     if (!PyArg_ParseTuple(args, "O:Seed", &o)) return NULL;
156 
157     if (!mpw_Check(o) || MPW_SIZE(z = (mpwObject*)o) > 0)
158 	return NULL;
159 
160     rc->rng->seed(rc->param, (byte*) MPW_DATA(z), MPW_SIZE(z));
161 
162 if (_rng_debug < 0)
163 fprintf(stderr, "*** rng_Seed(%p)\n", s);
164 
165     Py_INCREF(Py_None);
166     return Py_None;
167 }
168 
169 /** \ingroup py_c
170  */
171 static PyObject *
rng_Next(rngObject * s,PyObject * args)172 rng_Next(rngObject * s, PyObject * args)
173         /*@*/
174 {
175     PyObject * o = NULL;
176     randomGeneratorContext* rc = &s->rngc;
177     mpbarrett* b = &s->b;
178     mpwObject *z;
179 
180     if (!PyArg_ParseTuple(args, "|O:Next", &o)) return NULL;
181 
182     if (o) {
183 	if (mpw_Check(o) && MPW_SIZE(z = (mpwObject*)o) > 0) {
184 	    b = alloca(sizeof(*b));
185 	    mpbzero(b);
186 	    /* XXX z probably needs normalization here. */
187 	    mpbset(b, MPW_SIZE(z), MPW_DATA(z));
188 	} else
189 	    ;	/* XXX error? */
190     }
191 
192     if (b == NULL || b->size == 0 || b->modl == NULL) {
193 	z = mpw_New(1);
194 	rc->rng->next(rc->param, (byte*) MPW_DATA(z), sizeof(*MPW_DATA(z)));
195     } else {
196 	mpw* wksp = alloca(b->size * sizeof(*wksp));
197 	z = mpw_New(b->size);
198 	mpbrnd_w(b, rc, MPW_DATA(z), wksp);
199     }
200 
201 if (_rng_debug)
202 fprintf(stderr, "*** rng_Next(%p) %p[%d]\t", s, MPW_DATA(z), MPW_SIZE(z)), mpfprintln(stderr, MPW_SIZE(z), MPW_DATA(z));
203 
204     return (PyObject *)z;
205 }
206 
207 /** \ingroup py_c
208  */
209 static PyObject *
rng_Prime(rngObject * s,PyObject * args)210 rng_Prime(rngObject * s, PyObject * args)
211         /*@*/
212 {
213     randomGeneratorContext* rc = &s->rngc;
214     unsigned pbits = 160;
215     int trials = -1;
216     size_t psize;
217     mpbarrett* b;
218     mpw *temp;
219     mpwObject *z;
220 
221     if (!PyArg_ParseTuple(args, "|ii:Prime", &pbits, &trials)) return NULL;
222 
223     psize = MP_ROUND_B2W(pbits);
224     temp = alloca((8*psize+2) * sizeof(*temp));
225 
226     b = alloca(sizeof(*b));
227     mpbzero(b);
228 
229     if (trials <= 2)
230 	trials = mpptrials(pbits);
231 #if 1
232     mpprnd_w(b, rc, pbits, trials, (const mpnumber*) 0, temp);
233 #else
234     mpprndsafe_w(b, rc, pbits, trials, temp);
235 #endif
236 
237     z = mpw_FromMPW(b->size, b->modl, 1);
238 if (z != NULL && _rng_debug)
239 fprintf(stderr, "*** rng_Prime(%p) %p[%d]\t", s, MPW_DATA(z), MPW_SIZE(z)), mpfprintln(stderr, MPW_SIZE(z), MPW_DATA(z));
240 
241     return (PyObject *)z;
242 }
243 
244 /*@-fullinitblock@*/
245 /*@unchecked@*/ /*@observer@*/
246 static struct PyMethodDef rng_methods[] = {
247  {"Debug",	(PyCFunction)rng_Debug,	METH_VARARGS,
248 	NULL},
249  {"seed",	(PyCFunction)rng_Seed,	METH_VARARGS,
250 	NULL},
251  {"next",	(PyCFunction)rng_Next,	METH_VARARGS,
252 	NULL},
253  {"prime",	(PyCFunction)rng_Prime,	METH_VARARGS,
254 	NULL},
255  {NULL,		NULL}		/* sentinel */
256 };
257 /*@=fullinitblock@*/
258 
rng_getattro(PyObject * o,PyObject * n)259 static PyObject * rng_getattro(PyObject * o, PyObject * n)
260 	/*@*/
261 {
262     return PyObject_GenericGetAttr(o, n);
263 }
264 
rng_setattro(PyObject * o,PyObject * n,PyObject * v)265 static int rng_setattro(PyObject * o, PyObject * n, PyObject * v)
266 	/*@*/
267 {
268     return PyObject_GenericSetAttr(o, n, v);
269 }
270 
271 /* ---------- */
272 
273 /**
274  */
275 /*@unchecked@*/ /*@observer@*/
276 static char rng_doc[] =
277 "";
278 
279 /*@-fullinitblock@*/
280 PyTypeObject rng_Type = {
281 	PyObject_HEAD_INIT(&PyType_Type)
282 	0,				/* ob_size */
283 	"_bc.rng",			/* tp_name */
284 	sizeof(rngObject),		/* tp_basicsize */
285 	0,				/* tp_itemsize */
286 	/* methods */
287 	(destructor) rng_dealloc,	/* tp_dealloc */
288 	(printfunc) rng_print,		/* tp_print */
289 	(getattrfunc)0,			/* tp_getattr */
290 	(setattrfunc)0,			/* tp_setattr */
291 	(cmpfunc)0,			/* tp_compare */
292 	(reprfunc)0,			/* tp_repr */
293 	0,				/* tp_as_number */
294 	0,				/* tp_as_sequence */
295 	0,				/* tp_as_mapping */
296 	(hashfunc)0,			/* tp_hash */
297 	(ternaryfunc)0,			/* tp_call */
298 	(reprfunc)0,			/* tp_str */
299 	(getattrofunc) rng_getattro,	/* tp_getattro */
300 	(setattrofunc) rng_setattro,	/* tp_setattro */
301 	0,				/* tp_as_buffer */
302 	Py_TPFLAGS_DEFAULT,		/* tp_flags */
303 	rng_doc,			/* tp_doc */
304 #if Py_TPFLAGS_HAVE_ITER
305 	0,				/* tp_traverse */
306 	0,				/* tp_clear */
307 	0,				/* tp_richcompare */
308 	0,				/* tp_weaklistoffset */
309 	(getiterfunc)0,			/* tp_iter */
310 	(iternextfunc)0,		/* tp_iternext */
311 	rng_methods,			/* tp_methods */
312 	0,				/* tp_members */
313 	0,				/* tp_getset */
314 	0,				/* tp_base */
315 	0,				/* tp_dict */
316 	0,				/* tp_descr_get */
317 	0,				/* tp_descr_set */
318 	0,				/* tp_dictoffset */
319 	(initproc) rng_init,		/* tp_init */
320 	(allocfunc) rng_alloc,		/* tp_alloc */
321 	(newfunc) rng_new,		/* tp_new */
322 	(destructor) rng_free,		/* tp_free */
323 	0,				/* tp_is_gc */
324 #endif
325 };
326 /*@=fullinitblock@*/
327 
328 /* ---------- */
329