auth/credentials: use smb_krb5_cc_new_unique_memory() in cli_credentials_shallow_ccache()
[Samba.git] / lib / crypto / py_crypto.c
blob26a0a09f5eb68791785e1127049976731c72d36b
1 /*
2 Unix SMB/CIFS implementation.
3 Samba crypto functions
5 Copyright (C) Alexander Bokovoy <ab@samba.org> 2017
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "lib/replace/system/python.h"
22 #include "includes.h"
23 #include "python/py3compat.h"
25 #include <gnutls/gnutls.h>
26 #include <gnutls/crypto.h>
27 #include "lib/crypto/gnutls_helpers.h"
28 #include "lib/crypto/md4.h"
29 #include "libcli/auth/libcli_auth.h"
30 #include "libcli/util/pyerrors.h"
32 static bool samba_gnutls_datum_from_PyObject(PyObject *py_obj,
33 gnutls_datum_t *datum)
35 uint8_t *data = NULL;
36 Py_ssize_t size;
38 int ret;
40 ret = PyBytes_AsStringAndSize(py_obj,
41 (char **)&data,
42 &size);
43 if (ret != 0) {
44 return false;
47 datum->data = data;
48 datum->size = size;
50 return true;
53 static bool samba_DATA_BLOB_from_PyObject(PyObject *py_obj,
54 DATA_BLOB *blob)
56 uint8_t *data = NULL;
57 Py_ssize_t size;
59 int ret;
61 ret = PyBytes_AsStringAndSize(py_obj,
62 (char **)&data,
63 &size);
64 if (ret != 0) {
65 return false;
68 blob->data = data;
69 blob->length = size;
71 return true;
74 static PyObject *py_crypto_arcfour_crypt_blob(PyObject *module, PyObject *args)
76 DATA_BLOB data;
77 PyObject *py_data, *py_key, *result;
78 TALLOC_CTX *ctx;
79 gnutls_cipher_hd_t cipher_hnd = NULL;
80 gnutls_datum_t key;
81 int rc;
83 if (!PyArg_ParseTuple(args, "OO", &py_data, &py_key))
84 return NULL;
86 if (!PyBytes_Check(py_data)) {
87 PyErr_Format(PyExc_TypeError, "bytes expected");
88 return NULL;
91 if (!PyBytes_Check(py_key)) {
92 PyErr_Format(PyExc_TypeError, "bytes expected");
93 return NULL;
96 ctx = talloc_new(NULL);
98 data.length = PyBytes_Size(py_data);
99 data.data = talloc_memdup(ctx, PyBytes_AsString(py_data), data.length);
100 if (!data.data) {
101 talloc_free(ctx);
102 return PyErr_NoMemory();
105 key = (gnutls_datum_t) {
106 .data = (uint8_t *)PyBytes_AsString(py_key),
107 .size = PyBytes_Size(py_key),
110 rc = gnutls_cipher_init(&cipher_hnd,
111 GNUTLS_CIPHER_ARCFOUR_128,
112 &key,
113 NULL);
114 if (rc < 0) {
115 talloc_free(ctx);
116 PyErr_Format(PyExc_OSError, "encryption failed");
117 return NULL;
119 rc = gnutls_cipher_encrypt(cipher_hnd,
120 data.data,
121 data.length);
122 gnutls_cipher_deinit(cipher_hnd);
123 if (rc < 0) {
124 talloc_free(ctx);
125 PyErr_Format(PyExc_OSError, "encryption failed");
126 return NULL;
129 result = PyBytes_FromStringAndSize((const char*) data.data, data.length);
130 talloc_free(ctx);
131 return result;
134 static PyObject *py_crypto_set_relax_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
136 GNUTLS_FIPS140_SET_LAX_MODE();
138 Py_RETURN_NONE;
141 static PyObject *py_crypto_set_strict_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
143 GNUTLS_FIPS140_SET_STRICT_MODE();
145 Py_RETURN_NONE;
148 static PyObject *py_crypto_des_crypt_blob_16(PyObject *self, PyObject *args)
150 PyObject *py_data = NULL;
151 uint8_t *data = NULL;
152 Py_ssize_t data_size;
154 PyObject *py_key = NULL;
155 uint8_t *key = NULL;
156 Py_ssize_t key_size;
158 uint8_t result[16];
160 bool ok;
161 int ret;
163 ok = PyArg_ParseTuple(args, "SS",
164 &py_data, &py_key);
165 if (!ok) {
166 return NULL;
169 ret = PyBytes_AsStringAndSize(py_data,
170 (char **)&data,
171 &data_size);
172 if (ret != 0) {
173 return NULL;
176 ret = PyBytes_AsStringAndSize(py_key,
177 (char **)&key,
178 &key_size);
179 if (ret != 0) {
180 return NULL;
183 if (data_size != 16) {
184 return PyErr_Format(PyExc_ValueError,
185 "Expected data size of 16 bytes; got %zd",
186 data_size);
189 if (key_size != 14) {
190 return PyErr_Format(PyExc_ValueError,
191 "Expected key size of 14 bytes; got %zd",
192 key_size);
195 ret = des_crypt112_16(result, data, key,
196 SAMBA_GNUTLS_ENCRYPT);
197 if (ret != 0) {
198 return PyErr_Format(PyExc_RuntimeError,
199 "des_crypt112_16() failed: %d",
200 ret);
203 return PyBytes_FromStringAndSize((const char *)result,
204 sizeof(result));
207 static PyObject *py_crypto_md4_hash_blob(PyObject *self, PyObject *args)
209 PyObject *py_data = NULL;
210 uint8_t *data = NULL;
211 Py_ssize_t data_size;
213 uint8_t result[16];
215 bool ok;
216 int ret;
218 ok = PyArg_ParseTuple(args, "S",
219 &py_data);
220 if (!ok) {
221 return NULL;
224 ret = PyBytes_AsStringAndSize(py_data,
225 (char **)&data,
226 &data_size);
227 if (ret != 0) {
228 return NULL;
231 mdfour(result, data, data_size);
233 return PyBytes_FromStringAndSize((const char *)result,
234 sizeof(result));
237 static PyObject *py_crypto_sha512_pbkdf2(PyObject *self, PyObject *args)
239 PyObject *py_key = NULL;
240 uint8_t *key = NULL;
241 gnutls_datum_t key_datum = {0};
243 PyObject *py_salt = NULL;
244 gnutls_datum_t salt_datum = {0};
246 uint8_t result[16];
248 unsigned iterations = 0;
250 bool ok;
251 int ret;
252 NTSTATUS status;
254 ok = PyArg_ParseTuple(args, "SSI",
255 &py_key, &py_salt, &iterations);
256 if (!ok) {
257 return NULL;
260 ok = samba_gnutls_datum_from_PyObject(py_key, &key_datum);
261 if (!ok) {
262 return NULL;
265 ok = samba_gnutls_datum_from_PyObject(py_salt, &salt_datum);
266 if (!ok) {
267 return NULL;
270 ret = gnutls_pbkdf2(GNUTLS_MAC_SHA512,
271 &key_datum,
272 &salt_datum,
273 iterations,
274 result,
275 sizeof(result));
276 BURN_DATA(key);
277 if (ret < 0) {
278 status = gnutls_error_to_ntstatus(ret, NT_STATUS_CRYPTO_SYSTEM_INVALID);
279 PyErr_SetNTSTATUS(status);
280 return NULL;
283 return PyBytes_FromStringAndSize((const char *)result,
284 sizeof(result));
287 static PyObject *py_crypto_aead_aes_256_cbc_hmac_sha512_blob(PyObject *self, PyObject *args)
289 TALLOC_CTX *ctx = NULL;
291 PyObject *py_ciphertext = NULL;
292 DATA_BLOB ciphertext_blob = {0};
294 PyObject *py_auth_data = NULL;
295 PyObject *py_result = NULL;
297 PyObject *py_plaintext = NULL;
298 DATA_BLOB plaintext_blob = {0};
299 PyObject *py_cek = NULL;
300 DATA_BLOB cek_blob = {0};
301 PyObject *py_key_salt = NULL;
302 DATA_BLOB key_salt_blob = {0};
303 PyObject *py_mac_salt = NULL;
304 DATA_BLOB mac_salt_blob = {0};
305 PyObject *py_iv = NULL;
306 DATA_BLOB iv_blob = {0};
308 uint8_t auth_data[64];
310 bool ok;
311 NTSTATUS status;
313 ok = PyArg_ParseTuple(args, "SSSSS",
314 &py_plaintext,
315 &py_cek,
316 &py_key_salt,
317 &py_mac_salt,
318 &py_iv);
319 if (!ok) {
320 return NULL;
323 /* Create data blobs from the contents of the function parameters. */
325 ok = samba_DATA_BLOB_from_PyObject(py_plaintext, &plaintext_blob);
326 if (!ok) {
327 return NULL;
330 ok = samba_DATA_BLOB_from_PyObject(py_cek, &cek_blob);
331 if (!ok) {
332 return NULL;
335 ok = samba_DATA_BLOB_from_PyObject(py_key_salt, &key_salt_blob);
336 if (!ok) {
337 return NULL;
340 ok = samba_DATA_BLOB_from_PyObject(py_mac_salt, &mac_salt_blob);
341 if (!ok) {
342 return NULL;
345 ok = samba_DATA_BLOB_from_PyObject(py_iv, &iv_blob);
346 if (!ok) {
347 return NULL;
350 ctx = talloc_new(NULL);
351 if (ctx == NULL) {
352 return PyErr_NoMemory();
355 /* Encrypt the plaintext. */
356 status = samba_gnutls_aead_aes_256_cbc_hmac_sha512_encrypt(ctx,
357 &plaintext_blob,
358 &cek_blob,
359 &key_salt_blob,
360 &mac_salt_blob,
361 &iv_blob,
362 &ciphertext_blob,
363 auth_data);
364 if (!NT_STATUS_IS_OK(status)) {
365 PyErr_SetNTSTATUS(status);
366 talloc_free(ctx);
367 return NULL;
370 /* Convert the output into Python 'bytes' objects. */
371 py_ciphertext = PyBytes_FromStringAndSize((const char *)ciphertext_blob.data,
372 ciphertext_blob.length);
373 talloc_free(ctx);
374 if (py_ciphertext == NULL) {
375 return NULL;
377 py_auth_data = PyBytes_FromStringAndSize((const char *)auth_data,
378 sizeof(auth_data));
379 if (py_auth_data == NULL) {
380 return NULL;
383 /* Steal ciphertext and auth_data into a new tuple. */
384 py_result = Py_BuildValue("(NN)", py_ciphertext, py_auth_data);
386 return py_result;
391 static const char py_crypto_arcfour_crypt_blob_doc[] = "arcfour_crypt_blob(data, key)\n"
392 "Encrypt the data with RC4 algorithm using the key";
394 static const char py_crypto_des_crypt_blob_16_doc[] = "des_crypt_blob_16(data, key) -> bytes\n"
395 "Encrypt the 16-byte data with DES using "
396 "the 14-byte key";
398 static const char py_crypto_md4_hash_blob_doc[] = "md4_hash_blob(data) -> bytes\n"
399 "Hash the data with MD4 algorithm";
401 static const char py_crypto_sha512_pbkdf2_doc[] = "sha512_pbkdf2(key, salt, iterations) -> bytes\n"
402 "Derive a key from an existing one with SHA512 "
403 "algorithm";
405 static const char py_crypto_aead_aes_256_cbc_hmac_sha512_blob_doc[] =
406 "aead_aes_256_cbc_hmac_sha512_blob(plaintext, cek, key_salt, "
407 "mac_salt, iv) -> ciphertext, auth_data\n"
408 "Encrypt the plaintext with AES256 as specified in "
409 "[MS-SAMR] 3.2.2.4 AES Cipher Usage";
411 static PyMethodDef py_crypto_methods[] = {
412 { "arcfour_crypt_blob", (PyCFunction)py_crypto_arcfour_crypt_blob, METH_VARARGS, py_crypto_arcfour_crypt_blob_doc },
413 { "set_relax_mode", (PyCFunction)py_crypto_set_relax_mode, METH_NOARGS, "Set fips to relax mode" },
414 { "set_strict_mode", (PyCFunction)py_crypto_set_strict_mode, METH_NOARGS, "Set fips to strict mode" },
415 { "des_crypt_blob_16", (PyCFunction)py_crypto_des_crypt_blob_16, METH_VARARGS, py_crypto_des_crypt_blob_16_doc },
416 { "md4_hash_blob", (PyCFunction)py_crypto_md4_hash_blob, METH_VARARGS, py_crypto_md4_hash_blob_doc },
417 { "sha512_pbkdf2", (PyCFunction)py_crypto_sha512_pbkdf2, METH_VARARGS, py_crypto_sha512_pbkdf2_doc },
419 "aead_aes_256_cbc_hmac_sha512_blob",
420 (PyCFunction)py_crypto_aead_aes_256_cbc_hmac_sha512_blob,
421 METH_VARARGS,
422 py_crypto_aead_aes_256_cbc_hmac_sha512_blob_doc
424 {0},
427 static struct PyModuleDef moduledef = {
428 PyModuleDef_HEAD_INIT,
429 .m_name = "crypto",
430 .m_doc = "Crypto functions required for SMB",
431 .m_size = -1,
432 .m_methods = py_crypto_methods,
435 MODULE_INIT_FUNC(crypto)
437 PyObject *m;
439 m = PyModule_Create(&moduledef);
440 if (m == NULL)
441 return NULL;
443 return m;