*.c: Introduce a new input conversion for binary strings.
authorMark Wooding <mdw@distorted.org.uk>
Mon, 21 Oct 2019 00:43:54 +0000 (01:43 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 11 Apr 2020 11:44:21 +0000 (12:44 +0100)
One of the major differences in Python 3 is that it firmly distinguishes
between binary and text strings: the former consist of small integers,
while the latter consist of Unicode scalars.  The Python 3 `s#'
conversion's main purpose is to accept text strings, and though it will
also accept binary strings it's not really ideal for the purpose.
Python 3 introduces a new conversion `y#' specifically for binary
strings, though this isn't quite what we want because, for some reason,
it /doesn't/ work with bufferish objects which require explicit release.

The best answer seems to be to introduce our own custom conversion for
binary strings, so we do this here, replacing all of the binary-input
argument conversions.  While we're at it, replace all of the by-steam
argument conversions using `PyObject_AsReadBuffer' too.

13 files changed:
algorithms.c
buffer.c
bytestring.c
ec.c
group.c
key.c
mp.c
pubkey.c
pyke/pyke.c
pyke/pyke.h
rand.c
share.c
t/t-buffer.py

index 9dbebe6..babee57 100644 (file)
@@ -526,14 +526,13 @@ static PyObject *gcipher_pywrap(PyObject *cobj, gcipher *c)
 static PyObject *gcipher_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
   static const char *const kwlist[] = { "k", 0 };
-  char *k;
-  Py_ssize_t sz;
+  struct bin k;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &k))
     goto end;
-  if (keysz(sz, GCCIPHER_CC(ty)->keysz) != sz) VALERR("bad key length");
+  if (keysz(k.sz, GCCIPHER_CC(ty)->keysz) != k.sz) VALERR("bad key length");
   return (gcipher_pywrap((PyObject *)ty,
-                        GC_INIT(GCCIPHER_CC(ty), ksz)));
+                        GC_INIT(GCCIPHER_CC(ty), k.p, k.sz)));
 end:
   return (0);
 }
@@ -573,13 +572,12 @@ static PyObject *gccget_blksz(PyObject *me, void *hunoz)
 
 static PyObject *gcmeth_encrypt(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t sz;
+  struct bin m;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#:encrypt", &p, &sz)) return (0);
-  rc = bytestring_pywrap(0, sz);
-  GC_ENCRYPT(GCIPHER_C(me), p, PyString_AS_STRING(rc), sz);
+  if (!PyArg_ParseTuple(arg, "O&:encrypt", convbin, &m)) return (0);
+  rc = bytestring_pywrap(0, m.sz);
+  GC_ENCRYPT(GCIPHER_C(me), m.p, PyString_AS_STRING(rc), m.sz);
   return (rc);
 }
 
@@ -599,13 +597,12 @@ static PyObject *gcmeth_enczero(PyObject *me, PyObject *arg)
 
 static PyObject *gcmeth_decrypt(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t sz;
+  struct bin c;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#:decrypt", &p, &sz)) return (0);
-  rc = bytestring_pywrap(0, sz);
-  GC_DECRYPT(GCIPHER_C(me), p, PyString_AS_STRING(rc), sz);
+  if (!PyArg_ParseTuple(arg, "O&:decrypt", convbin, &c)) return (0);
+  rc = bytestring_pywrap(0, c.sz);
+  GC_DECRYPT(GCIPHER_C(me), c.p, PyString_AS_STRING(rc), c.sz);
   return (rc);
 }
 
@@ -625,14 +622,13 @@ static PyObject *gcmeth_deczero(PyObject *me, PyObject *arg)
 
 static PyObject *gcmeth_setiv(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t sz;
+  struct bin iv;
 
-  if (!PyArg_ParseTuple(arg, "s#:setiv", &p, &sz)) goto end;
+  if (!PyArg_ParseTuple(arg, "O&:setiv", convbin, &iv)) goto end;
   if (!GCIPHER_C(me)->ops->setiv) VALERR("`setiv' not supported");
   if (!GC_CLASS(GCIPHER_C(me))->blksz) VALERR("not a block cipher mode");
-  if (sz != GC_CLASS(GCIPHER_C(me))->blksz) VALERR("bad IV length");
-  GC_SETIV(GCIPHER_C(me), p);
+  if (iv.sz != GC_CLASS(GCIPHER_C(me))->blksz) VALERR("bad IV length");
+  GC_SETIV(GCIPHER_C(me), iv.p);
   RETURN_ME;
 end:
   return (0);
@@ -886,14 +882,13 @@ static PyObject *gaeadkey_pynew(PyTypeObject *ty,
                                PyObject *arg, PyObject *kw)
 {
   static const char *const kwlist[] = { "k", 0 };
-  char *k;
-  Py_ssize_t sz;
+  struct bin k;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &k))
     goto end;
-  if (keysz(sz, GCAEAD_AEC(ty)->keysz) != sz) VALERR("bad key length");
+  if (keysz(k.sz, GCAEAD_AEC(ty)->keysz) != k.sz) VALERR("bad key length");
   return (gaeadkey_pywrap((PyObject *)ty,
-                         GAEAD_KEY(GCAEAD_AEC(ty), ksz)));
+                         GAEAD_KEY(GCAEAD_AEC(ty), k.p, k.sz)));
 end:
   return (0);
 }
@@ -1018,18 +1013,18 @@ static PyObject *gaekmeth_enc(PyObject *me, PyObject *arg, PyObject *kw)
   const gaead_key *k = GAEADKEY_K(me);
   gaead_enc *e;
   PyObject *rc = 0;
-  char *n; Py_ssize_t nsz;
+  struct bin n;
   PyObject *hszobj = Py_None, *mszobj = Py_None, *tszobj = Py_None;
   size_t hsz = 0, msz = 0, tsz = 0;
   unsigned f;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|OOO:enc", KWLIST,
-                                  &n, &nsz, &hszobj, &mszobj, &tszobj))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|OOO:enc", KWLIST,
+                                  convbin, &n, &hszobj, &mszobj, &tszobj))
     goto end;
-  if (check_aead_encdec(k->ops->c, &f, nsz,
+  if (check_aead_encdec(k->ops->c, &f, n.sz,
                        hszobj, &hsz, mszobj, &msz, tszobj, &tsz))
     goto end;
-  e = GAEAD_ENC(GAEADKEY_K(me), n, nsz, hsz, msz, tsz);
+  e = GAEAD_ENC(GAEADKEY_K(me), n.p, n.sz, hsz, msz, tsz);
   if (!e) VALERR("bad aead parameter combination");
   rc = gaeadenc_pywrap((PyObject *)GCAEAD_ENC(Py_TYPE(me)),
                       e, f, hsz, msz, tsz);
@@ -1043,18 +1038,18 @@ static PyObject *gaekmeth_dec(PyObject *me, PyObject *arg, PyObject *kw)
   const gaead_key *k = GAEADKEY_K(me);
   gaead_dec *d;
   PyObject *rc = 0;
-  char *n; Py_ssize_t nsz;
+  struct bin n;
   PyObject *hszobj = Py_None, *cszobj = Py_None, *tszobj = Py_None;
   size_t hsz = 0, csz = 0, tsz = 0;
   unsigned f;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|OOO:dec", KWLIST,
-                                  &n, &nsz, &hszobj, &cszobj, &tszobj))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|OOO:dec", KWLIST,
+                                  convbin, &n, &hszobj, &cszobj, &tszobj))
     goto end;
-  if (check_aead_encdec(k->ops->c, &f, nsz,
+  if (check_aead_encdec(k->ops->c, &f, n.sz,
                        hszobj, &hsz, cszobj, &csz, tszobj, &tsz))
     goto end;
-  d = GAEAD_DEC(GAEADKEY_K(me), n, nsz, hsz, csz, tsz);
+  d = GAEAD_DEC(GAEADKEY_K(me), n.p, n.sz, hsz, csz, tsz);
   if (!d) VALERR("bad aead parameter combination");
   rc = gaeaddec_pywrap((PyObject *)GCAEAD_DEC(Py_TYPE(me)),
                       d, f, hsz, csz, tsz);
@@ -1161,10 +1156,10 @@ end:
 
 static PyObject *gaeameth_hash(PyObject *me, PyObject *arg)
 {
-  char *h; Py_ssize_t hsz;
+  struct bin h;
 
-  if (!PyArg_ParseTuple(arg, "s#:hash", &h, &hsz)) return (0);
-  if (gaeadaad_hash(me, h, hsz)) return (0);
+  if (!PyArg_ParseTuple(arg, "O&:hash", convbin, &h)) return (0);
+  if (gaeadaad_hash(me, h.p, h.sz)) return (0);
   RETURN_ME;
 }
 
@@ -1181,11 +1176,11 @@ DOUINTCONV(GAEAMETH_HASHU_)
 #define GAEAMETH_HASHBUF_(n, W, w)                                     \
   static PyObject *gaeameth_hashbuf##w(PyObject *me, PyObject *arg)    \
   {                                                                    \
-    char *p; Py_ssize_t sz; octet b[SZ_##W];                           \
-    if (!PyArg_ParseTuple(arg, "s#:hashbuf" #w, &p, &sz)) goto end;    \
-    if (sz > MASK##n) TYERR("string too long");                                \
-    STORE##W(b, sz); if (gaeadaad_hash(me, b, sizeof(b))) goto end;    \
-    if (gaeadaad_hash(me, p, sz)) goto end;                            \
+    struct bin in; octet b[SZ_##W];                                    \
+    if (!PyArg_ParseTuple(arg, "O&:hashbuf" #w, convbin, &in)) goto end; \
+    if (in.sz > MASK##n) TYERR("string too long");                     \
+    STORE##W(b, in.sz); if (gaeadaad_hash(me, b, sizeof(b))) goto end; \
+    if (gaeadaad_hash(me, in.p, in.sz)) goto end;                      \
     RETURN_ME;                                                         \
   end:                                                                 \
     return (0);                                                                \
@@ -1293,18 +1288,18 @@ static PyObject *gaeemeth_reinit(PyObject *me, PyObject *arg, PyObject *kw)
 {
   static const char *const kwlist[] = { "nonce", "hsz", "msz", "tsz", 0 };
   gaeadenc_pyobj *ge = (gaeadenc_pyobj *)me;
-  char *n; Py_ssize_t nsz;
+  struct bin n;
   PyObject *hszobj = Py_None, *mszobj = Py_None, *tszobj = Py_None;
   size_t hsz = 0, msz = 0, tsz = 0;
   unsigned f;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|OOO:enc", KWLIST,
-                                  &n, &nsz, &hszobj, &mszobj, &tszobj))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|OOO:enc", KWLIST,
+                                  convbin, &n, &hszobj, &mszobj, &tszobj))
     goto end;
-  if (check_aead_encdec(ge->e->ops->c, &f, nsz,
+  if (check_aead_encdec(ge->e->ops->c, &f, n.sz,
                        hszobj, &hsz, mszobj, &msz, tszobj, &tsz))
     goto end;
-  if (GAEAD_REINIT(ge->e, n, nsz, hsz, msz, tsz))
+  if (GAEAD_REINIT(ge->e, n.p, n.sz, hsz, msz, tsz))
     VALERR("bad aead parameter combination");
   gaea_sever(&ge->aad);
   ge->f = f; ge->hsz = hsz; ge->msz = msz; ge->tsz = tsz;
@@ -1315,22 +1310,22 @@ end:
 static PyObject *gaeemeth_encrypt(PyObject *me, PyObject *arg)
 {
   gaeadenc_pyobj *ge = (gaeadenc_pyobj *)me;
-  char *m; Py_ssize_t msz;
+  struct bin m;
   char *c = 0; size_t csz; buf b;
   int err;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#:encrypt", &m, &msz)) goto end;
+  if (!PyArg_ParseTuple(arg, "O&:encrypt", convbin, &m)) goto end;
   if (ge->f&AEADF_AADFIRST) {
     if ((ge->f&AEADF_PCHSZ) && (ge->aad ? ge->aad->hlen : 0) != ge->hsz)
       VALERR("header doesn't match precommitted length");
     gaea_invalidate(ge->aad);
   }
-  if ((ge->f&AEADF_PCMSZ) && msz > ge->msz - ge->mlen)
+  if ((ge->f&AEADF_PCMSZ) && m.sz > ge->msz - ge->mlen)
     VALERR("too large for precommitted message length");
-  csz = msz + ge->e->ops->c->bufsz; c = xmalloc(csz); buf_init(&b, c, csz);
-  err = GAEAD_ENCRYPT(ge->e, m, msz, &b); assert(!err); (void)err;
-  buf_flip(&b); rc = bytestring_pywrapbuf(&b); ge->mlen += msz;
+  csz = m.sz + ge->e->ops->c->bufsz; c = xmalloc(csz); buf_init(&b, c, csz);
+  err = GAEAD_ENCRYPT(ge->e, m.p, m.sz, &b); assert(!err); (void)err;
+  buf_flip(&b); rc = bytestring_pywrapbuf(&b); ge->mlen += m.sz;
 end:
   xfree(c);
   return (rc);
@@ -1462,18 +1457,18 @@ static PyObject *gaedmeth_reinit(PyObject *me, PyObject *arg, PyObject *kw)
 {
   static const char *const kwlist[] = { "nonce", "hsz", "csz", "tsz", 0 };
   gaeaddec_pyobj *gd = (gaeaddec_pyobj *)me;
-  char *n; Py_ssize_t nsz;
+  struct bin n;
   PyObject *hszobj = Py_None, *cszobj = Py_None, *tszobj = Py_None;
   size_t hsz = 0, csz = 0, tsz = 0;
   unsigned f;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|OOO:enc", KWLIST,
-                                  &n, &nsz, &hszobj, &cszobj, &tszobj))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|OOO:enc", KWLIST,
+                                  convbin, &n, &hszobj, &cszobj, &tszobj))
     goto end;
-  if (check_aead_encdec(gd->d->ops->c, &f, nsz,
+  if (check_aead_encdec(gd->d->ops->c, &f, n.sz,
                        hszobj, &hsz, cszobj, &csz, tszobj, &tsz))
     goto end;
-  if (GAEAD_REINIT(gd->d, n, nsz, hsz, csz, tsz))
+  if (GAEAD_REINIT(gd->d, n.p, n.sz, hsz, csz, tsz))
     VALERR("bad aead parameter combination");
   gaea_sever(&gd->aad);
   gd->f = f; gd->hsz = hsz; gd->csz = csz; gd->tsz = tsz;
@@ -1484,22 +1479,22 @@ end:
 static PyObject *gaedmeth_decrypt(PyObject *me, PyObject *arg)
 {
   gaeaddec_pyobj *gd = (gaeaddec_pyobj *)me;
-  char *c; Py_ssize_t csz;
+  struct bin c;
   char *m = 0; size_t msz; buf b;
   int err;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#:decrypt", &c, &csz)) goto end;
+  if (!PyArg_ParseTuple(arg, "O&:decrypt", convbin, &c)) goto end;
   if (gd->f&AEADF_AADFIRST) {
     if ((gd->f&AEADF_PCHSZ) && (gd->aad ? gd->aad->hlen : 0) != gd->hsz)
       VALERR("header doesn't match precommitted length");
     gaea_invalidate(gd->aad);
   }
-  if ((gd->f&AEADF_PCMSZ) && csz > gd->csz - gd->clen)
+  if ((gd->f&AEADF_PCMSZ) && c.sz > gd->csz - gd->clen)
     VALERR("too large for precommitted message length");
-  msz = csz + gd->d->ops->c->bufsz; m = xmalloc(msz); buf_init(&b, m, msz);
-  err = GAEAD_DECRYPT(gd->d, c, csz, &b); assert(!err); (void)err;
-  buf_flip(&b); rc = bytestring_pywrapbuf(&b); gd->clen += csz;
+  msz = c.sz + gd->d->ops->c->bufsz; m = xmalloc(msz); buf_init(&b, m, msz);
+  err = GAEAD_DECRYPT(gd->d, c.p, c.sz, &b); assert(!err); (void)err;
+  buf_flip(&b); rc = bytestring_pywrapbuf(&b); gd->clen += c.sz;
 end:
   xfree(m);
   return (rc);
@@ -1510,13 +1505,13 @@ static PyObject *gaedmeth_done(PyObject *me, PyObject *arg, PyObject *kw)
   static const char *const kwlist[] = { "tag", "aad", 0 };
   gaeaddec_pyobj *gd = (gaeaddec_pyobj *)me;
   PyObject *aad = Py_None;
-  char *t; Py_ssize_t tsz;
+  struct bin t;
   char *m = 0; size_t msz; buf b;
   int err;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O:done", KWLIST,
-                                  &t, &tsz, &aad))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O:done", KWLIST,
+                                  convbin, &t, &aad))
     goto end;
   if (aad != Py_None &&
       !PyObject_TypeCheck(aad,
@@ -1529,11 +1524,12 @@ static PyObject *gaedmeth_done(PyObject *me, PyObject *arg, PyObject *kw)
     VALERR("header doesn't match precommitted length");
   if ((gd->f&AEADF_PCMSZ) && gd->clen != gd->csz)
     VALERR("message doesn't match precommitted length");
-  if ((gd->f&AEADF_PCTSZ) && tsz != gd->tsz)
+  if ((gd->f&AEADF_PCTSZ) && t.sz != gd->tsz)
     VALERR("tag length doesn't match precommitted value");
-  if (keysz(tsz, gd->d->ops->c->tagsz) != tsz) VALERR("bad tag length");
+  if (keysz(t.sz, gd->d->ops->c->tagsz) != t.sz) VALERR("bad tag length");
   msz = gd->d->ops->c->bufsz; m = xmalloc(msz); buf_init(&b, m, msz);
-  err = GAEAD_DONE(gd->d, aad == Py_None ? 0 : GAEADAAD_A(aad), &b, t, tsz);
+  err = GAEAD_DONE(gd->d, aad == Py_None ? 0 : GAEADAAD_A(aad),
+                  &b, t.p, t.sz);
   assert(err >= 0);
   if (!err) VALERR("decryption failed");
   buf_flip(&b); rc = bytestring_pywrapbuf(&b);
@@ -2011,10 +2007,9 @@ static PyObject *ghmeth_copy(PyObject *me)
 
 static PyObject *ghmeth_hash(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t sz;
-  if (!PyArg_ParseTuple(arg, "s#:hash", &p, &sz)) return (0);
-  GH_HASH(GHASH_H(me), p, sz);
+  struct bin m;
+  if (!PyArg_ParseTuple(arg, "O&:hash", convbin, &m)) return (0);
+  GH_HASH(GHASH_H(me), m.p, m.sz);
   RETURN_ME;
 }
 
@@ -2031,11 +2026,10 @@ DOUINTCONV(GHMETH_HASHU_)
 #define GHMETH_HASHBUF_(n, W, w)                                       \
   static PyObject *ghmeth_hashbuf##w(PyObject *me, PyObject *arg)      \
   {                                                                    \
-    char *p;                                                           \
-    Py_ssize_t sz;                                                     \
-    if (!PyArg_ParseTuple(arg, "s#:hashbuf" #w, &p, &sz)) goto end;    \
-    if (sz > MASK##n) TYERR("string too long");                                \
-    GH_HASHBUF##W(GHASH_H(me), p, sz);                                 \
+    struct bin in;                                                     \
+    if (!PyArg_ParseTuple(arg, "O&:hashbuf" #w, convbin, &in)) goto end; \
+    if (in.sz > MASK##n) TYERR("string too long");                     \
+    GH_HASHBUF##W(GHASH_H(me), in.p, in.sz);                           \
     RETURN_ME;                                                         \
   end:                                                                 \
     return (0);                                                                \
@@ -2212,14 +2206,13 @@ extern int convgmac(PyObject *, void *);
 static PyObject *gmac_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
   static const char *const kwlist[] = { "k", 0 };
-  char *k;
-  Py_ssize_t sz;
+  struct bin k;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &k))
     goto end;
-  if (keysz(sz, GCMAC_CM(ty)->keysz) != sz) VALERR("bad key length");
+  if (keysz(k.sz, GCMAC_CM(ty)->keysz) != k.sz) VALERR("bad key length");
   return (gmac_pywrap((PyObject *)ty,
-                     GM_KEY(GCMAC_CM(ty), ksz)));
+                     GM_KEY(GCMAC_CM(ty), k.p, k.sz)));
 end:
   return (0);
 }
@@ -2470,16 +2463,15 @@ static PyObject *poly1305hash_pynew(PyTypeObject *ty,
   static const char *const kwlist[] = { "mask", 0 };
   poly1305key_pyobj *pk = (poly1305key_pyobj *)ty;
   poly1305hash_pyobj *ph;
-  char *m = 0;
-  Py_ssize_t sz;
+  struct bin m = { 0, 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "|s#:new", KWLIST, &m, &sz))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&:new", KWLIST, convbin, &m))
     return (0);
-  if (m && sz != POLY1305_MASKSZ) VALERR("bad mask length");
+  if (m.p && m.sz != POLY1305_MASKSZ) VALERR("bad mask length");
   ph = PyObject_NEW(poly1305hash_pyobj, ty);
   ph->f = 0;
-  if (m) ph->f |= f_mask;
-  poly1305_macinit(&ph->ctx, &pk->k, m);
+  if (m.p) ph->f |= f_mask;
+  poly1305_macinit(&ph->ctx, &pk->k, m.p);
   Py_INCREF(ty);
   return ((PyObject *)ph);
 end:
@@ -2491,12 +2483,11 @@ static PyObject *poly1305key_pynew(PyTypeObject *ty,
 {
   static const char *const kwlist[] = { "k", 0 };
   poly1305key_pyobj *pk;
-  char *k;
-  Py_ssize_t sz;
+  struct bin k;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &k))
     goto end;
-  if (keysz(sz, poly1305_keysz) != sz) VALERR("bad key length");
+  if (keysz(k.sz, poly1305_keysz) != k.sz) VALERR("bad key length");
 
   pk = newtype(ty, 0, 0);
   pk->ty.ht_name = PyString_FromString("poly1305(keyed)");
@@ -2512,7 +2503,7 @@ static PyObject *poly1305key_pynew(PyTypeObject *ty,
   pk->ty.ht_type.tp_new = poly1305hash_pynew;
   typeready(&pk->ty.ht_type);
 
-  poly1305_keyinit(&pk->k, ksz);
+  poly1305_keyinit(&pk->k, k.p, k.sz);
   return ((PyObject *)pk);
 
 end:
@@ -2542,10 +2533,9 @@ static PyObject *polymeth_copy(PyObject *me)
 
 static PyObject *polymeth_hash(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t sz;
-  if (!PyArg_ParseTuple(arg, "s#:hash", &p, &sz)) return (0);
-  poly1305_hash(P1305_CTX(me), p, sz);
+  struct bin m;
+  if (!PyArg_ParseTuple(arg, "O&:hash", convbin, &m)) return (0);
+  poly1305_hash(P1305_CTX(me), m.p, m.sz);
   RETURN_ME;
 }
 
@@ -2563,13 +2553,12 @@ DOUINTCONV(POLYMETH_HASHU_)
 #define POLYMETH_HASHBUF_(n, W, w)                                     \
   static PyObject *polymeth_hashbuf##w(PyObject *me, PyObject *arg)    \
   {                                                                    \
-    char *p;                                                           \
-    Py_ssize_t sz;                                                     \
+    struct bin in;                                                     \
     octet b[SZ_##W];                                                   \
-    if (!PyArg_ParseTuple(arg, "s#:hashbuf" #w, &p, &sz)) goto end;    \
-    if (sz > MASK##n) TYERR("string too long");                                \
-    STORE##W(b, sz); poly1305_hash(P1305_CTX(me), b, sizeof(b));       \
-    poly1305_hash(P1305_CTX(me), p, sz);                               \
+    if (!PyArg_ParseTuple(arg, "O&:hashbuf" #w, convbin, &in)) goto end; \
+    if (in.sz > MASK##n) TYERR("string too long");                     \
+    STORE##W(b, in.sz); poly1305_hash(P1305_CTX(me), b, sizeof(b));    \
+    poly1305_hash(P1305_CTX(me), in.p, in.sz);                         \
     RETURN_ME;                                                         \
   end:                                                                 \
     return (0);                                                                \
@@ -2796,17 +2785,16 @@ static const PyTypeObject poly1305hash_pytype_skel = {
   static PyObject *meth_##hdance##_prf(PyObject *me, PyObject *arg)    \
   {                                                                    \
     dance##_ctx dance;                                                 \
-    char *k, *n;                                                       \
-    Py_ssize_t ksz, nsz;                                               \
+    struct bin k, n;                                                   \
     PyObject *rc;                                                      \
-    if (!PyArg_ParseTuple(arg, "s#s#:" #hdance "_prf",                 \
-                         &k, &ksz, &n, &nsz))                          \
+    if (!PyArg_ParseTuple(arg, "O&O&:" #hdance "_prf",                 \
+                         convbin, &k, convbin, &n))                    \
       goto end;                                                                \
-    if (ksz != keysz(ksz, dance##_keysz)) VALERR("bad key length");    \
-    if (nsz != HDANCE##_INSZ) VALERR("bad input length");              \
+    if (k.sz != keysz(k.sz, dance##_keysz)) VALERR("bad key length");  \
+    if (n.sz != HDANCE##_INSZ) VALERR("bad input length");             \
     rc = bytestring_pywrap(0, HSALSA20_OUTSZ);                         \
-    dance##_init(&dance, k, ksz, 0);                                   \
-    hdance##_prf(&dance, n, PyString_AS_STRING(rc));                   \
+    dance##_init(&dance, k.p, k.sz, 0);                                        \
+    hdance##_prf(&dance, n.p, PyString_AS_STRING(rc));                         \
     return (rc);                                                       \
   end:                                                                 \
     return (0);                                                                \
@@ -2860,11 +2848,12 @@ static PyObject *kxvikmeth_mix(PyObject *me, PyObject *arg)
   const octet *q;
   octet buf[8];
   unsigned i;
-  char *p; Py_ssize_t n;
+  struct bin in;
+  size_t n;
 
-  if (!PyArg_ParseTuple(arg, "s#:mix", &p, &n)) goto end;
-  if (n > 200) VALERR("out of range");
-  q = (const octet *)p;
+  if (!PyArg_ParseTuple(arg, "O&:mix", convbin, &in)) goto end;
+  if (in.sz > 200) VALERR("out of range");
+  q = in.p; n = in.sz;
   i = 0;
   while (n > 8) { LOAD64_L_(t[i], q); i++; q += 8; n -= 8; }
   if (n) {
@@ -2988,15 +2977,14 @@ static PyObject *shake_dopynew(void (*initfn)(shake_ctx *,
                               PyObject *arg, PyObject *kw)
 {
   shake_pyobj *rc = 0;
-  char *p = 0, *f = 0;
-  Py_ssize_t psz = 0, fsz = 0;
+  struct bin p = { 0, 0 }, f = { 0, 0 };
   static const char *const kwlist[] = { "perso", "func", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "|s#s#:new", KWLIST,
-                                  &p, &psz, &f, &fsz))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "|O&O&:new", KWLIST,
+                                  convbin, &p, convbin, &f))
     goto end;
   rc = (shake_pyobj *)ty->tp_alloc(ty, 0);
-  initfn(&rc->h, f, fsz, p, psz);
+  initfn(&rc->h, f.p, f.sz, p.p, p.sz);
   rc->st = 0;
 end:
   return ((PyObject *)rc);
@@ -3020,11 +3008,10 @@ end:
 
 static PyObject *shakemeth_hash(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t sz;
-  if (!PyArg_ParseTuple(arg, "s#:hash", &p, &sz)) return (0);
+  struct bin m;
+  if (!PyArg_ParseTuple(arg, "O&:hash", convbin, &m)) return (0);
   if (shake_check(me, 0)) return (0);
-  shake_hash(SHAKE_H(me), p, sz);
+  shake_hash(SHAKE_H(me), m.p, m.sz);
   RETURN_ME;
 }
 
@@ -3043,14 +3030,13 @@ DOUINTCONV(SHAKEMETH_HASHU_)
 #define SHAKEMETH_HASHBUF_(n, W, w)                                    \
   static PyObject *shakemeth_hashbuf##w(PyObject *me, PyObject *arg)   \
   {                                                                    \
-    char *p;                                                           \
-    Py_ssize_t sz;                                                     \
+    struct bin in;                                                     \
     octet b[SZ_##W];                                                   \
-    if (!PyArg_ParseTuple(arg, "s#:hashbuf" #w, &p, &sz)) goto end;    \
-    if (sz > MASK##n) TYERR("string too long");                                \
+    if (!PyArg_ParseTuple(arg, "O&:hashbuf" #w, convbin, &in)) goto end; \
+    if (in.sz > MASK##n) TYERR("string too long");                     \
     if (shake_check(me, 0)) goto end;                                  \
-    STORE##W(b, sz); shake_hash(SHAKE_H(me), b, sizeof(b));            \
-    shake_hash(SHAKE_H(me), p, sz);                                    \
+    STORE##W(b, in.sz); shake_hash(SHAKE_H(me), b, sizeof(b));         \
+    shake_hash(SHAKE_H(me), in.p, in.sz);                              \
     RETURN_ME;                                                         \
   end:                                                                 \
     return (0);                                                                \
@@ -3115,12 +3101,12 @@ end:
 static PyObject *shakemeth_mask(PyObject *me, PyObject *arg)
 {
   PyObject *rc = 0;
-  char *p; Py_ssize_t sz;
+  struct bin in;
 
-  if (!PyArg_ParseTuple(arg, "s#:mask", &p, &sz)) goto end;
+  if (!PyArg_ParseTuple(arg, "O&:mask", convbin, &in)) goto end;
   if (shake_check(me, 1)) goto end;
-  rc = bytestring_pywrap(0, sz);
-  shake_mask(SHAKE_H(me), p, PyString_AS_STRING(rc), sz);
+  rc = bytestring_pywrap(0, in.sz);
+  shake_mask(SHAKE_H(me), in.p, PyString_AS_STRING(rc), in.sz);
 end:
   return (rc);
 }
@@ -3371,17 +3357,16 @@ typedef struct prp {
 static PyObject *gprp_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
   static const char *const kwlist[] = { "key", 0 };
-  char *k;
-  Py_ssize_t sz;
+  struct bin k;
   const prpinfo *prp = GCPRP_PRP(ty);
   PyObject *me;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &sz))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &k))
     goto end;
-  if (keysz(sz, prp->keysz) != sz) VALERR("bad key length");
+  if (keysz(k.sz, prp->keysz) != k.sz) VALERR("bad key length");
   me = (PyObject *)ty->tp_alloc(ty, 0);
   GPRP_PRP(me) = prp;
-  prp->init(GPRP_CTX(me), ksz);
+  prp->init(GPRP_CTX(me), k.p, k.sz);
   Py_INCREF(me);
   return (me);
 end:
@@ -3417,28 +3402,26 @@ static PyObject *gcpget_blksz(PyObject *me, void *hunoz)
 
 static PyObject *gpmeth_encrypt(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t n;
+  struct bin m;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#:encrypt", &p, &n)) goto end;
-  if (n != GPRP_PRP(me)->blksz) VALERR("incorrect block length");
-  rc = bytestring_pywrap(0, n);
-  GPRP_PRP(me)->eblk(GPRP_CTX(me), p, PyString_AS_STRING(rc));
+  if (!PyArg_ParseTuple(arg, "O&:encrypt", convbin, &m)) goto end;
+  if (m.sz != GPRP_PRP(me)->blksz) VALERR("incorrect block length");
+  rc = bytestring_pywrap(0, m.sz);
+  GPRP_PRP(me)->eblk(GPRP_CTX(me), m.p, PyString_AS_STRING(rc));
 end:
   return (rc);
 }
 
 static PyObject *gpmeth_decrypt(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t n;
+  struct bin c;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#:decrypt", &p, &n)) goto end;
-  if (n != GPRP_PRP(me)->blksz) VALERR("incorrect block length");
-  rc = bytestring_pywrap(0, n);
-  GPRP_PRP(me)->dblk(GPRP_CTX(me), p, PyString_AS_STRING(rc));
+  if (!PyArg_ParseTuple(arg, "O&:decrypt", convbin, &c)) goto end;
+  if (c.sz != GPRP_PRP(me)->blksz) VALERR("incorrect block length");
+  rc = bytestring_pywrap(0, c.sz);
+  GPRP_PRP(me)->dblk(GPRP_CTX(me), c.p, PyString_AS_STRING(rc));
 end:
   return (rc);
 }
index ea114c1..59eaec6 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -52,18 +52,18 @@ static PyObject *buferr;
 
 static PyObject *rbuf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
-  char *p, *q;
-  Py_ssize_t n;
+  struct bin in;
+  void *q;
   buf_pyobj *me = 0;
   static const char *const kwlist[] = { "data", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &p, &n))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &in))
     goto end;
-  q = xmalloc(n);
-  memcpy(q, p, n);
+  q = xmalloc(in.sz);
+  memcpy(q, in.p, in.sz);
   me = (buf_pyobj *)ty->tp_alloc(ty, 0);
   me->sub = 0;
-  buf_init(&me->b, q, n);
+  buf_init(&me->b, q, in.sz);
 end:
   return ((PyObject *)me);
 }
@@ -383,11 +383,10 @@ static PyObject *wbmeth_zero(PyObject *me, PyObject *arg)
 
 static PyObject *wbmeth_put(PyObject *me, PyObject *arg)
 {
-  void *p;
-  Py_ssize_t n;
-  if (!PyArg_ParseTuple(arg, "s#:put", &p, &n)) return (0);
-  ensure(me, n);
-  buf_put(BUF_B(me), p, n); assert(BOK(BUF_B(me)));
+  struct bin in;
+  if (!PyArg_ParseTuple(arg, "O&:put", convbin, &in)) return (0);
+  ensure(me, in.sz);
+  buf_put(BUF_B(me), in.p, in.sz); assert(BOK(BUF_B(me)));
   RETURN_ME;
 }
 
@@ -407,12 +406,11 @@ DOUINTCONV(WBMETH_PUTU_)
 #define WBMETH_PUTBLK_(n, W, w)                                                \
   static PyObject *wbmeth_putblk##w(PyObject *me, PyObject *arg)       \
   {                                                                    \
-    char *p;                                                           \
-    Py_ssize_t sz;                                                     \
-    if (!PyArg_ParseTuple(arg, "s#:putblk" #w, &p, &sz)) goto end;     \
-    if (MASK##W && sz > MASK##W) VALERR("too large");                  \
-    ensure(me, sz + SZ_##n);                                           \
-    buf_putmem##w(BUF_B(me), p, sz); assert(BOK(BUF_B(me)));           \
+    struct bin in;                                                     \
+    if (!PyArg_ParseTuple(arg, "O&:putblk" #w, convbin, &in)) goto end;        \
+    if (MASK##W && in.sz > MASK##W) VALERR("too large");               \
+    ensure(me, in.sz + SZ_##n);                                                \
+    buf_putmem##w(BUF_B(me), in.p, in.sz); assert(BOK(BUF_B(me)));     \
     RETURN_ME;                                                         \
   end:                                                                 \
     return (0);                                                                \
index 8e1d19a..fdc6e50 100644 (file)
@@ -76,21 +76,19 @@ PyObject *bytestring_pywrapbuf(buf *b)
 static PyObject *bytestring_pynew(PyTypeObject *ty,
                                  PyObject *arg, PyObject *kw)
 {
-  const char *p;
-  Py_ssize_t n;
+  struct bin in;
   static const char *const kwlist[] = { "data", 0 };
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &p, &n))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &in))
     return (0);
-  return (dowrap(ty, p, n));
+  return (dowrap(ty, in.p, in.sz));
 }
 
 static PyObject *meth_ctstreq(PyObject *me, PyObject *arg)
 {
-  char *p, *q;
-  Py_ssize_t psz, qsz;
-  if (!PyArg_ParseTuple(arg, "s#s#:ctstreq", &p, &psz, &q, &qsz))
+  struct bin s0, s1;
+  if (!PyArg_ParseTuple(arg, "O&O&:ctstreq", convbin, &s0 , convbin, &s1))
     goto end;
-  if (psz == qsz && ct_memeq(p, q, psz)) RETURN_TRUE;
+  if (s0.sz == s1.sz && ct_memeq(s0.p, s1.p, s0.sz)) RETURN_TRUE;
   else RETURN_FALSE;
 end:
   return (0);
@@ -110,25 +108,24 @@ end:
 static PyObject *bytestring_pyrichcompare(PyObject *me,
                                          PyObject *you, int op)
 {
+  struct bin s0, s1;
   int b;
-  void *mystr, *yourstr;
-  Py_ssize_t mylen, yourlen, minlen;
+  Py_ssize_t minlen;
 
-  if (!PyString_Check(me) || !PyString_Check(you)) RETURN_NOTIMPL;
-  mystr = PyString_AS_STRING(me); mylen = PyString_GET_SIZE(me);
-  yourstr = PyString_AS_STRING(you); yourlen = PyString_GET_SIZE(you);
+  s0.p = PyString_AS_STRING(me); s0.sz = PyString_GET_SIZE(me);
+  if (!convbin(you, &s1)) { PyErr_Clear(); RETURN_NOTIMPL; }
 
   switch (op) {
     case Py_EQ:
-      b = mylen == yourlen && ct_memeq(mystr, yourstr, mylen);
+      b = s0.sz == s1.sz && ct_memeq(s0.p, s1.p, s1.sz);
       break;
     case Py_NE:
-      b = mylen != yourlen || !ct_memeq(mystr, yourstr, mylen);
+      b = s0.sz != s1.sz || !ct_memeq(s0.p, s1.p, s1.sz);
       break;
     default:
-      minlen = mylen < yourlen ? mylen : yourlen;
-      b = memcmp(mystr, yourstr, minlen);
-      if (!b) b = mylen < yourlen ? -1 : mylen > yourlen ? +1 : 0;
+      minlen = s0.sz < s1.sz ? s0.sz : s1.sz;
+      b = memcmp(s0.p, s1.p, minlen);
+      if (!b) b = s0.sz < s1.sz ? -1 : s0.sz > s1.sz ? +1 : 0;
       switch (op) {
        case Py_LT: b = b <  0; break;
        case Py_LE: b = b <= 0; break;
@@ -143,17 +140,14 @@ static PyObject *bytestring_pyrichcompare(PyObject *me,
 
 static PyObject *bytestring_pyconcat(PyObject *x, PyObject *y)
 {
-  const void *xv; Py_ssize_t xsz;
-  const void *yv; Py_ssize_t ysz;
+  struct bin xx, yy;
   PyObject *z = 0; char *zp; size_t zsz;
 
-  if (PyObject_AsReadBuffer(x, &xv, &xsz) ||
-      PyObject_AsReadBuffer(y, &yv, &ysz))
-    goto end;
-  zsz = (size_t)xsz + (size_t)ysz;
-  if (xsz < 0 || ysz < 0 || zsz < xsz) VALERR("too long");
+  if (!convbin(x, &xx) || !convbin(y, &yy)) goto end;
+  zsz = (size_t)xx.sz + (size_t)yy.sz;
+  if (xx.sz < 0 || yy.sz < 0 || zsz < xx.sz) VALERR("too long");
   z = bytestring_pywrap(0, zsz); zp = PyString_AS_STRING(z);
-  memcpy(zp, xv, xsz); memcpy(zp + xsz, yv, ysz);
+  memcpy(zp, xx.p, xx.sz); memcpy(zp + xx.sz, yy.p, yy.sz);
 end:
   return (z);
 }
@@ -228,19 +222,16 @@ end:
 
 #define BINOP(name, op)                                                        \
   static PyObject *bytestring_py##name(PyObject *x, PyObject *y) {     \
-    const void *xv, *yv;                                               \
+    struct bin xx, yy;                                                 \
     const unsigned char *xp, *yp;                                      \
     unsigned char *zp;                                                 \
-    Py_ssize_t xsz, ysz;                                               \
     int i;                                                             \
     PyObject *rc = 0;                                                  \
-    if (PyObject_AsReadBuffer(x, &xv, &xsz) ||                         \
-       PyObject_AsReadBuffer(y, &yv, &ysz))                            \
-      goto end;                                                                \
-    if (xsz != ysz) VALERR("length mismatch");                         \
-    rc = bytestring_pywrap(0, xsz);                                    \
-    xp = xv; yp = yv; zp = (unsigned char *)PyString_AS_STRING(rc);    \
-    for (i = xsz; i > 0; i--) *zp++ = *xp++ op *yp++;                  \
+    if (!convbin(x, &xx) || !convbin(y, &yy)) goto end;                        \
+    if (xx.sz != yy.sz) VALERR("length mismatch");                     \
+    rc = bytestring_pywrap(0, xx.sz);                                  \
+    xp = xx.p; yp = yy.p; zp = (unsigned char *)PyString_AS_STRING(rc);        \
+    for (i = xx.sz; i > 0; i--) *zp++ = *xp++ op *yp++;                        \
   end:                                                                 \
     return (rc);                                                       \
   }
@@ -250,16 +241,15 @@ BINOP(xor, ^)
 
 #define UNOP(name, op)                                                 \
   static PyObject *bytestring_py##name(PyObject *x) {                  \
-    const void *xv;                                                    \
+    struct bin xx;                                                     \
     const unsigned char *xp;                                           \
     unsigned char *zp;                                                 \
-    Py_ssize_t xsz;                                                    \
     int i;                                                             \
     PyObject *rc = 0;                                                  \
-    if (PyObject_AsReadBuffer(x, &xv, &xsz)) goto end;                 \
-    rc = bytestring_pywrap(0, xsz);                                    \
-    xp = xv; zp = (unsigned char *)PyString_AS_STRING(rc);             \
-    for (i = xsz; i > 0; i--) *zp++ = op *xp++;                                \
+    if (!convbin(x, &xx)) goto end;                                    \
+    rc = bytestring_pywrap(0, xx.sz);                                  \
+    xp = xx.p; zp = (unsigned char *)PyString_AS_STRING(rc);           \
+    for (i = xx.sz; i > 0; i--) *zp++ = op *xp++;                      \
   end:                                                                 \
     return (rc);                                                       \
   }
diff --git a/ec.c b/ec.c
index 858aeaa..a67699e 100644 (file)
--- a/ec.c
+++ b/ec.c
@@ -310,14 +310,13 @@ end:
 
 static PyObject *epmeth_frombuf(PyObject *me, PyObject *arg)
 {
+  struct bin in;
   buf b;
-  char *p;
-  Py_ssize_t sz;
   PyObject *rc = 0;
   ec pp = EC_INIT;
 
-  if (!PyArg_ParseTuple(arg, "s#:frombuf", &p, &sz)) goto end;
-  buf_init(&b, p, sz);
+  if (!PyArg_ParseTuple(arg, "O&:frombuf", convbin, &in)) goto end;
+  buf_init(&b, (/*unconst*/ void *)in.p, in.sz);
   if (buf_getec(&b, &pp)) VALERR("malformed data");
   rc = Py_BuildValue("(NN)", ecpt_pywrapout(me, &pp),
                     bytestring_pywrapbuf(&b));
@@ -342,15 +341,14 @@ end:
 
 static PyObject *epmeth_fromraw(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t len;
+  struct bin in;
   buf b;
   PyObject *rc = 0;
   ec_curve *cc;
   ec pp = EC_INIT;
 
-  if (!PyArg_ParseTuple(arg, "s#:fromraw", &me, &p, &len)) return (0);
-  buf_init(&b, p, len);
+  if (!PyArg_ParseTuple(arg, "O&:fromraw", convbin, &in)) return (0);
+  buf_init(&b, (/*unconst*/ void *)in.p, in.sz);
   cc = ECCURVE_C(me);
   if (ec_getraw(cc, &b, &pp))
     VALERR("bad point");
@@ -362,8 +360,7 @@ end:
 
 static PyObject *epmeth_os2ecp(PyObject *me, PyObject *arg, PyObject *kw)
 {
-  char *p;
-  Py_ssize_t len;
+  struct bin in;
   buf b;
   PyObject *rc = 0;
   ec_curve *cc;
@@ -371,10 +368,10 @@ static PyObject *epmeth_os2ecp(PyObject *me, PyObject *arg, PyObject *kw)
   ec pp = EC_INIT;
   static const char *const kwlist[] = { "buf", "flags", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:os2ecp", KWLIST,
-                                  &p, &len, convuint, &f))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:os2ecp", KWLIST,
+                                  convbin, &in, convuint, &f))
     return (0);
-  buf_init(&b, p, len);
+  buf_init(&b, (/*unconst*/ void *)in.p, in.sz);
   cc = ECCURVE_C(me);
   if (ec_os2ecp(cc, f, &b, &pp)) VALERR("bad point");
   EC_IN(cc, &pp, &pp);
@@ -510,7 +507,6 @@ static int ecptxl_1(ec_curve *c, ec *p, PyObject *x)
   int rc = -1;
   PyObject *y = 0, *z = 0, *t = 0;
   mp *xx = 0;
-  const void *q;
   Py_ssize_t n;
   qd_parse qd;
 
@@ -521,9 +517,7 @@ static int ecptxl_1(ec_curve *c, ec *p, PyObject *x)
     getecptout(p, x);
     goto fix;
   } else if (PyString_Check(x)) {
-    if (PyObject_AsReadBuffer(x, &q, &n))
-      goto end;
-    qd.p = q;
+    qd.p = PyString_AS_STRING(x);
     qd.e = 0;
     if (!ec_ptparse(&qd, p))
       VALERR(qd.e);
diff --git a/group.c b/group.c
index 8dadb7a..0feb109 100644 (file)
--- a/group.c
+++ b/group.c
@@ -196,8 +196,7 @@ static PyObject *dimeth_gendsa(PyObject *me, PyObject *arg, PyObject *kw)
   unsigned ql, pl;
   unsigned steps = 0;
   dsa_seed ds;
-  char *k;
-  Py_ssize_t ksz;
+  struct bin k;
   struct excinfo exc = EXCINFO_INIT;
   pypgev evt = { { 0 } };
   static const char *const kwlist[] =
@@ -205,12 +204,12 @@ static PyObject *dimeth_gendsa(PyObject *me, PyObject *arg, PyObject *kw)
   PyObject *rc = 0;
 
   evt.exc = &exc;
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&s#|O&O&:gendsa", KWLIST,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&O&|O&O&:gendsa", KWLIST,
                                   convuint, &pl, convuint, &ql,
-                                  &k, &ksz, convpgev, &evt,
-                                  convuint, &steps))
+                                  convbin, &k,
+                                  convpgev, &evt, convuint, &steps))
     goto end;
-  if (dsa_gen(&dp, ql, pl, steps, k, ksz, &ds, evt.ev.proc, evt.ev.ctx))
+  if (dsa_gen(&dp, ql, pl, steps, k.p, k.sz, &ds, evt.ev.proc, evt.ev.ctx))
     PGENERR(&exc);
   rc = Py_BuildValue("(NNl)", fginfo_pywrap(&dp, dhinfo_pytype),
                     bytestring_pywrap(ds.p, ds.sz), (long)ds.count);
@@ -820,14 +819,13 @@ end:
 static PyObject *gemeth_frombuf(PyObject *me, PyObject *arg)
 {
   buf b;
-  char *p;
-  Py_ssize_t n;
+  struct bin in;
   group *g;
   ge *x = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#:frombuf", &p, &n)) return (0);
+  if (!PyArg_ParseTuple(arg, "O&:frombuf", convbin, &in)) return (0);
   g = GROUP_G(me);
-  buf_init(&b, p, n);
+  buf_init(&b, (/*unconst*/ void *)in.p, in.sz);
   x = G_CREATE(g);
   if (G_FROMBUF(g, &b, x)) VALERR("invalid data");
   return (Py_BuildValue("(NN)", ge_pywrap(me, x), bytestring_pywrapbuf(&b)));
@@ -839,14 +837,13 @@ end:
 static PyObject *gemeth_fromraw(PyObject *me, PyObject *arg)
 {
   buf b;
-  char *p;
-  Py_ssize_t n;
+  struct bin in;
   group *g;
   ge *x = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#:fromraw", &p, &n)) return (0);
+  if (!PyArg_ParseTuple(arg, "O&:fromraw", convbin, &in)) return (0);
   g = GROUP_G(me);
-  buf_init(&b, p, n);
+  buf_init(&b, (/*unconst*/ void *)in.p, in.sz);
   x = G_CREATE(g);
   if (G_FROMRAW(g, &b, x)) VALERR("invalid data");
   return (Py_BuildValue("(NN)", ge_pywrap(me, x), bytestring_pywrapbuf(&b)));
diff --git a/key.c b/key.c
index 5057b2f..368456c 100644 (file)
--- a/key.c
+++ b/key.c
@@ -377,14 +377,13 @@ end:
 
 static PyObject *kdmeth_lock(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t n;
+  struct bin pp;
   PyObject *rc = 0;
   key_data *kd;
 
-  if (!PyArg_ParseTuple(arg, "s#:lock", &p, &n))
+  if (!PyArg_ParseTuple(arg, "O&:lock", convbin, &pp))
     goto end;
-  key_lock(&kd, KEYDATA_KD(me), p, n);
+  key_lock(&kd, KEYDATA_KD(me), pp.p, pp.sz);
   rc = keydata_pywrap(kd);
 end:
   return (rc);
@@ -406,14 +405,13 @@ end:
 
 static PyObject *kdmeth_decode(PyObject *me, PyObject *arg)
 {
-  const char *p;
-  Py_ssize_t n;
+  struct bin in;
   key_data *kd;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#:decode", &p, &n)) goto end;
-  if ((kd = key_decode(p, n)) == 0) KEYERR(KERR_MALFORMED);
-  rc = keydata_pywrap(kd);
+  if (!PyArg_ParseTuple(arg, "O&:decode", convbin, &in)) goto end;
+  if ((kd = key_decode(in.p, in.sz)) == 0) KEYERR(KERR_MALFORMED);
+  rc = keydata_pywrap(kd);
 end:
   return (rc);
 }
@@ -496,17 +494,16 @@ static const PyTypeObject keydata_pytype_skel = {
 static PyObject *keydatabin_pynew(PyTypeObject *ty,
                                  PyObject *arg, PyObject *kw)
 {
-  char *p;
-  Py_ssize_t n;
+  struct bin in;
   unsigned f = 0;
   keydata_pyobj *me = 0;
   static const char *const kwlist[] = { "key", "flags", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:new", KWLIST,
-                                  &p, &n, convflags, &f))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", KWLIST,
+                                  convbin, &in, convflags, &f))
     goto end;
   me = (keydata_pyobj *)ty->tp_alloc(ty, 0);
-  me->kd = key_newbinary(f & ~KF_ENCMASK, p, n);
+  me->kd = key_newbinary(f & ~KF_ENCMASK, in.p, in.sz);
 end:
   return ((PyObject *)me);
 }
@@ -573,17 +570,16 @@ static const PyTypeObject keydatabin_pytype_skel = {
 static PyObject *keydataenc_pynew(PyTypeObject *ty,
                                  PyObject *arg, PyObject *kw)
 {
-  char *p;
-  Py_ssize_t n;
+  struct bin in;
   unsigned f = 0;
   keydata_pyobj *me = 0;
   static const char *const kwlist[] = { "key", "flags", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:new", KWLIST,
-                                  &p, &n, convflags, &f))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new", KWLIST,
+                                  convbin, &in, convflags, &f))
     goto end;
   me = (keydata_pyobj *)ty->tp_alloc(ty, 0);
-  me->kd = key_newencrypted(f & ~KF_ENCMASK, p, n);
+  me->kd = key_newencrypted(f & ~KF_ENCMASK, in.p, in.sz);
 end:
   return ((PyObject *)me);
 }
@@ -599,9 +595,8 @@ end:
 
 static PyObject *kdemeth_lock(PyObject *me, PyObject *arg)
 {
-  char *hunoz;
-  Py_ssize_t hukairz;
-  if (!PyArg_ParseTuple(arg, "s#:lock", &hunoz, &hukairz)) goto end;
+  struct bin hunoz;
+  if (!PyArg_ParseTuple(arg, "O&:lock", convbin, &hunoz)) goto end;
   KEYERR(KERR_WRONGTYPE);
 end:
   return (0);
@@ -625,15 +620,14 @@ end:
 
 static PyObject *kdemeth_unlock(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t n;
+  struct bin pp;
   int err;
   PyObject *rc = 0;
   key_data *kd;
 
-  if (!PyArg_ParseTuple(arg, "s#:unlock", &p, &n))
+  if (!PyArg_ParseTuple(arg, "O&:unlock", convbin, &pp))
     goto end;
-  if ((err = key_unlock(&kd, KEYDATA_KD(me), p, n)) != 0)
+  if ((err = key_unlock(&kd, KEYDATA_KD(me), pp.p, pp.sz)) != 0)
     KEYERR(err);
   rc = keydata_pywrap(kd);
 end:
diff --git a/mp.c b/mp.c
index 99a84d1..0da3a5e 100644 (file)
--- a/mp.c
+++ b/mp.c
@@ -723,13 +723,12 @@ STOREOP(storeb2c, 2c)
   static PyObject *ty##meth_frombuf(PyObject *me, PyObject *arg)       \
   {                                                                    \
     buf b;                                                             \
-    char *p;                                                           \
-    Py_ssize_t sz;                                                     \
+    struct bin in;                                                     \
     PyObject *rc = 0;                                                  \
     mp *x;                                                             \
                                                                        \
-    if (!PyArg_ParseTuple(arg, "s#:frombuf", &p, &sz)) goto end;       \
-    buf_init(&b, p, sz);                                               \
+    if (!PyArg_ParseTuple(arg, "O&:frombuf", convbin, &in)) goto end;  \
+    buf_init(&b, (/*unconst*/ void *)in.p, in.sz);                     \
     if ((x = buf_getmp(&b)) == 0) VALERR("malformed data");            \
     rc = Py_BuildValue("(NN)", ty##_pywrap(x),                         \
                       bytestring_pywrapbuf(&b));                       \
@@ -815,10 +814,9 @@ static PyObject *mpmeth_fibonacci(PyObject *me, PyObject *arg)
 #define LOADOP(pre, name)                                              \
   static PyObject *pre##meth_##name(PyObject *me, PyObject *arg)       \
   {                                                                    \
-    char *p;                                                           \
-    Py_ssize_t len;                                                    \
-    if (!PyArg_ParseTuple(arg, "s#:" #name, &p, &len)) return (0);     \
-    return (pre##_pywrap(mp_##name(MP_NEW, p, len)));                  \
+    struct bin in;                                                     \
+    if (!PyArg_ParseTuple(arg, "O&:" #name, convbin, &in)) return (0); \
+    return (pre##_pywrap(mp_##name(MP_NEW, in.p, in.sz)));             \
   }
 LOADOP(mp, loadl)
 LOADOP(mp, loadb)
index 2b0b29e..2455275 100644 (file)
--- a/pubkey.c
+++ b/pubkey.c
@@ -127,18 +127,17 @@ static PyObject *dsameth_endhash(PyObject *me, PyObject *arg)
 static PyObject *dsameth_sign(PyObject *me, PyObject *arg, PyObject *kw)
 {
   gdsa_sig s = GDSA_SIG_INIT;
-  char *p;
-  Py_ssize_t n;
+  struct bin h;
   mp *k = 0;
   PyObject *rc = 0;
   static const char *const kwlist[] = { "msg", "k", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:sign", KWLIST,
-                                  &p, &n, convmp, &k))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:sign", KWLIST,
+                                  convbin, &h, convmp, &k))
     goto end;
-  if (n != DSA_D(me)->h->hashsz)
+  if (h.sz != DSA_D(me)->h->hashsz)
     VALERR("bad message length (doesn't match hash size)");
-  gdsa_sign(DSA_D(me), &s, p, k);
+  gdsa_sign(DSA_D(me), &s, h.p, k);
   rc = Py_BuildValue("(NN)", mp_pywrap(s.r), mp_pywrap(s.s));
 end:
   mp_drop(k);
@@ -147,17 +146,16 @@ end:
 
 static PyObject *dsameth_verify(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t n;
+  struct bin h;
   gdsa_sig s = GDSA_SIG_INIT;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#(O&O&):verify",
-                       &p, &n, convmp, &s.r, convmp, &s.s))
+  if (!PyArg_ParseTuple(arg, "O&(O&O&):verify",
+                       convbin, &h, convmp, &s.r, convmp, &s.s))
     goto end;
-  if (n != DSA_D(me)->h->hashsz)
+  if (h.sz != DSA_D(me)->h->hashsz)
     VALERR("bad message length (doesn't match hash size)");
-  rc = getbool(!gdsa_verify(DSA_D(me), &s, p));
+  rc = getbool(!gdsa_verify(DSA_D(me), &s, h.p));
 end:
   mp_drop(s.r);
   mp_drop(s.s);
@@ -379,20 +377,19 @@ static PyObject *kcdsameth_endhash(PyObject *me, PyObject *arg)
 static PyObject *kcdsameth_sign(PyObject *me, PyObject *arg, PyObject *kw)
 {
   gkcdsa_sig s = GKCDSA_SIG_INIT;
-  char *p;
-  Py_ssize_t n;
+  struct bin h;
   mp *k = 0;
   PyObject *r = 0, *rc = 0;
   static const char *const kwlist[] = { "msg", "k", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#|O&:sign", KWLIST,
-                                  &p, &n, convmp, &k))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:sign", KWLIST,
+                                  convbin, &h, convmp, &k))
     goto end;
-  if (n != DSA_D(me)->h->hashsz)
+  if (h.sz != DSA_D(me)->h->hashsz)
     VALERR("bad message length (doesn't match hash size)");
   r = bytestring_pywrap(0, DSA_D(me)->h->hashsz);
   s.r = (octet *)PyString_AS_STRING(r);
-  gkcdsa_sign(DSA_D(me), &s, p, k);
+  gkcdsa_sign(DSA_D(me), &s, h.p, k);
   rc = Py_BuildValue("(ON)", r, mp_pywrap(s.s));
 end:
   Py_XDECREF(r);
@@ -402,19 +399,19 @@ end:
 
 static PyObject *kcdsameth_verify(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t n, rn;
+  struct bin h, sr;
   gkcdsa_sig s = GKCDSA_SIG_INIT;
   PyObject *rc = 0;
 
-  if (!PyArg_ParseTuple(arg, "s#(s#O&):verify",
-                       &p, &n, &s.r, &rn, convmp, &s.s))
+  if (!PyArg_ParseTuple(arg, "O&(O&O&):verify",
+                       convbin, &h, convbin, &sr, convmp, &s.s))
     goto end;
-  if (n != DSA_D(me)->h->hashsz)
+  if (h.sz != DSA_D(me)->h->hashsz)
     VALERR("bad message length (doesn't match hash size)");
-  if (rn != DSA_D(me)->h->hashsz)
+  if (sr.sz != DSA_D(me)->h->hashsz)
     VALERR("bad signature `r' length (doesn't match hash size)");
-  rc = getbool(!gkcdsa_verify(DSA_D(me), &s, p));
+  s.r = (/*unconst*/ octet *)sr.p;
+  rc = getbool(!gkcdsa_verify(DSA_D(me), &s, h.p));
 end:
   mp_drop(s.s);
   return (rc);
@@ -890,8 +887,7 @@ static PyObject *meth__p1crypt_encode(PyObject *me,
                                      PyObject *arg, PyObject *kw)
 {
   pkcs1 p1;
-  char *m, *ep;
-  Py_ssize_t msz, epsz;
+  struct bin m, ep = { 0, 0 };
   unsigned long nbits;
   PyObject *rc = 0;
   octet *b = 0;
@@ -899,16 +895,16 @@ static PyObject *meth__p1crypt_encode(PyObject *me,
   mp *x;
   static const char *const kwlist[] = { "msg", "nbits", "ep", "rng", 0 };
 
-  p1.r = &rand_global; ep = 0; epsz = 0;
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|s#O&:encode", KWLIST,
-                                  &m, &msz, convulong, &nbits,
-                                  &ep, &epsz, convgrand, &p1.r))
+  p1.r = &rand_global;
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:encode", KWLIST,
+                                  convbin, &m, convulong, &nbits,
+                                  convbin, &ep, convgrand, &p1.r))
     goto end;
   sz = (nbits + 7)/8;
-  p1.ep = ep; p1.epsz = epsz;
-  if (epsz + msz + 11 > sz) VALERR("buffer underflow");
+  p1.ep = ep.p; p1.epsz = ep.sz;
+  if (ep.sz + m.sz + 11 > sz) VALERR("buffer underflow");
   b = xmalloc(sz);
-  x = pkcs1_cryptencode(MP_NEW, m, msz, b, sz, nbits, &p1);
+  x = pkcs1_cryptencode(MP_NEW, m.p, m.sz, b, sz, nbits, &p1);
   rc = mp_pywrap(x);
 end:
   xfree(b);
@@ -919,8 +915,7 @@ static PyObject *meth__p1crypt_decode(PyObject *me,
                                      PyObject *arg, PyObject *kw)
 {
   pkcs1 p1;
-  char *ep;
-  Py_ssize_t epsz;
+  struct bin ep = { 0, 0 };
   unsigned long nbits;
   int n;
   PyObject *rc = 0;
@@ -929,14 +924,14 @@ static PyObject *meth__p1crypt_decode(PyObject *me,
   mp *x = 0;
   static const char *const kwlist[] = { "ct", "nbits", "ep", "rng", 0 };
 
-  p1.r = &rand_global; ep = 0; epsz = 0;
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|s#O&:decode", KWLIST,
+  p1.r = &rand_global;
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:decode", KWLIST,
                                   convmp, &x, convulong, &nbits,
-                                  &ep, &epsz, convgrand, &p1.r))
+                                  convbin, &ep, convgrand, &p1.r))
     goto end;
   sz = (nbits + 7)/8;
-  p1.ep = ep; p1.epsz = epsz;
-  if (epsz + 11 > sz) VALERR("buffer underflow");
+  p1.ep = ep.p; p1.epsz = ep.sz;
+  if (ep.sz + 11 > sz) VALERR("buffer underflow");
   b = xmalloc(sz);
   if ((n = pkcs1_cryptdecode(x, b, sz, nbits, &p1)) < 0)
     VALERR("decryption failed");
@@ -951,8 +946,7 @@ static PyObject *meth__p1sig_encode(PyObject *me,
                                    PyObject *arg, PyObject *kw)
 {
   pkcs1 p1;
-  char *m, *ep;
-  Py_ssize_t msz, epsz;
+  struct bin m, ep = { 0, 0 };
   unsigned long nbits;
   PyObject *rc = 0;
   octet *b = 0;
@@ -960,16 +954,16 @@ static PyObject *meth__p1sig_encode(PyObject *me,
   mp *x;
   static const char *const kwlist[] = { "msg", "nbits", "ep", "rng", 0 };
 
-  p1.r = &rand_global; ep = 0; epsz = 0;
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|s#O&:encode", KWLIST,
-                                  &m, &msz, convulong, &nbits,
-                                  &ep, &epsz, convgrand, &p1.r))
+  p1.r = &rand_global;
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:encode", KWLIST,
+                                  convbin, &m, convulong, &nbits,
+                                  convbin, &ep, convgrand, &p1.r))
     goto end;
   sz = (nbits + 7)/8;
-  p1.ep = ep; p1.epsz = epsz;
-  if (epsz + msz + 11 > sz) VALERR("buffer underflow");
+  p1.ep = ep.p; p1.epsz = ep.sz;
+  if (ep.sz + m.sz + 11 > sz) VALERR("buffer underflow");
   b = xmalloc(sz);
-  x = pkcs1_sigencode(MP_NEW, m, msz, b, sz, nbits, &p1);
+  x = pkcs1_sigencode(MP_NEW, m.p, m.sz, b, sz, nbits, &p1);
   rc = mp_pywrap(x);
 end:
   xfree(b);
@@ -980,8 +974,7 @@ static PyObject *meth__p1sig_decode(PyObject *me,
                                    PyObject *arg, PyObject *kw)
 {
   pkcs1 p1;
-  char *ep;
-  Py_ssize_t epsz;
+  struct bin ep = { 0, 0 };
   unsigned long nbits;
   int n;
   PyObject *hukairz;
@@ -992,14 +985,14 @@ static PyObject *meth__p1sig_decode(PyObject *me,
   static const char *const kwlist[] =
     { "msg", "sig", "nbits", "ep", "rng", 0 };
 
-  p1.r = &rand_global; ep = 0; epsz = 0;
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&|s#O&:decode", KWLIST,
+  p1.r = &rand_global;
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO&O&|O&O&:decode", KWLIST,
                                   &hukairz, convmp, &x, convulong, &nbits,
-                                  &ep, &epsz, convgrand, &p1.r))
+                                  convbin, &ep, convgrand, &p1.r))
     goto end;
   sz = (nbits + 7)/8;
-  p1.ep = ep; p1.epsz = epsz;
-  if (epsz + 10 > sz) VALERR("buffer underflow");
+  p1.ep = ep.p; p1.epsz = ep.sz;
+  if (ep.sz + 10 > sz) VALERR("buffer underflow");
   b = xmalloc(sz);
   if ((n = pkcs1_sigdecode(x, 0, 0, b, sz, nbits, &p1)) < 0)
     VALERR("verification failed");
@@ -1014,8 +1007,7 @@ static PyObject *meth__oaep_encode(PyObject *me,
                                   PyObject *arg, PyObject *kw)
 {
   oaep o;
-  char *m, *ep;
-  Py_ssize_t msz, epsz;
+  struct bin m, ep = { 0, 0 };
   unsigned long nbits;
   PyObject *rc = 0;
   octet *b = 0;
@@ -1024,19 +1016,20 @@ static PyObject *meth__oaep_encode(PyObject *me,
   static const char *const kwlist[] =
     { "msg", "nbits", "mgf", "hash", "ep", "rng", 0 };
 
-  o.r = &rand_global; o.cc = &sha_mgf; o.ch = &sha; ep = 0; epsz = 0;
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|O&O&s#O&:encode", KWLIST,
-                                  &m, &msz, convulong, &nbits,
+  o.r = &rand_global; o.cc = &sha_mgf; o.ch = &sha;
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&O&O&:encode",
+                                  KWLIST,
+                                  convbin, &m, convulong, &nbits,
                                   convgccipher, &o.cc,
                                   convgchash, &o.ch,
-                                  &ep, &epsz,
+                                  convbin, &ep,
                                   convgrand, &o.r))
     goto end;
   sz = (nbits + 7)/8;
-  o.ep = ep; o.epsz = epsz;
-  if (2 * o.ch->hashsz + 2 + msz > sz) VALERR("buffer underflow");
+  o.ep = ep.p; o.epsz = ep.sz;
+  if (2 * o.ch->hashsz + 2 + m.sz > sz) VALERR("buffer underflow");
   b = xmalloc(sz);
-  x = oaep_encode(MP_NEW, m, msz, b, sz, nbits, &o);
+  x = oaep_encode(MP_NEW, m.p, m.sz, b, sz, nbits, &o);
   rc = mp_pywrap(x);
 end:
   xfree(b);
@@ -1047,8 +1040,7 @@ static PyObject *meth__oaep_decode(PyObject *me,
                                   PyObject *arg, PyObject *kw)
 {
   oaep o;
-  char *ep;
-  Py_ssize_t epsz;
+  struct bin ep = { 0, 0 };
   unsigned long nbits;
   int n;
   PyObject *rc = 0;
@@ -1058,16 +1050,16 @@ static PyObject *meth__oaep_decode(PyObject *me,
   static const char *const kwlist[] =
     { "ct", "nbits", "mgf", "hash", "ep", "rng", 0 };
 
-  o.r = &rand_global; o.cc = &sha_mgf; o.ch = &sha; ep = 0; epsz = 0;
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&s#O&:decode", KWLIST,
+  o.r = &rand_global; o.cc = &sha_mgf; o.ch = &sha;
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&O&O&:decode", KWLIST,
                                   convmp, &x, convulong, &nbits,
                                   convgccipher, &o.cc,
                                   convgchash, &o.ch,
-                                  &ep, &epsz,
+                                  convbin, &ep,
                                   convgrand, &o.r))
     goto end;
   sz = (nbits + 7)/8;
-  o.ep = ep; o.epsz = epsz;
+  o.ep = ep.p; o.epsz = ep.sz;
   if (2 * o.ch->hashsz > sz) VALERR("buffer underflow");
   b = xmalloc(sz);
   if ((n = oaep_decode(x, b, sz, nbits, &o)) < 0)
@@ -1083,8 +1075,7 @@ static PyObject *meth__pss_encode(PyObject *me,
                                  PyObject *arg, PyObject *kw)
 {
   pss p;
-  char *m;
-  Py_ssize_t msz;
+  struct bin m;
   unsigned long nbits;
   PyObject *rc = 0;
   octet *b = 0;
@@ -1094,8 +1085,8 @@ static PyObject *meth__pss_encode(PyObject *me,
     { "msg", "nbits", "mgf", "hash", "saltsz", "rng", 0 };
 
   p.cc = &sha_mgf; p.ch = &sha; p.r = &rand_global; p.ssz = (size_t)-1;
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&|O&O&O&O&:encode", KWLIST,
-                                  &m, &msz, convulong, &nbits,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&O&O&:encode", KWLIST,
+                                  convbin, &m, convulong, &nbits,
                                   convgccipher, &p.cc,
                                   convgchash, &p.ch,
                                   convszt, &p.ssz,
@@ -1105,7 +1096,7 @@ static PyObject *meth__pss_encode(PyObject *me,
   if (p.ssz == (size_t)-1) p.ssz = p.ch->hashsz;
   if (p.ch->hashsz + p.ssz + 2 > sz) VALERR("buffer underflow");
   b = xmalloc(sz);
-  x = pss_encode(MP_NEW, m, msz, b, sz, nbits, &p);
+  x = pss_encode(MP_NEW, m.p, m.sz, b, sz, nbits, &p);
   rc = mp_pywrap(x);
 end:
   xfree(b);
@@ -1116,8 +1107,7 @@ static PyObject *meth__pss_decode(PyObject *me,
                                  PyObject *arg, PyObject *kw)
 {
   pss p;
-  char *m;
-  Py_ssize_t msz;
+  struct bin m;
   unsigned long nbits;
   PyObject *rc = 0;
   octet *b = 0;
@@ -1128,8 +1118,10 @@ static PyObject *meth__pss_decode(PyObject *me,
     { "msg", "sig", "nbits", "mgf", "hash", "saltsz", "rng", 0 };
 
   p.cc = &sha_mgf; p.ch = &sha; p.r = &rand_global; p.ssz = (size_t)-1;
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&O&|O&O&O&O&:decode", KWLIST,
-                                  &m, &msz, convmp, &x, convulong, &nbits,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&O&|O&O&O&O&:decode",
+                                  KWLIST,
+                                  convbin, &m, convmp, &x,
+                                  convulong, &nbits,
                                   convgccipher, &p.cc,
                                   convgchash, &p.ch,
                                   convszt, &p.ssz,
@@ -1139,7 +1131,7 @@ static PyObject *meth__pss_decode(PyObject *me,
   if (p.ssz == (size_t)-1) p.ssz = p.ch->hashsz;
   if (p.ch->hashsz + p.ssz + 2 > sz) VALERR("buffer underflow");
   b = xmalloc(sz);
-  if ((n = pss_decode(x, m, msz, b, sz, nbits, &p)) < 0)
+  if ((n = pss_decode(x, m.p, m.sz, b, sz, nbits, &p)) < 0)
     VALERR("verification failed");
   rc = Py_None; Py_INCREF(rc);
 end:
@@ -1157,16 +1149,14 @@ end:
 #define DEFXDH(X, x)                                                   \
   static PyObject *meth_##x(PyObject *me, PyObject *arg)               \
   {                                                                    \
-    const char *k, *p;                                                 \
-    Py_ssize_t ksz, psz;                                               \
+    struct bin k, p;                                                   \
     PyObject *rc = 0;                                                  \
-    if (!PyArg_ParseTuple(arg, "s#s#:" #x, &k, &ksz, &p, &psz))                \
+    if (!PyArg_ParseTuple(arg, "O&O&:" #x, convbin, &k, convbin, &p))  \
       goto end;                                                                \
-    if (ksz != X##_KEYSZ) VALERR("bad key length");                    \
-    if (psz != X##_PUBSZ) VALERR("bad public length");                 \
+    if (k.sz != X##_KEYSZ) VALERR("bad key length");                   \
+    if (p.sz != X##_PUBSZ) VALERR("bad public length");                        \
     rc = bytestring_pywrap(0, X##_OUTSZ);                              \
-    x((octet *)PyString_AS_STRING(rc),                                 \
-      (const octet *)k, (const octet *)p);                             \
+    x((octet *)PyString_AS_STRING(rc), k.p, p.p);                      \
     return (rc);                                                       \
   end:                                                                 \
     return (0);                                                                \
@@ -1184,13 +1174,12 @@ XDHS(DEFXDH)
                                                                        \
   static PyObject *meth_##ed##_pubkey(PyObject *me, PyObject *arg)     \
   {                                                                    \
-    const char *k;                                                     \
-    Py_ssize_t ksz;                                                    \
+   struct bin k;                                                       \
     PyObject *rc = 0;                                                  \
-    if (!PyArg_ParseTuple(arg, "s#:" #ed "_pubkey", &k, &ksz))         \
+    if (!PyArg_ParseTuple(arg, "O&:" #ed "_pubkey", convbin, &k))      \
       goto end;                                                                \
     rc = bytestring_pywrap(0, ED##_PUBSZ);                             \
-    ed##_pubkey((octet *)PyString_AS_STRING(rc), k, ksz);              \
+    ed##_pubkey((octet *)PyString_AS_STRING(rc), k.p, k.sz);           \
     return (rc);                                                       \
   end:                                                                 \
     return (0);                                                                \
@@ -1199,27 +1188,27 @@ XDHS(DEFXDH)
   static PyObject *meth_##ed##_sign(PyObject *me, PyObject *arg,       \
                                    PyObject *kw)                       \
   {                                                                    \
-    const char *k, *p = 0, *c = 0, *m;                                 \
-    Py_ssize_t ksz, psz, csz = 0, msz;                                 \
+    struct bin k, p = { 0, 0}, c = { 0, 0 }, m;                                \
     int ph = phdflt;                                                   \
     PyObject *rc = 0;                                                  \
     octet pp[ED##_PUBSZ];                                              \
     static const char *const kwlist[] =                                        \
       { "key", "msg", "pub", "perso", "phflag", 0 };                   \
     if (!PyArg_ParseTupleAndKeywords(arg, kw,                          \
-                                    "s#s#|s#s#O&:" #ed "_sign",        \
+                                    "O&O&|O&O&O&:" #ed "_sign",        \
                                     KWLIST,                            \
-                                    &k, &ksz, &m, &msz, &p, &psz,      \
-                                    &c, &csz, convbool, &ph))          \
+                                    convbin, &k, convbin, &m,          \
+                                    convbin, &p, convbin, &c,          \
+                                    convbool, &ph))                    \
       goto end;                                                                \
-    if (p && psz != ED##_PUBSZ) VALERR("bad public length");           \
-    if (c && csz > ED##_MAXPERSOSZ)                                    \
+    if (p.p && p.sz != ED##_PUBSZ) VALERR("bad public length");                \
+    if (c.p && c.sz > ED##_MAXPERSOSZ)                                 \
       VALERR("personalization string too long");                       \
-    if (c && ph == -1) ph = 0;                                         \
-    if (!p) { p = (const char *)pp; ed##_pubkey(pp, k, ksz); }         \
+    if (c.p && ph == -1) ph = 0;                                       \
+    if (!p.p) { p.p = pp; ed##_pubkey(pp, k.p, k.sz); }                        \
     rc = bytestring_pywrap(0, ED##_SIGSZ);                             \
-    ed##sigver##_sign((octet *)PyString_AS_STRING(rc), k, ksz,         \
-                     (const octet *)p, ph, c, csz, m, msz);            \
+    ed##sigver##_sign((octet *)PyString_AS_STRING(rc), k.p, k.sz,      \
+                     p.p, ph, c.p, c.sz, m.p, m.sz);                   \
     return (rc);                                                       \
   end:                                                                 \
     return (0);                                                                \
@@ -1228,25 +1217,25 @@ XDHS(DEFXDH)
   static PyObject *meth_##ed##_verify(PyObject *me,                    \
                                      PyObject *arg, PyObject *kw)      \
   {                                                                    \
-    const char *p, *c = 0, *m, *s;                                     \
-    Py_ssize_t psz, csz = 0, msz, ssz;                                 \
+    struct bin p, c = { 0, 0 }, m, s;                                  \
     int ph = phdflt;                                                   \
     PyObject *rc = 0;                                                  \
     static const char *const kwlist[] =                                        \
       { "pub", "msg", "sig", "perso", "phflag", 0 };                   \
     if (!PyArg_ParseTupleAndKeywords(arg, kw,                          \
-                                    "s#s#s#|s#O&:" #ed "_verify",      \
+                                    "O&O&O&|O&O&:" #ed "_verify",      \
                                     KWLIST,                            \
-                                    &p, &psz, &m, &msz, &s, &ssz,      \
-                                    &c, &csz, convbool, &ph))          \
+                                    convbin, &p, convbin, &m,          \
+                                    convbin, &s,                       \
+                                    convbin, &c, convbool, &ph))       \
       goto end;                                                                \
-    if (psz != ED##_PUBSZ) VALERR("bad public length");                        \
-    if (ssz != ED##_SIGSZ) VALERR("bad signature length");             \
-    if (c && csz > ED##_MAXPERSOSZ)                                    \
+    if (p.sz != ED##_PUBSZ) VALERR("bad public length");               \
+    if (s.sz != ED##_SIGSZ) VALERR("bad signature length");            \
+    if (c.p && c.sz > ED##_MAXPERSOSZ)                                 \
       VALERR("personalization string too long");                       \
-    if (c && ph == -1) ph = 0;                                         \
-    rc = getbool(!ed##sigver##_verify((const octet *)p, ph, c, csz,    \
-                                     m, msz, (const octet *)s));       \
+    if (c.p && ph == -1) ph = 0;                                       \
+    rc = getbool(!ed##sigver##_verify(p.p, ph, c.p, c.sz,              \
+                                     m.p, m.sz, s.p));                 \
     return (rc);                                                       \
   end:                                                                 \
     return (0);                                                                \
index 29dd8c5..d874763 100644 (file)
@@ -101,6 +101,25 @@ end:
   return (0);
 }
 
+int convbin(PyObject *o, void *pp)
+{
+  struct bin *r = pp;
+
+  if (PyString_Check(o)) {
+    r->p = PyString_AS_STRING(o);
+    r->sz = PyString_GET_SIZE(o);
+    return (1);
+  }
+  if (PyUnicode_Check(o)) {
+    o = _PyUnicode_AsDefaultEncodedString(o, 0);
+    if (!o) return (0);
+    r->p = PyString_AS_STRING(o);
+    r->sz = PyString_GET_SIZE(o);
+    return (1);
+  }
+  return (PyObject_AsReadBuffer(o, &r->p, &r->sz) ? 0 : 1);
+}
+
 /*----- Miscellaneous utilities -------------------------------------------*/
 
 PyObject *abstract_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
index 6c4e4e1..984b5d5 100644 (file)
@@ -169,10 +169,12 @@ extern void restore_exception(struct excinfo *, const char *, ...);
 /* Input conversion functions for standard kinds of objects, with overflow
  * checking where applicable.
  */
+struct bin { const void *p; Py_ssize_t sz; };
 extern int convulong(PyObject *, void *); /* unsigned long */
 extern int convuint(PyObject *, void *); /* unsigned int */
 extern int convszt(PyObject *, void *);        /* size_t */
 extern int convbool(PyObject *, void *); /* bool */
+extern int convbin(PyObject *, void *); /* read buffer holding bytes */
 
 /* Output conversions. */
 extern PyObject *getbool(int);         /* bool */
diff --git a/rand.c b/rand.c
index 6e5087c..069c351 100644 (file)
--- a/rand.c
+++ b/rand.c
@@ -186,13 +186,12 @@ end:
 
 static PyObject *grmeth_seedblock(PyObject *me, PyObject *arg)
 {
-  char *p;
-  Py_ssize_t n;
+  struct bin in;
   grand *r = GRAND_R(me);
-  if (!PyArg_ParseTuple(arg, "s#:seedblock", &p, &n) ||
+  if (!PyArg_ParseTuple(arg, "O&:seedblock", convbin, &in) ||
       grand_check(me) || checkop(r, GRAND_SEEDBLOCK, "seedblock"))
     goto end;
-  r->ops->misc(r, GRAND_SEEDBLOCK, p, (size_t)n);
+  r->ops->misc(r, GRAND_SEEDBLOCK, in.p, (size_t)in.sz);
   RETURN_ME;
 end:
   return (0);
@@ -232,16 +231,17 @@ end:
 static PyObject *grmeth_mask(PyObject *me, PyObject *arg)
 {
   grand *r = GRAND_R(me);
-  char *p, *q;
-  Py_ssize_t sz;
+  struct bin in;
+  const octet *p; size_t n;
+  octet *q;
   PyObject *rc;
 
-  if (!PyArg_ParseTuple(arg, "s#:mask", &p, &sz)) return (0);
+  if (!PyArg_ParseTuple(arg, "O&:mask", convbin, &in)) return (0);
   if (grand_check(me)) return (0);
-  rc = bytestring_pywrap(0, sz);
-  q = PyString_AS_STRING(rc);
-  GR_FILL(r, q, sz);
-  while (sz--) *q++ ^= *p++;
+  rc = bytestring_pywrap(0, in.sz);
+  q = (octet *)PyString_AS_STRING(rc);
+  GR_FILL(r, q, in.sz);
+  p = in.p; n = in.sz; while (n--) *q++ ^= *p++;
   return (rc);
 }
 
@@ -456,19 +456,19 @@ static PyObject *trmeth_stretch(PyObject *me)
 static PyObject *trmeth_add(PyObject *me, PyObject *arg)
 {
   grand *r = GRAND_R(me);
-  char *p; Py_ssize_t n; unsigned goodbits;
-  if (!PyArg_ParseTuple(arg, "s#O&:add", &p, &n, convuint, &goodbits))
+  struct bin in; unsigned goodbits;
+  if (!PyArg_ParseTuple(arg, "O&O&:add", convbin, &in, convuint, &goodbits))
     return (0);
-  r->ops->misc(r, RAND_ADD, p, (size_t)n, goodbits);
+  r->ops->misc(r, RAND_ADD, in.p, (size_t)in.sz, goodbits);
   RETURN_ME;
 }
 
 static PyObject *trmeth_key(PyObject *me, PyObject *arg)
 {
   grand *r = GRAND_R(me);
-  char *p; Py_ssize_t n;
-  if (!PyArg_ParseTuple(arg, "s#:key", &p, &n)) return (0);
-  r->ops->misc(r, RAND_KEY, p, (size_t)n);
+  struct bin k;
+  if (!PyArg_ParseTuple(arg, "O&:key", convbin, &k)) return (0);
+  r->ops->misc(r, RAND_KEY, k.p, (size_t)k.sz);
   RETURN_ME;
 }
 
@@ -627,13 +627,12 @@ static PyObject *gcrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
   const gccrand_info *info = GCCRAND_INFO(ty);
   static const char *const kwlist[] = { "key", 0 };
-  char *k;
-  Py_ssize_t n;
+  struct bin k;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &k, &n))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST,  convbin, &k))
     goto end;
-  if (keysz(n, info->keysz) != n) VALERR("bad key length");
-  return (grand_dopywrap(ty, info->func(k, n), f_freeme));
+  if (keysz(k.sz, info->keysz) != k.sz) VALERR("bad key length");
+  return (grand_dopywrap(ty, info->func(k.p, k.sz), f_freeme));
 end:
   return (0);
 }
@@ -643,15 +642,14 @@ static PyObject *gcirand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
   const gccrand_info *info = GCCRAND_INFO(ty);
   uint32 i = 0;
   static const char *const kwlist[] = { "key", "i", 0 };
-  char *k;
-  Py_ssize_t n;
+  struct bin k;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#O&:new", KWLIST,
-                                  &k, &n, convu32, &i))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST,
+                                  convbin, &k, convu32, &i))
     goto end;
-  if (keysz(n, info->keysz) != n) VALERR("bad key length");
+  if (keysz(k.sz, info->keysz) != k.sz) VALERR("bad key length");
   return (grand_dopywrap(ty,
-                        ((gcirand_func *)info->func)(k, n, i),
+                        ((gcirand_func *)info->func)(k.p, k.sz, i),
                         f_freeme));
 end:
   return (0);
@@ -661,16 +659,15 @@ static PyObject *gcnrand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
   const gccrand_info *info = GCCRAND_INFO(ty);
   static const char *const kwlist[] = { "key", "nonce", 0 };
-  char *k, *n;
-  Py_ssize_t ksz, nsz;
+  struct bin k, n;
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#:new", KWLIST,
-                                  &k, &ksz, &n, &nsz))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:new", KWLIST,
+                                  convbin, &k, convbin, &n))
     goto end;
-  if (keysz(ksz, info->keysz) != ksz) VALERR("bad key length");
-  if (nsz != info->noncesz) VALERR("bad nonce length");
+  if (keysz(k.sz, info->keysz) != k.sz) VALERR("bad key length");
+  if (n.sz != info->noncesz) VALERR("bad nonce length");
   return (grand_dopywrap(ty,
-                        ((gcnrand_func *)info->func)(k, ksz, n),
+                        ((gcnrand_func *)info->func)(k.p, k.sz, n.p),
                         f_freeme));
 end:
   return (0);
@@ -683,25 +680,25 @@ static PyObject *gcshakyrand_pynew(PyTypeObject *ty,
   static const char
     *const kwlist_shake[] = { "key", "func", "perso", 0 },
     *const kwlist_func[] = { "key", "perso", 0 };
-  char *k, *f = 0, *p = 0;
-  Py_ssize_t ksz, fsz = 0, psz = 0;
+  struct bin k, f = { 0, 0 }, p = { 0, 0 };
 
   if ((info->f&RNGF_MASK) == RNG_SHAKE
-       ? !PyArg_ParseTupleAndKeywords(arg, kw, "s#|s#s#:new",
+       ? !PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&O&:new",
                                       (/*unconst*/ char **)kwlist_shake,
-                                      &k, &ksz, &f, &fsz, &p, &psz)
-       : !PyArg_ParseTupleAndKeywords(arg, kw, "s#|s#:new",
+                                      convbin, &k,
+                                      convbin, &f, convbin, &p)
+       : !PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&:new",
                                       (/*unconst*/ char **)kwlist_func,
-                                      &k, &ksz, &p, &psz))
+                                      convbin, &k, convbin, &p))
     goto end;
-  if (keysz(ksz, info->keysz) != ksz) VALERR("bad key length");
+  if (keysz(k.sz, info->keysz) != k.sz) VALERR("bad key length");
   return (grand_dopywrap(ty,
                         (info->f&RNGF_MASK) == RNG_SHAKE
-                          ? ((gcshakerand_func *)info->func)(f, fsz,
-                                                             p, psz,
-                                                             k, ksz)
-                          : ((gcshafuncrand_func *)info->func)(p, psz,
-                                                               k, ksz),
+                          ? ((gcshakerand_func *)info->func)(f.p, f.sz,
+                                                             p.p, p.sz,
+                                                             k.p, k.sz)
+                          : ((gcshafuncrand_func *)info->func)(p.p, p.sz,
+                                                               k.p, k.sz),
                         f_freeme));
 end:
   return (0);
@@ -923,51 +920,50 @@ static const PyTypeObject gclatinrand_pytype_skel = {
 
 static PyObject *sslprf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
-  char *k, *s;
-  Py_ssize_t ksz, ssz;
+  struct bin k, s;
   const gchash *hco = &md5, *hci = &sha;
   PyObject *rc = 0;
   static const char *const kwlist[] = { "key", "seed", "ohash", "ihash", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&O&:new", KWLIST,
-                                  &k, &ksz, &s, &ssz,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:new", KWLIST,
+                                  convbin, &k, convbin, &s,
                                   convgchash, &hco, convgchash, &hci))
     goto end;
-  rc = grand_dopywrap(ty, sslprf_rand(hco, hci, k, ksz, s, ssz), f_freeme);
+  rc = grand_dopywrap(ty, sslprf_rand(hco, hci, k.p, k.sz, s.p, s.sz),
+                     f_freeme);
 end:
   return (rc);
 }
 
 static PyObject *tlsdx_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
-  char *k, *s;
-  Py_ssize_t ksz, ssz;
+  struct bin k, s;
   const gcmac *mc = &sha_hmac;
   PyObject *rc = 0;
   static const char *const kwlist[] = { "key", "seed", "mac", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&:new", KWLIST,
-                                  &k, &ksz, &s, &ssz,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&:new", KWLIST,
+                                  convbin, &k, convbin, &s,
                                   convgcmac, &mc))
     goto end;
-  rc = grand_dopywrap(ty, tlsdx_rand(mc, k, ksz, s, ssz), f_freeme);
+  rc = grand_dopywrap(ty, tlsdx_rand(mc, k.p, k.sz, s.p, s.sz), f_freeme);
 end:
   return (rc);
 }
 
 static PyObject *tlsprf_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
-  char *k, *s;
-  Py_ssize_t ksz, ssz;
+  struct bin k, s;
   const gcmac *mcl = &md5_hmac, *mcr = &sha_hmac;
   PyObject *rc = 0;
   static const char *const kwlist[] = { "key", "seed", "lmac", "rmac", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#s#|O&O&:new", KWLIST,
-                                  &k, &ksz, &s, &ssz,
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&O&:new", KWLIST,
+                                  convbin, &k, convbin, &s,
                                   convgcmac, &mcl, convgcmac, &mcr))
     goto end;
-  rc = grand_dopywrap(ty, tlsprf_rand(mcl, mcr, k, ksz, s, ssz), f_freeme);
+  rc = grand_dopywrap(ty, tlsprf_rand(mcl, mcr, k.p, k.sz, s.p, s.sz),
+                     f_freeme);
 end:
   return (rc);
 }
@@ -1123,14 +1119,13 @@ static const PyTypeObject tlsprf_pytype_skel = {
 
 static PyObject *dsarand_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
 {
-  char *p;
-  Py_ssize_t sz;
+  struct bin in;
   PyObject *rc = 0;
   static const char *const kwlist[] = { "seed", 0 };
 
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "s#:new", KWLIST, &p, &sz))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&:new", KWLIST, convbin, &in))
     goto end;
-  rc = grand_dopywrap(ty, dsarand_create(p, sz), f_freeme);
+  rc = grand_dopywrap(ty, dsarand_create(in.p, in.sz), f_freeme);
 end:
   return (rc);
 }
diff --git a/share.c b/share.c
index 3248f78..eadaa48 100644 (file)
--- a/share.c
+++ b/share.c
@@ -112,19 +112,19 @@ static const PyTypeObject gfshare_pytype_skel = {
 static PyObject *gfsharesplit_pynew(PyTypeObject *ty,
                                    PyObject *arg, PyObject *kw)
 {
-  char *p;
-  Py_ssize_t n;
+  struct bin in;
   unsigned t;
   grand *r = &rand_global;
   gfshare_pyobj *s;
   static const char *const kwlist[] = { "threshold", "secret", "rng", 0 };
-  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&s#|O&:new", KWLIST,
-                                  convuint, &t, &p, &n, convgrand, &r))
+  if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&|O&:new", KWLIST,
+                                  convuint, &t, convbin, &in,
+                                  convgrand, &r))
     goto end;
   if (!t || t > 255) VALERR("threshold must be nonzero and < 256");
   s = (gfshare_pyobj *)ty->tp_alloc(ty, 0);
-  gfshare_create(&s->s, t, n);
-  gfshare_mkshares(&s->s, r, p);
+  gfshare_create(&s->s, t, in.sz);
+  gfshare_mkshares(&s->s, r, in.p);
   return ((PyObject *)s);
 end:
   return (0);
@@ -228,14 +228,14 @@ end:
 static PyObject *gfsmeth_add(PyObject *me, PyObject *arg)
 {
   unsigned i;
-  char *p;
-  Py_ssize_t n;
-  if (!PyArg_ParseTuple(arg, "O&s#:add", convuint, &i, &p, &n)) goto end;
+  struct bin s;
+  if (!PyArg_ParseTuple(arg, "O&O&:add", convuint, &i, convbin, &s))
+    goto end;
   if (i > 254) VALERR("index must be < 255");
-  if (n != GFSHARE_S(me)->sz) VALERR("bad share size");
+  if (s.sz != GFSHARE_S(me)->sz) VALERR("bad share size");
   if (gfshare_addedp(GFSHARE_S(me), i)) VALERR("this share already added");
   if (GFSHARE_S(me)->i >= GFSHARE_S(me)->t) VALERR("enough shares already");
-  gfshare_add(GFSHARE_S(me), i, p);
+  gfshare_add(GFSHARE_S(me), i, s.p);
   return (PyInt_FromLong(GFSHARE_S(me)->t - GFSHARE_S(me)->i));
 end:
   return (0);
index 096e35b..21a83d8 100644 (file)
@@ -243,6 +243,7 @@ class TestWriteBuffer (U.TestCase):
     buf.zero(17)
     buf.put(T.span(23))
     me.assertEqual(buf.size, 40)
+    me.assertEqual(buf, C.ByteString.zero(17) + T.span(23))
     me.assertEqual(buf.contents, C.ByteString.zero(17) + T.span(23))
 
 ###----- That's all, folks --------------------------------------------------