blob: bfa180cf12fd58dd5cc2486957fa514e5c50853c [file] [log] [blame]
Gregory P. Smithf21a5f72005-08-21 18:45:59 +00001/* Module that wraps all OpenSSL hash algorithms */
2
3/*
4 * Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
5 * Licensed to PSF under a Contributor Agreement.
6 *
7 * Derived from a skeleton of shamodule.c containing work performed by:
8 *
9 * Andrew Kuchling (amk@amk.ca)
10 * Greg Stein (gstein@lyra.org)
11 *
12 */
13
14#include "Python.h"
15#include "structmember.h"
16
17/* EVP is the preferred interface to hashing in OpenSSL */
18#include <openssl/evp.h>
19
20
21typedef struct {
22 PyObject_HEAD
23 PyObject *name; /* name of this hash algorithm */
24 EVP_MD_CTX ctx; /* OpenSSL message digest context */
25} EVPobject;
26
27
28static PyTypeObject EVPtype;
29
30
31#define DEFINE_CONSTS_FOR_NEW(Name) \
32 static PyObject *CONST_ ## Name ## _name_obj; \
33 static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
34 static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
35
36DEFINE_CONSTS_FOR_NEW(md5);
37DEFINE_CONSTS_FOR_NEW(sha1);
38DEFINE_CONSTS_FOR_NEW(sha224);
39DEFINE_CONSTS_FOR_NEW(sha256);
40DEFINE_CONSTS_FOR_NEW(sha384);
41DEFINE_CONSTS_FOR_NEW(sha512);
42
43
44static EVPobject *
45newEVPobject(PyObject *name)
46{
47 EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype);
48
49 /* save the name for .name to return */
50 if (retval != NULL) {
51 Py_INCREF(name);
52 retval->name = name;
53 }
54
55 return retval;
56}
57
58/* Internal methods for a hash object */
59
60static void
61EVP_dealloc(PyObject *ptr)
62{
63 EVP_MD_CTX_cleanup(&((EVPobject *)ptr)->ctx);
64 Py_XDECREF(((EVPobject *)ptr)->name);
65 PyObject_Del(ptr);
66}
67
68
69/* External methods for a hash object */
70
71PyDoc_STRVAR(EVP_copy__doc__, "Return a copy of the hash object.");
72
73static PyObject *
74EVP_copy(EVPobject *self, PyObject *args)
75{
76 EVPobject *newobj;
77
78 if (!PyArg_ParseTuple(args, ":copy"))
79 return NULL;
80
81 if ( (newobj = newEVPobject(self->name))==NULL)
82 return NULL;
83
84 EVP_MD_CTX_copy(&newobj->ctx, &self->ctx);
85 return (PyObject *)newobj;
86}
87
88PyDoc_STRVAR(EVP_digest__doc__,
89"Return the digest value as a string of binary data.");
90
91static PyObject *
92EVP_digest(EVPobject *self, PyObject *args)
93{
94 unsigned char digest[EVP_MAX_MD_SIZE];
95 EVP_MD_CTX temp_ctx;
96 PyObject *retval;
97 unsigned int digest_size;
98
99 if (!PyArg_ParseTuple(args, ":digest"))
100 return NULL;
101
102 EVP_MD_CTX_copy(&temp_ctx, &self->ctx);
103 digest_size = EVP_MD_CTX_size(&temp_ctx);
104 EVP_DigestFinal(&temp_ctx, (char *)digest, NULL);
105
106 retval = PyString_FromStringAndSize((const char *)digest, digest_size);
107 EVP_MD_CTX_cleanup(&temp_ctx);
108 return retval;
109}
110
111PyDoc_STRVAR(EVP_hexdigest__doc__,
112"Return the digest value as a string of hexadecimal digits.");
113
114static PyObject *
115EVP_hexdigest(EVPobject *self, PyObject *args)
116{
117 unsigned char digest[EVP_MAX_MD_SIZE];
118 EVP_MD_CTX temp_ctx;
119 PyObject *retval;
120 char *hex_digest;
121 unsigned int i, j, digest_size;
122
123 if (!PyArg_ParseTuple(args, ":hexdigest"))
124 return NULL;
125
126 /* Get the raw (binary) digest value */
127 EVP_MD_CTX_copy(&temp_ctx, &self->ctx);
128 digest_size = EVP_MD_CTX_size(&temp_ctx);
129 EVP_DigestFinal(&temp_ctx, digest, NULL);
130
131 EVP_MD_CTX_cleanup(&temp_ctx);
132
133 /* Create a new string */
134 /* NOTE: not thread safe! modifying an already created string object */
135 /* (not a problem because we hold the GIL by default) */
136 retval = PyString_FromStringAndSize(NULL, digest_size * 2);
137 if (!retval)
138 return NULL;
139 hex_digest = PyString_AsString(retval);
140 if (!hex_digest) {
141 Py_DECREF(retval);
142 return NULL;
143 }
144
145 /* Make hex version of the digest */
146 for(i=j=0; i<digest_size; i++) {
147 char c;
148 c = (digest[i] >> 4) & 0xf;
149 c = (c>9) ? c+'a'-10 : c + '0';
150 hex_digest[j++] = c;
151 c = (digest[i] & 0xf);
152 c = (c>9) ? c+'a'-10 : c + '0';
153 hex_digest[j++] = c;
154 }
155 return retval;
156}
157
158PyDoc_STRVAR(EVP_update__doc__,
159"Update this hash object's state with the provided string.");
160
161static PyObject *
162EVP_update(EVPobject *self, PyObject *args)
163{
164 unsigned char *cp;
165 int len;
166
167 if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
168 return NULL;
169
170 EVP_DigestUpdate(&self->ctx, cp, len);
171
172 Py_INCREF(Py_None);
173 return Py_None;
174}
175
176static PyMethodDef EVP_methods[] = {
177 {"update", (PyCFunction)EVP_update, METH_VARARGS, EVP_update__doc__},
178 {"digest", (PyCFunction)EVP_digest, METH_VARARGS, EVP_digest__doc__},
179 {"hexdigest", (PyCFunction)EVP_hexdigest, METH_VARARGS, EVP_hexdigest__doc__},
180 {"copy", (PyCFunction)EVP_copy, METH_VARARGS, EVP_copy__doc__},
181 {NULL, NULL} /* sentinel */
182};
183
184static PyObject *
185EVP_get_block_size(EVPobject *self, void *closure)
186{
187 return PyInt_FromLong(EVP_MD_CTX_block_size(&((EVPobject *)self)->ctx));
188}
189
190static PyObject *
191EVP_get_digest_size(EVPobject *self, void *closure)
192{
193 return PyInt_FromLong(EVP_MD_CTX_size(&((EVPobject *)self)->ctx));
194}
195
196static PyMemberDef EVP_members[] = {
197 {"name", T_OBJECT, offsetof(EVPobject, name), READONLY, PyDoc_STR("algorithm name.")},
198 {NULL} /* Sentinel */
199};
200
201static PyGetSetDef EVP_getseters[] = {
202 {"digest_size",
203 (getter)EVP_get_digest_size, NULL,
204 NULL,
205 NULL},
206 {"block_size",
207 (getter)EVP_get_block_size, NULL,
208 NULL,
209 NULL},
210 /* the old md5 and sha modules support 'digest_size' as in PEP 247.
211 * the old sha module also supported 'digestsize'. ugh. */
212 {"digestsize",
213 (getter)EVP_get_digest_size, NULL,
214 NULL,
215 NULL},
216 {NULL} /* Sentinel */
217};
218
219
220static PyObject *
221EVP_repr(PyObject *self)
222{
223 char buf[100];
224 PyOS_snprintf(buf, sizeof(buf), "<%s HASH object @ %p>",
225 PyString_AsString(((EVPobject *)self)->name), self);
226 return PyString_FromString(buf);
227}
228
229#if HASH_OBJ_CONSTRUCTOR
230static int
231EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
232{
233 static char *kwlist[] = {"name", "string", NULL};
234 PyObject *name_obj = NULL;
235 char *nameStr;
236 unsigned char *cp = NULL;
237 unsigned int len;
238 const EVP_MD *digest;
239
240 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s#:HASH", kwlist,
241 &name_obj, &cp, &len)) {
242 return -1;
243 }
244
245 if (!PyArg_Parse(name_obj, "s", &nameStr)) {
246 PyErr_SetString(PyExc_TypeError, "name must be a string");
247 return -1;
248 }
249
250 digest = EVP_get_digestbyname(nameStr);
251 if (!digest) {
252 PyErr_SetString(PyExc_ValueError, "unknown hash function");
253 return -1;
254 }
255 EVP_DigestInit(&self->ctx, digest);
256
257 self->name = name_obj;
258 Py_INCREF(self->name);
259
260 if (cp && len)
261 EVP_DigestUpdate(&self->ctx, cp, len);
262
263 return 0;
264}
265#endif
266
267
268PyDoc_STRVAR(hashtype_doc,
269"A hash represents the object used to calculate a checksum of a\n\
270string of information.\n\
271\n\
272Methods:\n\
273\n\
274update() -- updates the current digest with an additional string\n\
275digest() -- return the current digest value\n\
276hexdigest() -- return the current digest as a string of hexadecimal digits\n\
277copy() -- return a copy of the current hash object\n\
278\n\
279Attributes:\n\
280\n\
281name -- the hash algorithm being used by this object\n\
282digest_size -- number of bytes in this hashes output\n");
283
284static PyTypeObject EVPtype = {
285 PyObject_HEAD_INIT(NULL)
286 0, /*ob_size*/
287 "_hashlib.HASH", /*tp_name*/
288 sizeof(EVPobject), /*tp_basicsize*/
289 0, /*tp_itemsize*/
290 /* methods */
291 EVP_dealloc, /*tp_dealloc*/
292 0, /*tp_print*/
293 0, /*tp_getattr*/
294 0, /*tp_setattr*/
295 0, /*tp_compare*/
296 EVP_repr, /*tp_repr*/
297 0, /*tp_as_number*/
298 0, /*tp_as_sequence*/
299 0, /*tp_as_mapping*/
300 0, /*tp_hash*/
301 0, /*tp_call*/
302 0, /*tp_str*/
303 0, /*tp_getattro*/
304 0, /*tp_setattro*/
305 0, /*tp_as_buffer*/
306 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
307 hashtype_doc, /*tp_doc*/
308 0, /*tp_traverse*/
309 0, /*tp_clear*/
310 0, /*tp_richcompare*/
311 0, /*tp_weaklistoffset*/
312 0, /*tp_iter*/
313 0, /*tp_iternext*/
314 EVP_methods, /* tp_methods */
315 EVP_members, /* tp_members */
316 EVP_getseters, /* tp_getset */
317#if 1
318 0, /* tp_base */
319 0, /* tp_dict */
320 0, /* tp_descr_get */
321 0, /* tp_descr_set */
322 0, /* tp_dictoffset */
323#endif
324#if HASH_OBJ_CONSTRUCTOR
325 (initproc)EVP_tp_init, /* tp_init */
326#endif
327};
328
329static PyObject *
330EVPnew(PyObject *name_obj,
331 const EVP_MD *digest, const EVP_MD_CTX *initial_ctx,
332 const char *cp, unsigned int len)
333{
334 EVPobject *self;
335
336 if (!digest && !initial_ctx) {
337 PyErr_SetString(PyExc_ValueError, "unsupported hash type");
338 return NULL;
339 }
340
341 if ((self = newEVPobject(name_obj)) == NULL)
342 return NULL;
343
344 if (initial_ctx) {
345 EVP_MD_CTX_copy(&self->ctx, initial_ctx);
346 } else {
347 EVP_DigestInit(&self->ctx, digest);
348 }
349
350 if (cp && len)
351 EVP_DigestUpdate(&self->ctx, cp, len);
352
353 return (PyObject *)self;
354}
355
356
357/* The module-level function: new() */
358
359PyDoc_STRVAR(EVP_new__doc__,
360"Return a new hash object using the named algorithm.\n\
361An optional string argument may be provided and will be\n\
362automatically hashed.\n\
363\n\
364The MD5 and SHA1 algorithms are always supported.\n");
365
366static PyObject *
367EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
368{
369 static char *kwlist[] = {"name", "string", NULL};
370 PyObject *name_obj = NULL;
371 char *name;
372 const EVP_MD *digest;
373 unsigned char *cp = NULL;
374 unsigned int len;
375
376 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|s#:new", kwlist,
377 &name_obj, &cp, &len)) {
378 return NULL;
379 }
380
381 if (!PyArg_Parse(name_obj, "s", &name)) {
382 PyErr_SetString(PyExc_TypeError, "name must be a string");
383 return NULL;
384 }
385
386 digest = EVP_get_digestbyname(name);
387
388 return EVPnew(name_obj, digest, NULL, cp, len);
389}
390
391/*
392 * This macro generates constructor function definitions for specific
393 * hash algorithms. These constructors are much faster than calling
394 * the generic one passing it a python string and are noticably
395 * faster than calling a python new() wrapper. Thats important for
396 * code that wants to make hashes of a bunch of small strings.
397 */
398#define GEN_CONSTRUCTOR(NAME) \
399 static PyObject * \
400 EVP_new_ ## NAME (PyObject *self, PyObject *args) \
401 { \
402 unsigned char *cp = NULL; \
403 unsigned int len; \
404 \
405 if (!PyArg_ParseTuple(args, "|s#:" #NAME , &cp, &len)) { \
406 return NULL; \
407 } \
408 \
409 return EVPnew( \
410 CONST_ ## NAME ## _name_obj, \
411 NULL, \
412 CONST_new_ ## NAME ## _ctx_p, \
413 cp, len); \
414 }
415
416/* a PyMethodDef structure for the constructor */
417#define CONSTRUCTOR_METH_DEF(NAME) \
418 {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
419 PyDoc_STR("Returns a " #NAME \
420 " hash object; optionally initialized with a string") \
421 }
422
423/* used in the init function to setup a constructor */
424#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
425 CONST_ ## NAME ## _name_obj = PyString_FromString(#NAME); \
426 if (EVP_get_digestbyname(#NAME)) { \
427 CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \
428 EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
429 } \
430} while (0);
431
432GEN_CONSTRUCTOR(md5)
433GEN_CONSTRUCTOR(sha1)
434GEN_CONSTRUCTOR(sha224)
435GEN_CONSTRUCTOR(sha256)
436GEN_CONSTRUCTOR(sha384)
437GEN_CONSTRUCTOR(sha512)
438
439/* List of functions exported by this module */
440
441static struct PyMethodDef EVP_functions[] = {
442 {"new", (PyCFunction)EVP_new, METH_VARARGS|METH_KEYWORDS, EVP_new__doc__},
443 CONSTRUCTOR_METH_DEF(md5),
444 CONSTRUCTOR_METH_DEF(sha1),
445 CONSTRUCTOR_METH_DEF(sha224),
446 CONSTRUCTOR_METH_DEF(sha256),
447 CONSTRUCTOR_METH_DEF(sha384),
448 CONSTRUCTOR_METH_DEF(sha512),
449 {NULL, NULL} /* Sentinel */
450};
451
452
453/* Initialize this module. */
454
455PyMODINIT_FUNC
456init_hashlib(void)
457{
458 PyObject *m;
459
460 OpenSSL_add_all_digests();
461
462 /* TODO build EVP_functions openssl_* entries dynamically based
463 * on what hashes are supported rather than listing many
464 * but having some be unsupported. Only init appropriate
465 * constants. */
466
467 EVPtype.ob_type = &PyType_Type;
468 if (PyType_Ready(&EVPtype) < 0)
469 return;
470
471 m = Py_InitModule("_hashlib", EVP_functions);
472 if (m == NULL)
473 return;
474
475#if HASH_OBJ_CONSTRUCTOR
476 Py_INCREF(&EVPtype);
477 PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
478#endif
479
480 /* these constants are used by the convenience constructors */
481 INIT_CONSTRUCTOR_CONSTANTS(md5);
482 INIT_CONSTRUCTOR_CONSTANTS(sha1);
483 INIT_CONSTRUCTOR_CONSTANTS(sha224);
484 INIT_CONSTRUCTOR_CONSTANTS(sha256);
485 INIT_CONSTRUCTOR_CONSTANTS(sha384);
486 INIT_CONSTRUCTOR_CONSTANTS(sha512);
487}