1 /*
2 * Written in 2013 by Dmitry Chestnykh <dmitry@codingrobots.com>
3 * Modified for CPython by Christian Heimes <christian@python.org>
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 #define ADD_INT_CONST(NAME, VALUE) do { \
78 if (PyModule_AddIntConstant(m, NAME, VALUE) < 0) { \
79 return -1; \
80 } \
81 } while (0)
82
83 static int
blake2_exec(PyObject * m)84 blake2_exec(PyObject *m)
85 {
86 Blake2State* st = blake2_get_state(m);
87
88 st->blake2b_type = (PyTypeObject *)PyType_FromModuleAndSpec(
89 m, &blake2b_type_spec, NULL);
90
91 if (NULL == st->blake2b_type)
92 return -1;
93 /* BLAKE2b */
94 if (PyModule_AddType(m, st->blake2b_type) < 0) {
95 return -1;
96 }
97
98 PyObject *d = st->blake2b_type->tp_dict;
99 ADD_INT(d, "SALT_SIZE", BLAKE2B_SALTBYTES);
100 ADD_INT(d, "PERSON_SIZE", BLAKE2B_PERSONALBYTES);
101 ADD_INT(d, "MAX_KEY_SIZE", BLAKE2B_KEYBYTES);
102 ADD_INT(d, "MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES);
103
104 ADD_INT_CONST("BLAKE2B_SALT_SIZE", BLAKE2B_SALTBYTES);
105 ADD_INT_CONST("BLAKE2B_PERSON_SIZE", BLAKE2B_PERSONALBYTES);
106 ADD_INT_CONST("BLAKE2B_MAX_KEY_SIZE", BLAKE2B_KEYBYTES);
107 ADD_INT_CONST("BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES);
108
109 /* BLAKE2s */
110 st->blake2s_type = (PyTypeObject *)PyType_FromModuleAndSpec(
111 m, &blake2s_type_spec, NULL);
112
113 if (NULL == st->blake2s_type)
114 return -1;
115
116 if (PyModule_AddType(m, st->blake2s_type) < 0) {
117 return -1;
118 }
119
120 d = st->blake2s_type->tp_dict;
121 ADD_INT(d, "SALT_SIZE", BLAKE2S_SALTBYTES);
122 ADD_INT(d, "PERSON_SIZE", BLAKE2S_PERSONALBYTES);
123 ADD_INT(d, "MAX_KEY_SIZE", BLAKE2S_KEYBYTES);
124 ADD_INT(d, "MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES);
125
126 ADD_INT_CONST("BLAKE2S_SALT_SIZE", BLAKE2S_SALTBYTES);
127 ADD_INT_CONST("BLAKE2S_PERSON_SIZE", BLAKE2S_PERSONALBYTES);
128 ADD_INT_CONST("BLAKE2S_MAX_KEY_SIZE", BLAKE2S_KEYBYTES);
129 ADD_INT_CONST("BLAKE2S_MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES);
130
131 return 0;
132 }
133
134 #undef ADD_INT
135 #undef ADD_INT_CONST
136
137 static PyModuleDef_Slot _blake2_slots[] = {
138 {Py_mod_exec, blake2_exec},
139 {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
140 {Py_mod_gil, Py_MOD_GIL_NOT_USED},
141 {0, NULL}
142 };
143
144 static struct PyModuleDef blake2_module = {
145 PyModuleDef_HEAD_INIT,
146 "_blake2",
147 .m_doc = blake2mod__doc__,
148 .m_size = sizeof(Blake2State),
149 .m_methods = blake2mod_functions,
150 .m_slots = _blake2_slots,
151 .m_traverse = _blake2_traverse,
152 .m_clear = _blake2_clear,
153 .m_free = _blake2_free,
154 };
155
156 PyMODINIT_FUNC
PyInit__blake2(void)157 PyInit__blake2(void)
158 {
159 return PyModuleDef_Init(&blake2_module);
160 }
161