chiark / gitweb /
gf: New methods for various modular operations.
[catacomb-python] / algorithms.c
CommitLineData
d7ab1bab 1/* -*-c-*-
2 *
3 * $Id$
4 *
5 * Symmetric cryptography
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#include "algorithms.h"
33
34/*----- Key sizes ---------------------------------------------------------*/
35
36PyTypeObject *keysz_pytype;
37PyTypeObject *keyszany_pytype, *keyszrange_pytype, *keyszset_pytype;
38PyObject *sha_pyobj, *has160_pyobj;
39
40PyObject *keysz_pywrap(const octet *k)
41{
42 switch (k[0]) {
43 case KSZ_ANY: {
44 keysz_pyobj *o = PyObject_New(keysz_pyobj, keyszany_pytype);
45 o->dfl = k[1];
46 return ((PyObject *)o);
47 } break;
48 case KSZ_RANGE: {
49 keyszrange_pyobj *o =
50 PyObject_New(keyszrange_pyobj, keyszrange_pytype);
51 o->dfl = k[1];
52 o->min = k[2];
53 o->max = k[3];
54 o->mod = k[4];
55 if (!o->mod) o->mod = 1;
56 return ((PyObject *)o);
57 } break;
58 case KSZ_SET: {
59 keyszset_pyobj *o =
60 PyObject_New(keyszset_pyobj, keyszset_pytype);
61 int i, n;
62 o->dfl = k[1];
63 for (i = 0; k[i + 1]; i++) ;
64 n = i; o->set = PyTuple_New(n);
65 for (i = 0; i < n; i++)
66 PyTuple_SET_ITEM(o->set, i, PyInt_FromLong(k[i + 1]));
67 return ((PyObject *)o);
68 } break;
69 default:
70 abort();
71 }
72}
73
74static PyObject *keyszany_pynew(PyTypeObject *ty,
75 PyObject *arg, PyObject *kw)
76{
77 char *kwlist[] = { "default", 0 };
78 int dfl;
79 keysz_pyobj *o;
80
81 if (!PyArg_ParseTupleAndKeywords(arg, kw, "i:new", kwlist, &dfl))
82 goto end;
83 if (dfl < 0) VALERR("key size cannot be negative");
84 o = (keysz_pyobj *)ty->tp_alloc(ty, 0);
85 o->dfl = dfl;
86 return ((PyObject *)o);
87end:
88 return (0);
89}
90
91static PyObject *keyszrange_pynew(PyTypeObject *ty,
92 PyObject *arg, PyObject *kw)
93{
94 char *kwlist[] = { "default", "min", "max", "mod", 0 };
95 int dfl, min = 0, max = 0, mod = 1;
96 keyszrange_pyobj *o;
97
98 if (!PyArg_ParseTupleAndKeywords(arg, kw, "i|iii:new", kwlist,
99 &dfl, &min, &max, &mod))
100 goto end;
101 if (dfl < 0 || min < 0 || max < 0)
102 VALERR("key size cannot be negative");
103 if (min > dfl || (max && dfl > max))
104 VALERR("bad key size bounds");
105 if (mod <= 0 || dfl % mod || min % mod || max % mod)
106 VALERR("bad key size modulus");
107 o = (keyszrange_pyobj *)ty->tp_alloc(ty, 0);
108 o->dfl = dfl;
109 o->min = min;
110 o->max = max;
111 o->mod = mod;
112 return ((PyObject *)o);
113end:
114 return (0);
115}
116
117static PyObject *keyszset_pynew(PyTypeObject *ty,
118 PyObject *arg, PyObject *kw)
119{
120 char *kwlist[] = { "default", "set", 0 };
121 int dfl, i, n, xx;
122 PyObject *set = 0;
123 PyObject *x = 0, *l = 0;
124 keyszset_pyobj *o = 0;
125
126 if (!PyArg_ParseTupleAndKeywords(arg, kw, "i|O:new", kwlist,
127 &dfl, &set))
128 goto end;
129 if (!set) set = PyTuple_New(0);
130 else Py_INCREF(set);
131 if (!PySequence_Check(set)) TYERR("want a sequence");
132 n = PySequence_Size(set);
133 l = PyList_New(0);
134 if (PyErr_Occurred()) goto end;
135 if (dfl < 0) VALERR("key size cannot be negative");
136 x = PyInt_FromLong(dfl);
137 PyList_Append(l, x);
138 Py_DECREF(x);
139 x = 0;
140 for (i = 0; i < n; i++) {
141 if ((x = PySequence_GetItem(set, i)) == 0) goto end;
142 xx = PyInt_AsLong(x);
143 if (PyErr_Occurred()) goto end;
144 if (xx == dfl) continue;
145 if (xx < 0) VALERR("key size cannot be negative");
146 PyList_Append(l, x);
147 Py_DECREF(x);
148 x = 0;
149 }
150 Py_DECREF(set);
151 if ((set = PySequence_Tuple(l)) == 0) goto end;
152 o = (keyszset_pyobj *)ty->tp_alloc(ty, 0);
153 o->dfl = dfl;
154 o->set = set;
155 Py_INCREF(set);
156end:
157 Py_XDECREF(set);
158 Py_XDECREF(l);
159 Py_XDECREF(x);
160 return ((PyObject *)o);
161}
162
163static PyObject *kaget_min(PyObject *me, void *hunoz)
164 { return (PyInt_FromLong(0)); }
165#define kaget_max kaget_min
166
167static PyObject *ksget_min(PyObject *me, void *hunoz)
168{
169 PyObject *set = ((keyszset_pyobj *)me)->set;
170 int i, n, y, x = -1;
171 n = PyTuple_Size(set);
172 for (i = 0; i < n; i++) {
173 y = PyInt_AsLong(PyTuple_GetItem(set, i));
174 if (x == -1 || y < x) x = y;
175 }
176 return (PyInt_FromLong(x));
177}
178
179static PyObject *ksget_max(PyObject *me, void *hunoz)
180{
181 PyObject *set = ((keyszset_pyobj *)me)->set;
182 int i, n, y, x = -1;
183 n = PyTuple_Size(set);
184 for (i = 0; i < n; i++) {
185 y = PyInt_AsLong(PyTuple_GetItem(set, i));
186 if (y > x) x = y;
187 }
188 return (PyInt_FromLong(x));
189}
190
191static PyMemberDef keysz_pymembers[] = {
192#define MEMBERSTRUCT keysz_pyobj
193#define default dfl /* ugh! */
194 MEMBER(default, T_INT, READONLY, "KSZ.default -> default key size")
195#undef default
196#undef MEMBERSTRUCT
197 { 0 }
198};
199
200static PyGetSetDef keyszany_pygetset[] = {
201#define GETSETNAME(op, name) ka##op##_##name
202 GET (min, "KSZ.min -> smallest allowed key size")
203 GET (max, "KSZ.min -> largest allowed key size")
204#undef GETSETNAME
205 { 0 }
206};
207
208static PyMemberDef keyszrange_pymembers[] = {
209#define MEMBERSTRUCT keyszrange_pyobj
210 MEMBER(min, T_INT, READONLY, "KSZ.min -> smallest allowed key size")
211 MEMBER(max, T_INT, READONLY, "KSZ.min -> largest allowed key size")
212 MEMBER(mod, T_INT, READONLY,
213 "KSZ.mod -> key size must be a multiple of this")
214#undef MEMBERSTRUCT
215 { 0 }
216};
217
218static PyGetSetDef keyszset_pygetset[] = {
219#define GETSETNAME(op, name) ks##op##_##name
220 GET (min, "KSZ.min -> smallest allowed key size")
221 GET (max, "KSZ.min -> largest allowed key size")
222#undef GETSETNAME
223 { 0 }
224};
225
226static PyMemberDef keyszset_pymembers[] = {
227#define MEMBERSTRUCT keyszset_pyobj
228 MEMBER(set, T_OBJECT, READONLY, "KSZ.set -> allowed key sizes")
229#undef MEMBERSTRUCT
230 { 0 }
231};
232
233static PyTypeObject keysz_pytype_skel = {
6d4db0bf 234 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 235 "catacomb.KeySZ", /* @tp_name@ */
236 sizeof(keysz_pyobj), /* @tp_basicsize@ */
237 0, /* @tp_itemsize@ */
238
3aa33042 239 0, /* @tp_dealloc@ */
d7ab1bab 240 0, /* @tp_print@ */
241 0, /* @tp_getattr@ */
242 0, /* @tp_setattr@ */
243 0, /* @tp_compare@ */
244 0, /* @tp_repr@ */
245 0, /* @tp_as_number@ */
246 0, /* @tp_as_sequence@ */
247 0, /* @tp_as_mapping@ */
248 0, /* @tp_hash@ */
249 0, /* @tp_call@ */
250 0, /* @tp_str@ */
251 0, /* @tp_getattro@ */
252 0, /* @tp_setattro@ */
253 0, /* @tp_as_buffer@ */
254 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
255 Py_TPFLAGS_BASETYPE,
256
257 /* @tp_doc@ */
258"Key size constraints.",
259
260 0, /* @tp_traverse@ */
261 0, /* @tp_clear@ */
262 0, /* @tp_richcompare@ */
263 0, /* @tp_weaklistoffset@ */
264 0, /* @tp_iter@ */
963a6148 265 0, /* @tp_iternext@ */
d7ab1bab 266 0, /* @tp_methods@ */
267 keysz_pymembers, /* @tp_members@ */
268 0, /* @tp_getset@ */
269 0, /* @tp_base@ */
270 0, /* @tp_dict@ */
271 0, /* @tp_descr_get@ */
272 0, /* @tp_descr_set@ */
273 0, /* @tp_dictoffset@ */
274 0, /* @tp_init@ */
275 PyType_GenericAlloc, /* @tp_alloc@ */
276 abstract_pynew, /* @tp_new@ */
3aa33042 277 0, /* @tp_free@ */
d7ab1bab 278 0 /* @tp_is_gc@ */
279};
280
281static PyTypeObject keyszany_pytype_skel = {
6d4db0bf 282 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 283 "catacomb.KeySZAny", /* @tp_name@ */
284 sizeof(keysz_pyobj), /* @tp_basicsize@ */
285 0, /* @tp_itemsize@ */
286
3aa33042 287 0, /* @tp_dealloc@ */
d7ab1bab 288 0, /* @tp_print@ */
289 0, /* @tp_getattr@ */
290 0, /* @tp_setattr@ */
291 0, /* @tp_compare@ */
292 0, /* @tp_repr@ */
293 0, /* @tp_as_number@ */
294 0, /* @tp_as_sequence@ */
295 0, /* @tp_as_mapping@ */
296 0, /* @tp_hash@ */
297 0, /* @tp_call@ */
298 0, /* @tp_str@ */
299 0, /* @tp_getattro@ */
300 0, /* @tp_setattro@ */
301 0, /* @tp_as_buffer@ */
302 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
303 Py_TPFLAGS_BASETYPE,
304
305 /* @tp_doc@ */
306"Key size constraints. This object imposes no constraints on size.",
307
308 0, /* @tp_traverse@ */
309 0, /* @tp_clear@ */
310 0, /* @tp_richcompare@ */
311 0, /* @tp_weaklistoffset@ */
312 0, /* @tp_iter@ */
963a6148 313 0, /* @tp_iternext@ */
d7ab1bab 314 0, /* @tp_methods@ */
315 0, /* @tp_members@ */
316 keyszany_pygetset, /* @tp_getset@ */
317 0, /* @tp_base@ */
318 0, /* @tp_dict@ */
319 0, /* @tp_descr_get@ */
320 0, /* @tp_descr_set@ */
321 0, /* @tp_dictoffset@ */
322 0, /* @tp_init@ */
323 PyType_GenericAlloc, /* @tp_alloc@ */
324 keyszany_pynew, /* @tp_new@ */
3aa33042 325 0, /* @tp_free@ */
d7ab1bab 326 0 /* @tp_is_gc@ */
327};
328
329static PyTypeObject keyszrange_pytype_skel = {
6d4db0bf 330 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 331 "catacomb.KeySZRange", /* @tp_name@ */
332 sizeof(keyszrange_pyobj), /* @tp_basicsize@ */
333 0, /* @tp_itemsize@ */
334
3aa33042 335 0, /* @tp_dealloc@ */
d7ab1bab 336 0, /* @tp_print@ */
337 0, /* @tp_getattr@ */
338 0, /* @tp_setattr@ */
339 0, /* @tp_compare@ */
340 0, /* @tp_repr@ */
341 0, /* @tp_as_number@ */
342 0, /* @tp_as_sequence@ */
343 0, /* @tp_as_mapping@ */
344 0, /* @tp_hash@ */
345 0, /* @tp_call@ */
346 0, /* @tp_str@ */
347 0, /* @tp_getattro@ */
348 0, /* @tp_setattro@ */
349 0, /* @tp_as_buffer@ */
350 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
351 Py_TPFLAGS_BASETYPE,
352
353 /* @tp_doc@ */
354"Key size constraints. This object asserts minimum and maximum (if\n\
355sizes, and requires the key length to be a multiple of some value.",
356
357 0, /* @tp_traverse@ */
358 0, /* @tp_clear@ */
359 0, /* @tp_richcompare@ */
360 0, /* @tp_weaklistoffset@ */
361 0, /* @tp_iter@ */
963a6148 362 0, /* @tp_iternext@ */
d7ab1bab 363 0, /* @tp_methods@ */
364 keyszrange_pymembers, /* @tp_members@ */
365 0, /* @tp_getset@ */
366 0, /* @tp_base@ */
367 0, /* @tp_dict@ */
368 0, /* @tp_descr_get@ */
369 0, /* @tp_descr_set@ */
370 0, /* @tp_dictoffset@ */
371 0, /* @tp_init@ */
372 PyType_GenericAlloc, /* @tp_alloc@ */
373 keyszrange_pynew, /* @tp_new@ */
3aa33042 374 0, /* @tp_free@ */
d7ab1bab 375 0 /* @tp_is_gc@ */
376};
377
378static PyTypeObject keyszset_pytype_skel = {
6d4db0bf 379 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 380 "catacomb.KeySZSet", /* @tp_name@ */
381 sizeof(keyszset_pyobj), /* @tp_basicsize@ */
382 0, /* @tp_itemsize@ */
383
3aa33042 384 0, /* @tp_dealloc@ */
d7ab1bab 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"Key size constraints. This object requires the key to be one of a\n\
404few listed sizes.",
405
406 0, /* @tp_traverse@ */
407 0, /* @tp_clear@ */
408 0, /* @tp_richcompare@ */
409 0, /* @tp_weaklistoffset@ */
410 0, /* @tp_iter@ */
963a6148 411 0, /* @tp_iternext@ */
d7ab1bab 412 0, /* @tp_methods@ */
413 keyszset_pymembers, /* @tp_members@ */
414 keyszset_pygetset, /* @tp_getset@ */
415 0, /* @tp_base@ */
416 0, /* @tp_dict@ */
417 0, /* @tp_descr_get@ */
418 0, /* @tp_descr_set@ */
419 0, /* @tp_dictoffset@ */
420 0, /* @tp_init@ */
421 PyType_GenericAlloc, /* @tp_alloc@ */
422 keyszset_pynew, /* @tp_new@ */
3aa33042 423 0, /* @tp_free@ */
d7ab1bab 424 0 /* @tp_is_gc@ */
425};
426
427/*----- Symmetric encryption ----------------------------------------------*/
428
429PyTypeObject *gccipher_pytype, *gcipher_pytype;
430
431CONVFUNC(gccipher, gccipher *, GCCIPHER_CC)
432CONVFUNC(gcipher, gcipher *, GCIPHER_C)
433
434PyObject *gcipher_pywrap(PyObject *cobj, gcipher *c, unsigned f)
435{
436 gcipher_pyobj *g;
437 if (!cobj) cobj = gccipher_pywrap((/*unconst*/ gccipher *)GC_CLASS(c));
438 else Py_INCREF(cobj);
439 g = PyObject_NEW(gcipher_pyobj, (PyTypeObject *)cobj);
440 g->c = c;
441 g->f = f;
442 return ((PyObject *)g);
443}
444
445static PyObject *gcipher_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
446{
447 char *kwlist[] = { "k", 0 };
448 char *k;
449 int sz;
450
451 if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz))
452 goto end;
453 if (keysz(sz, GCCIPHER_CC(ty)->keysz) != sz) VALERR("bad key length");
454 return (gcipher_pywrap((PyObject *)ty,
455 GC_INIT(GCCIPHER_CC(ty), k, sz),
456 f_freeme));
457end:
458 return (0);
459}
460
461PyObject *gccipher_pywrap(gccipher *cc)
462{
df9f8366 463 gccipher_pyobj *g = newtype(gccipher_pytype, 0, cc->name);
d7ab1bab 464 g->cc = cc;
df9f8366 465 g->ty.type.tp_basicsize = sizeof(gcipher_pyobj);
466 g->ty.type.tp_base = gcipher_pytype;
d7ab1bab 467 Py_INCREF(gcipher_pytype);
df9f8366 468 g->ty.type.tp_flags = (Py_TPFLAGS_DEFAULT |
469 Py_TPFLAGS_BASETYPE |
470 Py_TPFLAGS_HEAPTYPE);
471 g->ty.type.tp_alloc = PyType_GenericAlloc;
472 g->ty.type.tp_free = 0;
473 g->ty.type.tp_new = gcipher_pynew;
474 PyType_Ready(&g->ty.type);
d7ab1bab 475 return ((PyObject *)g);
476}
477
478static void gcipher_pydealloc(PyObject *me)
479{
480 if (GCIPHER_F(me) & f_freeme)
481 GC_DESTROY(GCIPHER_C(me));
482 Py_DECREF(me->ob_type);
3aa33042 483 FREEOBJ(me);
d7ab1bab 484}
485
486static PyObject *gccget_name(PyObject *me, void *hunoz)
487 { return (PyString_FromString(GCCIPHER_CC(me)->name)); }
488
489static PyObject *gccget_keysz(PyObject *me, void *hunoz)
490 { return (keysz_pywrap(GCCIPHER_CC(me)->keysz)); }
491
492static PyObject *gccget_blksz(PyObject *me, void *hunoz)
493 { return (PyInt_FromLong(GCCIPHER_CC(me)->blksz)); }
494
495static PyObject *gcmeth_encrypt(PyObject *me, PyObject *arg)
496{
497 char *p;
498 int sz;
499 PyObject *rc = 0;
500
501 if (!PyArg_ParseTuple(arg, "s#:encrypt", &p, &sz)) return (0);
502 rc = bytestring_pywrap(0, sz);
503 GC_ENCRYPT(GCIPHER_C(me), p, PyString_AS_STRING(rc), sz);
504 return (rc);
505}
506
507static PyObject *gcmeth_enczero(PyObject *me, PyObject *arg)
508{
509 char *p;
510 int sz;
511 PyObject *rc = 0;
512
513 if (!PyArg_ParseTuple(arg, "i:enczero", &sz)) return (0);
514 rc = bytestring_pywrap(0, sz);
515 p = PyString_AS_STRING(rc);
516 memset(p, 0, sz);
517 GC_ENCRYPT(GCIPHER_C(me), p, p, sz);
518 return (rc);
519}
520
521static PyObject *gcmeth_decrypt(PyObject *me, PyObject *arg)
522{
523 char *p;
524 int sz;
525 PyObject *rc = 0;
526
527 if (!PyArg_ParseTuple(arg, "s#:decrypt", &p, &sz)) return (0);
528 rc = bytestring_pywrap(0, sz);
529 GC_DECRYPT(GCIPHER_C(me), p, PyString_AS_STRING(rc), sz);
530 return (rc);
531}
532
533static PyObject *gcmeth_deczero(PyObject *me, PyObject *arg)
534{
535 char *p;
536 int sz;
537 PyObject *rc = 0;
538
539 if (!PyArg_ParseTuple(arg, "i:deczero", &sz)) return (0);
540 rc = bytestring_pywrap(0, sz);
541 p = PyString_AS_STRING(rc);
542 memset(p, 0, sz);
543 GC_DECRYPT(GCIPHER_C(me), p, p, sz);
544 return (rc);
545}
546
547static PyObject *gcmeth_setiv(PyObject *me, PyObject *arg)
548{
549 char *p;
550 int sz;
551
552 if (!PyArg_ParseTuple(arg, "s#:setiv", &p, &sz)) goto end;
553 if (!GC_CLASS(GCIPHER_C(me))->blksz) VALERR("not a block cipher mode");
554 if (sz != GC_CLASS(GCIPHER_C(me))->blksz) VALERR("bad IV length");
555 GC_SETIV(GCIPHER_C(me), p);
556 RETURN_ME;
557end:
558 return (0);
559}
560
561static PyObject *gcmeth_bdry(PyObject *me, PyObject *arg)
562{
563 if (!PyArg_ParseTuple(arg, ":bdry")) goto end;
564 if (!GC_CLASS(GCIPHER_C(me))->blksz) VALERR("not a block cipher mode");
565 GC_BDRY(GCIPHER_C(me));
566 RETURN_ME;
567end:
568 return (0);
569}
570
571static PyGetSetDef gccipher_pygetset[] = {
572#define GETSETNAME(op, name) gcc##op##_##name
573 GET (keysz, "CC.keysz -> acceptable key sizes")
574 GET (blksz, "CC.blksz -> block size, or zero")
575 GET (name, "CC.name -> name of this kind of cipher")
576#undef GETSETNAME
577 { 0 }
578};
579
580static PyMethodDef gcipher_pymethods[] = {
581#define METHNAME(name) gcmeth_##name
582 METH (encrypt, "C.encrypt(PT) -> CT")
583 METH (enczero, "C.enczero(N) -> CT")
584 METH (decrypt, "C.decrypt(CT) -> PT")
585 METH (deczero, "C.deczero(N) -> PT")
586 METH (setiv, "C.setiv(IV)")
587 METH (bdry, "C.bdry()")
588#undef METHNAME
589 { 0 }
590};
591
592static PyTypeObject gccipher_pytype_skel = {
6d4db0bf 593 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 594 "catacomb.GCCipher", /* @tp_name@ */
595 sizeof(gccipher_pyobj), /* @tp_basicsize@ */
596 0, /* @tp_itemsize@ */
597
598 0, /* @tp_dealloc@ */
599 0, /* @tp_print@ */
600 0, /* @tp_getattr@ */
601 0, /* @tp_setattr@ */
602 0, /* @tp_compare@ */
603 0, /* @tp_repr@ */
604 0, /* @tp_as_number@ */
605 0, /* @tp_as_sequence@ */
606 0, /* @tp_as_mapping@ */
607 0, /* @tp_hash@ */
608 0, /* @tp_call@ */
609 0, /* @tp_str@ */
610 0, /* @tp_getattro@ */
611 0, /* @tp_setattro@ */
612 0, /* @tp_as_buffer@ */
613 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
614 Py_TPFLAGS_BASETYPE,
615
616 /* @tp_doc@ */
617"Symmetric cipher metaclass.",
618
619 0, /* @tp_traverse@ */
620 0, /* @tp_clear@ */
621 0, /* @tp_richcompare@ */
622 0, /* @tp_weaklistoffset@ */
623 0, /* @tp_iter@ */
963a6148 624 0, /* @tp_iternext@ */
d7ab1bab 625 0, /* @tp_methods@ */
626 0, /* @tp_members@ */
627 gccipher_pygetset, /* @tp_getset@ */
628 0, /* @tp_base@ */
629 0, /* @tp_dict@ */
630 0, /* @tp_descr_get@ */
631 0, /* @tp_descr_set@ */
632 0, /* @tp_dictoffset@ */
633 0, /* @tp_init@ */
634 PyType_GenericAlloc, /* @tp_alloc@ */
635 abstract_pynew, /* @tp_new@ */
3aa33042 636 0, /* @tp_free@ */
d7ab1bab 637 0 /* @tp_is_gc@ */
638};
639
640static PyTypeObject gcipher_pytype_skel = {
6d4db0bf 641 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 642 "catacomb.GCipher", /* @tp_name@ */
643 sizeof(gcipher_pyobj), /* @tp_basicsize@ */
644 0, /* @tp_itemsize@ */
645
646 gcipher_pydealloc, /* @tp_dealloc@ */
647 0, /* @tp_print@ */
648 0, /* @tp_getattr@ */
649 0, /* @tp_setattr@ */
650 0, /* @tp_compare@ */
651 0, /* @tp_repr@ */
652 0, /* @tp_as_number@ */
653 0, /* @tp_as_sequence@ */
654 0, /* @tp_as_mapping@ */
655 0, /* @tp_hash@ */
656 0, /* @tp_call@ */
657 0, /* @tp_str@ */
658 0, /* @tp_getattro@ */
659 0, /* @tp_setattro@ */
660 0, /* @tp_as_buffer@ */
661 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
662 Py_TPFLAGS_BASETYPE,
663
664 /* @tp_doc@ */
665"Symmetric cipher, abstract base class.",
666
667 0, /* @tp_traverse@ */
668 0, /* @tp_clear@ */
669 0, /* @tp_richcompare@ */
670 0, /* @tp_weaklistoffset@ */
671 0, /* @tp_iter@ */
963a6148 672 0, /* @tp_iternext@ */
d7ab1bab 673 gcipher_pymethods, /* @tp_methods@ */
674 0, /* @tp_members@ */
675 0, /* @tp_getset@ */
676 0, /* @tp_base@ */
677 0, /* @tp_dict@ */
678 0, /* @tp_descr_get@ */
679 0, /* @tp_descr_set@ */
680 0, /* @tp_dictoffset@ */
681 0, /* @tp_init@ */
682 PyType_GenericAlloc, /* @tp_alloc@ */
683 abstract_pynew, /* @tp_new@ */
3aa33042 684 0, /* @tp_free@ */
d7ab1bab 685 0 /* @tp_is_gc@ */
686};
687
688/*----- Hash functions ----------------------------------------------------*/
689
690PyTypeObject *gchash_pytype, *ghash_pytype;
691
692CONVFUNC(gchash, gchash *, GCHASH_CH)
693CONVFUNC(ghash, ghash *, GHASH_H)
694
695static PyObject *ghash_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
696{
697 char *kwlist[] = { 0 };
698 if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", kwlist))
699 goto end;
700 return (ghash_pywrap((PyObject *)ty, GH_INIT(GCHASH_CH(ty)), f_freeme));
701end:
702 return (0);
703}
704
705PyObject *gchash_pywrap(gchash *ch)
706{
df9f8366 707 gchash_pyobj *g = newtype(gchash_pytype, 0, ch->name);
d7ab1bab 708 g->ch = ch;
df9f8366 709 g->ty.type.tp_basicsize = sizeof(ghash_pyobj);
710 g->ty.type.tp_base = ghash_pytype;
d7ab1bab 711 Py_INCREF(ghash_pytype);
df9f8366 712 g->ty.type.tp_flags = (Py_TPFLAGS_DEFAULT |
713 Py_TPFLAGS_BASETYPE |
714 Py_TPFLAGS_HEAPTYPE);
715 g->ty.type.tp_alloc = PyType_GenericAlloc;
716 g->ty.type.tp_free = 0;
717 g->ty.type.tp_new = ghash_pynew;
718 PyType_Ready(&g->ty.type);
d7ab1bab 719 return ((PyObject *)g);
720}
721
722PyObject *ghash_pywrap(PyObject *cobj, ghash *h, unsigned f)
723{
724 ghash_pyobj *g;
725 if (!cobj) cobj = gchash_pywrap((/*unconst*/ gchash *)GH_CLASS(h));
726 else Py_INCREF(cobj);
727 g = PyObject_NEW(ghash_pyobj, (PyTypeObject *)cobj);
728 g->h = h;
729 g->f = f;
730 return ((PyObject *)g);
731}
732
733static void ghash_pydealloc(PyObject *me)
734{
735 if (GHASH_F(me) & f_freeme)
736 GH_DESTROY(GHASH_H(me));
737 Py_DECREF(me->ob_type);
3aa33042 738 FREEOBJ(me);
d7ab1bab 739}
740
741static PyObject *gchget_name(PyObject *me, void *hunoz)
742 { return (PyString_FromString(GCHASH_CH(me)->name)); }
743
744static PyObject *gchget_hashsz(PyObject *me, void *hunoz)
745 { return (PyInt_FromLong(GCHASH_CH(me)->hashsz)); }
746
747static PyObject *gchget_bufsz(PyObject *me, void *hunoz)
748 { return (PyInt_FromLong(GCHASH_CH(me)->bufsz)); }
749
750static PyObject *ghmeth_hash(PyObject *me, PyObject *arg)
751{
752 char *p;
753 int sz;
754 if (!PyArg_ParseTuple(arg, "s#:hash", &p, &sz)) return (0);
755 GH_HASH(GHASH_H(me), p, sz);
756 RETURN_ME;
757}
758
759static PyObject *ghmeth_done(PyObject *me, PyObject *arg)
760{
761 ghash *g;
762 PyObject *rc;
763 if (!PyArg_ParseTuple(arg, ":done")) return (0);
764 g = GH_COPY(GHASH_H(me));
765 rc = bytestring_pywrap(0, g->ops->c->hashsz);
766 GH_DONE(g, PyString_AS_STRING(rc));
767 GH_DESTROY(g);
768 return (rc);
769}
770
771static PyGetSetDef gchash_pygetset[] = {
772#define GETSETNAME(op, name) gch##op##_##name
773 GET (bufsz, "CH.bufsz -> hash buffer size, or zero")
774 GET (hashsz, "CH.blksz -> hash output size")
775 GET (name, "CH.name -> name of this kind of hash")
776#undef GETSETNAME
777 { 0 }
778};
779
46e6ad89 780#define GHMETH_HASHU_(n, W, w) \
781 static PyObject *ghmeth_hashu##w(PyObject *me, PyObject *arg) \
782 { \
783 uint##n x; \
784 if (!PyArg_ParseTuple(arg, "O&:hashu" #w, convu##n, &x)) goto end; \
785 GH_HASHU##W(GHASH_H(me), x); \
786 RETURN_ME; \
787 end: \
788 return (0); \
789 }
790DOUINTCONV(GHMETH_HASHU_)
791
792#define GHMETH_HASHBUF_(n, W, w) \
793 static PyObject *ghmeth_hashbuf##w(PyObject *me, PyObject *arg) \
794 { \
795 char *p; \
796 int sz; \
797 if (!PyArg_ParseTuple(arg, "s#:hashbuf" #w, &p, &sz)) goto end; \
798 if (sz > MASK##n) TYERR("string too long"); \
799 GH_HASHBUF##W(GHASH_H(me), p, sz); \
800 RETURN_ME; \
801 end: \
802 return (0); \
803 }
804DOUINTCONV(GHMETH_HASHBUF_)
805
806static PyObject *ghmeth_hashstrz(PyObject *me, PyObject *arg)
807{
808 char *p;
809 if (!PyArg_ParseTuple(arg, "s:hashstrz", &p)) return (0);
810 GH_HASHSTRZ(GHASH_H(me), p);
811 RETURN_ME;
812}
813
d7ab1bab 814static PyMethodDef ghash_pymethods[] = {
815#define METHNAME(name) ghmeth_##name
816 METH (hash, "H.hash(M)")
46e6ad89 817#define METHU_(n, W, w) METH(hashu##w, "H.hashu" #w "(WORD)")
818 DOUINTCONV(METHU_)
819#define METHBUF_(n, W, w) METH(hashbuf##w, "H.hashbuf" #w "(BYTES)")
820 DOUINTCONV(METHBUF_)
821 METH (hashstrz, "H.hashstrz(STRING)")
d7ab1bab 822 METH (done, "H.done() -> HASH")
823#undef METHNAME
824 { 0 }
825};
826
827static PyTypeObject gchash_pytype_skel = {
6d4db0bf 828 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 829 "catacomb.GCHash", /* @tp_name@ */
830 sizeof(gchash_pyobj), /* @tp_basicsize@ */
831 0, /* @tp_itemsize@ */
832
833 0, /* @tp_dealloc@ */
834 0, /* @tp_print@ */
835 0, /* @tp_getattr@ */
836 0, /* @tp_setattr@ */
837 0, /* @tp_compare@ */
838 0, /* @tp_repr@ */
839 0, /* @tp_as_number@ */
840 0, /* @tp_as_sequence@ */
841 0, /* @tp_as_mapping@ */
842 0, /* @tp_hash@ */
843 0, /* @tp_call@ */
844 0, /* @tp_str@ */
845 0, /* @tp_getattro@ */
846 0, /* @tp_setattro@ */
847 0, /* @tp_as_buffer@ */
848 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
849 Py_TPFLAGS_BASETYPE,
850
851 /* @tp_doc@ */
852"Hash function metaclass.",
853
854 0, /* @tp_traverse@ */
855 0, /* @tp_clear@ */
856 0, /* @tp_richcompare@ */
857 0, /* @tp_weaklistoffset@ */
858 0, /* @tp_iter@ */
963a6148 859 0, /* @tp_iternext@ */
d7ab1bab 860 0, /* @tp_methods@ */
861 0, /* @tp_members@ */
862 gchash_pygetset, /* @tp_getset@ */
863 0, /* @tp_base@ */
864 0, /* @tp_dict@ */
865 0, /* @tp_descr_get@ */
866 0, /* @tp_descr_set@ */
867 0, /* @tp_dictoffset@ */
868 0, /* @tp_init@ */
869 PyType_GenericAlloc, /* @tp_alloc@ */
870 abstract_pynew, /* @tp_new@ */
3aa33042 871 0, /* @tp_free@ */
d7ab1bab 872 0 /* @tp_is_gc@ */
873};
874
875static PyTypeObject ghash_pytype_skel = {
6d4db0bf 876 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 877 "catacomb.GHash", /* @tp_name@ */
878 sizeof(ghash_pyobj), /* @tp_basicsize@ */
879 0, /* @tp_itemsize@ */
880
881 ghash_pydealloc, /* @tp_dealloc@ */
882 0, /* @tp_print@ */
883 0, /* @tp_getattr@ */
884 0, /* @tp_setattr@ */
885 0, /* @tp_compare@ */
886 0, /* @tp_repr@ */
887 0, /* @tp_as_number@ */
888 0, /* @tp_as_sequence@ */
889 0, /* @tp_as_mapping@ */
890 0, /* @tp_hash@ */
891 0, /* @tp_call@ */
892 0, /* @tp_str@ */
893 0, /* @tp_getattro@ */
894 0, /* @tp_setattro@ */
895 0, /* @tp_as_buffer@ */
896 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
897 Py_TPFLAGS_BASETYPE,
898
899 /* @tp_doc@ */
900"Hash function, abstract base class.",
901
902 0, /* @tp_traverse@ */
903 0, /* @tp_clear@ */
904 0, /* @tp_richcompare@ */
905 0, /* @tp_weaklistoffset@ */
906 0, /* @tp_iter@ */
963a6148 907 0, /* @tp_iternext@ */
d7ab1bab 908 ghash_pymethods, /* @tp_methods@ */
909 0, /* @tp_members@ */
910 0, /* @tp_getset@ */
911 0, /* @tp_base@ */
912 0, /* @tp_dict@ */
913 0, /* @tp_descr_get@ */
914 0, /* @tp_descr_set@ */
915 0, /* @tp_dictoffset@ */
916 0, /* @tp_init@ */
917 PyType_GenericAlloc, /* @tp_alloc@ */
918 abstract_pynew, /* @tp_new@ */
3aa33042 919 0, /* @tp_free@ */
d7ab1bab 920 0 /* @tp_is_gc@ */
921};
922
923/*----- Message authentication --------------------------------------------*/
924
925PyTypeObject *gcmac_pytype, *gmac_pytype, *gmhash_pytype;
926
927CONVFUNC(gcmac, gcmac *, GCMAC_CM)
928CONVFUNC(gmac, gmac *, GMAC_M)
929CONVFUNC(gmhash, ghash *, GHASH_H)
930
931static PyObject *gmac_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
932{
933 char *kwlist[] = { "k", 0 };
934 char *k;
935 int sz;
936
937 if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz))
938 goto end;
939 if (keysz(sz, GCMAC_CM(ty)->keysz) != sz) VALERR("bad key length");
940 return (gmac_pywrap((PyObject *)ty,
941 GM_KEY(GCMAC_CM(ty), k, sz),
942 f_freeme));
943end:
944 return (0);
945}
946
947static PyObject *gmhash_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
948{
949 char *kwlist[] = { 0 };
950 ghash_pyobj *g;
951
952 if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", kwlist)) return (0);
953 g = PyObject_NEW(ghash_pyobj, ty);
954 g->h = GM_INIT(GMAC_M(ty));
955 g->f = f_freeme;
956 Py_INCREF(ty);
957 return ((PyObject *)g);
958}
959
960PyObject *gcmac_pywrap(gcmac *cm)
961{
df9f8366 962 gcmac_pyobj *g = newtype(gcmac_pytype, 0, cm->name);
d7ab1bab 963 g->cm = cm;
df9f8366 964 g->ty.type.tp_basicsize = sizeof(gmac_pyobj);
965 g->ty.type.tp_base = gmac_pytype;
d7ab1bab 966 Py_INCREF(gmac_pytype);
df9f8366 967 g->ty.type.tp_flags = (Py_TPFLAGS_DEFAULT |
d7ab1bab 968 Py_TPFLAGS_BASETYPE |
969 Py_TPFLAGS_HEAPTYPE);
df9f8366 970 g->ty.type.tp_alloc = PyType_GenericAlloc;
971 g->ty.type.tp_free = 0;
972 g->ty.type.tp_new = gmac_pynew;
973 PyType_Ready(&g->ty.type);
d7ab1bab 974 return ((PyObject *)g);
975}
976
977PyObject *gmac_pywrap(PyObject *cobj, gmac *m, unsigned f)
978{
979 gmac_pyobj *g;
980 if (!cobj) cobj = gcmac_pywrap((/*unconst*/ gcmac *)GM_CLASS(m));
981 else Py_INCREF(cobj);
df9f8366 982 g = newtype((PyTypeObject *)cobj, 0, 0);
983 g->ty.name = PyString_FromFormat("%s(keyed)", m->ops->c->name);
984 g->ty.type.tp_name = PyString_AS_STRING(g->ty.name);
985 g->ty.type.tp_base = gmhash_pytype;
d7ab1bab 986 Py_INCREF(gmac_pytype);
df9f8366 987 g->ty.type.tp_flags = (Py_TPFLAGS_DEFAULT |
988 Py_TPFLAGS_BASETYPE |
989 Py_TPFLAGS_HEAPTYPE);
990 g->ty.type.tp_alloc = PyType_GenericAlloc;
991 g->ty.type.tp_free = 0;
992 g->ty.type.tp_new = gmhash_pynew;
993 PyType_Ready(&g->ty.type);
d7ab1bab 994 g->m = m;
995 g->f = f;
996 return ((PyObject *)g);
997}
998
999static void gmac_pydealloc(PyObject *me)
1000{
1001 if (GMAC_F(me) & f_freeme)
1002 GM_DESTROY(GMAC_M(me));
1003 Py_DECREF(me->ob_type);
d7ab1bab 1004 PyType_Type.tp_dealloc(me);
1005}
1006
1007static PyObject *gcmget_name(PyObject *me, void *hunoz)
1008 { return (PyString_FromString(GCMAC_CM(me)->name)); }
1009
1010static PyObject *gcmget_keysz(PyObject *me, void *hunoz)
1011 { return (keysz_pywrap(GCMAC_CM(me)->keysz)); }
1012
1013static PyObject *gcmget_tagsz(PyObject *me, void *hunoz)
1014 { return (PyInt_FromLong(GCMAC_CM(me)->hashsz)); }
1015
1016static PyGetSetDef gcmac_pygetset[] = {
1017#define GETSETNAME(op, name) gcm##op##_##name
1018 GET (keysz, "CM.keysz -> acceptable key sizes")
1019 GET (tagsz, "CM.tagsz -> MAC output size")
1020 GET (name, "CM.name -> name of this kind of MAC")
1021#undef GETSETNAME
1022 { 0 }
1023};
1024
1025static PyTypeObject gcmac_pytype_skel = {
6d4db0bf 1026 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 1027 "catacomb.GCMAC", /* @tp_name@ */
1028 sizeof(gchash_pyobj), /* @tp_basicsize@ */
1029 0, /* @tp_itemsize@ */
1030
1031 0, /* @tp_dealloc@ */
1032 0, /* @tp_print@ */
1033 0, /* @tp_getattr@ */
1034 0, /* @tp_setattr@ */
1035 0, /* @tp_compare@ */
1036 0, /* @tp_repr@ */
1037 0, /* @tp_as_number@ */
1038 0, /* @tp_as_sequence@ */
1039 0, /* @tp_as_mapping@ */
1040 0, /* @tp_hash@ */
1041 0, /* @tp_call@ */
1042 0, /* @tp_str@ */
1043 0, /* @tp_getattro@ */
1044 0, /* @tp_setattro@ */
1045 0, /* @tp_as_buffer@ */
1046 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
1047 Py_TPFLAGS_BASETYPE,
1048
1049 /* @tp_doc@ */
1050"Message authentication code metametaclass.",
1051
1052 0, /* @tp_traverse@ */
1053 0, /* @tp_clear@ */
1054 0, /* @tp_richcompare@ */
1055 0, /* @tp_weaklistoffset@ */
1056 0, /* @tp_iter@ */
963a6148 1057 0, /* @tp_iternext@ */
d7ab1bab 1058 0, /* @tp_methods@ */
1059 0, /* @tp_members@ */
1060 gcmac_pygetset, /* @tp_getset@ */
1061 0, /* @tp_base@ */
1062 0, /* @tp_dict@ */
1063 0, /* @tp_descr_get@ */
1064 0, /* @tp_descr_set@ */
1065 0, /* @tp_dictoffset@ */
1066 0, /* @tp_init@ */
1067 PyType_GenericAlloc, /* @tp_alloc@ */
1068 abstract_pynew, /* @tp_new@ */
3aa33042 1069 0, /* @tp_free@ */
d7ab1bab 1070 0 /* @tp_is_gc@ */
1071};
1072
1073static PyTypeObject gmac_pytype_skel = {
6d4db0bf 1074 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 1075 "catacomb.GMAC", /* @tp_name@ */
1076 sizeof(gmac_pyobj), /* @tp_basicsize@ */
1077 0, /* @tp_itemsize@ */
1078
1079 gmac_pydealloc, /* @tp_dealloc@ */
1080 0, /* @tp_print@ */
1081 0, /* @tp_getattr@ */
1082 0, /* @tp_setattr@ */
1083 0, /* @tp_compare@ */
1084 0, /* @tp_repr@ */
1085 0, /* @tp_as_number@ */
1086 0, /* @tp_as_sequence@ */
1087 0, /* @tp_as_mapping@ */
1088 0, /* @tp_hash@ */
1089 0, /* @tp_call@ */
1090 0, /* @tp_str@ */
1091 0, /* @tp_getattro@ */
1092 0, /* @tp_setattro@ */
1093 0, /* @tp_as_buffer@ */
1094 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
1095 Py_TPFLAGS_BASETYPE,
1096
1097 /* @tp_doc@ */
1098"Message authentication code metaclass, abstract base class.",
1099
1100 0, /* @tp_traverse@ */
1101 0, /* @tp_clear@ */
1102 0, /* @tp_richcompare@ */
1103 0, /* @tp_weaklistoffset@ */
1104 0, /* @tp_iter@ */
963a6148 1105 0, /* @tp_iternext@ */
d7ab1bab 1106 0, /* @tp_methods@ */
1107 0, /* @tp_members@ */
1108 0, /* @tp_getset@ */
1109 0, /* @tp_base@ */
1110 0, /* @tp_dict@ */
1111 0, /* @tp_descr_get@ */
1112 0, /* @tp_descr_set@ */
1113 0, /* @tp_dictoffset@ */
1114 0, /* @tp_init@ */
1115 PyType_GenericAlloc, /* @tp_alloc@ */
1116 abstract_pynew, /* @tp_new@ */
3aa33042 1117 0, /* @tp_free@ */
d7ab1bab 1118 0 /* @tp_is_gc@ */
1119};
1120
1121static PyTypeObject gmhash_pytype_skel = {
6d4db0bf 1122 PyObject_HEAD_INIT(0) 0, /* Header */
d7ab1bab 1123 "catacomb.GMACHash", /* @tp_name@ */
1124 sizeof(ghash_pyobj), /* @tp_basicsize@ */
1125 0, /* @tp_itemsize@ */
1126
1127 ghash_pydealloc, /* @tp_dealloc@ */
1128 0, /* @tp_print@ */
1129 0, /* @tp_getattr@ */
1130 0, /* @tp_setattr@ */
1131 0, /* @tp_compare@ */
1132 0, /* @tp_repr@ */
1133 0, /* @tp_as_number@ */
1134 0, /* @tp_as_sequence@ */
1135 0, /* @tp_as_mapping@ */
1136 0, /* @tp_hash@ */
1137 0, /* @tp_call@ */
1138 0, /* @tp_str@ */
1139 0, /* @tp_getattro@ */
1140 0, /* @tp_setattro@ */
1141 0, /* @tp_as_buffer@ */
1142 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
1143 Py_TPFLAGS_BASETYPE,
1144
1145 /* @tp_doc@ */
1146"Message authentication code, abstract base class.",
1147
1148 0, /* @tp_traverse@ */
1149 0, /* @tp_clear@ */
1150 0, /* @tp_richcompare@ */
1151 0, /* @tp_weaklistoffset@ */
1152 0, /* @tp_iter@ */
963a6148 1153 0, /* @tp_iternext@ */
d7ab1bab 1154 0, /* @tp_methods@ */
1155 0, /* @tp_members@ */
1156 0, /* @tp_getset@ */
1157 0, /* @tp_base@ */
1158 0, /* @tp_dict@ */
1159 0, /* @tp_descr_get@ */
1160 0, /* @tp_descr_set@ */
1161 0, /* @tp_dictoffset@ */
1162 0, /* @tp_init@ */
1163 PyType_GenericAlloc, /* @tp_alloc@ */
1164 abstract_pynew, /* @tp_new@ */
3aa33042 1165 0, /* @tp_free@ */
d7ab1bab 1166 0 /* @tp_is_gc@ */
1167};
1168
03ed9abb
MW
1169/*----- Pseudorandom permutations -----------------------------------------*/
1170
1171static PyTypeObject *gcprp_pytype, *gprp_pytype;
1172
1173typedef struct prpinfo {
1174 const char *name;
1175 const octet *keysz;
1176 size_t ctxsz;
1177 size_t blksz;
1178 void (*init)(void *, const void *, size_t);
1179 void (*eblk)(void *, const void *, void *);
1180 void (*dblk)(void *, const void *, void *);
1181} prpinfo;
1182
1183#define PRP_DEF(PRE, pre) \
1184 static void pre##_prpinit(void *ctx, const void *k, size_t ksz) \
1185 { pre##_init(ctx, k, ksz); } \
1186 static void pre##_prpeblk(void *ctx, const void *in, void *out) \
1187 { \
1188 uint32 w[PRE##_BLKSZ/4]; BLKC_LOAD(PRE, w, in); \
1189 pre##_eblk(ctx, w, w); BLKC_STORE(PRE, out, w); \
1190 } \
1191 static void pre##_prpdblk(void *ctx, const void *in, void *out) \
1192 { \
1193 uint32 w[PRE##_BLKSZ/4]; BLKC_LOAD(PRE, w, in); \
1194 pre##_dblk(ctx, w, w); BLKC_STORE(PRE, out, w); \
1195 } \
1196 static const prpinfo pre##_prpinfo = { \
1197 #pre, pre##_keysz, sizeof(pre##_ctx), PRE##_BLKSZ, \
1198 pre##_prpinit, pre##_prpeblk, pre##_prpdblk \
1199 };
1200PRPS(PRP_DEF)
1201
1202static const struct prpinfo *const gprptab[] = {
1203#define PRP_ENTRY(PRE, pre) &pre##_prpinfo,
1204 PRPS(PRP_ENTRY)
1205 0
1206};
1207
1208typedef struct gcprp_pyobj {
1209 PyHeapTypeObject ty;
1210 const prpinfo *prp;
1211} gcprp_pyobj;
1212#define GCPRP_PRP(o) (((gcprp_pyobj *)(o))->prp)
1213
1214typedef struct gprp_pyobj {
1215 PyObject_HEAD
1216 const prpinfo *prp;
1217} gprp_pyobj;
1218#define GPRP_PRP(o) (((gprp_pyobj *)(o))->prp)
1219#define GPRP_CTX(o) (((gprp_pyobj *)(o)) + 1)
1220
1221typedef struct prp {
1222 const prpinfo *prp;
1223 void *ctx;
1224} prp;
1225
1226static PyObject *gprp_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
1227{
1228 char *kwlist[] = { "key", 0 };
1229 char *k;
1230 int sz;
1231 const prpinfo *prp = GCPRP_PRP(ty);
1232 PyObject *me;
1233
1234 if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz))
1235 goto end;
1236 if (keysz(sz, prp->keysz) != sz) VALERR("bad key length");
1237 me = (PyObject *)ty->tp_alloc(ty, 0);
1238 GPRP_PRP(me) = prp;
1239 prp->init(GPRP_CTX(me), k, sz);
1240 Py_INCREF(me);
1241 return (me);
1242end:
1243 return (0);
1244}
1245
1246static void gprp_pydealloc(PyObject *me)
1247 { Py_DECREF(me->ob_type); FREEOBJ(me); }
1248
1249static PyObject *gcprp_pywrap(const prpinfo *prp)
1250{
1251 gcprp_pyobj *g = newtype(gcprp_pytype, 0, prp->name);
1252 g->prp = prp;
1253 g->ty.type.tp_basicsize = sizeof(gprp_pyobj) + prp->ctxsz;
1254 g->ty.type.tp_base = gprp_pytype;
1255 Py_INCREF(gprp_pytype);
1256 g->ty.type.tp_flags = (Py_TPFLAGS_DEFAULT |
1257 Py_TPFLAGS_BASETYPE |
1258 Py_TPFLAGS_HEAPTYPE);
1259 g->ty.type.tp_alloc = PyType_GenericAlloc;
1260 g->ty.type.tp_free = 0;
1261 g->ty.type.tp_new = gprp_pynew;
1262 PyType_Ready(&g->ty.type);
1263 return ((PyObject *)g);
1264}
1265
1266static PyObject *gcpget_name(PyObject *me, void *hunoz)
1267 { return (PyString_FromString(GCPRP_PRP(me)->name)); }
1268static PyObject *gcpget_keysz(PyObject *me, void *hunoz)
1269 { return (keysz_pywrap(GCPRP_PRP(me)->keysz)); }
1270static PyObject *gcpget_blksz(PyObject *me, void *hunoz)
1271 { return (PyInt_FromLong(GCPRP_PRP(me)->blksz)); }
1272
1273static PyObject *gpmeth_encrypt(PyObject *me, PyObject *arg)
1274{
1275 char *p;
1276 int n;
1277 PyObject *rc = 0;
1278
1279 if (!PyArg_ParseTuple(arg, "s#:encrypt", &p, &n)) goto end;
1280 if (n != GPRP_PRP(me)->blksz) VALERR("incorrect block length");
1281 rc = bytestring_pywrap(0, n);
1282 GPRP_PRP(me)->eblk(GPRP_CTX(me), p, PyString_AS_STRING(rc));
1283end:
1284 return (rc);
1285}
1286
1287static PyObject *gpmeth_decrypt(PyObject *me, PyObject *arg)
1288{
1289 char *p;
1290 int n;
1291 PyObject *rc = 0;
1292
1293 if (!PyArg_ParseTuple(arg, "s#:decrypt", &p, &n)) goto end;
1294 if (n != GPRP_PRP(me)->blksz) VALERR("incorrect block length");
1295 rc = bytestring_pywrap(0, n);
1296 GPRP_PRP(me)->dblk(GPRP_CTX(me), p, PyString_AS_STRING(rc));
1297end:
1298 return (rc);
1299}
1300
1301static PyGetSetDef gcprp_pygetset[] = {
1302#define GETSETNAME(op, name) gcp##op##_##name
1303 GET (keysz, "CP.keysz -> acceptable key sizes")
1304 GET (blksz, "CP.blksz -> block size")
1305 GET (name, "CP.name -> name of this kind of PRP")
1306#undef GETSETNAME
1307 { 0 }
1308};
1309
1310static PyMethodDef gprp_pymethods[] = {
1311#define METHNAME(name) gpmeth_##name
1312 METH (encrypt, "P.encrypt(PT) -> CT")
1313 METH (decrypt, "P.decrypt(CT) -> PT")
1314#undef METHNAME
1315 { 0 }
1316};
1317
1318static PyTypeObject gcprp_pytype_skel = {
1319 PyObject_HEAD_INIT(0) 0, /* Header */
1320 "catacomb.GCPRP", /* @tp_name@ */
1321 sizeof(gcprp_pyobj), /* @tp_basicsize@ */
1322 0, /* @tp_itemsize@ */
1323
1324 0, /* @tp_dealloc@ */
1325 0, /* @tp_print@ */
1326 0, /* @tp_getattr@ */
1327 0, /* @tp_setattr@ */
1328 0, /* @tp_compare@ */
1329 0, /* @tp_repr@ */
1330 0, /* @tp_as_number@ */
1331 0, /* @tp_as_sequence@ */
1332 0, /* @tp_as_mapping@ */
1333 0, /* @tp_hash@ */
1334 0, /* @tp_call@ */
1335 0, /* @tp_str@ */
1336 0, /* @tp_getattro@ */
1337 0, /* @tp_setattro@ */
1338 0, /* @tp_as_buffer@ */
1339 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
1340 Py_TPFLAGS_BASETYPE,
1341
1342 /* @tp_doc@ */
1343"Pseudorandom permutation metaclass.",
1344
1345 0, /* @tp_traverse@ */
1346 0, /* @tp_clear@ */
1347 0, /* @tp_richcompare@ */
1348 0, /* @tp_weaklistoffset@ */
1349 0, /* @tp_iter@ */
1350 0, /* @tp_iternext@ */
1351 0, /* @tp_methods@ */
1352 0, /* @tp_members@ */
1353 gcprp_pygetset, /* @tp_getset@ */
1354 0, /* @tp_base@ */
1355 0, /* @tp_dict@ */
1356 0, /* @tp_descr_get@ */
1357 0, /* @tp_descr_set@ */
1358 0, /* @tp_dictoffset@ */
1359 0, /* @tp_init@ */
1360 PyType_GenericAlloc, /* @tp_alloc@ */
1361 abstract_pynew, /* @tp_new@ */
1362 0, /* @tp_free@ */
1363 0 /* @tp_is_gc@ */
1364};
1365
1366static PyTypeObject gprp_pytype_skel = {
1367 PyObject_HEAD_INIT(0) 0, /* Header */
1368 "catacomb.GPRP", /* @tp_name@ */
1369 sizeof(gprp_pyobj), /* @tp_basicsize@ */
1370 0, /* @tp_itemsize@ */
1371
1372 gprp_pydealloc, /* @tp_dealloc@ */
1373 0, /* @tp_print@ */
1374 0, /* @tp_getattr@ */
1375 0, /* @tp_setattr@ */
1376 0, /* @tp_compare@ */
1377 0, /* @tp_repr@ */
1378 0, /* @tp_as_number@ */
1379 0, /* @tp_as_sequence@ */
1380 0, /* @tp_as_mapping@ */
1381 0, /* @tp_hash@ */
1382 0, /* @tp_call@ */
1383 0, /* @tp_str@ */
1384 0, /* @tp_getattro@ */
1385 0, /* @tp_setattro@ */
1386 0, /* @tp_as_buffer@ */
1387 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
1388 Py_TPFLAGS_BASETYPE,
1389
1390 /* @tp_doc@ */
1391"Pseudorandom permutation, abstract base class.",
1392
1393 0, /* @tp_traverse@ */
1394 0, /* @tp_clear@ */
1395 0, /* @tp_richcompare@ */
1396 0, /* @tp_weaklistoffset@ */
1397 0, /* @tp_iter@ */
1398 0, /* @tp_iternext@ */
1399 gprp_pymethods, /* @tp_methods@ */
1400 0, /* @tp_members@ */
1401 0, /* @tp_getset@ */
1402 0, /* @tp_base@ */
1403 0, /* @tp_dict@ */
1404 0, /* @tp_descr_get@ */
1405 0, /* @tp_descr_set@ */
1406 0, /* @tp_dictoffset@ */
1407 0, /* @tp_init@ */
1408 PyType_GenericAlloc, /* @tp_alloc@ */
1409 abstract_pynew, /* @tp_new@ */
1410 0, /* @tp_free@ */
1411 0 /* @tp_is_gc@ */
1412};
1413
d7ab1bab 1414/*----- Main code ---------------------------------------------------------*/
1415
1416void algorithms_pyinit(void)
1417{
1418 INITTYPE(keysz, root);
1419 INITTYPE(keyszany, keysz);
1420 INITTYPE(keyszrange, keysz);
1421 INITTYPE(keyszset, keysz);
1422 INITTYPE(gccipher, type);
1423 INITTYPE(gcipher, root);
1424 INITTYPE(gchash, type);
1425 INITTYPE(ghash, root);
1426 INITTYPE(gcmac, type);
1427 INITTYPE(gmac, type);
1428 INITTYPE(gmhash, ghash);
03ed9abb
MW
1429 INITTYPE(gcprp, type);
1430 INITTYPE(gprp, root);
d7ab1bab 1431}
1432
d7ab1bab 1433GEN(gcciphers, cipher)
1434GEN(gchashes, hash)
1435GEN(gcmacs, mac)
03ed9abb
MW
1436#define gcprp prpinfo
1437GEN(gcprps, prp)
d7ab1bab 1438
1439void algorithms_pyinsert(PyObject *mod)
1440{
1441 PyObject *d;
1442 INSERT("KeySZ", keysz_pytype);
1443 INSERT("KeySZAny", keyszany_pytype);
1444 INSERT("KeySZRange", keyszrange_pytype);
1445 INSERT("KeySZSet", keyszset_pytype);
1446 INSERT("GCCipher", gccipher_pytype);
1447 INSERT("GCipher", gcipher_pytype);
1448 INSERT("gcciphers", gcciphers());
1449 INSERT("GCHash", gchash_pytype);
1450 INSERT("GHash", ghash_pytype);
1451 INSERT("gchashes", d = gchashes());
1452 sha_pyobj = PyDict_GetItemString(d, "sha"); Py_INCREF(sha_pyobj);
1453 has160_pyobj = PyDict_GetItemString(d, "has160"); Py_INCREF(has160_pyobj);
1454 INSERT("GCMAC", gcmac_pytype);
1455 INSERT("GMAC", gmac_pytype);
1456 INSERT("GMACHash", gmhash_pytype);
1457 INSERT("gcmacs", gcmacs());
03ed9abb
MW
1458 INSERT("GCPRP", gcprp_pytype);
1459 INSERT("GPRP", gprp_pytype);
1460 INSERT("gcprps", gcprps());
d7ab1bab 1461}
1462
1463/*----- That's all, folks -------------------------------------------------*/