1 /*
2 * Written in 2013 by Dmitry Chestnykh <[email protected]>
3 * Modified for CPython by Christian Heimes <[email protected]>
4 *
5 * To the extent possible under law, the author have dedicated all
6 * copyright and related and neighboring rights to this software to
7 * the public domain worldwide. This software is distributed without
8 * any warranty. http://creativecommons.org/publicdomain/zero/1.0/
9 */
10
11 #ifndef Py_BUILD_CORE_BUILTIN
12 # define Py_BUILD_CORE_MODULE 1
13 #endif
14
15 #include "Python.h"
16 #include "blake2module.h"
17
18 extern PyType_Spec blake2b_type_spec;
19 extern PyType_Spec blake2s_type_spec;
20
21 PyDoc_STRVAR(blake2mod__doc__,
22 "_blake2b provides BLAKE2b for hashlib\n"
23 );
24
25 typedef struct {
26 PyTypeObject* blake2b_type;
27 PyTypeObject* blake2s_type;
28 } Blake2State;
29
30 static inline Blake2State*
blake2_get_state(PyObject * module)31 blake2_get_state(PyObject *module)
32 {
33 void *state = PyModule_GetState(module);
34 assert(state != NULL);
35 return (Blake2State *)state;
36 }
37
38 static struct PyMethodDef blake2mod_functions[] = {
39 {NULL, NULL}
40 };
41
42 static int
_blake2_traverse(PyObject * module,visitproc visit,void * arg)43 _blake2_traverse(PyObject *module, visitproc visit, void *arg)
44 {
45 Blake2State *state = blake2_get_state(module);
46 Py_VISIT(state->blake2b_type);
47 Py_VISIT(state->blake2s_type);
48 return 0;
49 }
50
51 static int
_blake2_clear(PyObject * module)52 _blake2_clear(PyObject *module)
53 {
54 Blake2State *state = blake2_get_state(module);
55 Py_CLEAR(state->blake2b_type);
56 Py_CLEAR(state->blake2s_type);
57 return 0;
58 }
59
60 static void
_blake2_free(void * module)61 _blake2_free(void *module)
62 {
63 _blake2_clear((PyObject *)module);
64 }
65
66 #define ADD_INT(d, name, value) do { \
67 PyObject *x = PyLong_FromLong(value); \
68 if (!x) \
69 return -1; \
70 if (PyDict_SetItemString(d, name, x) < 0) { \
71 Py_DECREF(x); \
72 return -1; \
73 } \
74 Py_DECREF(x); \
75 } while(0)
76
77 static int
blake2_exec(PyObject * m)78 blake2_exec(PyObject *m)
79 {
80 Blake2State* st = blake2_get_state(m);
81
82 st->blake2b_type = (PyTypeObject *)PyType_FromModuleAndSpec(
83 m, &blake2b_type_spec, NULL);
84
85 if (NULL == st->blake2b_type)
86 return -1;
87 /* BLAKE2b */
88 if (PyModule_AddType(m, st->blake2b_type) < 0) {
89 return -1;
90 }
91
92 PyObject *d = st->blake2b_type->tp_dict;
93 ADD_INT(d, "SALT_SIZE", BLAKE2B_SALTBYTES);
94 ADD_INT(d, "PERSON_SIZE", BLAKE2B_PERSONALBYTES);
95 ADD_INT(d, "MAX_KEY_SIZE", BLAKE2B_KEYBYTES);
96 ADD_INT(d, "MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES);
97
98 PyModule_AddIntConstant(m, "BLAKE2B_SALT_SIZE", BLAKE2B_SALTBYTES);
99 PyModule_AddIntConstant(m, "BLAKE2B_PERSON_SIZE", BLAKE2B_PERSONALBYTES);
100 PyModule_AddIntConstant(m, "BLAKE2B_MAX_KEY_SIZE", BLAKE2B_KEYBYTES);
101 PyModule_AddIntConstant(m, "BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES);
102
103 /* BLAKE2s */
104 st->blake2s_type = (PyTypeObject *)PyType_FromModuleAndSpec(
105 m, &blake2s_type_spec, NULL);
106
107 if (NULL == st->blake2s_type)
108 return -1;
109
110 if (PyModule_AddType(m, st->blake2s_type) < 0) {
111 return -1;
112 }
113
114 d = st->blake2s_type->tp_dict;
115 ADD_INT(d, "SALT_SIZE", BLAKE2S_SALTBYTES);
116 ADD_INT(d, "PERSON_SIZE", BLAKE2S_PERSONALBYTES);
117 ADD_INT(d, "MAX_KEY_SIZE", BLAKE2S_KEYBYTES);
118 ADD_INT(d, "MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES);
119
120 PyModule_AddIntConstant(m, "BLAKE2S_SALT_SIZE", BLAKE2S_SALTBYTES);
121 PyModule_AddIntConstant(m, "BLAKE2S_PERSON_SIZE", BLAKE2S_PERSONALBYTES);
122 PyModule_AddIntConstant(m, "BLAKE2S_MAX_KEY_SIZE", BLAKE2S_KEYBYTES);
123 PyModule_AddIntConstant(m, "BLAKE2S_MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES);
124
125 return 0;
126 }
127
128 static PyModuleDef_Slot _blake2_slots[] = {
129 {Py_mod_exec, blake2_exec},
130 {0, NULL}
131 };
132
133 static struct PyModuleDef blake2_module = {
134 PyModuleDef_HEAD_INIT,
135 "_blake2",
136 .m_doc = blake2mod__doc__,
137 .m_size = sizeof(Blake2State),
138 .m_methods = blake2mod_functions,
139 .m_slots = _blake2_slots,
140 .m_traverse = _blake2_traverse,
141 .m_clear = _blake2_clear,
142 .m_free = _blake2_free,
143 };
144
145 PyMODINIT_FUNC
PyInit__blake2(void)146 PyInit__blake2(void)
147 {
148 return PyModuleDef_Init(&blake2_module);
149 }