2 Unix SMB/CIFS implementation.
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"
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
)
40 ret
= PyBytes_AsStringAndSize(py_obj
,
53 static bool samba_DATA_BLOB_from_PyObject(PyObject
*py_obj
,
61 ret
= PyBytes_AsStringAndSize(py_obj
,
74 static PyObject
*py_crypto_arcfour_crypt_blob(PyObject
*module
, PyObject
*args
)
77 PyObject
*py_data
, *py_key
, *result
;
79 gnutls_cipher_hd_t cipher_hnd
= NULL
;
83 if (!PyArg_ParseTuple(args
, "OO", &py_data
, &py_key
))
86 if (!PyBytes_Check(py_data
)) {
87 PyErr_Format(PyExc_TypeError
, "bytes expected");
91 if (!PyBytes_Check(py_key
)) {
92 PyErr_Format(PyExc_TypeError
, "bytes expected");
96 ctx
= talloc_new(NULL
);
98 data
.length
= PyBytes_Size(py_data
);
99 data
.data
= talloc_memdup(ctx
, PyBytes_AsString(py_data
), data
.length
);
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
,
116 PyErr_Format(PyExc_OSError
, "encryption failed");
119 rc
= gnutls_cipher_encrypt(cipher_hnd
,
122 gnutls_cipher_deinit(cipher_hnd
);
125 PyErr_Format(PyExc_OSError
, "encryption failed");
129 result
= PyBytes_FromStringAndSize((const char*) data
.data
, data
.length
);
134 static PyObject
*py_crypto_set_relax_mode(PyObject
*module
, PyObject
*Py_UNUSED(ignored
))
136 GNUTLS_FIPS140_SET_LAX_MODE();
141 static PyObject
*py_crypto_set_strict_mode(PyObject
*module
, PyObject
*Py_UNUSED(ignored
))
143 GNUTLS_FIPS140_SET_STRICT_MODE();
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
;
163 ok
= PyArg_ParseTuple(args
, "SS",
169 ret
= PyBytes_AsStringAndSize(py_data
,
176 ret
= PyBytes_AsStringAndSize(py_key
,
183 if (data_size
!= 16) {
184 return PyErr_Format(PyExc_ValueError
,
185 "Expected data size of 16 bytes; got %zd",
189 if (key_size
!= 14) {
190 return PyErr_Format(PyExc_ValueError
,
191 "Expected key size of 14 bytes; got %zd",
195 ret
= des_crypt112_16(result
, data
, key
,
196 SAMBA_GNUTLS_ENCRYPT
);
198 return PyErr_Format(PyExc_RuntimeError
,
199 "des_crypt112_16() failed: %d",
203 return PyBytes_FromStringAndSize((const char *)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
;
218 ok
= PyArg_ParseTuple(args
, "S",
224 ret
= PyBytes_AsStringAndSize(py_data
,
231 mdfour(result
, data
, data_size
);
233 return PyBytes_FromStringAndSize((const char *)result
,
237 static PyObject
*py_crypto_sha512_pbkdf2(PyObject
*self
, PyObject
*args
)
239 PyObject
*py_key
= NULL
;
241 gnutls_datum_t key_datum
= {0};
243 PyObject
*py_salt
= NULL
;
244 gnutls_datum_t salt_datum
= {0};
248 unsigned iterations
= 0;
254 ok
= PyArg_ParseTuple(args
, "SSI",
255 &py_key
, &py_salt
, &iterations
);
260 ok
= samba_gnutls_datum_from_PyObject(py_key
, &key_datum
);
265 ok
= samba_gnutls_datum_from_PyObject(py_salt
, &salt_datum
);
270 ret
= gnutls_pbkdf2(GNUTLS_MAC_SHA512
,
278 status
= gnutls_error_to_ntstatus(ret
, NT_STATUS_CRYPTO_SYSTEM_INVALID
);
279 PyErr_SetNTSTATUS(status
);
283 return PyBytes_FromStringAndSize((const char *)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];
313 ok
= PyArg_ParseTuple(args
, "SSSSS",
323 /* Create data blobs from the contents of the function parameters. */
325 ok
= samba_DATA_BLOB_from_PyObject(py_plaintext
, &plaintext_blob
);
330 ok
= samba_DATA_BLOB_from_PyObject(py_cek
, &cek_blob
);
335 ok
= samba_DATA_BLOB_from_PyObject(py_key_salt
, &key_salt_blob
);
340 ok
= samba_DATA_BLOB_from_PyObject(py_mac_salt
, &mac_salt_blob
);
345 ok
= samba_DATA_BLOB_from_PyObject(py_iv
, &iv_blob
);
350 ctx
= talloc_new(NULL
);
352 return PyErr_NoMemory();
355 /* Encrypt the plaintext. */
356 status
= samba_gnutls_aead_aes_256_cbc_hmac_sha512_encrypt(ctx
,
364 if (!NT_STATUS_IS_OK(status
)) {
365 PyErr_SetNTSTATUS(status
);
370 /* Convert the output into Python 'bytes' objects. */
371 py_ciphertext
= PyBytes_FromStringAndSize((const char *)ciphertext_blob
.data
,
372 ciphertext_blob
.length
);
374 if (py_ciphertext
== NULL
) {
377 py_auth_data
= PyBytes_FromStringAndSize((const char *)auth_data
,
379 if (py_auth_data
== NULL
) {
383 /* Steal ciphertext and auth_data into a new tuple. */
384 py_result
= Py_BuildValue("(NN)", py_ciphertext
, py_auth_data
);
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 "
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 "
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
,
422 py_crypto_aead_aes_256_cbc_hmac_sha512_blob_doc
427 static struct PyModuleDef moduledef
= {
428 PyModuleDef_HEAD_INIT
,
430 .m_doc
= "Crypto functions required for SMB",
432 .m_methods
= py_crypto_methods
,
435 MODULE_INIT_FUNC(crypto
)
439 m
= PyModule_Create(&moduledef
);