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