11/* Module that wraps all OpenSSL hash algorithms */
22
33/*
4- * Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com )
4+ * Copyright (C) 2005-2007 Gregory P. Smith (greg@krypto.org )
55 * Licensed to PSF under a Contributor Agreement.
66 *
77 * Derived from a skeleton of shamodule.c containing work performed by:
@@ -28,6 +28,11 @@ typedef struct {
2828 PyObject_HEAD
2929 PyObject * name ; /* name of this hash algorithm */
3030 EVP_MD_CTX ctx ; /* OpenSSL message digest context */
31+ /*
32+ * TODO investigate performance impact of including a lock for this object
33+ * here and releasing the Python GIL while hash updates are in progress.
34+ * (perhaps only release GIL if input length will take long to process?)
35+ */
3136} EVPobject ;
3237
3338
@@ -147,20 +152,41 @@ EVP_hexdigest(EVPobject *self, PyObject *unused)
147152 return retval ;
148153}
149154
155+ #define MY_GET_BUFFER_VIEW_OR_ERROUT (obj , viewp ) do { \
156+ if (!PyObject_CheckBuffer((obj))) { \
157+ PyErr_SetString(PyExc_TypeError, \
158+ "object supporting the buffer API required"); \
159+ return NULL; \
160+ } \
161+ if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \
162+ return NULL; \
163+ } \
164+ if ((viewp)->ndim > 1) { \
165+ PyErr_SetString(PyExc_BufferError, \
166+ "Buffer must be single dimension"); \
167+ PyObject_ReleaseBuffer((obj), (viewp)); \
168+ return NULL; \
169+ } \
170+ } while(0);
171+
150172PyDoc_STRVAR (EVP_update__doc__ ,
151173"Update this hash object's state with the provided string." );
152174
153175static PyObject *
154176EVP_update (EVPobject * self , PyObject * args )
155177{
156- unsigned char * cp ;
157- Py_ssize_t len ;
178+ PyObject * obj ;
179+ PyBuffer view ;
158180
159- if (!PyArg_ParseTuple (args , "s# :update" , & cp , & len ))
181+ if (!PyArg_ParseTuple (args , "O :update" , & obj ))
160182 return NULL ;
161183
162- EVP_DigestUpdate (& self -> ctx , cp , Py_SAFE_DOWNCAST (len , Py_ssize_t ,
163- unsigned int ));
184+ MY_GET_BUFFER_VIEW_OR_ERROUT (obj , & view );
185+
186+ EVP_DigestUpdate (& self -> ctx , (unsigned char * )view .buf ,
187+ Py_SAFE_DOWNCAST (view .len , Py_ssize_t , unsigned int ));
188+
189+ PyObject_ReleaseBuffer (obj , & view );
164190
165191 Py_INCREF (Py_None );
166192 return Py_None ;
@@ -225,34 +251,43 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
225251{
226252 static char * kwlist [] = {"name" , "string" , NULL };
227253 PyObject * name_obj = NULL ;
254+ PyObject * data_obj = NULL ;
255+ PyBuffer view ;
228256 char * nameStr ;
229- unsigned char * cp = NULL ;
230- Py_ssize_t len = 0 ;
231257 const EVP_MD * digest ;
232258
233- if (!PyArg_ParseTupleAndKeywords (args , kwds , "O|s# :HASH" , kwlist ,
234- & name_obj , & cp , & len )) {
259+ if (!PyArg_ParseTupleAndKeywords (args , kwds , "O|O :HASH" , kwlist ,
260+ & name_obj , & data_obj )) {
235261 return -1 ;
236262 }
237263
264+ if (data_obj )
265+ MY_GET_BUFFER_VIEW_OR_ERROUT (data_obj , & view );
266+
238267 if (!PyArg_Parse (name_obj , "s" , & nameStr )) {
239268 PyErr_SetString (PyExc_TypeError , "name must be a string" );
269+ if (data_obj )
270+ PyObject_ReleaseBuffer (data_obj , & view );
240271 return -1 ;
241272 }
242273
243274 digest = EVP_get_digestbyname (nameStr );
244275 if (!digest ) {
245276 PyErr_SetString (PyExc_ValueError , "unknown hash function" );
277+ if (data_obj )
278+ PyObject_ReleaseBuffer (data_obj , & view );
246279 return -1 ;
247280 }
248281 EVP_DigestInit (& self -> ctx , digest );
249282
250283 self -> name = name_obj ;
251284 Py_INCREF (self -> name );
252285
253- if (cp && len )
254- EVP_DigestUpdate (& self -> ctx , cp , Py_SAFE_DOWNCAST (len , Py_ssize_t ,
255- unsigned int ));
286+ if (data_obj ) {
287+ EVP_DigestUpdate (& self -> ctx , (unsigned char * )view .buf ,
288+ Py_SAFE_DOWNCAST (view .len , Py_ssize_t , unsigned int ));
289+ PyObject_ReleaseBuffer (data_obj , & view );
290+ }
256291
257292 return 0 ;
258293}
@@ -361,13 +396,14 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
361396{
362397 static char * kwlist [] = {"name" , "string" , NULL };
363398 PyObject * name_obj = NULL ;
399+ PyObject * data_obj = NULL ;
400+ PyBuffer view = { 0 };
401+ PyObject * ret_obj ;
364402 char * name ;
365403 const EVP_MD * digest ;
366- unsigned char * cp = NULL ;
367- Py_ssize_t len = 0 ;
368404
369- if (!PyArg_ParseTupleAndKeywords (args , kwdict , "O|s# :new" , kwlist ,
370- & name_obj , & cp , & len )) {
405+ if (!PyArg_ParseTupleAndKeywords (args , kwdict , "O|O :new" , kwlist ,
406+ & name_obj , & data_obj )) {
371407 return NULL ;
372408 }
373409
@@ -376,10 +412,17 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
376412 return NULL ;
377413 }
378414
415+ if (data_obj )
416+ MY_GET_BUFFER_VIEW_OR_ERROUT (data_obj , & view );
417+
379418 digest = EVP_get_digestbyname (name );
380419
381- return EVPnew (name_obj , digest , NULL , cp , Py_SAFE_DOWNCAST (len , Py_ssize_t ,
382- unsigned int ));
420+ ret_obj = EVPnew (name_obj , digest , NULL , (unsigned char * )view .buf ,
421+ Py_SAFE_DOWNCAST (view .len , Py_ssize_t , unsigned int ));
422+
423+ if (data_obj )
424+ PyObject_ReleaseBuffer (data_obj , & view );
425+ return ret_obj ;
383426}
384427
385428/*
@@ -393,18 +436,27 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
393436 static PyObject * \
394437 EVP_new_ ## NAME (PyObject *self, PyObject *args) \
395438 { \
396- unsigned char *cp = NULL; \
397- Py_ssize_t len = 0; \
439+ PyObject *data_obj = NULL; \
440+ PyBuffer view = { 0 }; \
441+ PyObject *ret_obj; \
398442 \
399- if (!PyArg_ParseTuple(args, "|s# :" #NAME , &cp, &len )) { \
443+ if (!PyArg_ParseTuple(args, "|O :" #NAME , &data_obj )) { \
400444 return NULL; \
401445 } \
402446 \
403- return EVPnew( \
404- CONST_ ## NAME ## _name_obj, \
405- NULL, \
406- CONST_new_ ## NAME ## _ctx_p, \
407- cp, Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int)); \
447+ if (data_obj) \
448+ MY_GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); \
449+ \
450+ ret_obj = EVPnew( \
451+ CONST_ ## NAME ## _name_obj, \
452+ NULL, \
453+ CONST_new_ ## NAME ## _ctx_p, \
454+ (unsigned char*)view.buf, \
455+ Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); \
456+ \
457+ if (data_obj) \
458+ PyObject_ReleaseBuffer(data_obj, &view); \
459+ return ret_obj; \
408460 }
409461
410462/* a PyMethodDef structure for the constructor */
0 commit comments