Use default python to build.
[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 = {
234 PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
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@ */
265 0, /* @tp_iternexr@ */
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 = {
282 PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
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@ */
313 0, /* @tp_iternexr@ */
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 = {
330 PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
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@ */
362 0, /* @tp_iternexr@ */
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 = {
379 PyObject_HEAD_INIT(&PyType_Type) 0, /* Header */
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@ */
411 0, /* @tp_iternexr@ */
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{
463 gccipher_pyobj *g = newtype(gccipher_pytype, 0);
464 g->cc = cc;
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;
3aa33042 473 g->ty.tp_free = 0;
d7ab1bab 474 g->ty.tp_new = gcipher_pynew;
475 PyType_Ready(&g->ty);
476 return ((PyObject *)g);
477}
478
479static void gcipher_pydealloc(PyObject *me)
480{
481 if (GCIPHER_F(me) & f_freeme)
482 GC_DESTROY(GCIPHER_C(me));
483 Py_DECREF(me->ob_type);
3aa33042 484 FREEOBJ(me);
d7ab1bab 485}
486
487static PyObject *gccget_name(PyObject *me, void *hunoz)
488 { return (PyString_FromString(GCCIPHER_CC(me)->name)); }
489
490static PyObject *gccget_keysz(PyObject *me, void *hunoz)
491 { return (keysz_pywrap(GCCIPHER_CC(me)->keysz)); }
492
493static PyObject *gccget_blksz(PyObject *me, void *hunoz)
494 { return (PyInt_FromLong(GCCIPHER_CC(me)->blksz)); }
495
496static PyObject *gcmeth_encrypt(PyObject *me, PyObject *arg)
497{
498 char *p;
499 int sz;
500 PyObject *rc = 0;
501
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);
505 return (rc);
506}
507
508static PyObject *gcmeth_enczero(PyObject *me, PyObject *arg)
509{
510 char *p;
511 int sz;
512 PyObject *rc = 0;
513
514 if (!PyArg_ParseTuple(arg, "i:enczero", &sz)) return (0);
515 rc = bytestring_pywrap(0, sz);
516 p = PyString_AS_STRING(rc);
517 memset(p, 0, sz);
518 GC_ENCRYPT(GCIPHER_C(me), p, p, sz);
519 return (rc);
520}
521
522static PyObject *gcmeth_decrypt(PyObject *me, PyObject *arg)
523{
524 char *p;
525 int sz;
526 PyObject *rc = 0;
527
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);
531 return (rc);
532}
533
534static PyObject *gcmeth_deczero(PyObject *me, PyObject *arg)
535{
536 char *p;
537 int sz;
538 PyObject *rc = 0;
539
540 if (!PyArg_ParseTuple(arg, "i:deczero", &sz)) return (0);
541 rc = bytestring_pywrap(0, sz);
542 p = PyString_AS_STRING(rc);
543 memset(p, 0, sz);
544 GC_DECRYPT(GCIPHER_C(me), p, p, sz);
545 return (rc);
546}
547
548static PyObject *gcmeth_setiv(PyObject *me, PyObject *arg)
549{
550 char *p;
551 int sz;
552
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);
557 RETURN_ME;
558end:
559 return (0);
560}
561
562static PyObject *gcmeth_bdry(PyObject *me, PyObject *arg)
563{
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));
567 RETURN_ME;
568end:
569 return (0);
570}
571
572static 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")
577#undef GETSETNAME
578 { 0 }
579};
580
581static 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()")
589#undef METHNAME
590 { 0 }
591};
592
593static 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@ */
598
599 0, /* @tp_dealloc@ */
600 0, /* @tp_print@ */
601 0, /* @tp_getattr@ */
602 0, /* @tp_setattr@ */
603 0, /* @tp_compare@ */
604 0, /* @tp_repr@ */
605 0, /* @tp_as_number@ */
606 0, /* @tp_as_sequence@ */
607 0, /* @tp_as_mapping@ */
608 0, /* @tp_hash@ */
609 0, /* @tp_call@ */
610 0, /* @tp_str@ */
611 0, /* @tp_getattro@ */
612 0, /* @tp_setattro@ */
613 0, /* @tp_as_buffer@ */
614 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
615 Py_TPFLAGS_BASETYPE,
616
617 /* @tp_doc@ */
618"Symmetric cipher metaclass.",
619
620 0, /* @tp_traverse@ */
621 0, /* @tp_clear@ */
622 0, /* @tp_richcompare@ */
623 0, /* @tp_weaklistoffset@ */
624 0, /* @tp_iter@ */
625 0, /* @tp_iternexr@ */
626 0, /* @tp_methods@ */
627 0, /* @tp_members@ */
628 gccipher_pygetset, /* @tp_getset@ */
629 0, /* @tp_base@ */
630 0, /* @tp_dict@ */
631 0, /* @tp_descr_get@ */
632 0, /* @tp_descr_set@ */
633 0, /* @tp_dictoffset@ */
634 0, /* @tp_init@ */
635 PyType_GenericAlloc, /* @tp_alloc@ */
636 abstract_pynew, /* @tp_new@ */
3aa33042 637 0, /* @tp_free@ */
d7ab1bab 638 0 /* @tp_is_gc@ */
639};
640
641static 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@ */
646
647 gcipher_pydealloc, /* @tp_dealloc@ */
648 0, /* @tp_print@ */
649 0, /* @tp_getattr@ */
650 0, /* @tp_setattr@ */
651 0, /* @tp_compare@ */
652 0, /* @tp_repr@ */
653 0, /* @tp_as_number@ */
654 0, /* @tp_as_sequence@ */
655 0, /* @tp_as_mapping@ */
656 0, /* @tp_hash@ */
657 0, /* @tp_call@ */
658 0, /* @tp_str@ */
659 0, /* @tp_getattro@ */
660 0, /* @tp_setattro@ */
661 0, /* @tp_as_buffer@ */
662 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
663 Py_TPFLAGS_BASETYPE,
664
665 /* @tp_doc@ */
666"Symmetric cipher, abstract base class.",
667
668 0, /* @tp_traverse@ */
669 0, /* @tp_clear@ */
670 0, /* @tp_richcompare@ */
671 0, /* @tp_weaklistoffset@ */
672 0, /* @tp_iter@ */
673 0, /* @tp_iternexr@ */
674 gcipher_pymethods, /* @tp_methods@ */
675 0, /* @tp_members@ */
676 0, /* @tp_getset@ */
677 0, /* @tp_base@ */
678 0, /* @tp_dict@ */
679 0, /* @tp_descr_get@ */
680 0, /* @tp_descr_set@ */
681 0, /* @tp_dictoffset@ */
682 0, /* @tp_init@ */
683 PyType_GenericAlloc, /* @tp_alloc@ */
684 abstract_pynew, /* @tp_new@ */
3aa33042 685 0, /* @tp_free@ */
d7ab1bab 686 0 /* @tp_is_gc@ */
687};
688
689/*----- Hash functions ----------------------------------------------------*/
690
691PyTypeObject *gchash_pytype, *ghash_pytype;
692
693CONVFUNC(gchash, gchash *, GCHASH_CH)
694CONVFUNC(ghash, ghash *, GHASH_H)
695
696static PyObject *ghash_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
697{
698 char *kwlist[] = { 0 };
699 if (!PyArg_ParseTupleAndKeywords(arg, kw, ":new", kwlist))
700 goto end;
701 return (ghash_pywrap((PyObject *)ty, GH_INIT(GCHASH_CH(ty)), f_freeme));
702end:
703 return (0);
704}
705
706PyObject *gchash_pywrap(gchash *ch)
707{
708 gchash_pyobj *g = newtype(gchash_pytype, 0);
709 g->ch = ch;
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;
3aa33042 718 g->ty.tp_free = 0;
d7ab1bab 719 g->ty.tp_new = ghash_pynew;
720 PyType_Ready(&g->ty);
721 return ((PyObject *)g);
722}
723
724PyObject *ghash_pywrap(PyObject *cobj, ghash *h, unsigned f)
725{
726 ghash_pyobj *g;
727 if (!cobj) cobj = gchash_pywrap((/*unconst*/ gchash *)GH_CLASS(h));
728 else Py_INCREF(cobj);
729 g = PyObject_NEW(ghash_pyobj, (PyTypeObject *)cobj);
730 g->h = h;
731 g->f = f;
732 return ((PyObject *)g);
733}
734
735static void ghash_pydealloc(PyObject *me)
736{
737 if (GHASH_F(me) & f_freeme)
738 GH_DESTROY(GHASH_H(me));
739 Py_DECREF(me->ob_type);
3aa33042 740 FREEOBJ(me);
d7ab1bab 741}
742
743static PyObject *gchget_name(PyObject *me, void *hunoz)
744 { return (PyString_FromString(GCHASH_CH(me)->name)); }
745
746static PyObject *gchget_hashsz(PyObject *me, void *hunoz)
747 { return (PyInt_FromLong(GCHASH_CH(me)->hashsz)); }
748
749static PyObject *gchget_bufsz(PyObject *me, void *hunoz)
750 { return (PyInt_FromLong(GCHASH_CH(me)->bufsz)); }
751
752static PyObject *ghmeth_hash(PyObject *me, PyObject *arg)
753{
754 char *p;
755 int sz;
756 if (!PyArg_ParseTuple(arg, "s#:hash", &p, &sz)) return (0);
757 GH_HASH(GHASH_H(me), p, sz);
758 RETURN_ME;
759}
760
761static PyObject *ghmeth_done(PyObject *me, PyObject *arg)
762{
763 ghash *g;
764 PyObject *rc;
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));
769 GH_DESTROY(g);
770 return (rc);
771}
772
773static 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")
778#undef GETSETNAME
779 { 0 }
780};
781
782static PyMethodDef ghash_pymethods[] = {
783#define METHNAME(name) ghmeth_##name
784 METH (hash, "H.hash(M)")
785 METH (done, "H.done() -> HASH")
786#undef METHNAME
787 { 0 }
788};
789
790static 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@ */
795
796 0, /* @tp_dealloc@ */
797 0, /* @tp_print@ */
798 0, /* @tp_getattr@ */
799 0, /* @tp_setattr@ */
800 0, /* @tp_compare@ */
801 0, /* @tp_repr@ */
802 0, /* @tp_as_number@ */
803 0, /* @tp_as_sequence@ */
804 0, /* @tp_as_mapping@ */
805 0, /* @tp_hash@ */
806 0, /* @tp_call@ */
807 0, /* @tp_str@ */
808 0, /* @tp_getattro@ */
809 0, /* @tp_setattro@ */
810 0, /* @tp_as_buffer@ */
811 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
812 Py_TPFLAGS_BASETYPE,
813
814 /* @tp_doc@ */
815"Hash function metaclass.",
816
817 0, /* @tp_traverse@ */
818 0, /* @tp_clear@ */
819 0, /* @tp_richcompare@ */
820 0, /* @tp_weaklistoffset@ */
821 0, /* @tp_iter@ */
822 0, /* @tp_iternexr@ */
823 0, /* @tp_methods@ */
824 0, /* @tp_members@ */
825 gchash_pygetset, /* @tp_getset@ */
826 0, /* @tp_base@ */
827 0, /* @tp_dict@ */
828 0, /* @tp_descr_get@ */
829 0, /* @tp_descr_set@ */
830 0, /* @tp_dictoffset@ */
831 0, /* @tp_init@ */
832 PyType_GenericAlloc, /* @tp_alloc@ */
833 abstract_pynew, /* @tp_new@ */
3aa33042 834 0, /* @tp_free@ */
d7ab1bab 835 0 /* @tp_is_gc@ */
836};
837
838static 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@ */
843
844 ghash_pydealloc, /* @tp_dealloc@ */
845 0, /* @tp_print@ */
846 0, /* @tp_getattr@ */
847 0, /* @tp_setattr@ */
848 0, /* @tp_compare@ */
849 0, /* @tp_repr@ */
850 0, /* @tp_as_number@ */
851 0, /* @tp_as_sequence@ */
852 0, /* @tp_as_mapping@ */
853 0, /* @tp_hash@ */
854 0, /* @tp_call@ */
855 0, /* @tp_str@ */
856 0, /* @tp_getattro@ */
857 0, /* @tp_setattro@ */
858 0, /* @tp_as_buffer@ */
859 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
860 Py_TPFLAGS_BASETYPE,
861
862 /* @tp_doc@ */
863"Hash function, abstract base class.",
864
865 0, /* @tp_traverse@ */
866 0, /* @tp_clear@ */
867 0, /* @tp_richcompare@ */
868 0, /* @tp_weaklistoffset@ */
869 0, /* @tp_iter@ */
870 0, /* @tp_iternexr@ */
871 ghash_pymethods, /* @tp_methods@ */
872 0, /* @tp_members@ */
873 0, /* @tp_getset@ */
874 0, /* @tp_base@ */
875 0, /* @tp_dict@ */
876 0, /* @tp_descr_get@ */
877 0, /* @tp_descr_set@ */
878 0, /* @tp_dictoffset@ */
879 0, /* @tp_init@ */
880 PyType_GenericAlloc, /* @tp_alloc@ */
881 abstract_pynew, /* @tp_new@ */
3aa33042 882 0, /* @tp_free@ */
d7ab1bab 883 0 /* @tp_is_gc@ */
884};
885
886/*----- Message authentication --------------------------------------------*/
887
888PyTypeObject *gcmac_pytype, *gmac_pytype, *gmhash_pytype;
889
890CONVFUNC(gcmac, gcmac *, GCMAC_CM)
891CONVFUNC(gmac, gmac *, GMAC_M)
892CONVFUNC(gmhash, ghash *, GHASH_H)
893
894static PyObject *gmac_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
895{
896 char *kwlist[] = { "k", 0 };
897 char *k;
898 int sz;
899
900 if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", kwlist, &k, &sz))
901 goto end;
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),
905 f_freeme));
906end:
907 return (0);
908}
909
910static PyObject *gmhash_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
911{
912 char *kwlist[] = { 0 };
913 ghash_pyobj *g;
914
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));
918 g->f = f_freeme;
919 Py_INCREF(ty);
920 return ((PyObject *)g);
921}
922
923PyObject *gcmac_pywrap(gcmac *cm)
924{
925 gcmac_pyobj *g = newtype(gcmac_pytype, 0);
926 g->cm = cm;
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;
3aa33042 935 g->ty.tp_free = 0;
d7ab1bab 936 g->ty.tp_new = gmac_pynew;
937 PyType_Ready(&g->ty);
938 return ((PyObject *)g);
939}
940
941PyObject *gmac_pywrap(PyObject *cobj, gmac *m, unsigned f)
942{
943 gmac_pyobj *g;
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;
3aa33042 955 g->ty.tp_free = 0;
d7ab1bab 956 g->ty.tp_new = gmhash_pynew;
957 PyType_Ready(&g->ty);
958 g->m = m;
959 g->f = f;
960 return ((PyObject *)g);
961}
962
963static void gmac_pydealloc(PyObject *me)
964{
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);
970}
971
972static PyObject *gcmget_name(PyObject *me, void *hunoz)
973 { return (PyString_FromString(GCMAC_CM(me)->name)); }
974
975static PyObject *gcmget_keysz(PyObject *me, void *hunoz)
976 { return (keysz_pywrap(GCMAC_CM(me)->keysz)); }
977
978static PyObject *gcmget_tagsz(PyObject *me, void *hunoz)
979 { return (PyInt_FromLong(GCMAC_CM(me)->hashsz)); }
980
981static 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")
986#undef GETSETNAME
987 { 0 }
988};
989
990static 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@ */
995
996 0, /* @tp_dealloc@ */
997 0, /* @tp_print@ */
998 0, /* @tp_getattr@ */
999 0, /* @tp_setattr@ */
1000 0, /* @tp_compare@ */
1001 0, /* @tp_repr@ */
1002 0, /* @tp_as_number@ */
1003 0, /* @tp_as_sequence@ */
1004 0, /* @tp_as_mapping@ */
1005 0, /* @tp_hash@ */
1006 0, /* @tp_call@ */
1007 0, /* @tp_str@ */
1008 0, /* @tp_getattro@ */
1009 0, /* @tp_setattro@ */
1010 0, /* @tp_as_buffer@ */
1011 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
1012 Py_TPFLAGS_BASETYPE,
1013
1014 /* @tp_doc@ */
1015"Message authentication code metametaclass.",
1016
1017 0, /* @tp_traverse@ */
1018 0, /* @tp_clear@ */
1019 0, /* @tp_richcompare@ */
1020 0, /* @tp_weaklistoffset@ */
1021 0, /* @tp_iter@ */
1022 0, /* @tp_iternexr@ */
1023 0, /* @tp_methods@ */
1024 0, /* @tp_members@ */
1025 gcmac_pygetset, /* @tp_getset@ */
1026 0, /* @tp_base@ */
1027 0, /* @tp_dict@ */
1028 0, /* @tp_descr_get@ */
1029 0, /* @tp_descr_set@ */
1030 0, /* @tp_dictoffset@ */
1031 0, /* @tp_init@ */
1032 PyType_GenericAlloc, /* @tp_alloc@ */
1033 abstract_pynew, /* @tp_new@ */
3aa33042 1034 0, /* @tp_free@ */
d7ab1bab 1035 0 /* @tp_is_gc@ */
1036};
1037
1038static 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@ */
1043
1044 gmac_pydealloc, /* @tp_dealloc@ */
1045 0, /* @tp_print@ */
1046 0, /* @tp_getattr@ */
1047 0, /* @tp_setattr@ */
1048 0, /* @tp_compare@ */
1049 0, /* @tp_repr@ */
1050 0, /* @tp_as_number@ */
1051 0, /* @tp_as_sequence@ */
1052 0, /* @tp_as_mapping@ */
1053 0, /* @tp_hash@ */
1054 0, /* @tp_call@ */
1055 0, /* @tp_str@ */
1056 0, /* @tp_getattro@ */
1057 0, /* @tp_setattro@ */
1058 0, /* @tp_as_buffer@ */
1059 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
1060 Py_TPFLAGS_BASETYPE,
1061
1062 /* @tp_doc@ */
1063"Message authentication code metaclass, abstract base class.",
1064
1065 0, /* @tp_traverse@ */
1066 0, /* @tp_clear@ */
1067 0, /* @tp_richcompare@ */
1068 0, /* @tp_weaklistoffset@ */
1069 0, /* @tp_iter@ */
1070 0, /* @tp_iternexr@ */
1071 0, /* @tp_methods@ */
1072 0, /* @tp_members@ */
1073 0, /* @tp_getset@ */
1074 0, /* @tp_base@ */
1075 0, /* @tp_dict@ */
1076 0, /* @tp_descr_get@ */
1077 0, /* @tp_descr_set@ */
1078 0, /* @tp_dictoffset@ */
1079 0, /* @tp_init@ */
1080 PyType_GenericAlloc, /* @tp_alloc@ */
1081 abstract_pynew, /* @tp_new@ */
3aa33042 1082 0, /* @tp_free@ */
d7ab1bab 1083 0 /* @tp_is_gc@ */
1084};
1085
1086static 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@ */
1091
1092 ghash_pydealloc, /* @tp_dealloc@ */
1093 0, /* @tp_print@ */
1094 0, /* @tp_getattr@ */
1095 0, /* @tp_setattr@ */
1096 0, /* @tp_compare@ */
1097 0, /* @tp_repr@ */
1098 0, /* @tp_as_number@ */
1099 0, /* @tp_as_sequence@ */
1100 0, /* @tp_as_mapping@ */
1101 0, /* @tp_hash@ */
1102 0, /* @tp_call@ */
1103 0, /* @tp_str@ */
1104 0, /* @tp_getattro@ */
1105 0, /* @tp_setattro@ */
1106 0, /* @tp_as_buffer@ */
1107 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
1108 Py_TPFLAGS_BASETYPE,
1109
1110 /* @tp_doc@ */
1111"Message authentication code, abstract base class.",
1112
1113 0, /* @tp_traverse@ */
1114 0, /* @tp_clear@ */
1115 0, /* @tp_richcompare@ */
1116 0, /* @tp_weaklistoffset@ */
1117 0, /* @tp_iter@ */
1118 0, /* @tp_iternexr@ */
1119 0, /* @tp_methods@ */
1120 0, /* @tp_members@ */
1121 0, /* @tp_getset@ */
1122 0, /* @tp_base@ */
1123 0, /* @tp_dict@ */
1124 0, /* @tp_descr_get@ */
1125 0, /* @tp_descr_set@ */
1126 0, /* @tp_dictoffset@ */
1127 0, /* @tp_init@ */
1128 PyType_GenericAlloc, /* @tp_alloc@ */
1129 abstract_pynew, /* @tp_new@ */
3aa33042 1130 0, /* @tp_free@ */
d7ab1bab 1131 0 /* @tp_is_gc@ */
1132};
1133
1134/*----- Main code ---------------------------------------------------------*/
1135
1136void algorithms_pyinit(void)
1137{
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);
1149}
1150
1151#define GEN(func, base) \
1152 static PyObject *func(void) \
1153 { \
1154 PyObject *d = PyDict_New(); \
1155 PyObject *o; \
1156 int i; \
1157 \
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, \
1162 o); \
1163 Py_DECREF(o); \
1164 } \
1165 return (d); \
1166 }
1167GEN(gcciphers, cipher)
1168GEN(gchashes, hash)
1169GEN(gcmacs, mac)
1170
1171void algorithms_pyinsert(PyObject *mod)
1172{
1173 PyObject *d;
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());
1190}
1191
1192/*----- That's all, folks -------------------------------------------------*/