5 * Symmetric cryptography
7 * (c) 2004 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of the Python interface to Catacomb.
14 * Catacomb/Python is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * Catacomb/Python is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Catacomb/Python; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /*----- Header files ------------------------------------------------------*/
31 #include "catacomb-python.h"
32 #include "algorithms.h"
34 /*----- Key sizes ---------------------------------------------------------*/
36 PyTypeObject
*keysz_pytype
;
37 PyTypeObject
*keyszany_pytype
, *keyszrange_pytype
, *keyszset_pytype
;
38 PyObject
*sha_pyobj
, *has160_pyobj
;
40 PyObject
*keysz_pywrap(const octet
*k
)
44 keysz_pyobj
*o
= PyObject_New(keysz_pyobj
, keyszany_pytype
);
46 return ((PyObject
*)o
);
50 PyObject_New(keyszrange_pyobj
, keyszrange_pytype
);
55 if (!o
->mod
) o
->mod
= 1;
56 return ((PyObject
*)o
);
60 PyObject_New(keyszset_pyobj
, keyszset_pytype
);
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
);
74 static PyObject
*keyszany_pynew(PyTypeObject
*ty
,
75 PyObject
*arg
, PyObject
*kw
)
77 char *kwlist
[] = { "default", 0 };
81 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "i:new", kwlist
, &dfl
))
83 if (dfl
< 0) VALERR("key size cannot be negative");
84 o
= (keysz_pyobj
*)ty
->tp_alloc(ty
, 0);
86 return ((PyObject
*)o
);
91 static PyObject
*keyszrange_pynew(PyTypeObject
*ty
,
92 PyObject
*arg
, PyObject
*kw
)
94 char *kwlist
[] = { "default", "min", "max", "mod", 0 };
95 int dfl
, min
= 0, max
= 0, mod
= 1;
98 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "i|iii:new", kwlist
,
99 &dfl
, &min
, &max
, &mod
))
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);
112 return ((PyObject
*)o
);
117 static PyObject
*keyszset_pynew(PyTypeObject
*ty
,
118 PyObject
*arg
, PyObject
*kw
)
120 char *kwlist
[] = { "default", "set", 0 };
123 PyObject
*x
= 0, *l
= 0;
124 keyszset_pyobj
*o
= 0;
126 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "i|O:new", kwlist
,
129 if (!set
) set
= PyTuple_New(0);
131 if (!PySequence_Check(set
)) TYERR("want a sequence");
132 n
= PySequence_Size(set
);
134 if (PyErr_Occurred()) goto end
;
135 if (dfl
< 0) VALERR("key size cannot be negative");
136 x
= PyInt_FromLong(dfl
);
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");
151 if ((set
= PySequence_Tuple(l
)) == 0) goto end
;
152 o
= (keyszset_pyobj
*)ty
->tp_alloc(ty
, 0);
160 return ((PyObject
*)o
);
163 static PyObject
*kaget_min(PyObject
*me
, void *hunoz
)
164 { return (PyInt_FromLong(0)); }
165 #define kaget_max kaget_min
167 static PyObject
*ksget_min(PyObject
*me
, void *hunoz
)
169 PyObject
*set
= ((keyszset_pyobj
*)me
)->set
;
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
;
176 return (PyInt_FromLong(x
));
179 static PyObject
*ksget_max(PyObject
*me
, void *hunoz
)
181 PyObject
*set
= ((keyszset_pyobj
*)me
)->set
;
183 n
= PyTuple_Size(set
);
184 for (i
= 0; i
< n
; i
++) {
185 y
= PyInt_AsLong(PyTuple_GetItem(set
, i
));
188 return (PyInt_FromLong(x
));
191 static PyMemberDef keysz_pymembers
[] = {
192 #define MEMBERSTRUCT keysz_pyobj
193 #define default dfl /* ugh! */
194 MEMBER(default, T_INT
, READONLY
, "KSZ.default -> default key size")
200 static 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")
208 static 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")
218 static 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")
226 static PyMemberDef keyszset_pymembers
[] = {
227 #define MEMBERSTRUCT keyszset_pyobj
228 MEMBER(set
, T_OBJECT
, READONLY
, "KSZ.set -> allowed key sizes")
233 static PyTypeObject keysz_pytype_skel
= {
234 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
235 "catacomb.KeySZ", /* @tp_name@ */
236 sizeof(keysz_pyobj
), /* @tp_basicsize@ */
237 0, /* @tp_itemsize@ */
239 _PyObject_Del
, /* @tp_dealloc@ */
241 0, /* @tp_getattr@ */
242 0, /* @tp_setattr@ */
243 0, /* @tp_compare@ */
245 0, /* @tp_as_number@ */
246 0, /* @tp_as_sequence@ */
247 0, /* @tp_as_mapping@ */
251 0, /* @tp_getattro@ */
252 0, /* @tp_setattro@ */
253 0, /* @tp_as_buffer@ */
254 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
258 "Key size constraints.",
260 0, /* @tp_traverse@ */
262 0, /* @tp_richcompare@ */
263 0, /* @tp_weaklistoffset@ */
265 0, /* @tp_iternexr@ */
266 0, /* @tp_methods@ */
267 keysz_pymembers
, /* @tp_members@ */
271 0, /* @tp_descr_get@ */
272 0, /* @tp_descr_set@ */
273 0, /* @tp_dictoffset@ */
275 PyType_GenericAlloc
, /* @tp_alloc@ */
276 abstract_pynew
, /* @tp_new@ */
277 _PyObject_Del
, /* @tp_free@ */
281 static PyTypeObject keyszany_pytype_skel
= {
282 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
283 "catacomb.KeySZAny", /* @tp_name@ */
284 sizeof(keysz_pyobj
), /* @tp_basicsize@ */
285 0, /* @tp_itemsize@ */
287 _PyObject_Del
, /* @tp_dealloc@ */
289 0, /* @tp_getattr@ */
290 0, /* @tp_setattr@ */
291 0, /* @tp_compare@ */
293 0, /* @tp_as_number@ */
294 0, /* @tp_as_sequence@ */
295 0, /* @tp_as_mapping@ */
299 0, /* @tp_getattro@ */
300 0, /* @tp_setattro@ */
301 0, /* @tp_as_buffer@ */
302 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
306 "Key size constraints. This object imposes no constraints on size.",
308 0, /* @tp_traverse@ */
310 0, /* @tp_richcompare@ */
311 0, /* @tp_weaklistoffset@ */
313 0, /* @tp_iternexr@ */
314 0, /* @tp_methods@ */
315 0, /* @tp_members@ */
316 keyszany_pygetset
, /* @tp_getset@ */
319 0, /* @tp_descr_get@ */
320 0, /* @tp_descr_set@ */
321 0, /* @tp_dictoffset@ */
323 PyType_GenericAlloc
, /* @tp_alloc@ */
324 keyszany_pynew
, /* @tp_new@ */
325 _PyObject_Del
, /* @tp_free@ */
329 static PyTypeObject keyszrange_pytype_skel
= {
330 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
331 "catacomb.KeySZRange", /* @tp_name@ */
332 sizeof(keyszrange_pyobj
), /* @tp_basicsize@ */
333 0, /* @tp_itemsize@ */
335 _PyObject_Del
, /* @tp_dealloc@ */
337 0, /* @tp_getattr@ */
338 0, /* @tp_setattr@ */
339 0, /* @tp_compare@ */
341 0, /* @tp_as_number@ */
342 0, /* @tp_as_sequence@ */
343 0, /* @tp_as_mapping@ */
347 0, /* @tp_getattro@ */
348 0, /* @tp_setattro@ */
349 0, /* @tp_as_buffer@ */
350 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
354 "Key size constraints. This object asserts minimum and maximum (if\n\
355 sizes, and requires the key length to be a multiple of some value.",
357 0, /* @tp_traverse@ */
359 0, /* @tp_richcompare@ */
360 0, /* @tp_weaklistoffset@ */
362 0, /* @tp_iternexr@ */
363 0, /* @tp_methods@ */
364 keyszrange_pymembers
, /* @tp_members@ */
368 0, /* @tp_descr_get@ */
369 0, /* @tp_descr_set@ */
370 0, /* @tp_dictoffset@ */
372 PyType_GenericAlloc
, /* @tp_alloc@ */
373 keyszrange_pynew
, /* @tp_new@ */
374 _PyObject_Del
, /* @tp_free@ */
378 static PyTypeObject keyszset_pytype_skel
= {
379 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
380 "catacomb.KeySZSet", /* @tp_name@ */
381 sizeof(keyszset_pyobj
), /* @tp_basicsize@ */
382 0, /* @tp_itemsize@ */
384 _PyObject_Del
, /* @tp_dealloc@ */
386 0, /* @tp_getattr@ */
387 0, /* @tp_setattr@ */
388 0, /* @tp_compare@ */
390 0, /* @tp_as_number@ */
391 0, /* @tp_as_sequence@ */
392 0, /* @tp_as_mapping@ */
396 0, /* @tp_getattro@ */
397 0, /* @tp_setattro@ */
398 0, /* @tp_as_buffer@ */
399 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
403 "Key size constraints. This object requires the key to be one of a\n\
406 0, /* @tp_traverse@ */
408 0, /* @tp_richcompare@ */
409 0, /* @tp_weaklistoffset@ */
411 0, /* @tp_iternexr@ */
412 0, /* @tp_methods@ */
413 keyszset_pymembers
, /* @tp_members@ */
414 keyszset_pygetset
, /* @tp_getset@ */
417 0, /* @tp_descr_get@ */
418 0, /* @tp_descr_set@ */
419 0, /* @tp_dictoffset@ */
421 PyType_GenericAlloc
, /* @tp_alloc@ */
422 keyszset_pynew
, /* @tp_new@ */
423 _PyObject_Del
, /* @tp_free@ */
427 /*----- Symmetric encryption ----------------------------------------------*/
429 PyTypeObject
*gccipher_pytype
, *gcipher_pytype
;
431 CONVFUNC(gccipher
, gccipher
*, GCCIPHER_CC
)
432 CONVFUNC(gcipher
, gcipher
*, GCIPHER_C
)
434 PyObject
*gcipher_pywrap(PyObject
*cobj
, gcipher
*c
, unsigned f
)
437 if (!cobj
) cobj
= gccipher_pywrap((/*unconst*/ gccipher
*)GC_CLASS(c
));
438 else Py_INCREF(cobj
);
439 g
= PyObject_NEW(gcipher_pyobj
, (PyTypeObject
*)cobj
);
442 return ((PyObject
*)g
);
445 static PyObject
*gcipher_pynew(PyTypeObject
*ty
, PyObject
*arg
, PyObject
*kw
)
447 char *kwlist
[] = { "k", 0 };
451 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "s#:new", kwlist
, &k
, &sz
))
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
),
461 PyObject
*gccipher_pywrap(gccipher
*cc
)
463 gccipher_pyobj
*g
= newtype(gccipher_pytype
, 0);
465 g
->ty
.tp_name
= (/*unconst*/ char *)cc
->name
;
466 g
->ty
.tp_basicsize
= sizeof(gcipher_pyobj
);
467 g
->ty
.tp_base
= gcipher_pytype
;
468 Py_INCREF(gcipher_pytype
);
469 g
->ty
.tp_flags
= (Py_TPFLAGS_DEFAULT
|
470 Py_TPFLAGS_BASETYPE
|
471 Py_TPFLAGS_HEAPTYPE
);
472 g
->ty
.tp_alloc
= PyType_GenericAlloc
;
473 g
->ty
.tp_free
= _PyObject_Del
;
474 g
->ty
.tp_new
= gcipher_pynew
;
475 PyType_Ready(&g
->ty
);
476 return ((PyObject
*)g
);
479 static void gcipher_pydealloc(PyObject
*me
)
481 if (GCIPHER_F(me
) & f_freeme
)
482 GC_DESTROY(GCIPHER_C(me
));
483 Py_DECREF(me
->ob_type
);
487 static PyObject
*gccget_name(PyObject
*me
, void *hunoz
)
488 { return (PyString_FromString(GCCIPHER_CC(me
)->name
)); }
490 static PyObject
*gccget_keysz(PyObject
*me
, void *hunoz
)
491 { return (keysz_pywrap(GCCIPHER_CC(me
)->keysz
)); }
493 static PyObject
*gccget_blksz(PyObject
*me
, void *hunoz
)
494 { return (PyInt_FromLong(GCCIPHER_CC(me
)->blksz
)); }
496 static PyObject
*gcmeth_encrypt(PyObject
*me
, PyObject
*arg
)
502 if (!PyArg_ParseTuple(arg
, "s#:encrypt", &p
, &sz
)) return (0);
503 rc
= bytestring_pywrap(0, sz
);
504 GC_ENCRYPT(GCIPHER_C(me
), p
, PyString_AS_STRING(rc
), sz
);
508 static PyObject
*gcmeth_enczero(PyObject
*me
, PyObject
*arg
)
514 if (!PyArg_ParseTuple(arg
, "i:enczero", &sz
)) return (0);
515 rc
= bytestring_pywrap(0, sz
);
516 p
= PyString_AS_STRING(rc
);
518 GC_ENCRYPT(GCIPHER_C(me
), p
, p
, sz
);
522 static PyObject
*gcmeth_decrypt(PyObject
*me
, PyObject
*arg
)
528 if (!PyArg_ParseTuple(arg
, "s#:decrypt", &p
, &sz
)) return (0);
529 rc
= bytestring_pywrap(0, sz
);
530 GC_DECRYPT(GCIPHER_C(me
), p
, PyString_AS_STRING(rc
), sz
);
534 static PyObject
*gcmeth_deczero(PyObject
*me
, PyObject
*arg
)
540 if (!PyArg_ParseTuple(arg
, "i:deczero", &sz
)) return (0);
541 rc
= bytestring_pywrap(0, sz
);
542 p
= PyString_AS_STRING(rc
);
544 GC_DECRYPT(GCIPHER_C(me
), p
, p
, sz
);
548 static PyObject
*gcmeth_setiv(PyObject
*me
, PyObject
*arg
)
553 if (!PyArg_ParseTuple(arg
, "s#:setiv", &p
, &sz
)) goto end
;
554 if (!GC_CLASS(GCIPHER_C(me
))->blksz
) VALERR("not a block cipher mode");
555 if (sz
!= GC_CLASS(GCIPHER_C(me
))->blksz
) VALERR("bad IV length");
556 GC_SETIV(GCIPHER_C(me
), p
);
562 static PyObject
*gcmeth_bdry(PyObject
*me
, PyObject
*arg
)
564 if (!PyArg_ParseTuple(arg
, ":bdry")) goto end
;
565 if (!GC_CLASS(GCIPHER_C(me
))->blksz
) VALERR("not a block cipher mode");
566 GC_BDRY(GCIPHER_C(me
));
572 static PyGetSetDef gccipher_pygetset
[] = {
573 #define GETSETNAME(op, name) gcc##op##_##name
574 GET (keysz
, "CC.keysz -> acceptable key sizes")
575 GET (blksz
, "CC.blksz -> block size, or zero")
576 GET (name
, "CC.name -> name of this kind of cipher")
581 static PyMethodDef gcipher_pymethods
[] = {
582 #define METHNAME(name) gcmeth_##name
583 METH (encrypt
, "C.encrypt(PT) -> CT")
584 METH (enczero
, "C.enczero(N) -> CT")
585 METH (decrypt
, "C.decrypt(CT) -> PT")
586 METH (deczero
, "C.deczero(N) -> PT")
587 METH (setiv
, "C.setiv(IV)")
588 METH (bdry
, "C.bdry()")
593 static PyTypeObject gccipher_pytype_skel
= {
594 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
595 "catacomb.GCCipher", /* @tp_name@ */
596 sizeof(gccipher_pyobj
), /* @tp_basicsize@ */
597 0, /* @tp_itemsize@ */
599 0, /* @tp_dealloc@ */
601 0, /* @tp_getattr@ */
602 0, /* @tp_setattr@ */
603 0, /* @tp_compare@ */
605 0, /* @tp_as_number@ */
606 0, /* @tp_as_sequence@ */
607 0, /* @tp_as_mapping@ */
611 0, /* @tp_getattro@ */
612 0, /* @tp_setattro@ */
613 0, /* @tp_as_buffer@ */
614 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
618 "Symmetric cipher metaclass.",
620 0, /* @tp_traverse@ */
622 0, /* @tp_richcompare@ */
623 0, /* @tp_weaklistoffset@ */
625 0, /* @tp_iternexr@ */
626 0, /* @tp_methods@ */
627 0, /* @tp_members@ */
628 gccipher_pygetset
, /* @tp_getset@ */
631 0, /* @tp_descr_get@ */
632 0, /* @tp_descr_set@ */
633 0, /* @tp_dictoffset@ */
635 PyType_GenericAlloc
, /* @tp_alloc@ */
636 abstract_pynew
, /* @tp_new@ */
637 _PyObject_Del
, /* @tp_free@ */
641 static PyTypeObject gcipher_pytype_skel
= {
642 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
643 "catacomb.GCipher", /* @tp_name@ */
644 sizeof(gcipher_pyobj
), /* @tp_basicsize@ */
645 0, /* @tp_itemsize@ */
647 gcipher_pydealloc
, /* @tp_dealloc@ */
649 0, /* @tp_getattr@ */
650 0, /* @tp_setattr@ */
651 0, /* @tp_compare@ */
653 0, /* @tp_as_number@ */
654 0, /* @tp_as_sequence@ */
655 0, /* @tp_as_mapping@ */
659 0, /* @tp_getattro@ */
660 0, /* @tp_setattro@ */
661 0, /* @tp_as_buffer@ */
662 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
666 "Symmetric cipher, abstract base class.",
668 0, /* @tp_traverse@ */
670 0, /* @tp_richcompare@ */
671 0, /* @tp_weaklistoffset@ */
673 0, /* @tp_iternexr@ */
674 gcipher_pymethods
, /* @tp_methods@ */
675 0, /* @tp_members@ */
679 0, /* @tp_descr_get@ */
680 0, /* @tp_descr_set@ */
681 0, /* @tp_dictoffset@ */
683 PyType_GenericAlloc
, /* @tp_alloc@ */
684 abstract_pynew
, /* @tp_new@ */
685 _PyObject_Del
, /* @tp_free@ */
689 /*----- Hash functions ----------------------------------------------------*/
691 PyTypeObject
*gchash_pytype
, *ghash_pytype
;
693 CONVFUNC(gchash
, gchash
*, GCHASH_CH
)
694 CONVFUNC(ghash
, ghash
*, GHASH_H
)
696 static PyObject
*ghash_pynew(PyTypeObject
*ty
, PyObject
*arg
, PyObject
*kw
)
698 char *kwlist
[] = { 0 };
699 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, ":new", kwlist
))
701 return (ghash_pywrap((PyObject
*)ty
, GH_INIT(GCHASH_CH(ty
)), f_freeme
));
706 PyObject
*gchash_pywrap(gchash
*ch
)
708 gchash_pyobj
*g
= newtype(gchash_pytype
, 0);
710 g
->ty
.tp_name
= (/*unconst*/ char *)ch
->name
;
711 g
->ty
.tp_basicsize
= sizeof(ghash_pyobj
);
712 g
->ty
.tp_base
= ghash_pytype
;
713 Py_INCREF(ghash_pytype
);
714 g
->ty
.tp_flags
= (Py_TPFLAGS_DEFAULT
|
715 Py_TPFLAGS_BASETYPE
|
716 Py_TPFLAGS_HEAPTYPE
);
717 g
->ty
.tp_alloc
= PyType_GenericAlloc
;
718 g
->ty
.tp_free
= _PyObject_Del
;
719 g
->ty
.tp_new
= ghash_pynew
;
720 PyType_Ready(&g
->ty
);
721 return ((PyObject
*)g
);
724 PyObject
*ghash_pywrap(PyObject
*cobj
, ghash
*h
, unsigned f
)
727 if (!cobj
) cobj
= gchash_pywrap((/*unconst*/ gchash
*)GH_CLASS(h
));
728 else Py_INCREF(cobj
);
729 g
= PyObject_NEW(ghash_pyobj
, (PyTypeObject
*)cobj
);
732 return ((PyObject
*)g
);
735 static void ghash_pydealloc(PyObject
*me
)
737 if (GHASH_F(me
) & f_freeme
)
738 GH_DESTROY(GHASH_H(me
));
739 Py_DECREF(me
->ob_type
);
743 static PyObject
*gchget_name(PyObject
*me
, void *hunoz
)
744 { return (PyString_FromString(GCHASH_CH(me
)->name
)); }
746 static PyObject
*gchget_hashsz(PyObject
*me
, void *hunoz
)
747 { return (PyInt_FromLong(GCHASH_CH(me
)->hashsz
)); }
749 static PyObject
*gchget_bufsz(PyObject
*me
, void *hunoz
)
750 { return (PyInt_FromLong(GCHASH_CH(me
)->bufsz
)); }
752 static PyObject
*ghmeth_hash(PyObject
*me
, PyObject
*arg
)
756 if (!PyArg_ParseTuple(arg
, "s#:hash", &p
, &sz
)) return (0);
757 GH_HASH(GHASH_H(me
), p
, sz
);
761 static PyObject
*ghmeth_done(PyObject
*me
, PyObject
*arg
)
765 if (!PyArg_ParseTuple(arg
, ":done")) return (0);
766 g
= GH_COPY(GHASH_H(me
));
767 rc
= bytestring_pywrap(0, g
->ops
->c
->hashsz
);
768 GH_DONE(g
, PyString_AS_STRING(rc
));
773 static PyGetSetDef gchash_pygetset
[] = {
774 #define GETSETNAME(op, name) gch##op##_##name
775 GET (bufsz
, "CH.bufsz -> hash buffer size, or zero")
776 GET (hashsz
, "CH.blksz -> hash output size")
777 GET (name
, "CH.name -> name of this kind of hash")
782 static PyMethodDef ghash_pymethods
[] = {
783 #define METHNAME(name) ghmeth_##name
784 METH (hash
, "H.hash(M)")
785 METH (done
, "H.done() -> HASH")
790 static PyTypeObject gchash_pytype_skel
= {
791 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
792 "catacomb.GCHash", /* @tp_name@ */
793 sizeof(gchash_pyobj
), /* @tp_basicsize@ */
794 0, /* @tp_itemsize@ */
796 0, /* @tp_dealloc@ */
798 0, /* @tp_getattr@ */
799 0, /* @tp_setattr@ */
800 0, /* @tp_compare@ */
802 0, /* @tp_as_number@ */
803 0, /* @tp_as_sequence@ */
804 0, /* @tp_as_mapping@ */
808 0, /* @tp_getattro@ */
809 0, /* @tp_setattro@ */
810 0, /* @tp_as_buffer@ */
811 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
815 "Hash function metaclass.",
817 0, /* @tp_traverse@ */
819 0, /* @tp_richcompare@ */
820 0, /* @tp_weaklistoffset@ */
822 0, /* @tp_iternexr@ */
823 0, /* @tp_methods@ */
824 0, /* @tp_members@ */
825 gchash_pygetset
, /* @tp_getset@ */
828 0, /* @tp_descr_get@ */
829 0, /* @tp_descr_set@ */
830 0, /* @tp_dictoffset@ */
832 PyType_GenericAlloc
, /* @tp_alloc@ */
833 abstract_pynew
, /* @tp_new@ */
834 _PyObject_Del
, /* @tp_free@ */
838 static PyTypeObject ghash_pytype_skel
= {
839 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
840 "catacomb.GHash", /* @tp_name@ */
841 sizeof(ghash_pyobj
), /* @tp_basicsize@ */
842 0, /* @tp_itemsize@ */
844 ghash_pydealloc
, /* @tp_dealloc@ */
846 0, /* @tp_getattr@ */
847 0, /* @tp_setattr@ */
848 0, /* @tp_compare@ */
850 0, /* @tp_as_number@ */
851 0, /* @tp_as_sequence@ */
852 0, /* @tp_as_mapping@ */
856 0, /* @tp_getattro@ */
857 0, /* @tp_setattro@ */
858 0, /* @tp_as_buffer@ */
859 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
863 "Hash function, abstract base class.",
865 0, /* @tp_traverse@ */
867 0, /* @tp_richcompare@ */
868 0, /* @tp_weaklistoffset@ */
870 0, /* @tp_iternexr@ */
871 ghash_pymethods
, /* @tp_methods@ */
872 0, /* @tp_members@ */
876 0, /* @tp_descr_get@ */
877 0, /* @tp_descr_set@ */
878 0, /* @tp_dictoffset@ */
880 PyType_GenericAlloc
, /* @tp_alloc@ */
881 abstract_pynew
, /* @tp_new@ */
882 _PyObject_Del
, /* @tp_free@ */
886 /*----- Message authentication --------------------------------------------*/
888 PyTypeObject
*gcmac_pytype
, *gmac_pytype
, *gmhash_pytype
;
890 CONVFUNC(gcmac
, gcmac
*, GCMAC_CM
)
891 CONVFUNC(gmac
, gmac
*, GMAC_M
)
892 CONVFUNC(gmhash
, ghash
*, GHASH_H
)
894 static PyObject
*gmac_pynew(PyTypeObject
*ty
, PyObject
*arg
, PyObject
*kw
)
896 char *kwlist
[] = { "k", 0 };
900 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "s#:new", kwlist
, &k
, &sz
))
902 if (keysz(sz
, GCMAC_CM(ty
)->keysz
) != sz
) VALERR("bad key length");
903 return (gmac_pywrap((PyObject
*)ty
,
904 GM_KEY(GCMAC_CM(ty
), k
, sz
),
910 static PyObject
*gmhash_pynew(PyTypeObject
*ty
, PyObject
*arg
, PyObject
*kw
)
912 char *kwlist
[] = { 0 };
915 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, ":new", kwlist
)) return (0);
916 g
= PyObject_NEW(ghash_pyobj
, ty
);
917 g
->h
= GM_INIT(GMAC_M(ty
));
920 return ((PyObject
*)g
);
923 PyObject
*gcmac_pywrap(gcmac
*cm
)
925 gcmac_pyobj
*g
= newtype(gcmac_pytype
, 0);
927 g
->ty
.tp_name
= (/*unconst*/ char *)cm
->name
;
928 g
->ty
.tp_basicsize
= sizeof(gmac_pyobj
);
929 g
->ty
.tp_base
= gmac_pytype
;
930 Py_INCREF(gmac_pytype
);
931 g
->ty
.tp_flags
= (Py_TPFLAGS_DEFAULT
|
932 Py_TPFLAGS_BASETYPE
|
933 Py_TPFLAGS_HEAPTYPE
);
934 g
->ty
.tp_alloc
= PyType_GenericAlloc
;
935 g
->ty
.tp_free
= _PyObject_Del
;
936 g
->ty
.tp_new
= gmac_pynew
;
937 PyType_Ready(&g
->ty
);
938 return ((PyObject
*)g
);
941 PyObject
*gmac_pywrap(PyObject
*cobj
, gmac
*m
, unsigned f
)
944 if (!cobj
) cobj
= gcmac_pywrap((/*unconst*/ gcmac
*)GM_CLASS(m
));
945 else Py_INCREF(cobj
);
946 g
= newtype((PyTypeObject
*)cobj
, 0);
947 g
->nameobj
= PyString_FromFormat("%s(keyed)", m
->ops
->c
->name
);
948 g
->ty
.tp_name
= PyString_AS_STRING(g
->nameobj
);
949 g
->ty
.tp_base
= gmhash_pytype
;
950 Py_INCREF(gmac_pytype
);
951 g
->ty
.tp_flags
= (Py_TPFLAGS_DEFAULT
|
952 Py_TPFLAGS_BASETYPE
|
953 Py_TPFLAGS_HEAPTYPE
);
954 g
->ty
.tp_alloc
= PyType_GenericAlloc
;
955 g
->ty
.tp_free
= _PyObject_Del
;
956 g
->ty
.tp_new
= gmhash_pynew
;
957 PyType_Ready(&g
->ty
);
960 return ((PyObject
*)g
);
963 static void gmac_pydealloc(PyObject
*me
)
965 if (GMAC_F(me
) & f_freeme
)
966 GM_DESTROY(GMAC_M(me
));
967 Py_DECREF(me
->ob_type
);
968 Py_DECREF(GMAC_NAMEOBJ(me
));
969 PyType_Type
.tp_dealloc(me
);
972 static PyObject
*gcmget_name(PyObject
*me
, void *hunoz
)
973 { return (PyString_FromString(GCMAC_CM(me
)->name
)); }
975 static PyObject
*gcmget_keysz(PyObject
*me
, void *hunoz
)
976 { return (keysz_pywrap(GCMAC_CM(me
)->keysz
)); }
978 static PyObject
*gcmget_tagsz(PyObject
*me
, void *hunoz
)
979 { return (PyInt_FromLong(GCMAC_CM(me
)->hashsz
)); }
981 static PyGetSetDef gcmac_pygetset
[] = {
982 #define GETSETNAME(op, name) gcm##op##_##name
983 GET (keysz
, "CM.keysz -> acceptable key sizes")
984 GET (tagsz
, "CM.tagsz -> MAC output size")
985 GET (name
, "CM.name -> name of this kind of MAC")
990 static PyTypeObject gcmac_pytype_skel
= {
991 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
992 "catacomb.GCMAC", /* @tp_name@ */
993 sizeof(gchash_pyobj
), /* @tp_basicsize@ */
994 0, /* @tp_itemsize@ */
996 0, /* @tp_dealloc@ */
998 0, /* @tp_getattr@ */
999 0, /* @tp_setattr@ */
1000 0, /* @tp_compare@ */
1002 0, /* @tp_as_number@ */
1003 0, /* @tp_as_sequence@ */
1004 0, /* @tp_as_mapping@ */
1008 0, /* @tp_getattro@ */
1009 0, /* @tp_setattro@ */
1010 0, /* @tp_as_buffer@ */
1011 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
1012 Py_TPFLAGS_BASETYPE
,
1015 "Message authentication code metametaclass.",
1017 0, /* @tp_traverse@ */
1019 0, /* @tp_richcompare@ */
1020 0, /* @tp_weaklistoffset@ */
1022 0, /* @tp_iternexr@ */
1023 0, /* @tp_methods@ */
1024 0, /* @tp_members@ */
1025 gcmac_pygetset
, /* @tp_getset@ */
1028 0, /* @tp_descr_get@ */
1029 0, /* @tp_descr_set@ */
1030 0, /* @tp_dictoffset@ */
1032 PyType_GenericAlloc
, /* @tp_alloc@ */
1033 abstract_pynew
, /* @tp_new@ */
1034 _PyObject_Del
, /* @tp_free@ */
1038 static PyTypeObject gmac_pytype_skel
= {
1039 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
1040 "catacomb.GMAC", /* @tp_name@ */
1041 sizeof(gmac_pyobj
), /* @tp_basicsize@ */
1042 0, /* @tp_itemsize@ */
1044 gmac_pydealloc
, /* @tp_dealloc@ */
1046 0, /* @tp_getattr@ */
1047 0, /* @tp_setattr@ */
1048 0, /* @tp_compare@ */
1050 0, /* @tp_as_number@ */
1051 0, /* @tp_as_sequence@ */
1052 0, /* @tp_as_mapping@ */
1056 0, /* @tp_getattro@ */
1057 0, /* @tp_setattro@ */
1058 0, /* @tp_as_buffer@ */
1059 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
1060 Py_TPFLAGS_BASETYPE
,
1063 "Message authentication code metaclass, abstract base class.",
1065 0, /* @tp_traverse@ */
1067 0, /* @tp_richcompare@ */
1068 0, /* @tp_weaklistoffset@ */
1070 0, /* @tp_iternexr@ */
1071 0, /* @tp_methods@ */
1072 0, /* @tp_members@ */
1073 0, /* @tp_getset@ */
1076 0, /* @tp_descr_get@ */
1077 0, /* @tp_descr_set@ */
1078 0, /* @tp_dictoffset@ */
1080 PyType_GenericAlloc
, /* @tp_alloc@ */
1081 abstract_pynew
, /* @tp_new@ */
1082 _PyObject_Del
, /* @tp_free@ */
1086 static PyTypeObject gmhash_pytype_skel
= {
1087 PyObject_HEAD_INIT(&PyType_Type
) 0, /* Header */
1088 "catacomb.GMACHash", /* @tp_name@ */
1089 sizeof(ghash_pyobj
), /* @tp_basicsize@ */
1090 0, /* @tp_itemsize@ */
1092 ghash_pydealloc
, /* @tp_dealloc@ */
1094 0, /* @tp_getattr@ */
1095 0, /* @tp_setattr@ */
1096 0, /* @tp_compare@ */
1098 0, /* @tp_as_number@ */
1099 0, /* @tp_as_sequence@ */
1100 0, /* @tp_as_mapping@ */
1104 0, /* @tp_getattro@ */
1105 0, /* @tp_setattro@ */
1106 0, /* @tp_as_buffer@ */
1107 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
1108 Py_TPFLAGS_BASETYPE
,
1111 "Message authentication code, abstract base class.",
1113 0, /* @tp_traverse@ */
1115 0, /* @tp_richcompare@ */
1116 0, /* @tp_weaklistoffset@ */
1118 0, /* @tp_iternexr@ */
1119 0, /* @tp_methods@ */
1120 0, /* @tp_members@ */
1121 0, /* @tp_getset@ */
1124 0, /* @tp_descr_get@ */
1125 0, /* @tp_descr_set@ */
1126 0, /* @tp_dictoffset@ */
1128 PyType_GenericAlloc
, /* @tp_alloc@ */
1129 abstract_pynew
, /* @tp_new@ */
1130 _PyObject_Del
, /* @tp_free@ */
1134 /*----- Main code ---------------------------------------------------------*/
1136 void algorithms_pyinit(void)
1138 INITTYPE(keysz
, root
);
1139 INITTYPE(keyszany
, keysz
);
1140 INITTYPE(keyszrange
, keysz
);
1141 INITTYPE(keyszset
, keysz
);
1142 INITTYPE(gccipher
, type
);
1143 INITTYPE(gcipher
, root
);
1144 INITTYPE(gchash
, type
);
1145 INITTYPE(ghash
, root
);
1146 INITTYPE(gcmac
, type
);
1147 INITTYPE(gmac
, type
);
1148 INITTYPE(gmhash
, ghash
);
1151 #define GEN(func, base) \
1152 static PyObject *func(void) \
1154 PyObject *d = PyDict_New(); \
1158 for (i = 0; g##base##tab[i]; i++) { \
1159 o = gc##base##_pywrap((/*unconst*/ gc##base *)g##base##tab[i]); \
1160 PyDict_SetItemString(d, \
1161 (/*unconst*/ char *)g##base##tab[i]->name, \
1167 GEN(gcciphers
, cipher
)
1171 void algorithms_pyinsert(PyObject
*mod
)
1174 INSERT("KeySZ", keysz_pytype
);
1175 INSERT("KeySZAny", keyszany_pytype
);
1176 INSERT("KeySZRange", keyszrange_pytype
);
1177 INSERT("KeySZSet", keyszset_pytype
);
1178 INSERT("GCCipher", gccipher_pytype
);
1179 INSERT("GCipher", gcipher_pytype
);
1180 INSERT("gcciphers", gcciphers());
1181 INSERT("GCHash", gchash_pytype
);
1182 INSERT("GHash", ghash_pytype
);
1183 INSERT("gchashes", d
= gchashes());
1184 sha_pyobj
= PyDict_GetItemString(d
, "sha"); Py_INCREF(sha_pyobj
);
1185 has160_pyobj
= PyDict_GetItemString(d
, "has160"); Py_INCREF(has160_pyobj
);
1186 INSERT("GCMAC", gcmac_pytype
);
1187 INSERT("GMAC", gmac_pytype
);
1188 INSERT("GMACHash", gmhash_pytype
);
1189 INSERT("gcmacs", gcmacs());
1192 /*----- That's all, folks -------------------------------------------------*/