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 }