##// END OF EJS Templates
sha1dc: declare all variables at begininng of block...
Gregory Szorc -
r44541:c3f741bb default
parent child Browse files
Show More
@@ -1,197 +1,198 b''
1 #define PY_SSIZE_T_CLEAN
1 #define PY_SSIZE_T_CLEAN
2 #include <Python.h>
2 #include <Python.h>
3
3
4 #include "lib/sha1.h"
4 #include "lib/sha1.h"
5
5
6 #if PY_MAJOR_VERSION >= 3
6 #if PY_MAJOR_VERSION >= 3
7 #define IS_PY3K
7 #define IS_PY3K
8 #endif
8 #endif
9
9
10 /* helper to switch things like string literal depending on Python version */
10 /* helper to switch things like string literal depending on Python version */
11 #ifdef IS_PY3K
11 #ifdef IS_PY3K
12 #define PY23(py2, py3) py3
12 #define PY23(py2, py3) py3
13 #else
13 #else
14 #define PY23(py2, py3) py2
14 #define PY23(py2, py3) py2
15 #endif
15 #endif
16
16
17 static char sha1dc_doc[] = "Efficient detection of SHA1 collision constructs.";
17 static char sha1dc_doc[] = "Efficient detection of SHA1 collision constructs.";
18
18
19 /* clang-format off */
19 /* clang-format off */
20 typedef struct {
20 typedef struct {
21 PyObject_HEAD
21 PyObject_HEAD
22 SHA1_CTX ctx;
22 SHA1_CTX ctx;
23 } pysha1ctx;
23 } pysha1ctx;
24 /* clang-format on */
24 /* clang-format on */
25
25
26 static int pysha1ctx_init(pysha1ctx *self, PyObject *args)
26 static int pysha1ctx_init(pysha1ctx *self, PyObject *args)
27 {
27 {
28 const char *data = NULL;
28 const char *data = NULL;
29 Py_ssize_t len;
29 Py_ssize_t len;
30
30
31 SHA1DCInit(&(self->ctx));
31 SHA1DCInit(&(self->ctx));
32 /* We don't want "safe" sha1s, wherein sha1dc can give you a
32 /* We don't want "safe" sha1s, wherein sha1dc can give you a
33 different hash for something that's trying to give you a
33 different hash for something that's trying to give you a
34 collision. We just want to detect collisions.
34 collision. We just want to detect collisions.
35 */
35 */
36 SHA1DCSetSafeHash(&(self->ctx), 0);
36 SHA1DCSetSafeHash(&(self->ctx), 0);
37 if (!PyArg_ParseTuple(args, PY23("|s#", "|y#"), &data, &len)) {
37 if (!PyArg_ParseTuple(args, PY23("|s#", "|y#"), &data, &len)) {
38 return -1;
38 return -1;
39 }
39 }
40 if (data) {
40 if (data) {
41 SHA1DCUpdate(&(self->ctx), data, len);
41 SHA1DCUpdate(&(self->ctx), data, len);
42 }
42 }
43 return 0;
43 return 0;
44 }
44 }
45
45
46 static void pysha1ctx_dealloc(pysha1ctx *self)
46 static void pysha1ctx_dealloc(pysha1ctx *self)
47 {
47 {
48 PyObject_Del(self);
48 PyObject_Del(self);
49 }
49 }
50
50
51 static PyObject *pysha1ctx_update(pysha1ctx *self, PyObject *args)
51 static PyObject *pysha1ctx_update(pysha1ctx *self, PyObject *args)
52 {
52 {
53 const char *data;
53 const char *data;
54 Py_ssize_t len;
54 Py_ssize_t len;
55 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &data, &len)) {
55 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &data, &len)) {
56 return NULL;
56 return NULL;
57 }
57 }
58 SHA1DCUpdate(&(self->ctx), data, len);
58 SHA1DCUpdate(&(self->ctx), data, len);
59 Py_RETURN_NONE;
59 Py_RETURN_NONE;
60 }
60 }
61
61
62 /* it is intentional that this take a ctx by value, as that clones the
62 /* it is intentional that this take a ctx by value, as that clones the
63 context so we can keep using .update() without poisoning the state
63 context so we can keep using .update() without poisoning the state
64 with padding.
64 with padding.
65 */
65 */
66 static int finalize(SHA1_CTX ctx, unsigned char *hash_out)
66 static int finalize(SHA1_CTX ctx, unsigned char *hash_out)
67 {
67 {
68 if (SHA1DCFinal(hash_out, &ctx)) {
68 if (SHA1DCFinal(hash_out, &ctx)) {
69 PyErr_SetString(PyExc_OverflowError,
69 PyErr_SetString(PyExc_OverflowError,
70 "sha1 collision attack detected");
70 "sha1 collision attack detected");
71 return 0;
71 return 0;
72 }
72 }
73 return 1;
73 return 1;
74 }
74 }
75
75
76 static PyObject *pysha1ctx_digest(pysha1ctx *self)
76 static PyObject *pysha1ctx_digest(pysha1ctx *self)
77 {
77 {
78 unsigned char hash[20];
78 unsigned char hash[20];
79 if (!finalize(self->ctx, hash)) {
79 if (!finalize(self->ctx, hash)) {
80 return NULL;
80 return NULL;
81 }
81 }
82 return PyBytes_FromStringAndSize((char *)hash, 20);
82 return PyBytes_FromStringAndSize((char *)hash, 20);
83 }
83 }
84
84
85 static PyObject *pysha1ctx_hexdigest(pysha1ctx *self)
85 static PyObject *pysha1ctx_hexdigest(pysha1ctx *self)
86 {
86 {
87 static const char hexdigit[] = "0123456789abcdef";
87 unsigned char hash[20];
88 unsigned char hash[20];
89 char hexhash[40];
90 int i;
88 if (!finalize(self->ctx, hash)) {
91 if (!finalize(self->ctx, hash)) {
89 return NULL;
92 return NULL;
90 }
93 }
91 char hexhash[40];
94 for (i = 0; i < 20; ++i) {
92 static const char hexdigit[] = "0123456789abcdef";
93 for (int i = 0; i < 20; ++i) {
94 hexhash[i * 2] = hexdigit[hash[i] >> 4];
95 hexhash[i * 2] = hexdigit[hash[i] >> 4];
95 hexhash[i * 2 + 1] = hexdigit[hash[i] & 15];
96 hexhash[i * 2 + 1] = hexdigit[hash[i] & 15];
96 }
97 }
97 return PyString_FromStringAndSize(hexhash, 40);
98 return PyString_FromStringAndSize(hexhash, 40);
98 }
99 }
99
100
100 static PyTypeObject sha1ctxType;
101 static PyTypeObject sha1ctxType;
101
102
102 static PyObject *pysha1ctx_copy(pysha1ctx *self)
103 static PyObject *pysha1ctx_copy(pysha1ctx *self)
103 {
104 {
104 pysha1ctx *clone = (pysha1ctx *)PyObject_New(pysha1ctx, &sha1ctxType);
105 pysha1ctx *clone = (pysha1ctx *)PyObject_New(pysha1ctx, &sha1ctxType);
105 if (!clone) {
106 if (!clone) {
106 return NULL;
107 return NULL;
107 }
108 }
108 clone->ctx = self->ctx;
109 clone->ctx = self->ctx;
109 return (PyObject *)clone;
110 return (PyObject *)clone;
110 }
111 }
111
112
112 static PyMethodDef pysha1ctx_methods[] = {
113 static PyMethodDef pysha1ctx_methods[] = {
113 {"update", (PyCFunction)pysha1ctx_update, METH_VARARGS,
114 {"update", (PyCFunction)pysha1ctx_update, METH_VARARGS,
114 "Update this hash object's state with the provided bytes."},
115 "Update this hash object's state with the provided bytes."},
115 {"digest", (PyCFunction)pysha1ctx_digest, METH_NOARGS,
116 {"digest", (PyCFunction)pysha1ctx_digest, METH_NOARGS,
116 "Return the digest value as a string of binary data."},
117 "Return the digest value as a string of binary data."},
117 {"hexdigest", (PyCFunction)pysha1ctx_hexdigest, METH_NOARGS,
118 {"hexdigest", (PyCFunction)pysha1ctx_hexdigest, METH_NOARGS,
118 "Return the digest value as a string of hexadecimal digits."},
119 "Return the digest value as a string of hexadecimal digits."},
119 {"copy", (PyCFunction)pysha1ctx_copy, METH_NOARGS,
120 {"copy", (PyCFunction)pysha1ctx_copy, METH_NOARGS,
120 "Return a copy of the hash object."},
121 "Return a copy of the hash object."},
121 {NULL},
122 {NULL},
122 };
123 };
123
124
124 /* clang-format off */
125 /* clang-format off */
125 static PyTypeObject sha1ctxType = {
126 static PyTypeObject sha1ctxType = {
126 PyVarObject_HEAD_INIT(NULL, 0) /* header */
127 PyVarObject_HEAD_INIT(NULL, 0) /* header */
127 "sha1dc.sha1", /* tp_name */
128 "sha1dc.sha1", /* tp_name */
128 sizeof(pysha1ctx), /* tp_basicsize */
129 sizeof(pysha1ctx), /* tp_basicsize */
129 0, /* tp_itemsize */
130 0, /* tp_itemsize */
130 (destructor)pysha1ctx_dealloc, /* tp_dealloc */
131 (destructor)pysha1ctx_dealloc, /* tp_dealloc */
131 0, /* tp_print */
132 0, /* tp_print */
132 0, /* tp_getattr */
133 0, /* tp_getattr */
133 0, /* tp_setattr */
134 0, /* tp_setattr */
134 0, /* tp_compare */
135 0, /* tp_compare */
135 0, /* tp_repr */
136 0, /* tp_repr */
136 0, /* tp_as_number */
137 0, /* tp_as_number */
137 0, /* tp_as_sequence */
138 0, /* tp_as_sequence */
138 0, /* tp_as_mapping */
139 0, /* tp_as_mapping */
139 0, /* tp_hash */
140 0, /* tp_hash */
140 0, /* tp_call */
141 0, /* tp_call */
141 0, /* tp_str */
142 0, /* tp_str */
142 0, /* tp_getattro */
143 0, /* tp_getattro */
143 0, /* tp_setattro */
144 0, /* tp_setattro */
144 0, /* tp_as_buffer */
145 0, /* tp_as_buffer */
145 Py_TPFLAGS_DEFAULT, /* tp_flags */
146 Py_TPFLAGS_DEFAULT, /* tp_flags */
146 "sha1 implementation that looks for collisions", /* tp_doc */
147 "sha1 implementation that looks for collisions", /* tp_doc */
147 0, /* tp_traverse */
148 0, /* tp_traverse */
148 0, /* tp_clear */
149 0, /* tp_clear */
149 0, /* tp_richcompare */
150 0, /* tp_richcompare */
150 0, /* tp_weaklistoffset */
151 0, /* tp_weaklistoffset */
151 0, /* tp_iter */
152 0, /* tp_iter */
152 0, /* tp_iternext */
153 0, /* tp_iternext */
153 pysha1ctx_methods, /* tp_methods */
154 pysha1ctx_methods, /* tp_methods */
154 0, /* tp_members */
155 0, /* tp_members */
155 0, /* tp_getset */
156 0, /* tp_getset */
156 0, /* tp_base */
157 0, /* tp_base */
157 0, /* tp_dict */
158 0, /* tp_dict */
158 0, /* tp_descr_get */
159 0, /* tp_descr_get */
159 0, /* tp_descr_set */
160 0, /* tp_descr_set */
160 0, /* tp_dictoffset */
161 0, /* tp_dictoffset */
161 (initproc)pysha1ctx_init, /* tp_init */
162 (initproc)pysha1ctx_init, /* tp_init */
162 0, /* tp_alloc */
163 0, /* tp_alloc */
163 };
164 };
164 /* clang-format on */
165 /* clang-format on */
165
166
166 static PyMethodDef methods[] = {
167 static PyMethodDef methods[] = {
167 {NULL, NULL},
168 {NULL, NULL},
168 };
169 };
169
170
170 static void module_init(PyObject *mod)
171 static void module_init(PyObject *mod)
171 {
172 {
172 sha1ctxType.tp_new = PyType_GenericNew;
173 sha1ctxType.tp_new = PyType_GenericNew;
173 if (PyType_Ready(&sha1ctxType) < 0) {
174 if (PyType_Ready(&sha1ctxType) < 0) {
174 return;
175 return;
175 }
176 }
176 Py_INCREF(&sha1ctxType);
177 Py_INCREF(&sha1ctxType);
177
178
178 PyModule_AddObject(mod, "sha1", (PyObject *)&sha1ctxType);
179 PyModule_AddObject(mod, "sha1", (PyObject *)&sha1ctxType);
179 }
180 }
180
181
181 #ifdef IS_PY3K
182 #ifdef IS_PY3K
182 static struct PyModuleDef sha1dc_module = {PyModuleDef_HEAD_INIT, "sha1dc",
183 static struct PyModuleDef sha1dc_module = {PyModuleDef_HEAD_INIT, "sha1dc",
183 sha1dc_doc, -1, methods};
184 sha1dc_doc, -1, methods};
184
185
185 PyMODINIT_FUNC PyInit_sha1dc(void)
186 PyMODINIT_FUNC PyInit_sha1dc(void)
186 {
187 {
187 PyObject *mod = PyModule_Create(&sha1dc_module);
188 PyObject *mod = PyModule_Create(&sha1dc_module);
188 module_init(mod);
189 module_init(mod);
189 return mod;
190 return mod;
190 }
191 }
191 #else
192 #else
192 PyMODINIT_FUNC initsha1dc(void)
193 PyMODINIT_FUNC initsha1dc(void)
193 {
194 {
194 PyObject *mod = Py_InitModule3("sha1dc", methods, sha1dc_doc);
195 PyObject *mod = Py_InitModule3("sha1dc", methods, sha1dc_doc);
195 module_init(mod);
196 module_init(mod);
196 }
197 }
197 #endif
198 #endif
General Comments 0
You need to be logged in to leave comments. Login now