[pycrypto] ERROR: testRsaUnversionedSignAndVerify failed
Dwayne C. Litzenberger
dlitz at dlitz.net
Thu Aug 20 20:55:05 CST 2009
On Thu, Aug 20, 2009 at 11:11:46AM +0200, Hans-Peter Jansen wrote:
> openSUSE incorporated two patches to 2.0.1:
>
> This one, I ported to trunk:
> --- src/hash_template.c~ 2009-08-16 23:39:34.053841534 +0200
> +++ src/hash_template.c 2009-08-20 10:16:05.877840748 +0200
> @@ -111,13 +111,15 @@ ALG_hexdigest(ALGobject *self, PyObject
> PyObject *value, *retval;
> unsigned char *raw_digest, *hex_digest;
> int i, j, size;
> + Py_ssize_t ssize;
>
> if (!PyArg_ParseTuple(args, ""))
> return NULL;
>
> /* Get the raw (binary) digest value */
> value = (PyObject *)hash_digest(&(self->st));
> - size = PyString_Size(value);
> + ssize = PyString_Size(value);
> + size = (ssize > INT_MAX) ? INT_MAX : ssize;
> raw_digest = (unsigned char *) PyString_AsString(value);
>
> /* Create a new string */
>
> Dwayne, is this in order or just plain silly?
Hmm... What's the purpose of this patch?
I'm assuming this patch is for 64-bit machines, but even with the patch
applied, you will still have other problems if ssize > INT_MAX (or even
INT_MAX/2).
Here's the code (with that patch applied) in context:
/* Get the raw (binary) digest value */
value = (PyObject *)hash_digest(&(self->st));
ssize = PyString_Size(value);
size = (ssize > INT_MAX) ? INT_MAX : ssize;
raw_digest = (unsigned char *) PyString_AsString(value);
/* Create a new string */
retval = PyString_FromStringAndSize(NULL, size * 2 );
hex_digest = (unsigned char *) PyString_AsString(retval);
/* Make hex version of the digest */
for(i=j=0; i<size; i++)
{
char c;
c = raw_digest[i] / 16; c = (c>9) ? c+'a'-10 : c + '0';
hex_digest[j++] = c;
c = raw_digest[i] % 16; c = (c>9) ? c+'a'-10 : c + '0';
hex_digest[j++] = c;
}
Py_DECREF(value);
return retval;
If ssize > INT_MAX, then the "size * 2" argument passed to
PyString_FromStringAndSize() will overflow, causing one of the following
things to happen:
- If size*2 overflows to a negative number, PyString_FromStringAndSize will
presumably return NULL, causing a null-pointer dereference in the
subsequent code.
- If size*2 overflows to a positive number, PyString_FromStringAndSize will
allocate a smaller buffer than we expect, and the subsequent loop wil
overflow this buffer. Even if we fixed that, if size ended up larger
than INT_MAX/2, we would *still* overflow the buffer, since j would wrap
around to a negative number.
None of PyCrypto's hash functions return anything close to INT_MAX bytes
(SHA256 outputs a whopping 32 bytes), so I wonder about the rationale
behind this patch. Does it suppress some lint warning?
/me runs splint against the code
No, I doubt it's that. The C code isn't even close to being lint-clean.
/my adds a TODO item...
Thanks,
- Dwayne
--
Dwayne C. Litzenberger <dlitz at dlitz.net>
Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7
More information about the pycrypto
mailing list