chiark / gitweb /
*.c: Introduce a new input conversion for binary strings.
[catacomb-python] / pubkey.c
1 /* -*-c-*-
2  *
3  * Public-key cryptography
4  *
5  * (c) 2004 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the Python interface to Catacomb.
11  *
12  * Catacomb/Python is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Catacomb/Python is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Catacomb/Python; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /*----- Header files ------------------------------------------------------*/
28
29 #include "catacomb-python.h"
30
31 /*----- DSA and similar ---------------------------------------------------*/
32
33 typedef struct dsa_pyobj {
34   PyObject_HEAD
35   PyObject *G, *u, *p, *rng, *hash;
36   gdsa d;
37 } dsa_pyobj;
38
39 static PyTypeObject *dsapub_pytype, *dsapriv_pytype;
40 static PyTypeObject *kcdsapub_pytype, *kcdsapriv_pytype;
41 #define DSA_D(o) (&((dsa_pyobj *)(o))->d)
42 #define DSA_G(o) (((dsa_pyobj *)(o))->G)
43 #define DSA_U(o) (((dsa_pyobj *)(o))->u)
44 #define DSA_P(o) (((dsa_pyobj *)(o))->p)
45 #define DSA_RNG(o) (((dsa_pyobj *)(o))->rng)
46 #define DSA_HASH(o) (((dsa_pyobj *)(o))->hash)
47
48 static void dsa_pydealloc(PyObject *me)
49 {
50   dsa_pyobj *g = (dsa_pyobj *)me;
51   Py_DECREF(g->G); Py_DECREF(g->u); Py_DECREF(g->p);
52   Py_DECREF(g->rng); Py_DECREF(g->hash);
53   FREEOBJ(me);
54 }
55
56 static PyObject *dsa_setup(PyTypeObject *ty, PyObject *G, PyObject *u,
57                            PyObject *p, PyObject *rng, PyObject *hash,
58                            void (*calcpub)(group *, ge *, mp *))
59 {
60   dsa_pyobj *g;
61   ge *pp;
62
63   g = PyObject_New(dsa_pyobj, ty);
64   if (p) Py_INCREF(p);
65   if (!u) {
66     g->d.u = 0;
67     u = Py_None;
68   } else {
69     if ((g->d.u = getmp(u)) == 0)
70       goto end;
71     if (MP_PYCHECK(u)) Py_INCREF(u);
72     else u = mp_pywrap(g->d.u);
73   }
74   if (!p) {
75     assert(g->d.u); assert(calcpub);
76     pp = G_CREATE(GROUP_G(G));
77     calcpub(GROUP_G(G), pp, g->d.u);
78     p = ge_pywrap(G, pp);
79   } else if (GROUP_G(G) != GE_G(p) && !group_samep(GROUP_G(G), GE_G(p)))
80     TYERR("public key not from group");
81   g->d.g = GROUP_G(G);
82   g->d.p = GE_X(p);
83   g->d.r = GRAND_R(rng);
84   g->d.h = GCHASH_CH(hash);
85   g->G = G; Py_INCREF(G); g->u = u; g->p = p;
86   g->rng = rng; Py_INCREF(rng); g->hash = hash; Py_INCREF(hash);
87   return ((PyObject *)g);
88 end:
89   Py_XDECREF(p); FREEOBJ(g);
90   return (0);
91 }
92
93 static PyObject *dsapub_pynew(PyTypeObject *ty,
94                               PyObject *arg, PyObject *kw)
95 {
96   PyObject *G, *p, *rng = rand_pyobj, *hash = sha_pyobj;
97   PyObject *rc = 0;
98   static const char *const kwlist[] = { "G", "p", "hash", "rng", 0 };
99
100   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|O!O!:new", KWLIST,
101                                    group_pytype, &G,
102                                    ge_pytype, &p,
103                                    gchash_pytype, &hash,
104                                    grand_pytype, &rng) ||
105       (rc = dsa_setup(dsapub_pytype, G, 0, p, rng, hash, 0)) == 0)
106     goto end;
107 end:
108   return (rc);
109 }
110
111 static PyObject *dsameth_beginhash(PyObject *me)
112   { return (ghash_pywrap(DSA_HASH(me), gdsa_beginhash(DSA_D(me)))); }
113
114 static PyObject *dsameth_endhash(PyObject *me, PyObject *arg)
115 {
116   ghash *h;
117   PyObject *rc;
118   if (!PyArg_ParseTuple(arg, "O&:endhash", convghash, &h)) return (0);
119   gdsa_endhash(DSA_D(me), h);
120   h = GH_COPY(h);
121   rc = bytestring_pywrap(0, GH_CLASS(h)->hashsz);
122   GH_DONE(h, PyString_AS_STRING(rc));
123   GH_DESTROY(h);
124   return (rc);
125 }
126
127 static PyObject *dsameth_sign(PyObject *me, PyObject *arg, PyObject *kw)
128 {
129   gdsa_sig s = GDSA_SIG_INIT;
130   struct bin h;
131   mp *k = 0;
132   PyObject *rc = 0;
133   static const char *const kwlist[] = { "msg", "k", 0 };
134
135   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:sign", KWLIST,
136                                    convbin, &h, convmp, &k))
137     goto end;
138   if (h.sz != DSA_D(me)->h->hashsz)
139     VALERR("bad message length (doesn't match hash size)");
140   gdsa_sign(DSA_D(me), &s, h.p, k);
141   rc = Py_BuildValue("(NN)", mp_pywrap(s.r), mp_pywrap(s.s));
142 end:
143   mp_drop(k);
144   return (rc);
145 }
146
147 static PyObject *dsameth_verify(PyObject *me, PyObject *arg)
148 {
149   struct bin h;
150   gdsa_sig s = GDSA_SIG_INIT;
151   PyObject *rc = 0;
152
153   if (!PyArg_ParseTuple(arg, "O&(O&O&):verify",
154                         convbin, &h, convmp, &s.r, convmp, &s.s))
155     goto end;
156   if (h.sz != DSA_D(me)->h->hashsz)
157     VALERR("bad message length (doesn't match hash size)");
158   rc = getbool(!gdsa_verify(DSA_D(me), &s, h.p));
159 end:
160   mp_drop(s.r);
161   mp_drop(s.s);
162   return (rc);
163 }
164
165 static void dsa_calcpub(group *g, ge *p, mp *u) { G_EXP(g, p, g->g, u); }
166
167 static PyObject *dsapriv_pynew(PyTypeObject *ty,
168                                PyObject *arg, PyObject *kw)
169 {
170   PyObject *G, *p = 0, *u, *rng = rand_pyobj, *hash = sha_pyobj;
171   PyObject *rc = 0;
172   static const char *const kwlist[] = { "G", "u", "p", "hash", "rng", 0 };
173
174   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O|O!O!O!:new", KWLIST,
175                                    group_pytype, &G,
176                                    &u,
177                                    ge_pytype, &p,
178                                    gchash_pytype, &hash,
179                                    grand_pytype, &rng) ||
180       (rc = dsa_setup(dsapriv_pytype, G, u, p, rng, hash, dsa_calcpub)) == 0)
181     goto end;
182 end:
183   return (rc);
184 }
185
186 static const PyMethodDef dsapub_pymethods[] = {
187 #define METHNAME(name) dsameth_##name
188   NAMETH(beginhash,     "D.beginhash() -> hash object")
189   METH  (endhash,       "D.endhash(H) -> BYTES")
190   METH  (verify,        "D.verify(MSG, (R, S)) -> true/false")
191 #undef METHNAME
192   { 0 }
193 };
194
195 static const PyMethodDef dsapriv_pymethods[] = {
196 #define METHNAME(name) dsameth_##name
197   KWMETH(sign,          "D.sign(MSG, [k = K]) -> R, S")
198 #undef METHNAME
199   { 0 }
200 };
201
202 static const PyMemberDef dsapub_pymembers[] = {
203 #define MEMBERSTRUCT dsa_pyobj
204   MEMBER(G,     T_OBJECT, READONLY, "D.G -> group to work in")
205   MEMBER(p,     T_OBJECT, READONLY, "D.p -> public key (group element")
206   MEMBER(rng,   T_OBJECT, READONLY, "D.rng -> random number generator")
207   MEMBER(hash,  T_OBJECT, READONLY, "D.hash -> hash class")
208 #undef MEMBERSTRUCT
209   { 0 }
210 };
211
212 static const PyMemberDef dsapriv_pymembers[] = {
213 #define MEMBERSTRUCT dsa_pyobj
214   MEMBER(u,     T_OBJECT, READONLY, "D.u -> private key (exponent)")
215 #undef MEMBERSTRUCT
216   { 0 }
217 };
218
219 static const PyTypeObject dsapub_pytype_skel = {
220   PyVarObject_HEAD_INIT(0, 0)           /* Header */
221   "DSAPub",                             /* @tp_name@ */
222   sizeof(dsa_pyobj),                    /* @tp_basicsize@ */
223   0,                                    /* @tp_itemsize@ */
224
225   dsa_pydealloc,                        /* @tp_dealloc@ */
226   0,                                    /* @tp_print@ */
227   0,                                    /* @tp_getattr@ */
228   0,                                    /* @tp_setattr@ */
229   0,                                    /* @tp_compare@ */
230   0,                                    /* @tp_repr@ */
231   0,                                    /* @tp_as_number@ */
232   0,                                    /* @tp_as_sequence@ */
233   0,                                    /* @tp_as_mapping@ */
234   0,                                    /* @tp_hash@ */
235   0,                                    /* @tp_call@ */
236   0,                                    /* @tp_str@ */
237   0,                                    /* @tp_getattro@ */
238   0,                                    /* @tp_setattro@ */
239   0,                                    /* @tp_as_buffer@ */
240   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
241     Py_TPFLAGS_BASETYPE,
242
243   /* @tp_doc@ */
244   "DSAPub(GROUP, P, [hash = sha], [rng = rand]): DSA public key.",
245
246   0,                                    /* @tp_traverse@ */
247   0,                                    /* @tp_clear@ */
248   0,                                    /* @tp_richcompare@ */
249   0,                                    /* @tp_weaklistoffset@ */
250   0,                                    /* @tp_iter@ */
251   0,                                    /* @tp_iternext@ */
252   PYMETHODS(dsapub),                    /* @tp_methods@ */
253   PYMEMBERS(dsapub),                    /* @tp_members@ */
254   0,                                    /* @tp_getset@ */
255   0,                                    /* @tp_base@ */
256   0,                                    /* @tp_dict@ */
257   0,                                    /* @tp_descr_get@ */
258   0,                                    /* @tp_descr_set@ */
259   0,                                    /* @tp_dictoffset@ */
260   0,                                    /* @tp_init@ */
261   PyType_GenericAlloc,                  /* @tp_alloc@ */
262   dsapub_pynew,                         /* @tp_new@ */
263   0,                                    /* @tp_free@ */
264   0                                     /* @tp_is_gc@ */
265 };
266
267 static const PyTypeObject dsapriv_pytype_skel = {
268   PyVarObject_HEAD_INIT(0, 0)           /* Header */
269   "DSAPriv",                            /* @tp_name@ */
270   sizeof(dsa_pyobj),                    /* @tp_basicsize@ */
271   0,                                    /* @tp_itemsize@ */
272
273   0,                                    /* @tp_dealloc@ */
274   0,                                    /* @tp_print@ */
275   0,                                    /* @tp_getattr@ */
276   0,                                    /* @tp_setattr@ */
277   0,                                    /* @tp_compare@ */
278   0,                                    /* @tp_repr@ */
279   0,                                    /* @tp_as_number@ */
280   0,                                    /* @tp_as_sequence@ */
281   0,                                    /* @tp_as_mapping@ */
282   0,                                    /* @tp_hash@ */
283   0,                                    /* @tp_call@ */
284   0,                                    /* @tp_str@ */
285   0,                                    /* @tp_getattro@ */
286   0,                                    /* @tp_setattro@ */
287   0,                                    /* @tp_as_buffer@ */
288   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
289     Py_TPFLAGS_BASETYPE,
290
291   /* @tp_doc@ */
292   "DSAPriv(GROUP, U, [p = u G], [hash = sha], [rng = rand]): "
293                                                           "DSA private key.",
294
295   0,                                    /* @tp_traverse@ */
296   0,                                    /* @tp_clear@ */
297   0,                                    /* @tp_richcompare@ */
298   0,                                    /* @tp_weaklistoffset@ */
299   0,                                    /* @tp_iter@ */
300   0,                                    /* @tp_iternext@ */
301   PYMETHODS(dsapriv),                   /* @tp_methods@ */
302   PYMEMBERS(dsapriv),                   /* @tp_members@ */
303   0,                                    /* @tp_getset@ */
304   0,                                    /* @tp_base@ */
305   0,                                    /* @tp_dict@ */
306   0,                                    /* @tp_descr_get@ */
307   0,                                    /* @tp_descr_set@ */
308   0,                                    /* @tp_dictoffset@ */
309   0,                                    /* @tp_init@ */
310   PyType_GenericAlloc,                  /* @tp_alloc@ */
311   dsapriv_pynew,                        /* @tp_new@ */
312   0,                                    /* @tp_free@ */
313   0                                     /* @tp_is_gc@ */
314 };
315
316 static PyObject *kcdsapub_pynew(PyTypeObject *ty,
317                                 PyObject *arg, PyObject *kw)
318 {
319   PyObject *G, *p, *rng = rand_pyobj, *hash = has160_pyobj;
320   PyObject *rc = 0;
321   static const char *const kwlist[] = { "G", "p", "hash", "rng", 0 };
322
323   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O!|O!O!:new", KWLIST,
324                                    group_pytype, &G,
325                                    ge_pytype, &p,
326                                    gchash_pytype, &hash,
327                                    grand_pytype, &rng) ||
328       (rc = dsa_setup(kcdsapub_pytype, G, 0, p, rng, hash, 0)) == 0)
329     goto end;
330 end:
331   return (rc);
332 }
333
334 static void kcdsa_calcpub(group *g, ge *p, mp *u)
335 {
336   mp *uinv = mp_modinv(MP_NEW, u, g->r);
337   G_EXP(g, p, g->g, uinv);
338   mp_drop(uinv);
339 }
340
341 static PyObject *kcdsapriv_pynew(PyTypeObject *ty,
342                                  PyObject *arg, PyObject *kw)
343 {
344   PyObject *G, *u, *p = 0, *rng = rand_pyobj, *hash = has160_pyobj;
345   PyObject *rc = 0;
346   static const char *const kwlist[] = { "G", "u", "p", "hash", "rng", 0 };
347
348   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O!O|O!O!O!:new", KWLIST,
349                                    group_pytype, &G,
350                                    &u,
351                                    ge_pytype, &p,
352                                    gchash_pytype, &hash,
353                                    grand_pytype, &rng) ||
354       (rc = dsa_setup(kcdsapriv_pytype, G, u, p,
355                       rng, hash, kcdsa_calcpub)) == 0)
356     goto end;
357 end:
358   return (rc);
359 }
360
361 static PyObject *kcdsameth_beginhash(PyObject *me)
362   { return (ghash_pywrap(DSA_HASH(me), gkcdsa_beginhash(DSA_D(me)))); }
363
364 static PyObject *kcdsameth_endhash(PyObject *me, PyObject *arg)
365 {
366   ghash *h;
367   PyObject *rc;
368   if (!PyArg_ParseTuple(arg, "O&:endhash", convghash, &h)) return (0);
369   gkcdsa_endhash(DSA_D(me), h);
370   h = GH_COPY(h);
371   rc = bytestring_pywrap(0, GH_CLASS(h)->hashsz);
372   GH_DONE(h, PyString_AS_STRING(rc));
373   GH_DESTROY(h);
374   return (rc);
375 }
376
377 static PyObject *kcdsameth_sign(PyObject *me, PyObject *arg, PyObject *kw)
378 {
379   gkcdsa_sig s = GKCDSA_SIG_INIT;
380   struct bin h;
381   mp *k = 0;
382   PyObject *r = 0, *rc = 0;
383   static const char *const kwlist[] = { "msg", "k", 0 };
384
385   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:sign", KWLIST,
386                                    convbin, &h, convmp, &k))
387     goto end;
388   if (h.sz != DSA_D(me)->h->hashsz)
389     VALERR("bad message length (doesn't match hash size)");
390   r = bytestring_pywrap(0, DSA_D(me)->h->hashsz);
391   s.r = (octet *)PyString_AS_STRING(r);
392   gkcdsa_sign(DSA_D(me), &s, h.p, k);
393   rc = Py_BuildValue("(ON)", r, mp_pywrap(s.s));
394 end:
395   Py_XDECREF(r);
396   mp_drop(k);
397   return (rc);
398 }
399
400 static PyObject *kcdsameth_verify(PyObject *me, PyObject *arg)
401 {
402   struct bin h, sr;
403   gkcdsa_sig s = GKCDSA_SIG_INIT;
404   PyObject *rc = 0;
405
406   if (!PyArg_ParseTuple(arg, "O&(O&O&):verify",
407                         convbin, &h, convbin, &sr, convmp, &s.s))
408     goto end;
409   if (h.sz != DSA_D(me)->h->hashsz)
410     VALERR("bad message length (doesn't match hash size)");
411   if (sr.sz != DSA_D(me)->h->hashsz)
412     VALERR("bad signature `r' length (doesn't match hash size)");
413   s.r = (/*unconst*/ octet *)sr.p;
414   rc = getbool(!gkcdsa_verify(DSA_D(me), &s, h.p));
415 end:
416   mp_drop(s.s);
417   return (rc);
418 }
419
420 static const PyMethodDef kcdsapub_pymethods[] = {
421 #define METHNAME(name) kcdsameth_##name
422   NAMETH(beginhash,     "D.beginhash() -> hash object")
423   METH  (endhash,       "D.endhash(H) -> BYTES")
424   METH  (verify,        "D.verify(MSG, (R, S)) -> true/false")
425 #undef METHNAME
426   { 0 }
427 };
428
429 static const PyMethodDef kcdsapriv_pymethods[] = {
430 #define METHNAME(name) kcdsameth_##name
431   KWMETH(sign,          "D.sign(MSG, [k = K]) -> R, S")
432 #undef METHNAME
433   { 0 }
434 };
435
436 static const PyTypeObject kcdsapub_pytype_skel = {
437   PyVarObject_HEAD_INIT(0, 0)           /* Header */
438   "KCDSAPub",                           /* @tp_name@ */
439   sizeof(dsa_pyobj),                    /* @tp_basicsize@ */
440   0,                                    /* @tp_itemsize@ */
441
442   dsa_pydealloc,                        /* @tp_dealloc@ */
443   0,                                    /* @tp_print@ */
444   0,                                    /* @tp_getattr@ */
445   0,                                    /* @tp_setattr@ */
446   0,                                    /* @tp_compare@ */
447   0,                                    /* @tp_repr@ */
448   0,                                    /* @tp_as_number@ */
449   0,                                    /* @tp_as_sequence@ */
450   0,                                    /* @tp_as_mapping@ */
451   0,                                    /* @tp_hash@ */
452   0,                                    /* @tp_call@ */
453   0,                                    /* @tp_str@ */
454   0,                                    /* @tp_getattro@ */
455   0,                                    /* @tp_setattro@ */
456   0,                                    /* @tp_as_buffer@ */
457   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
458     Py_TPFLAGS_BASETYPE,
459
460   /* @tp_doc@ */
461   "KCDSAPub(GROUP, P, [hash = sha], [rng = rand]): KCDSA public key.",
462
463   0,                                    /* @tp_traverse@ */
464   0,                                    /* @tp_clear@ */
465   0,                                    /* @tp_richcompare@ */
466   0,                                    /* @tp_weaklistoffset@ */
467   0,                                    /* @tp_iter@ */
468   0,                                    /* @tp_iternext@ */
469   PYMETHODS(kcdsapub),                  /* @tp_methods@ */
470   PYMEMBERS(dsapub),                    /* @tp_members@ */
471   0,                                    /* @tp_getset@ */
472   0,                                    /* @tp_base@ */
473   0,                                    /* @tp_dict@ */
474   0,                                    /* @tp_descr_get@ */
475   0,                                    /* @tp_descr_set@ */
476   0,                                    /* @tp_dictoffset@ */
477   0,                                    /* @tp_init@ */
478   PyType_GenericAlloc,                  /* @tp_alloc@ */
479   kcdsapub_pynew,                       /* @tp_new@ */
480   0,                                    /* @tp_free@ */
481   0                                     /* @tp_is_gc@ */
482 };
483
484 static const PyTypeObject kcdsapriv_pytype_skel = {
485   PyVarObject_HEAD_INIT(0, 0)           /* Header */
486   "KCDSAPriv",                          /* @tp_name@ */
487   sizeof(dsa_pyobj),                    /* @tp_basicsize@ */
488   0,                                    /* @tp_itemsize@ */
489
490   0,                                    /* @tp_dealloc@ */
491   0,                                    /* @tp_print@ */
492   0,                                    /* @tp_getattr@ */
493   0,                                    /* @tp_setattr@ */
494   0,                                    /* @tp_compare@ */
495   0,                                    /* @tp_repr@ */
496   0,                                    /* @tp_as_number@ */
497   0,                                    /* @tp_as_sequence@ */
498   0,                                    /* @tp_as_mapping@ */
499   0,                                    /* @tp_hash@ */
500   0,                                    /* @tp_call@ */
501   0,                                    /* @tp_str@ */
502   0,                                    /* @tp_getattro@ */
503   0,                                    /* @tp_setattro@ */
504   0,                                    /* @tp_as_buffer@ */
505   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
506     Py_TPFLAGS_BASETYPE,
507
508   /* @tp_doc@ */
509   "KCDSAPriv(GROUP, U, [p = u G], [hash = sha], [rng = rand]): "
510                                                         "KCDSA private key.",
511
512   0,                                    /* @tp_traverse@ */
513   0,                                    /* @tp_clear@ */
514   0,                                    /* @tp_richcompare@ */
515   0,                                    /* @tp_weaklistoffset@ */
516   0,                                    /* @tp_iter@ */
517   0,                                    /* @tp_iternext@ */
518   PYMETHODS(kcdsapriv),                 /* @tp_methods@ */
519   PYMEMBERS(dsapriv),                   /* @tp_members@ */
520   0,                                    /* @tp_getset@ */
521   0,                                    /* @tp_base@ */
522   0,                                    /* @tp_dict@ */
523   0,                                    /* @tp_descr_get@ */
524   0,                                    /* @tp_descr_set@ */
525   0,                                    /* @tp_dictoffset@ */
526   0,                                    /* @tp_init@ */
527   PyType_GenericAlloc,                  /* @tp_alloc@ */
528   kcdsapriv_pynew,                      /* @tp_new@ */
529   0,                                    /* @tp_free@ */
530   0                                     /* @tp_is_gc@ */
531 };
532
533 /*----- RSA ---------------------------------------------------------------*/
534
535 typedef struct rsapub_pyobj {
536   PyObject_HEAD
537   rsa_pub pub;
538   rsa_pubctx pubctx;
539 } rsapub_pyobj;
540
541 #define RSA_PUB(o) (&((rsapub_pyobj *)(o))->pub)
542 #define RSA_PUBCTX(o) (&((rsapub_pyobj *)(o))->pubctx)
543
544 typedef struct rsapriv_pyobj {
545   PyObject_HEAD
546   rsa_pub pub;
547   rsa_pubctx pubctx;
548   rsa_priv priv;
549   rsa_privctx privctx;
550   PyObject *rng;
551 } rsapriv_pyobj;
552
553 #define RSA_PRIV(o) (&((rsapriv_pyobj *)(o))->priv)
554 #define RSA_PRIVCTX(o) (&((rsapriv_pyobj *)(o))->privctx)
555 #define RSA_RNG(o) (((rsapriv_pyobj *)(o))->rng)
556
557 static PyTypeObject *rsapub_pytype, *rsapriv_pytype;
558
559 static PyObject *rsapub_pynew(PyTypeObject *ty,
560                               PyObject *arg, PyObject *kw)
561 {
562   rsa_pub rp = { 0 };
563   rsapub_pyobj *o;
564   static const char *const kwlist[] = { "n", "e", 0 };
565
566   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST,
567                                    convmp, &rp.n, convmp, &rp.e))
568     goto end;
569   if (!MP_ODDP(rp.n)) VALERR("RSA modulus must be even");
570   o = (rsapub_pyobj *)ty->tp_alloc(ty, 0);
571   o->pub = rp;
572   rsa_pubcreate(&o->pubctx, &o->pub);
573   return ((PyObject *)o);
574 end:
575   rsa_pubfree(&rp);
576   return (0);
577 }
578
579 static void rsapub_pydealloc(PyObject *me)
580 {
581   rsa_pubdestroy(RSA_PUBCTX(me));
582   rsa_pubfree(RSA_PUB(me));
583   FREEOBJ(me);
584 }
585
586 static PyObject *rsaget_n(PyObject *me, void *hunoz)
587   { return mp_pywrap(MP_COPY(RSA_PUB(me)->n)); }
588
589 static PyObject *rsaget_e(PyObject *me, void *hunoz)
590   { return mp_pywrap(MP_COPY(RSA_PUB(me)->e)); }
591
592 static PyObject *rsameth_pubop(PyObject *me, PyObject *arg)
593 {
594   mp *x = 0;
595   PyObject *rc = 0;
596
597   if (!PyArg_ParseTuple(arg, "O&:pubop", convmp, &x)) goto end;
598   rc = mp_pywrap(rsa_pubop(RSA_PUBCTX(me), MP_NEW, x));
599 end:
600   mp_drop(x);
601   return (rc);
602 }
603
604 static PyObject *rsapriv_dopywrap(PyTypeObject *ty,
605                                   rsa_priv *rp, PyObject *rng)
606 {
607   rsapriv_pyobj *o;
608
609   o = (rsapriv_pyobj *)ty->tp_alloc(ty, 0);
610   o->priv = *rp;
611   o->pub.n = rp->n;
612   o->pub.e = rp->e;
613   rsa_privcreate(&o->privctx, &o->priv, &rand_global);
614   rsa_pubcreate(&o->pubctx, &o->pub);
615   if (!rng) {
616     rng = Py_None;
617     Py_INCREF(rng);
618   }
619   o->rng = rng;
620   return ((PyObject *)o);
621 }
622
623 PyObject *rsapriv_pywrap(rsa_priv *rp)
624   { return rsapriv_dopywrap(rsapriv_pytype, rp, 0); }
625
626 static PyObject *rsapriv_pynew(PyTypeObject *ty,
627                                PyObject *arg, PyObject *kw)
628 {
629   rsa_priv rp = { 0 };
630   PyObject *rng = Py_None;
631   static const char *const kwlist[] =
632     { "n", "e", "d", "p", "q", "dp", "dq", "q_inv", "rng", 0 };
633
634   if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&O&O&O&O&O&O&O&O:new", KWLIST,
635                                    convmp, &rp.n, convmp, &rp.e,
636                                    convmp, &rp.d,
637                                    convmp, &rp.p, convmp, &rp.q,
638                                    convmp, &rp.dp, convmp, &rp.dq,
639                                    convmp, &rp.q_inv,
640                                    &rng))
641     goto end;
642   if ((rp.n && !MP_ODDP(rp.n)) ||
643       (rp.p && !MP_ODDP(rp.p)) ||
644       (rp.q && !MP_ODDP(rp.q)))
645     VALERR("RSA modulus and factors must be odd");
646   if (rsa_recover(&rp)) VALERR("couldn't construct private key");
647   if (rng != Py_None && !GRAND_PYCHECK(rng))
648     TYERR("not a random number source");
649   Py_INCREF(rng);
650   return (rsapriv_dopywrap(ty, &rp, rng));
651 end:
652   rsa_privfree(&rp);
653   return (0);
654 }
655
656 static void rsapriv_pydealloc(PyObject *me)
657 {
658   RSA_PRIVCTX(me)->r = &rand_global;
659   rsa_privdestroy(RSA_PRIVCTX(me));
660   rsa_privfree(RSA_PRIV(me));
661   Py_DECREF(RSA_RNG(me));
662   FREEOBJ(me);
663 }
664
665 static PyObject *rsaget_d(PyObject *me, void *hunoz)
666   { return mp_pywrap(MP_COPY(RSA_PRIV(me)->d)); }
667
668 static PyObject *rsaget_p(PyObject *me, void *hunoz)
669   { return mp_pywrap(MP_COPY(RSA_PRIV(me)->p)); }
670
671 static PyObject *rsaget_q(PyObject *me, void *hunoz)
672   { return mp_pywrap(MP_COPY(RSA_PRIV(me)->q)); }
673
674 static PyObject *rsaget_dp(PyObject *me, void *hunoz)
675   { return mp_pywrap(MP_COPY(RSA_PRIV(me)->dp)); }
676
677 static PyObject *rsaget_dq(PyObject *me, void *hunoz)
678   { return mp_pywrap(MP_COPY(RSA_PRIV(me)->dq)); }
679
680 static PyObject *rsaget_q_inv(PyObject *me, void *hunoz)
681   { return mp_pywrap(MP_COPY(RSA_PRIV(me)->q_inv)); }
682
683 static PyObject *rsaget_rng(PyObject *me, void *hunoz)
684   { RETURN_OBJ(RSA_RNG(me)); }
685
686 static int rsaset_rng(PyObject *me, PyObject *val, void *hunoz)
687 {
688   int rc = -1;
689   if (!val)
690     val = Py_None;
691   else if (val != Py_None && !GRAND_PYCHECK(val))
692     TYERR("expected grand or None");
693   Py_DECREF(RSA_RNG(me));
694   RSA_RNG(me) = val;
695   Py_INCREF(val);
696   rc = 0;
697 end:
698   return (rc);
699 }
700
701 static PyObject *rsameth_privop(PyObject *me, PyObject *arg, PyObject *kw)
702 {
703   PyObject *rng = RSA_RNG(me);
704   mp *x = 0;
705   PyObject *rc = 0;
706   static const char *const kwlist[] = { "x", "rng", 0 };
707
708   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O:privop", KWLIST,
709                                    convmp, &x, &rng))
710     goto end;
711   if (rng != Py_None && !GRAND_PYCHECK(rng))
712     TYERR("not a random number source");
713   RSA_PRIVCTX(me)->r = (rng == Py_None) ? 0 : GRAND_R(rng);
714   rc = mp_pywrap(rsa_privop(RSA_PRIVCTX(me), MP_NEW, x));
715 end:
716   mp_drop(x);
717   return (rc);
718 }
719
720 static PyObject *rsameth_generate(PyObject *me, PyObject *arg, PyObject *kw)
721 {
722   grand *r = &rand_global;
723   unsigned nbits;
724   unsigned n = 0;
725   rsa_priv rp;
726   mp *e = 0;
727   struct excinfo exc = EXCINFO_INIT;
728   pypgev evt = { { 0 } };
729   static const char *const kwlist[] =
730     { "nbits", "event", "rng", "nsteps", "e", 0 };
731   PyObject *rc = 0;
732
733   evt.exc = &exc;
734   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&O&O&O&:generate", KWLIST,
735                                    convuint, &nbits, convpgev, &evt,
736                                    convgrand, &r, convuint, &n,
737                                    convmp, &e))
738     goto end;
739   if (e) MP_COPY(e);
740   else e = mp_fromulong(MP_NEW, 65537);
741   if (rsa_gen_e(&rp, nbits, e, r, n, evt.ev.proc, evt.ev.ctx))
742     PGENERR(&exc);
743   rc = rsapriv_pywrap(&rp);
744 end:
745   droppgev(&evt);
746   mp_drop(e);
747   return (rc);
748 }
749
750 static const PyGetSetDef rsapub_pygetset[] = {
751 #define GETSETNAME(op, name) rsa##op##_##name
752   GET   (n,             "R.n -> N")
753   GET   (e,             "R.e -> E")
754 #undef GETSETNAME
755   { 0 }
756 };
757
758 static const PyMethodDef rsapub_pymethods[] = {
759 #define METHNAME(name) rsameth_##name
760   METH  (pubop,         "R.pubop(X) -> X^E (mod N)")
761 #undef METHNAME
762   { 0 }
763 };
764
765 static const PyGetSetDef rsapriv_pygetset[] = {
766 #define GETSETNAME(op, name) rsa##op##_##name
767   GET   (d,             "R.d -> D")
768   GET   (p,             "R.p -> P")
769   GET   (q,             "R.q -> Q")
770   GET   (dp,            "R.dp -> D mod (P - 1)")
771   GET   (dq,            "R.dq -> D mod (Q - 1)")
772   GET   (q_inv,         "R.q_inv -> Q^{-1} mod P")
773   GETSET(rng,           "R.rng -> random number source for blinding")
774 #undef GETSETNAME
775   { 0 }
776 };
777
778 static const PyMethodDef rsapriv_pymethods[] = {
779 #define METHNAME(name) rsameth_##name
780   KWMETH(privop,        "R.privop(X, [rng = None]) -> X^D (mod N)")
781   KWSMTH(generate, "generate(NBITS, [event = pgen_nullev], [rng = rand], "
782                                                         "[nsteps = 0]) -> R")
783 #undef METHNAME
784   { 0 }
785 };
786
787 static const PyTypeObject rsapub_pytype_skel = {
788   PyVarObject_HEAD_INIT(0, 0)           /* Header */
789   "RSAPub",                             /* @tp_name@ */
790   sizeof(rsapub_pyobj),                 /* @tp_basicsize@ */
791   0,                                    /* @tp_itemsize@ */
792
793   rsapub_pydealloc,                     /* @tp_dealloc@ */
794   0,                                    /* @tp_print@ */
795   0,                                    /* @tp_getattr@ */
796   0,                                    /* @tp_setattr@ */
797   0,                                    /* @tp_compare@ */
798   0,                                    /* @tp_repr@ */
799   0,                                    /* @tp_as_number@ */
800   0,                                    /* @tp_as_sequence@ */
801   0,                                    /* @tp_as_mapping@ */
802   0,                                    /* @tp_hash@ */
803   0,                                    /* @tp_call@ */
804   0,                                    /* @tp_str@ */
805   0,                                    /* @tp_getattro@ */
806   0,                                    /* @tp_setattro@ */
807   0,                                    /* @tp_as_buffer@ */
808   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
809     Py_TPFLAGS_BASETYPE,
810
811   /* @tp_doc@ */
812   "RSAPub(N, E): RSA public key.",
813
814   0,                                    /* @tp_traverse@ */
815   0,                                    /* @tp_clear@ */
816   0,                                    /* @tp_richcompare@ */
817   0,                                    /* @tp_weaklistoffset@ */
818   0,                                    /* @tp_iter@ */
819   0,                                    /* @tp_iternext@ */
820   PYMETHODS(rsapub),                    /* @tp_methods@ */
821   0,                                    /* @tp_members@ */
822   PYGETSET(rsapub),                     /* @tp_getset@ */
823   0,                                    /* @tp_base@ */
824   0,                                    /* @tp_dict@ */
825   0,                                    /* @tp_descr_get@ */
826   0,                                    /* @tp_descr_set@ */
827   0,                                    /* @tp_dictoffset@ */
828   0,                                    /* @tp_init@ */
829   PyType_GenericAlloc,                  /* @tp_alloc@ */
830   rsapub_pynew,                         /* @tp_new@ */
831   0,                                    /* @tp_free@ */
832   0                                     /* @tp_is_gc@ */
833 };
834
835 static const PyTypeObject rsapriv_pytype_skel = {
836   PyVarObject_HEAD_INIT(0, 0)           /* Header */
837   "RSAPriv",                            /* @tp_name@ */
838   sizeof(rsapriv_pyobj),                /* @tp_basicsize@ */
839   0,                                    /* @tp_itemsize@ */
840
841   rsapriv_pydealloc,                    /* @tp_dealloc@ */
842   0,                                    /* @tp_print@ */
843   0,                                    /* @tp_getattr@ */
844   0,                                    /* @tp_setattr@ */
845   0,                                    /* @tp_compare@ */
846   0,                                    /* @tp_repr@ */
847   0,                                    /* @tp_as_number@ */
848   0,                                    /* @tp_as_sequence@ */
849   0,                                    /* @tp_as_mapping@ */
850   0,                                    /* @tp_hash@ */
851   0,                                    /* @tp_call@ */
852   0,                                    /* @tp_str@ */
853   0,                                    /* @tp_getattro@ */
854   0,                                    /* @tp_setattro@ */
855   0,                                    /* @tp_as_buffer@ */
856   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
857     Py_TPFLAGS_BASETYPE,
858
859   /* @tp_doc@ */
860   "RSAPriv(..., [rng = rand]): RSA private key.\n"
861   "  Keywords: n, e, d, p, q, dp, dq, q_inv; must provide enough",
862
863   0,                                    /* @tp_traverse@ */
864   0,                                    /* @tp_clear@ */
865   0,                                    /* @tp_richcompare@ */
866   0,                                    /* @tp_weaklistoffset@ */
867   0,                                    /* @tp_iter@ */
868   0,                                    /* @tp_iternext@ */
869   PYMETHODS(rsapriv),                   /* @tp_methods@ */
870   0,                                    /* @tp_members@ */
871   PYGETSET(rsapriv),                    /* @tp_getset@ */
872   0,                                    /* @tp_base@ */
873   0,                                    /* @tp_dict@ */
874   0,                                    /* @tp_descr_get@ */
875   0,                                    /* @tp_descr_set@ */
876   0,                                    /* @tp_dictoffset@ */
877   0,                                    /* @tp_init@ */
878   PyType_GenericAlloc,                  /* @tp_alloc@ */
879   rsapriv_pynew,                        /* @tp_new@ */
880   0,                                    /* @tp_free@ */
881   0                                     /* @tp_is_gc@ */
882 };
883
884 /*----- RSA padding schemes -----------------------------------------------*/
885
886 static PyObject *meth__p1crypt_encode(PyObject *me,
887                                       PyObject *arg, PyObject *kw)
888 {
889   pkcs1 p1;
890   struct bin m, ep = { 0, 0 };
891   unsigned long nbits;
892   PyObject *rc = 0;
893   octet *b = 0;
894   size_t sz;
895   mp *x;
896   static const char *const kwlist[] = { "msg", "nbits", "ep", "rng", 0 };
897
898   p1.r = &rand_global;
899   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:encode", KWLIST,
900                                    convbin, &m, convulong, &nbits,
901                                    convbin, &ep, convgrand, &p1.r))
902     goto end;
903   sz = (nbits + 7)/8;
904   p1.ep = ep.p; p1.epsz = ep.sz;
905   if (ep.sz + m.sz + 11 > sz) VALERR("buffer underflow");
906   b = xmalloc(sz);
907   x = pkcs1_cryptencode(MP_NEW, m.p, m.sz, b, sz, nbits, &p1);
908   rc = mp_pywrap(x);
909 end:
910   xfree(b);
911   return (rc);
912 }
913
914 static PyObject *meth__p1crypt_decode(PyObject *me,
915                                       PyObject *arg, PyObject *kw)
916 {
917   pkcs1 p1;
918   struct bin ep = { 0, 0 };
919   unsigned long nbits;
920   int n;
921   PyObject *rc = 0;
922   octet *b = 0;
923   size_t sz;
924   mp *x = 0;
925   static const char *const kwlist[] = { "ct", "nbits", "ep", "rng", 0 };
926
927   p1.r = &rand_global;
928   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:decode", KWLIST,
929                                    convmp, &x, convulong, &nbits,
930                                    convbin, &ep, convgrand, &p1.r))
931     goto end;
932   sz = (nbits + 7)/8;
933   p1.ep = ep.p; p1.epsz = ep.sz;
934   if (ep.sz + 11 > sz) VALERR("buffer underflow");
935   b = xmalloc(sz);
936   if ((n = pkcs1_cryptdecode(x, b, sz, nbits, &p1)) < 0)
937     VALERR("decryption failed");
938   rc = bytestring_pywrap(b, n);
939 end:
940   mp_drop(x);
941   xfree(b);
942   return (rc);
943 }
944
945 static PyObject *meth__p1sig_encode(PyObject *me,
946                                     PyObject *arg, PyObject *kw)
947 {
948   pkcs1 p1;
949   struct bin m, ep = { 0, 0 };
950   unsigned long nbits;
951   PyObject *rc = 0;
952   octet *b = 0;
953   size_t sz;
954   mp *x;
955   static const char *const kwlist[] = { "msg", "nbits", "ep", "rng", 0 };
956
957   p1.r = &rand_global;
958   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:encode", KWLIST,
959                                    convbin, &m, convulong, &nbits,
960                                    convbin, &ep, convgrand, &p1.r))
961     goto end;
962   sz = (nbits + 7)/8;
963   p1.ep = ep.p; p1.epsz = ep.sz;
964   if (ep.sz + m.sz + 11 > sz) VALERR("buffer underflow");
965   b = xmalloc(sz);
966   x = pkcs1_sigencode(MP_NEW, m.p, m.sz, b, sz, nbits, &p1);
967   rc = mp_pywrap(x);
968 end:
969   xfree(b);
970   return (rc);
971 }
972
973 static PyObject *meth__p1sig_decode(PyObject *me,
974                                     PyObject *arg, PyObject *kw)
975 {
976   pkcs1 p1;
977   struct bin ep = { 0, 0 };
978   unsigned long nbits;
979   int n;
980   PyObject *hukairz;
981   PyObject *rc = 0;
982   octet *b = 0;
983   size_t sz;
984   mp *x = 0;
985   static const char *const kwlist[] =
986     { "msg", "sig", "nbits", "ep", "rng", 0 };
987
988   p1.r = &rand_global;
989   if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&|O&O&:decode", KWLIST,
990                                    &hukairz, convmp, &x, convulong, &nbits,
991                                    convbin, &ep, convgrand, &p1.r))
992     goto end;
993   sz = (nbits + 7)/8;
994   p1.ep = ep.p; p1.epsz = ep.sz;
995   if (ep.sz + 10 > sz) VALERR("buffer underflow");
996   b = xmalloc(sz);
997   if ((n = pkcs1_sigdecode(x, 0, 0, b, sz, nbits, &p1)) < 0)
998     VALERR("verification failed");
999   rc = bytestring_pywrap(b, n);
1000 end:
1001   mp_drop(x);
1002   xfree(b);
1003   return (rc);
1004 }
1005
1006 static PyObject *meth__oaep_encode(PyObject *me,
1007                                    PyObject *arg, PyObject *kw)
1008 {
1009   oaep o;
1010   struct bin m, ep = { 0, 0 };
1011   unsigned long nbits;
1012   PyObject *rc = 0;
1013   octet *b = 0;
1014   size_t sz;
1015   mp *x;
1016   static const char *const kwlist[] =
1017     { "msg", "nbits", "mgf", "hash", "ep", "rng", 0 };
1018
1019   o.r = &rand_global; o.cc = &sha_mgf; o.ch = &sha;
1020   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&O&O&:encode",
1021                                    KWLIST,
1022                                    convbin, &m, convulong, &nbits,
1023                                    convgccipher, &o.cc,
1024                                    convgchash, &o.ch,
1025                                    convbin, &ep,
1026                                    convgrand, &o.r))
1027     goto end;
1028   sz = (nbits + 7)/8;
1029   o.ep = ep.p; o.epsz = ep.sz;
1030   if (2 * o.ch->hashsz + 2 + m.sz > sz) VALERR("buffer underflow");
1031   b = xmalloc(sz);
1032   x = oaep_encode(MP_NEW, m.p, m.sz, b, sz, nbits, &o);
1033   rc = mp_pywrap(x);
1034 end:
1035   xfree(b);
1036   return (rc);
1037 }
1038
1039 static PyObject *meth__oaep_decode(PyObject *me,
1040                                    PyObject *arg, PyObject *kw)
1041 {
1042   oaep o;
1043   struct bin ep = { 0, 0 };
1044   unsigned long nbits;
1045   int n;
1046   PyObject *rc = 0;
1047   octet *b = 0;
1048   size_t sz;
1049   mp *x = 0;
1050   static const char *const kwlist[] =
1051     { "ct", "nbits", "mgf", "hash", "ep", "rng", 0 };
1052
1053   o.r = &rand_global; o.cc = &sha_mgf; o.ch = &sha;
1054   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&O&O&:decode", KWLIST,
1055                                    convmp, &x, convulong, &nbits,
1056                                    convgccipher, &o.cc,
1057                                    convgchash, &o.ch,
1058                                    convbin, &ep,
1059                                    convgrand, &o.r))
1060     goto end;
1061   sz = (nbits + 7)/8;
1062   o.ep = ep.p; o.epsz = ep.sz;
1063   if (2 * o.ch->hashsz > sz) VALERR("buffer underflow");
1064   b = xmalloc(sz);
1065   if ((n = oaep_decode(x, b, sz, nbits, &o)) < 0)
1066     VALERR("decryption failed");
1067   rc = bytestring_pywrap(b, n);
1068 end:
1069   mp_drop(x);
1070   xfree(b);
1071   return (rc);
1072 }
1073
1074 static PyObject *meth__pss_encode(PyObject *me,
1075                                   PyObject *arg, PyObject *kw)
1076 {
1077   pss p;
1078   struct bin m;
1079   unsigned long nbits;
1080   PyObject *rc = 0;
1081   octet *b = 0;
1082   size_t sz;
1083   mp *x = 0;
1084   static const char *const kwlist[] =
1085     { "msg", "nbits", "mgf", "hash", "saltsz", "rng", 0 };
1086
1087   p.cc = &sha_mgf; p.ch = &sha; p.r = &rand_global; p.ssz = (size_t)-1;
1088   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&O&O&:encode", KWLIST,
1089                                    convbin, &m, convulong, &nbits,
1090                                    convgccipher, &p.cc,
1091                                    convgchash, &p.ch,
1092                                    convszt, &p.ssz,
1093                                    convgrand, &p.r))
1094     goto end;
1095   sz = (nbits + 7)/8;
1096   if (p.ssz == (size_t)-1) p.ssz = p.ch->hashsz;
1097   if (p.ch->hashsz + p.ssz + 2 > sz) VALERR("buffer underflow");
1098   b = xmalloc(sz);
1099   x = pss_encode(MP_NEW, m.p, m.sz, b, sz, nbits, &p);
1100   rc = mp_pywrap(x);
1101 end:
1102   xfree(b);
1103   return (rc);
1104 }
1105
1106 static PyObject *meth__pss_decode(PyObject *me,
1107                                   PyObject *arg, PyObject *kw)
1108 {
1109   pss p;
1110   struct bin m;
1111   unsigned long nbits;
1112   PyObject *rc = 0;
1113   octet *b = 0;
1114   size_t sz;
1115   int n;
1116   mp *x = 0;
1117   static const char *const kwlist[] =
1118     { "msg", "sig", "nbits", "mgf", "hash", "saltsz", "rng", 0 };
1119
1120   p.cc = &sha_mgf; p.ch = &sha; p.r = &rand_global; p.ssz = (size_t)-1;
1121   if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&O&|O&O&O&O&:decode",
1122                                    KWLIST,
1123                                    convbin, &m, convmp, &x,
1124                                    convulong, &nbits,
1125                                    convgccipher, &p.cc,
1126                                    convgchash, &p.ch,
1127                                    convszt, &p.ssz,
1128                                    convgrand, &p.r))
1129     goto end;
1130   sz = (nbits + 7)/8;
1131   if (p.ssz == (size_t)-1) p.ssz = p.ch->hashsz;
1132   if (p.ch->hashsz + p.ssz + 2 > sz) VALERR("buffer underflow");
1133   b = xmalloc(sz);
1134   if ((n = pss_decode(x, m.p, m.sz, b, sz, nbits, &p)) < 0)
1135     VALERR("verification failed");
1136   rc = Py_None; Py_INCREF(rc);
1137 end:
1138   mp_drop(x);
1139   xfree(b);
1140   return (rc);
1141 }
1142
1143 /*----- X25519 and related algorithms -------------------------------------*/
1144
1145 #define XDHS(_)                                                         \
1146   _(X25519, x25519)                                                     \
1147   _(X448, x448)
1148
1149 #define DEFXDH(X, x)                                                    \
1150   static PyObject *meth_##x(PyObject *me, PyObject *arg)                \
1151   {                                                                     \
1152     struct bin k, p;                                                    \
1153     PyObject *rc = 0;                                                   \
1154     if (!PyArg_ParseTuple(arg, "O&O&:" #x, convbin, &k, convbin, &p))   \
1155       goto end;                                                         \
1156     if (k.sz != X##_KEYSZ) VALERR("bad key length");                    \
1157     if (p.sz != X##_PUBSZ) VALERR("bad public length");                 \
1158     rc = bytestring_pywrap(0, X##_OUTSZ);                               \
1159     x((octet *)PyString_AS_STRING(rc), k.p, p.p);                       \
1160     return (rc);                                                        \
1161   end:                                                                  \
1162     return (0);                                                         \
1163   }
1164 XDHS(DEFXDH)
1165 #undef DEFXDH
1166
1167 /*----- Ed25519 and related algorithms ------------------------------------*/
1168
1169 #define EDDSAS(_)                                                       \
1170   _(ED25519, ed25519, -1, ctx)                                          \
1171   _(ED448, ed448, 0, )
1172
1173 #define DEFEDDSA(ED, ed, phdflt, sigver)                                \
1174                                                                         \
1175   static PyObject *meth_##ed##_pubkey(PyObject *me, PyObject *arg)      \
1176   {                                                                     \
1177    struct bin k;                                                        \
1178     PyObject *rc = 0;                                                   \
1179     if (!PyArg_ParseTuple(arg, "O&:" #ed "_pubkey", convbin, &k))       \
1180       goto end;                                                         \
1181     rc = bytestring_pywrap(0, ED##_PUBSZ);                              \
1182     ed##_pubkey((octet *)PyString_AS_STRING(rc), k.p, k.sz);            \
1183     return (rc);                                                        \
1184   end:                                                                  \
1185     return (0);                                                         \
1186   }                                                                     \
1187                                                                         \
1188   static PyObject *meth_##ed##_sign(PyObject *me, PyObject *arg,        \
1189                                     PyObject *kw)                       \
1190   {                                                                     \
1191     struct bin k, p = { 0, 0}, c = { 0, 0 }, m;                         \
1192     int ph = phdflt;                                                    \
1193     PyObject *rc = 0;                                                   \
1194     octet pp[ED##_PUBSZ];                                               \
1195     static const char *const kwlist[] =                                 \
1196       { "key", "msg", "pub", "perso", "phflag", 0 };                    \
1197     if (!PyArg_ParseTupleAndKeywords(arg, kw,                           \
1198                                      "O&O&|O&O&O&:" #ed "_sign",        \
1199                                      KWLIST,                            \
1200                                      convbin, &k, convbin, &m,          \
1201                                      convbin, &p, convbin, &c,          \
1202                                      convbool, &ph))                    \
1203       goto end;                                                         \
1204     if (p.p && p.sz != ED##_PUBSZ) VALERR("bad public length");         \
1205     if (c.p && c.sz > ED##_MAXPERSOSZ)                                  \
1206       VALERR("personalization string too long");                        \
1207     if (c.p && ph == -1) ph = 0;                                        \
1208     if (!p.p) { p.p = pp; ed##_pubkey(pp, k.p, k.sz); }                 \
1209     rc = bytestring_pywrap(0, ED##_SIGSZ);                              \
1210     ed##sigver##_sign((octet *)PyString_AS_STRING(rc), k.p, k.sz,       \
1211                       p.p, ph, c.p, c.sz, m.p, m.sz);                   \
1212     return (rc);                                                        \
1213   end:                                                                  \
1214     return (0);                                                         \
1215   }                                                                     \
1216                                                                         \
1217   static PyObject *meth_##ed##_verify(PyObject *me,                     \
1218                                       PyObject *arg, PyObject *kw)      \
1219   {                                                                     \
1220     struct bin p, c = { 0, 0 }, m, s;                                   \
1221     int ph = phdflt;                                                    \
1222     PyObject *rc = 0;                                                   \
1223     static const char *const kwlist[] =                                 \
1224       { "pub", "msg", "sig", "perso", "phflag", 0 };                    \
1225     if (!PyArg_ParseTupleAndKeywords(arg, kw,                           \
1226                                      "O&O&O&|O&O&:" #ed "_verify",      \
1227                                      KWLIST,                            \
1228                                      convbin, &p, convbin, &m,          \
1229                                      convbin, &s,                       \
1230                                      convbin, &c, convbool, &ph))       \
1231       goto end;                                                         \
1232     if (p.sz != ED##_PUBSZ) VALERR("bad public length");                \
1233     if (s.sz != ED##_SIGSZ) VALERR("bad signature length");             \
1234     if (c.p && c.sz > ED##_MAXPERSOSZ)                                  \
1235       VALERR("personalization string too long");                        \
1236     if (c.p && ph == -1) ph = 0;                                        \
1237     rc = getbool(!ed##sigver##_verify(p.p, ph, c.p, c.sz,               \
1238                                       m.p, m.sz, s.p));                 \
1239     return (rc);                                                        \
1240   end:                                                                  \
1241     return (0);                                                         \
1242   }
1243 EDDSAS(DEFEDDSA)
1244 #undef DEFEDDSA
1245
1246 /*----- Global stuff ------------------------------------------------------*/
1247
1248 static const struct nameval consts[] = {
1249   CONST(X25519_KEYSZ), CONST(X25519_PUBSZ), CONST(X25519_OUTSZ),
1250   CONST(X448_KEYSZ), CONST(X448_PUBSZ), CONST(X448_OUTSZ),
1251   CONST(ED25519_KEYSZ), CONST(ED25519_PUBSZ), CONST(ED25519_SIGSZ),
1252     CONST(ED25519_MAXPERSOSZ),
1253   CONST(ED448_KEYSZ), CONST(ED448_PUBSZ), CONST(ED448_SIGSZ),
1254     CONST(ED448_MAXPERSOSZ),
1255   { 0 }
1256 };
1257
1258 static const PyMethodDef methods[] = {
1259 #define METHNAME(name) meth_##name
1260   KWMETH(_p1crypt_encode, 0)
1261   KWMETH(_p1crypt_decode, 0)
1262   KWMETH(_p1sig_encode, 0)
1263   KWMETH(_p1sig_decode, 0)
1264   KWMETH(_oaep_encode,  0)
1265   KWMETH(_oaep_decode,  0)
1266   KWMETH(_pss_encode,   0)
1267   KWMETH(_pss_decode,   0)
1268 #define DEFMETH(X, x)                                                   \
1269   METH  (x,             "" #x "(KEY, PUBLIC) -> SHARED")
1270   XDHS(DEFMETH)
1271 #undef DEFMETH
1272 #define DEFMETH(ED, ed, phdflt, sigver)                                 \
1273   METH  (ed##_pubkey,   "" #ed "_pubkey(KEY) -> PUBLIC")                \
1274   KWMETH(ed##_sign,     "" #ed "_sign(KEY, MSG, [pub = PUBLIC], "       \
1275                            "[perso = STRING], [phflag = BOOL]) -> SIG") \
1276   KWMETH(ed##_verify,   "" #ed "_verify(PUBLIC, MSG, SIG, "             \
1277                           "[perso = STRING], [phflag = BOOL]) -> BOOL")
1278   EDDSAS(DEFMETH)
1279 #undef DEFMETH
1280 #undef METHNAME
1281   { 0 }
1282 };
1283
1284 void pubkey_pyinit(void)
1285 {
1286   INITTYPE(dsapub, root);
1287   INITTYPE(dsapriv, dsapub);
1288   INITTYPE(kcdsapub, root);
1289   INITTYPE(kcdsapriv, kcdsapub);
1290   INITTYPE(rsapub, root);
1291   INITTYPE(rsapriv, rsapub);
1292   addmethods(methods);
1293 }
1294
1295 void pubkey_pyinsert(PyObject *mod)
1296 {
1297   INSERT("DSAPub", dsapub_pytype);
1298   INSERT("DSAPriv", dsapriv_pytype);
1299   INSERT("KCDSAPub", kcdsapub_pytype);
1300   INSERT("KCDSAPriv", kcdsapriv_pytype);
1301   INSERT("RSAPub", rsapub_pytype);
1302   INSERT("RSAPriv", rsapriv_pytype);
1303   setconstants(mod, consts);
1304 }
1305
1306 /*----- That's all, folks -------------------------------------------------*/