Back to index

python3.2  3.2.2
Classes | Defines | Typedefs | Functions | Variables
_hashopenssl.c File Reference
#include "Python.h"
#include "structmember.h"
#include "hashlib.h"
#include <openssl/evp.h>
#include <openssl/objects.h>

Go to the source code of this file.

Classes

struct  EVPobject
struct  _internal_name_mapper_state

Defines

#define PY_SSIZE_T_CLEAN
#define ENTER_HASHLIB(obj)
#define LEAVE_HASHLIB(obj)
#define MUNCH_SIZE   INT_MAX
#define HASHLIB_GIL_MINSIZE   2048
#define HASH_OBJ_CONSTRUCTOR   0
#define DEFINE_CONSTS_FOR_NEW(Name)
#define GEN_CONSTRUCTOR(NAME)
#define CONSTRUCTOR_METH_DEF(NAME)
#define INIT_CONSTRUCTOR_CONSTANTS(NAME)

Typedefs

typedef struct
_internal_name_mapper_state 
_InternalNameMapperState

Functions

static EVPobjectnewEVPobject (PyObject *name)
static void EVP_hash (EVPobject *self, const void *vp, Py_ssize_t len)
static void EVP_dealloc (EVPobject *self)
static void locked_EVP_MD_CTX_copy (EVP_MD_CTX *new_ctx_p, EVPobject *self)
 PyDoc_STRVAR (EVP_copy__doc__,"Return a copy of the hash object.")
static PyObjectEVP_copy (EVPobject *self, PyObject *unused)
 PyDoc_STRVAR (EVP_digest__doc__,"Return the digest value as a string of binary data.")
static PyObjectEVP_digest (EVPobject *self, PyObject *unused)
 PyDoc_STRVAR (EVP_hexdigest__doc__,"Return the digest value as a string of hexadecimal digits.")
static PyObjectEVP_hexdigest (EVPobject *self, PyObject *unused)
 PyDoc_STRVAR (EVP_update__doc__,"Update this hash object's state with the provided string.")
static PyObjectEVP_update (EVPobject *self, PyObject *args)
static PyObjectEVP_get_block_size (EVPobject *self, void *closure)
static PyObjectEVP_get_digest_size (EVPobject *self, void *closure)
static PyObjectEVP_repr (EVPobject *self)
 PyDoc_STRVAR (hashtype_doc,"A hash represents the object used to calculate a checksum of a\n\ string of information.\n\ \n\ Methods:\n\ \n\ update() -- updates the current digest with an additional string\n\ digest() -- return the current digest value\n\ hexdigest() -- return the current digest as a string of hexadecimal digits\n\ copy() -- return a copy of the current hash object\n\ \n\ Attributes:\n\ \n\ name -- the hash algorithm being used by this object\n\ digest_size -- number of bytes in this hashes output\n")
static PyObjectEVPnew (PyObject *name_obj, const EVP_MD *digest, const EVP_MD_CTX *initial_ctx, const unsigned char *cp, Py_ssize_t len)
 PyDoc_STRVAR (EVP_new__doc__,"Return a new hash object using the named algorithm.\n\ An optional string argument may be provided and will be\n\ automatically hashed.\n\ \n\ The MD5 and SHA1 algorithms are always supported.\n")
static PyObjectEVP_new (PyObject *self, PyObject *args, PyObject *kwdict)
static void _openssl_hash_name_mapper (const OBJ_NAME *openssl_obj_name, void *arg)
static PyObjectgenerate_hash_name_list (void)
PyMODINIT_FUNC PyInit__hashlib (void)

Variables

static PyTypeObject EVPtype
static PyMethodDef EVP_methods []
static PyMemberDef EVP_members []
static PyGetSetDef EVP_getseters []
static struct PyMethodDef []
static struct PyModuleDef

Class Documentation

struct EVPobject

Definition at line 59 of file _hashopenssl.c.

Collaboration diagram for EVPobject:
Class Members
EVP_MD_CTX ctx
PyObject_HEAD PyObject * name
struct _internal_name_mapper_state

Definition at line 495 of file _hashopenssl.c.

Collaboration diagram for _internal_name_mapper_state:
Class Members
int error
PyObject * set

Define Documentation

#define CONSTRUCTOR_METH_DEF (   NAME)
Value:
{"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
        PyDoc_STR("Returns a " #NAME \
                  " hash object; optionally initialized with a string") \
    }

Definition at line 584 of file _hashopenssl.c.

#define DEFINE_CONSTS_FOR_NEW (   Name)
Value:
static PyObject *CONST_ ## Name ## _name_obj; \
    static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
    static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;

Definition at line 72 of file _hashopenssl.c.

#define ENTER_HASHLIB (   obj)

Definition at line 35 of file _hashopenssl.c.

#define GEN_CONSTRUCTOR (   NAME)
Value:
static PyObject * \
    EVP_new_ ## NAME (PyObject *self, PyObject *args) \
    { \
        PyObject *data_obj = NULL; \
        Py_buffer view = { 0 }; \
        PyObject *ret_obj; \
     \
        if (!PyArg_ParseTuple(args, "|O:" #NAME , &data_obj)) { \
            return NULL; \
        } \
     \
        if (data_obj) \
            GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); \
     \
        ret_obj = EVPnew( \
                    CONST_ ## NAME ## _name_obj, \
                    NULL, \
                    CONST_new_ ## NAME ## _ctx_p, \
                    (unsigned char*)view.buf, \
                    view.len); \
     \
        if (data_obj) \
            PyBuffer_Release(&view); \
        return ret_obj; \
    }

Definition at line 556 of file _hashopenssl.c.

#define HASH_OBJ_CONSTRUCTOR   0

Definition at line 51 of file _hashopenssl.c.

#define HASHLIB_GIL_MINSIZE   2048

Definition at line 48 of file _hashopenssl.c.

Value:
do { \
    CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \
    if (EVP_get_digestbyname(#NAME)) { \
        CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \
        EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
    } \
} while (0);

Definition at line 591 of file _hashopenssl.c.

#define LEAVE_HASHLIB (   obj)

Definition at line 36 of file _hashopenssl.c.

#define MUNCH_SIZE   INT_MAX

Definition at line 44 of file _hashopenssl.c.

Definition at line 14 of file _hashopenssl.c.


Typedef Documentation


Function Documentation

static void _openssl_hash_name_mapper ( const OBJ_NAME *  openssl_obj_name,
void arg 
) [static]

Definition at line 503 of file _hashopenssl.c.

{
    _InternalNameMapperState *state = (_InternalNameMapperState *)arg;
    PyObject *py_name;

    assert(state != NULL);
    if (openssl_obj_name == NULL)
        return;
    /* Ignore aliased names, they pollute the list and OpenSSL appears to
     * have a its own definition of alias as the resulting list still
     * contains duplicate and alternate names for several algorithms.     */
    if (openssl_obj_name->alias)
        return;

    py_name = PyUnicode_FromString(openssl_obj_name->name);
    if (py_name == NULL) {
        state->error = 1;
    } else {
        if (PySet_Add(state->set, py_name) != 0) {
            Py_DECREF(py_name);
            state->error = 1;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PyObject* EVP_copy ( EVPobject self,
PyObject unused 
) [static]

Definition at line 147 of file _hashopenssl.c.

{
    EVPobject *newobj;

    if ( (newobj = newEVPobject(self->name))==NULL)
        return NULL;

    locked_EVP_MD_CTX_copy(&newobj->ctx, self);
    return (PyObject *)newobj;
}

Here is the call graph for this function:

static void EVP_dealloc ( EVPobject self) [static]

Definition at line 123 of file _hashopenssl.c.

{
#ifdef WITH_THREAD
    if (self->lock != NULL)
        PyThread_free_lock(self->lock);
#endif
    EVP_MD_CTX_cleanup(&self->ctx);
    Py_XDECREF(self->name);
    PyObject_Del(self);
}

Here is the call graph for this function:

static PyObject* EVP_digest ( EVPobject self,
PyObject unused 
) [static]

Definition at line 162 of file _hashopenssl.c.

{
    unsigned char digest[EVP_MAX_MD_SIZE];
    EVP_MD_CTX temp_ctx;
    PyObject *retval;
    unsigned int digest_size;

    locked_EVP_MD_CTX_copy(&temp_ctx, self);
    digest_size = EVP_MD_CTX_size(&temp_ctx);
    EVP_DigestFinal(&temp_ctx, digest, NULL);

    retval = PyBytes_FromStringAndSize((const char *)digest, digest_size);
    EVP_MD_CTX_cleanup(&temp_ctx);
    return retval;
}

Here is the call graph for this function:

static PyObject* EVP_get_block_size ( EVPobject self,
void closure 
) [static]

Definition at line 263 of file _hashopenssl.c.

{
    long block_size;
    block_size = EVP_MD_CTX_block_size(&self->ctx);
    return PyLong_FromLong(block_size);
}

Here is the call graph for this function:

static PyObject* EVP_get_digest_size ( EVPobject self,
void closure 
) [static]

Definition at line 271 of file _hashopenssl.c.

{
    long size;
    size = EVP_MD_CTX_size(&self->ctx);
    return PyLong_FromLong(size);
}

Here is the call graph for this function:

static void EVP_hash ( EVPobject self,
const void vp,
Py_ssize_t  len 
) [static]

Definition at line 105 of file _hashopenssl.c.

{
    unsigned int process;
    const unsigned char *cp = (const unsigned char *)vp;
    while (0 < len) {
        if (len > (Py_ssize_t)MUNCH_SIZE)
            process = MUNCH_SIZE;
        else
            process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int);
        EVP_DigestUpdate(&self->ctx, (const void*)cp, process);
        len -= process;
        cp += process;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PyObject* EVP_hexdigest ( EVPobject self,
PyObject unused 
) [static]

Definition at line 182 of file _hashopenssl.c.

{
    unsigned char digest[EVP_MAX_MD_SIZE];
    EVP_MD_CTX temp_ctx;
    PyObject *retval;
    char *hex_digest;
    unsigned int i, j, digest_size;

    /* Get the raw (binary) digest value */
    locked_EVP_MD_CTX_copy(&temp_ctx, self);
    digest_size = EVP_MD_CTX_size(&temp_ctx);
    EVP_DigestFinal(&temp_ctx, digest, NULL);

    EVP_MD_CTX_cleanup(&temp_ctx);

    /* Allocate a new buffer */
    hex_digest = PyMem_Malloc(digest_size * 2 + 1);
    if (!hex_digest)
        return PyErr_NoMemory();

    /* Make hex version of the digest */
    for(i=j=0; i<digest_size; i++) {
        char c;
        c = (digest[i] >> 4) & 0xf;
        c = (c>9) ? c+'a'-10 : c + '0';
        hex_digest[j++] = c;
        c = (digest[i] & 0xf);
        c = (c>9) ? c+'a'-10 : c + '0';
        hex_digest[j++] = c;
    }
    retval = PyUnicode_FromStringAndSize(hex_digest, digest_size * 2);
    PyMem_Free(hex_digest);
    return retval;
}

Here is the call graph for this function:

static PyObject* EVP_new ( PyObject self,
PyObject args,
PyObject kwdict 
) [static]

Definition at line 461 of file _hashopenssl.c.

{
    static char *kwlist[] = {"name", "string", NULL};
    PyObject *name_obj = NULL;
    PyObject *data_obj = NULL;
    Py_buffer view = { 0 };
    PyObject *ret_obj;
    char *name;
    const EVP_MD *digest;

    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|O:new", kwlist,
                                     &name_obj, &data_obj)) {
        return NULL;
    }

    if (!PyArg_Parse(name_obj, "s", &name)) {
        PyErr_SetString(PyExc_TypeError, "name must be a string");
        return NULL;
    }

    if (data_obj)
        GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view);

    digest = EVP_get_digestbyname(name);

    ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf, view.len);

    if (data_obj)
        PyBuffer_Release(&view);
    return ret_obj;
}

Here is the call graph for this function:

static PyObject* EVP_repr ( EVPobject self) [static]

Definition at line 297 of file _hashopenssl.c.

{
    return PyUnicode_FromFormat("<%U HASH object @ %p>", self->name, self);
}
static PyObject* EVP_update ( EVPobject self,
PyObject args 
) [static]

Definition at line 221 of file _hashopenssl.c.

{
    PyObject *obj;
    Py_buffer view;

    if (!PyArg_ParseTuple(args, "O:update", &obj))
        return NULL;

    GET_BUFFER_VIEW_OR_ERROUT(obj, &view);

#ifdef WITH_THREAD
    if (self->lock == NULL && view.len >= HASHLIB_GIL_MINSIZE) {
        self->lock = PyThread_allocate_lock();
        /* fail? lock = NULL and we fail over to non-threaded code. */
    }

    if (self->lock != NULL) {
        Py_BEGIN_ALLOW_THREADS
        PyThread_acquire_lock(self->lock, 1);
        EVP_hash(self, view.buf, view.len);
        PyThread_release_lock(self->lock);
        Py_END_ALLOW_THREADS
    } else {
        EVP_hash(self, view.buf, view.len);
    }
#else
    EVP_hash(self, view.buf, view.len);
#endif

    PyBuffer_Release(&view);
    Py_RETURN_NONE;
}

Here is the call graph for this function:

static PyObject* EVPnew ( PyObject name_obj,
const EVP_MD *  digest,
const EVP_MD_CTX *  initial_ctx,
const unsigned char *  cp,
Py_ssize_t  len 
) [static]

Definition at line 417 of file _hashopenssl.c.

{
    EVPobject *self;

    if (!digest && !initial_ctx) {
        PyErr_SetString(PyExc_ValueError, "unsupported hash type");
        return NULL;
    }

    if ((self = newEVPobject(name_obj)) == NULL)
        return NULL;

    if (initial_ctx) {
        EVP_MD_CTX_copy(&self->ctx, initial_ctx);
    } else {
        EVP_DigestInit(&self->ctx, digest);
    }

    if (cp && len) {
        if (len >= HASHLIB_GIL_MINSIZE) {
            Py_BEGIN_ALLOW_THREADS
            EVP_hash(self, cp, len);
            Py_END_ALLOW_THREADS
        } else {
            EVP_hash(self, cp, len);
        }
    }

    return (PyObject *)self;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PyObject* generate_hash_name_list ( void  ) [static]

Definition at line 531 of file _hashopenssl.c.

{
    _InternalNameMapperState state;
    state.set = PyFrozenSet_New(NULL);
    if (state.set == NULL)
        return NULL;
    state.error = 0;

    OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, &_openssl_hash_name_mapper, &state);

    if (state.error) {
        Py_DECREF(state.set);
        return NULL;
    }
    return state.set;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void locked_EVP_MD_CTX_copy ( EVP_MD_CTX *  new_ctx_p,
EVPobject self 
) [static]

Definition at line 134 of file _hashopenssl.c.

{
    ENTER_HASHLIB(self);
    EVP_MD_CTX_copy(new_ctx_p, &self->ctx);
    LEAVE_HASHLIB(self);
}

Here is the caller graph for this function:

static EVPobject* newEVPobject ( PyObject name) [static]

Definition at line 88 of file _hashopenssl.c.

{
    EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype);

    /* save the name for .name to return */
    if (retval != NULL) {
        Py_INCREF(name);
        retval->name = name;
#ifdef WITH_THREAD
        retval->lock = NULL;
#endif
    }

    return retval;
}

Here is the caller graph for this function:

PyDoc_STRVAR ( EVP_copy__doc__  ,
"Return a copy of the hash object."   
)
PyDoc_STRVAR ( EVP_digest__doc__  ,
"Return the digest value as a string of binary data."   
)
PyDoc_STRVAR ( EVP_hexdigest__doc__  ,
"Return the digest value as a string of hexadecimal digits."   
)
PyDoc_STRVAR ( EVP_update__doc__  ,
"Update this hash object's state with the provided string."   
)
PyDoc_STRVAR ( hashtype_doc  ,
"A hash represents the object used to calculate a checksum of a\n\string of information.\n\\n\Methods:\n\\n\update() -- updates the current digest with an additional string\n\digest() -- return the current digest value\n\hexdigest() -- return the current digest as a string of hexadecimal digits\n\copy() -- return a copy of the current hash object\n\\n\Attributes:\n\\n\name -- the hash algorithm being used by this object\n\digest_size -- number of bytes in this hashes output\n  
)
PyDoc_STRVAR ( EVP_new__doc__  ,
"Return a new hash object using the named algorithm.\n\An optional string argument may be provided and will be\n\automatically hashed.\n\\n\The MD5 and SHA1 algorithms are always supported.\n  
)

Definition at line 640 of file _hashopenssl.c.

{
    PyObject *m, *openssl_md_meth_names;

    OpenSSL_add_all_digests();

    /* TODO build EVP_functions openssl_* entries dynamically based
     * on what hashes are supported rather than listing many
     * but having some be unsupported.  Only init appropriate
     * constants. */

    Py_TYPE(&EVPtype) = &PyType_Type;
    if (PyType_Ready(&EVPtype) < 0)
        return NULL;

    m = PyModule_Create(&_hashlibmodule);
    if (m == NULL)
        return NULL;

    openssl_md_meth_names = generate_hash_name_list();
    if (openssl_md_meth_names == NULL) {
        Py_DECREF(m);
        return NULL;
    }
    if (PyModule_AddObject(m, "openssl_md_meth_names", openssl_md_meth_names)) {
        Py_DECREF(m);
        return NULL;
    }

#if HASH_OBJ_CONSTRUCTOR
    Py_INCREF(&EVPtype);
    PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
#endif

    /* these constants are used by the convenience constructors */
    INIT_CONSTRUCTOR_CONSTANTS(md5);
    INIT_CONSTRUCTOR_CONSTANTS(sha1);
#ifdef _OPENSSL_SUPPORTS_SHA2
    INIT_CONSTRUCTOR_CONSTANTS(sha224);
    INIT_CONSTRUCTOR_CONSTANTS(sha256);
    INIT_CONSTRUCTOR_CONSTANTS(sha384);
    INIT_CONSTRUCTOR_CONSTANTS(sha512);
#endif
    return m;
}

Here is the call graph for this function:


Variable Documentation

Initial value:
 {
    {"digest_size",
     (getter)EVP_get_digest_size, NULL,
     NULL,
     NULL},
    {"block_size",
     (getter)EVP_get_block_size, NULL,
     NULL,
     NULL},
    {NULL}  
}

Definition at line 283 of file _hashopenssl.c.

Initial value:
 {
    {"name", T_OBJECT, offsetof(EVPobject, name), READONLY, PyDoc_STR("algorithm name.")},
    {NULL}  
}

Definition at line 278 of file _hashopenssl.c.

Initial value:
 {
    {"update",    (PyCFunction)EVP_update,    METH_VARARGS, EVP_update__doc__},
    {"digest",    (PyCFunction)EVP_digest,    METH_NOARGS,  EVP_digest__doc__},
    {"hexdigest", (PyCFunction)EVP_hexdigest, METH_NOARGS,  EVP_hexdigest__doc__},
    {"copy",      (PyCFunction)EVP_copy,      METH_NOARGS,  EVP_copy__doc__},
    {NULL, NULL}  
}

Definition at line 254 of file _hashopenssl.c.

static PyTypeObject EVPtype [static]

Definition at line 69 of file _hashopenssl.c.

struct PyMethodDef[] [static]
Initial value:

Definition at line 610 of file _hashopenssl.c.

struct PyModuleDef [static]
Initial value:
 {
    PyModuleDef_HEAD_INIT,
    "_hashlib",
    NULL,
    -1,
    EVP_functions,
    NULL,
    NULL,
    NULL,
    NULL
}

Definition at line 627 of file _hashopenssl.c.