| @@ -0,0 +1,367 @@ |
| | 1 | /* Plan 9 sechash(2) module */ |
| | 2 | |
| | 3 | #include "Python.h" |
| | 4 | #include "structmember.h" |
| | 5 | |
| | 6 | #define _PLAN9_SOURCE |
| | 7 | #include <libsec.h> |
| | 8 | |
| | 9 | typedef struct { |
| | 10 | PyObject_HEAD |
| | 11 | |
| | 12 | char *t; |
| | 13 | int n, b; |
| | 14 | DigestState *(*f)(uchar *, ulong, uchar *, DigestState *); |
| | 15 | DigestState s; |
| | 16 | } SHobject; |
| | 17 | |
| | 18 | static PyTypeObject MD5type; |
| | 19 | static PyTypeObject SHA1type; |
| | 20 | static PyTypeObject SHA224type; |
| | 21 | static PyTypeObject SHA256type; |
| | 22 | static PyTypeObject SHA384type; |
| | 23 | static PyTypeObject SHA512type; |
| | 24 | |
| | 25 | static void |
| | 26 | sh_copy(SHobject *src, SHobject *dest) |
| | 27 | { |
| | 28 | dest->t = src->t; |
| | 29 | dest->n = src->n; |
| | 30 | dest->b = src->b; |
| | 31 | dest->f = src->f; |
| | 32 | dest->s = src->s; |
| | 33 | } |
| | 34 | |
| | 35 | static void |
| | 36 | sh_update(SHobject *s, uchar *buffer, int count) |
| | 37 | { |
| | 38 | (*s->f)(buffer, count, NULL, &s->s); |
| | 39 | } |
| | 40 | |
| | 41 | static void |
| | 42 | sh_final(SHobject *s, uchar digest[]) |
| | 43 | { |
| | 44 | (*s->f)(NULL, 0, (uchar*)digest, &s->s); |
| | 45 | } |
| | 46 | |
| | 47 | static void |
| | 48 | sh_dealloc(PyObject *ptr) |
| | 49 | { |
| | 50 | PyObject_Del(ptr); |
| | 51 | } |
| | 52 | |
| | 53 | PyDoc_STRVAR(SH_copy__doc__, "Return a copy of the hash object."); |
| | 54 | |
| | 55 | static PyObject * |
| | 56 | SH_copy(SHobject *self, PyObject *unused) |
| | 57 | { |
| | 58 | SHobject *newobj; |
| | 59 | |
| | 60 | newobj = PyObject_New(SHobject, ((PyObject*)self)->ob_type); |
| | 61 | if(newobj != NULL) |
| | 62 | sh_copy(self, newobj); |
| | 63 | return (PyObject *)newobj; |
| | 64 | } |
| | 65 | |
| | 66 | PyDoc_STRVAR(SH_digest__doc__, |
| | 67 | "Return the digest value as a string of binary data."); |
| | 68 | |
| | 69 | static PyObject * |
| | 70 | SH_digest(SHobject *self, PyObject *unused) |
| | 71 | { |
| | 72 | uchar digest[64]; |
| | 73 | SHobject temp; |
| | 74 | |
| | 75 | sh_copy(self, &temp); |
| | 76 | sh_final(&temp, digest); |
| | 77 | return PyString_FromStringAndSize((const char *)digest, self->n); |
| | 78 | } |
| | 79 | |
| | 80 | PyDoc_STRVAR(SH_hexdigest__doc__, |
| | 81 | "Return the digest value as a string of hexadecimal digits."); |
| | 82 | |
| | 83 | static PyObject * |
| | 84 | SH_hexdigest(SHobject *self, PyObject *unused) |
| | 85 | { |
| | 86 | uchar digest[64]; |
| | 87 | SHobject temp; |
| | 88 | PyObject *retval; |
| | 89 | char *hex_digest; |
| | 90 | int i, j; |
| | 91 | |
| | 92 | /* Get the raw (binary) digest value */ |
| | 93 | sh_copy(self, &temp); |
| | 94 | sh_final(&temp, digest); |
| | 95 | |
| | 96 | /* Create a new string */ |
| | 97 | retval = PyString_FromStringAndSize(NULL, self->n * 2); |
| | 98 | if (!retval) |
| | 99 | return NULL; |
| | 100 | hex_digest = PyString_AsString(retval); |
| | 101 | if (!hex_digest) { |
| | 102 | Py_DECREF(retval); |
| | 103 | return NULL; |
| | 104 | } |
| | 105 | |
| | 106 | /* Make hex version of the digest */ |
| | 107 | for (i=j=0; i<self->n; i++) { |
| | 108 | char c; |
| | 109 | c = (digest[i] >> 4) & 0xf; |
| | 110 | c = (c>9) ? c+'a'-10 : c + '0'; |
| | 111 | hex_digest[j++] = c; |
| | 112 | c = (digest[i] & 0xf); |
| | 113 | c = (c>9) ? c+'a'-10 : c + '0'; |
| | 114 | hex_digest[j++] = c; |
| | 115 | } |
| | 116 | return retval; |
| | 117 | } |
| | 118 | |
| | 119 | PyDoc_STRVAR(SH_update__doc__, |
| | 120 | "Update this hash object's state with the provided string."); |
| | 121 | |
| | 122 | static PyObject * |
| | 123 | SH_update(SHobject *self, PyObject *args) |
| | 124 | { |
| | 125 | uchar *cp; |
| | 126 | int len; |
| | 127 | |
| | 128 | if (!PyArg_ParseTuple(args, "s#:update", &cp, &len)) |
| | 129 | return NULL; |
| | 130 | sh_update(self, cp, len); |
| | 131 | Py_INCREF(Py_None); |
| | 132 | return Py_None; |
| | 133 | } |
| | 134 | |
| | 135 | static PyMethodDef SH_methods[] = { |
| | 136 | {"copy", (PyCFunction)SH_copy, METH_NOARGS, SH_copy__doc__}, |
| | 137 | {"digest", (PyCFunction)SH_digest, METH_NOARGS, SH_digest__doc__}, |
| | 138 | {"hexdigest", (PyCFunction)SH_hexdigest, METH_NOARGS, SH_hexdigest__doc__}, |
| | 139 | {"update", (PyCFunction)SH_update, METH_VARARGS, SH_update__doc__}, |
| | 140 | {NULL, NULL} |
| | 141 | }; |
| | 142 | |
| | 143 | static PyObject * |
| | 144 | SH_get_block_size(PyObject *self, void *closure) |
| | 145 | { |
| | 146 | return PyInt_FromLong(((SHobject*)self)->b); |
| | 147 | } |
| | 148 | |
| | 149 | static PyObject * |
| | 150 | SH_get_name(PyObject *self, void *closure) |
| | 151 | { |
| | 152 | char *s = ((SHobject*)self)->t; |
| | 153 | return PyString_FromStringAndSize(s, strlen(s)); |
| | 154 | } |
| | 155 | |
| | 156 | static PyGetSetDef SH_getseters[] = { |
| | 157 | {"block_size", (getter)SH_get_block_size, NULL, NULL, NULL}, |
| | 158 | {"name", (getter)SH_get_name, NULL, NULL, NULL}, |
| | 159 | {NULL} |
| | 160 | }; |
| | 161 | |
| | 162 | static PyMemberDef SH_members[] = { |
| | 163 | {"digest_size", T_INT, offsetof(SHobject, n), READONLY, NULL}, |
| | 164 | {"digestsize", T_INT, offsetof(SHobject, n), READONLY, NULL}, |
| | 165 | {NULL} |
| | 166 | }; |
| | 167 | |
| | 168 | static PyTypeObject MD5type = {PyObject_HEAD_INIT(NULL)0,"_sechash.md5",sizeof(SHobject),0,sh_dealloc, |
| | 169 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; |
| | 170 | static PyTypeObject SHA1type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha1",sizeof(SHobject),0,sh_dealloc, |
| | 171 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; |
| | 172 | static PyTypeObject SHA224type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha224",sizeof(SHobject),0,sh_dealloc, |
| | 173 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; |
| | 174 | static PyTypeObject SHA256type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha256",sizeof(SHobject),0,sh_dealloc, |
| | 175 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; |
| | 176 | static PyTypeObject SHA384type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha384",sizeof(SHobject),0,sh_dealloc, |
| | 177 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; |
| | 178 | static PyTypeObject SHA512type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha512",sizeof(SHobject),0,sh_dealloc, |
| | 179 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; |
| | 180 | |
| | 181 | |
| | 182 | PyDoc_STRVAR(SHA512_new__doc__, |
| | 183 | "Return a new SHA-512 hash object; optionally initialized with a string."); |
| | 184 | |
| | 185 | static PyObject * |
| | 186 | SHA512_new(PyObject *self, PyObject *args, PyObject *kwdict) |
| | 187 | { |
| | 188 | static char *kwlist[] = {"string", NULL}; |
| | 189 | SHobject *new; |
| | 190 | uchar *cp = NULL; |
| | 191 | int len; |
| | 192 | |
| | 193 | if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) |
| | 194 | return NULL; |
| | 195 | if ((new = (SHobject *)PyObject_New(SHobject, &SHA512type)) == NULL) |
| | 196 | return NULL; |
| | 197 | memset(&new->s, 0, sizeof(new->s)); |
| | 198 | new->t = "SHA512"; |
| | 199 | new->b = 128; |
| | 200 | new->n = SHA2_512dlen; |
| | 201 | new->f = sha2_512; |
| | 202 | if (cp) |
| | 203 | sh_update(new, cp, len); |
| | 204 | return (PyObject *)new; |
| | 205 | } |
| | 206 | |
| | 207 | PyDoc_STRVAR(SHA384_new__doc__, |
| | 208 | "Return a new SHA-384 hash object; optionally initialized with a string."); |
| | 209 | |
| | 210 | static PyObject * |
| | 211 | SHA384_new(PyObject *self, PyObject *args, PyObject *kwdict) |
| | 212 | { |
| | 213 | static char *kwlist[] = {"string", NULL}; |
| | 214 | SHobject *new; |
| | 215 | uchar *cp = NULL; |
| | 216 | int len; |
| | 217 | |
| | 218 | if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) |
| | 219 | return NULL; |
| | 220 | if ((new = (SHobject *)PyObject_New(SHobject, &SHA384type)) == NULL) |
| | 221 | return NULL; |
| | 222 | memset(&new->s, 0, sizeof(new->s)); |
| | 223 | new->t = "SHA384"; |
| | 224 | new->b = 128; |
| | 225 | new->n = SHA2_384dlen; |
| | 226 | new->f = sha2_384; |
| | 227 | if (cp) |
| | 228 | sh_update(new, cp, len); |
| | 229 | return (PyObject *)new; |
| | 230 | } |
| | 231 | |
| | 232 | PyDoc_STRVAR(SHA256_new__doc__, |
| | 233 | "Return a new SHA-256 hash object; optionally initialized with a string."); |
| | 234 | |
| | 235 | static PyObject * |
| | 236 | SHA256_new(PyObject *self, PyObject *args, PyObject *kwdict) |
| | 237 | { |
| | 238 | static char *kwlist[] = {"string", NULL}; |
| | 239 | SHobject *new; |
| | 240 | uchar *cp = NULL; |
| | 241 | int len; |
| | 242 | |
| | 243 | if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) |
| | 244 | return NULL; |
| | 245 | if ((new = (SHobject *)PyObject_New(SHobject, &SHA256type)) == NULL) |
| | 246 | return NULL; |
| | 247 | memset(&new->s, 0, sizeof(new->s)); |
| | 248 | new->t = "SHA256"; |
| | 249 | new->b = 64; |
| | 250 | new->n = SHA2_256dlen; |
| | 251 | new->f = sha2_256; |
| | 252 | if (cp) |
| | 253 | sh_update(new, cp, len); |
| | 254 | return (PyObject *)new; |
| | 255 | } |
| | 256 | |
| | 257 | PyDoc_STRVAR(SHA224_new__doc__, |
| | 258 | "Return a new SHA-224 hash object; optionally initialized with a string."); |
| | 259 | |
| | 260 | static PyObject * |
| | 261 | SHA224_new(PyObject *self, PyObject *args, PyObject *kwdict) |
| | 262 | { |
| | 263 | static char *kwlist[] = {"string", NULL}; |
| | 264 | SHobject *new; |
| | 265 | uchar *cp = NULL; |
| | 266 | int len; |
| | 267 | |
| | 268 | if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) |
| | 269 | return NULL; |
| | 270 | if ((new = (SHobject *)PyObject_New(SHobject, &SHA224type)) == NULL) |
| | 271 | return NULL; |
| | 272 | memset(&new->s, 0, sizeof(new->s)); |
| | 273 | new->t = "SHA224"; |
| | 274 | new->b = 64; |
| | 275 | new->n = SHA2_224dlen; |
| | 276 | new->f = sha2_224; |
| | 277 | if (cp) |
| | 278 | sh_update(new, cp, len); |
| | 279 | return (PyObject *)new; |
| | 280 | } |
| | 281 | |
| | 282 | PyDoc_STRVAR(SHA1_new__doc__, |
| | 283 | "Return a new SHA1 hash object; optionally initialized with a string."); |
| | 284 | |
| | 285 | static PyObject * |
| | 286 | SHA1_new(PyObject *self, PyObject *args, PyObject *kwdict) |
| | 287 | { |
| | 288 | static char *kwlist[] = {"string", NULL}; |
| | 289 | SHobject *new; |
| | 290 | uchar *cp = NULL; |
| | 291 | int len; |
| | 292 | |
| | 293 | if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) |
| | 294 | return NULL; |
| | 295 | if ((new = (SHobject *)PyObject_New(SHobject, &SHA1type)) == NULL) |
| | 296 | return NULL; |
| | 297 | memset(&new->s, 0, sizeof(new->s)); |
| | 298 | new->t = "SHA1"; |
| | 299 | new->b = 64; |
| | 300 | new->n = SHA1dlen; |
| | 301 | new->f = sha1; |
| | 302 | if (cp) |
| | 303 | sh_update(new, cp, len); |
| | 304 | return (PyObject *)new; |
| | 305 | } |
| | 306 | |
| | 307 | PyDoc_STRVAR(MD5_new__doc__, |
| | 308 | "Return a new MD5 hash object; optionally initialized with a string."); |
| | 309 | |
| | 310 | static PyObject * |
| | 311 | MD5_new(PyObject *self, PyObject *args, PyObject *kwdict) |
| | 312 | { |
| | 313 | static char *kwlist[] = {"string", NULL}; |
| | 314 | SHobject *new; |
| | 315 | uchar *cp = NULL; |
| | 316 | int len; |
| | 317 | |
| | 318 | if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) |
| | 319 | return NULL; |
| | 320 | if ((new = (SHobject *)PyObject_New(SHobject, &MD5type)) == NULL) |
| | 321 | return NULL; |
| | 322 | memset(&new->s, 0, sizeof(new->s)); |
| | 323 | new->t = "MD5"; |
| | 324 | new->b = 16; |
| | 325 | new->n = MD5dlen; |
| | 326 | new->f = md5; |
| | 327 | if (cp) |
| | 328 | sh_update(new, cp, len); |
| | 329 | return (PyObject *)new; |
| | 330 | } |
| | 331 | |
| | 332 | |
| | 333 | /* List of functions exported by this module */ |
| | 334 | |
| | 335 | static struct PyMethodDef SH_functions[] = { |
| | 336 | {"sha512", (PyCFunction)SHA512_new, METH_VARARGS|METH_KEYWORDS, SHA512_new__doc__}, |
| | 337 | {"sha384", (PyCFunction)SHA384_new, METH_VARARGS|METH_KEYWORDS, SHA384_new__doc__}, |
| | 338 | {"sha256", (PyCFunction)SHA256_new, METH_VARARGS|METH_KEYWORDS, SHA256_new__doc__}, |
| | 339 | {"sha224", (PyCFunction)SHA224_new, METH_VARARGS|METH_KEYWORDS, SHA224_new__doc__}, |
| | 340 | {"sha1", (PyCFunction)SHA1_new, METH_VARARGS|METH_KEYWORDS, SHA1_new__doc__}, |
| | 341 | {"md5", (PyCFunction)MD5_new, METH_VARARGS|METH_KEYWORDS, MD5_new__doc__}, |
| | 342 | {NULL, NULL} /* Sentinel */ |
| | 343 | }; |
| | 344 | |
| | 345 | PyMODINIT_FUNC |
| | 346 | init_sechash(void) |
| | 347 | { |
| | 348 | MD5type.ob_type = &PyType_Type; |
| | 349 | if (PyType_Ready(&MD5type) < 0) |
| | 350 | return; |
| | 351 | SHA1type.ob_type = &PyType_Type; |
| | 352 | if (PyType_Ready(&SHA1type) < 0) |
| | 353 | return; |
| | 354 | SHA224type.ob_type = &PyType_Type; |
| | 355 | if (PyType_Ready(&SHA224type) < 0) |
| | 356 | return; |
| | 357 | SHA256type.ob_type = &PyType_Type; |
| | 358 | if (PyType_Ready(&SHA256type) < 0) |
| | 359 | return; |
| | 360 | SHA384type.ob_type = &PyType_Type; |
| | 361 | if (PyType_Ready(&SHA384type) < 0) |
| | 362 | return; |
| | 363 | SHA512type.ob_type = &PyType_Type; |
| | 364 | if (PyType_Ready(&SHA512type) < 0) |
| | 365 | return; |
| | 366 | Py_InitModule("_sechash", SH_functions); |
| | 367 | } |