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