From d418bfa2fd690e46f1f6e0686ceb70ad3c793cc6 Mon Sep 17 00:00:00 2001 From: Joachim Metz Date: Sun, 14 Jan 2024 18:05:37 +0100 Subject: [PATCH] Worked on Python bindings --- ChangeLog | 6 +- include/libfcrypto.h.in | 18 ++ libfcrypto/libfcrypto_des3_context.c | 429 +++++++++++++++++++++++++-- libfcrypto/libfcrypto_des3_context.h | 22 ++ manuals/libfcrypto.3 | 2 +- pyfcrypto/pyfcrypto.c | 20 +- pyfcrypto/pyfcrypto_crypt.c | 286 +++++++++++++++++- pyfcrypto/pyfcrypto_crypt.h | 10 + tests/fcrypto_test_des3_context.c | 26 +- tests/fcrypto_test_serpent_context.c | 6 +- 10 files changed, 788 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index fbdf5aa..068b910 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,13 @@ To do: -* RC4 add libfcrypto_rc4_crypt_cbc functions * Add support for cast5 * Add support for cast6 -* Add support for blowfish * Add support for Anubis * Add support for reversed Serpent * Add support for Twofish +* Blowfish add support for CFB and OFB +* DES3 add support for CBC, CFB and OFB +* RC4 add libfcrypto_rc4_crypt_cbc functions +* Serpent add support for CFB and OFB 20170901 * see `git log' for more recent change log diff --git a/include/libfcrypto.h.in b/include/libfcrypto.h.in index 96d3e36..53457b7 100644 --- a/include/libfcrypto.h.in +++ b/include/libfcrypto.h.in @@ -183,8 +183,12 @@ int libfcrypto_des3_context_set_key( libfcrypto_error_t **error ); /* De- or encrypts a buffer of data using DES3 + * + * This function is deprecated use libfcrypto_des3_crypt_ecb instead + * * Returns 1 if successful or -1 on error */ +LIBFCRYPTO_DEPRECATED \ LIBFCRYPTO_EXTERN \ int libfcrypto_des3_crypt( libfcrypto_des3_context_t *context, @@ -195,6 +199,20 @@ int libfcrypto_des3_crypt( size_t output_data_size, libfcrypto_error_t **error ); +/* De- or encrypts a block of data using DES3-ECB (Electronic CodeBook) + * The size must be a multitude of the DES3 block size (8 byte) + * Returns 1 if successful or -1 on error + */ +LIBFCRYPTO_EXTERN \ +int libfcrypto_des3_crypt_ecb( + libfcrypto_des3_context_t *context, + int mode, + const uint8_t *input_data, + size_t input_data_size, + uint8_t *output_data, + size_t output_data_size, + libfcrypto_error_t **error ); + /* ------------------------------------------------------------------------- * RC4 context functions * ------------------------------------------------------------------------- */ diff --git a/libfcrypto/libfcrypto_des3_context.c b/libfcrypto/libfcrypto_des3_context.c index 52c8c77..e6813cf 100644 --- a/libfcrypto/libfcrypto_des3_context.c +++ b/libfcrypto/libfcrypto_des3_context.c @@ -549,23 +549,33 @@ int libfcrypto_internal_des3_context_crypt_block( return( 1 ); } -/* De- or encrypts a buffer of data using DES3 +/* De- or encrypts a block of data using DES3-CBC (Cipher Block Chaining) + * The size must be a multitude of the DES3 block size (8 byte) * Returns 1 if successful or -1 on error */ -int libfcrypto_des3_crypt( +int libfcrypto_des3_crypt_cbc( libfcrypto_des3_context_t *context, int mode, + const uint8_t *initialization_vector, + size_t initialization_vector_size, const uint8_t *input_data, size_t input_data_size, uint8_t *output_data, size_t output_data_size, libcerror_error_t **error ) { + uint8_t block_data[ 8 ]; + uint8_t internal_initialization_vector[ 8 ]; + libfcrypto_internal_des3_context_t *internal_context = NULL; - static char *function = "libfcrypto_des3_crypt"; + static char *function = "libfcrypto_des3_crypt_cbc"; size_t data_offset = 0; uint64_t value_64bit = 0; +#if !defined( LIBFCRYPTO_UNFOLLED_LOOPS ) + uint8_t block_index = 0; +#endif + if( context == NULL ) { libcerror_error_set( @@ -579,8 +589,30 @@ int libfcrypto_des3_crypt( } internal_context = (libfcrypto_internal_des3_context_t *) context; - if( ( mode != LIBFCRYPTO_DES3_CRYPT_MODE_ENCRYPT ) - && ( mode != LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT ) ) + if( initialization_vector == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid initialization vector.", + function ); + + return( -1 ); + } + if( initialization_vector_size != 8 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid initialization vector size value out of bounds.", + function ); + + return( -1 ); + } + if( ( mode != LIBFCRYPTO_BLOWFISH_CRYPT_MODE_ENCRYPT ) + && ( mode != LIBFCRYPTO_BLOWFISH_CRYPT_MODE_DECRYPT ) ) { libcerror_error_set( error, @@ -602,7 +634,10 @@ int libfcrypto_des3_crypt( return( -1 ); } - if( ( input_data_size < 8 ) + /* Check if the input data size is a multitude of 8-byte + */ + if( ( ( input_data_size & (size_t) 0x07 ) != 0 ) + || ( input_data_size < 8 ) || ( input_data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( @@ -614,48 +649,369 @@ int libfcrypto_des3_crypt( return( -1 ); } - /* Check if the input data size is a multitude of 8-byte - */ - if( ( input_data_size & (size_t) 0x07 ) != 0 ) + if( output_data == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid output data.", + function ); + + return( -1 ); + } + if( ( output_data_size < input_data_size ) + || ( output_data_size > (size_t) SSIZE_MAX ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, - "%s: invalid input data size value out of bounds.", + "%s: invalid output data size value out of bounds.", function ); return( -1 ); } - if( output_data == NULL ) + if( memory_copy( + internal_initialization_vector, + initialization_vector, + 8 ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy initialization vector.", + function ); + + goto on_error; + } + while( data_offset < input_data_size ) + { + if( mode == LIBFCRYPTO_DES3_CRYPT_MODE_ENCRYPT ) + { +#if defined( LIBFCRYPTO_UNFOLLED_LOOPS ) + block_data[ 0 ] = input_data[ data_offset++ ] ^ internal_initialization_vector[ 0 ]; + block_data[ 1 ] = input_data[ data_offset++ ] ^ internal_initialization_vector[ 1 ]; + block_data[ 2 ] = input_data[ data_offset++ ] ^ internal_initialization_vector[ 2 ]; + block_data[ 3 ] = input_data[ data_offset++ ] ^ internal_initialization_vector[ 3 ]; + block_data[ 4 ] = input_data[ data_offset++ ] ^ internal_initialization_vector[ 4 ]; + block_data[ 5 ] = input_data[ data_offset++ ] ^ internal_initialization_vector[ 5 ]; + block_data[ 6 ] = input_data[ data_offset++ ] ^ internal_initialization_vector[ 6 ]; + block_data[ 7 ] = input_data[ data_offset++ ] ^ internal_initialization_vector[ 7 ]; +#else + for( block_index = 0; + block_index < 8; + block_index++ ) + { + block_data[ block_index ] = input_data[ data_offset++ ] ^ internal_initialization_vector[ block_index ]; + } +#endif + data_offset -= 8; + + byte_stream_copy_to_uint64_big_endian( + block_data, + value_64bit ); + + if( libfcrypto_internal_des3_context_crypt_block( + internal_context, + internal_context->keys[ 0 ], + LIBFCRYPTO_DES3_CRYPT_MODE_ENCRYPT, + value_64bit, + &value_64bit, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ENCRYPTION, + LIBCERROR_ENCRYPTION_ERROR_GENERIC, + "%s: unable to encrypt input data with first key.", + function ); + + goto on_error; + } + if( libfcrypto_internal_des3_context_crypt_block( + internal_context, + internal_context->keys[ 1 ], + LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, + value_64bit, + &value_64bit, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ENCRYPTION, + LIBCERROR_ENCRYPTION_ERROR_GENERIC, + "%s: unable to decrypt input data with second key.", + function ); + + goto on_error; + } + if( libfcrypto_internal_des3_context_crypt_block( + internal_context, + internal_context->keys[ 2 ], + LIBFCRYPTO_DES3_CRYPT_MODE_ENCRYPT, + value_64bit, + &value_64bit, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ENCRYPTION, + LIBCERROR_ENCRYPTION_ERROR_GENERIC, + "%s: unable to encrypt input data with third key.", + function ); + + goto on_error; + } + byte_stream_copy_from_uint64_big_endian( + &( output_data[ data_offset ] ), + value_64bit ); + + if( memory_copy( + internal_initialization_vector, + &( output_data[ data_offset ] ), + 8 ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy encrypted output data to initialization vector.", + function ); + + goto on_error; + } + } + else + { + byte_stream_copy_to_uint64_big_endian( + &( input_data[ data_offset ] ), + value_64bit ); + + if( libfcrypto_internal_des3_context_crypt_block( + internal_context, + internal_context->keys[ 2 ], + LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, + value_64bit, + &value_64bit, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ENCRYPTION, + LIBCERROR_ENCRYPTION_ERROR_GENERIC, + "%s: unable to decrypt input data with third key.", + function ); + + goto on_error; + } + if( libfcrypto_internal_des3_context_crypt_block( + internal_context, + internal_context->keys[ 1 ], + LIBFCRYPTO_DES3_CRYPT_MODE_ENCRYPT, + value_64bit, + &value_64bit, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ENCRYPTION, + LIBCERROR_ENCRYPTION_ERROR_GENERIC, + "%s: unable to endrypt input data with second key.", + function ); + + goto on_error; + } + if( libfcrypto_internal_des3_context_crypt_block( + internal_context, + internal_context->keys[ 0 ], + LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, + value_64bit, + &value_64bit, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ENCRYPTION, + LIBCERROR_ENCRYPTION_ERROR_GENERIC, + "%s: unable to decrypt input data with first key.", + function ); + + goto on_error; + } + byte_stream_copy_from_uint64_big_endian( + &( output_data[ data_offset ] ), + value_64bit ); + +#if defined( LIBFCRYPTO_UNFOLLED_LOOPS ) + output_data[ data_offset++ ] ^= internal_initialization_vector[ 0 ]; + output_data[ data_offset++ ] ^= internal_initialization_vector[ 1 ]; + output_data[ data_offset++ ] ^= internal_initialization_vector[ 2 ]; + output_data[ data_offset++ ] ^= internal_initialization_vector[ 3 ]; + output_data[ data_offset++ ] ^= internal_initialization_vector[ 4 ]; + output_data[ data_offset++ ] ^= internal_initialization_vector[ 5 ]; + output_data[ data_offset++ ] ^= internal_initialization_vector[ 6 ]; + output_data[ data_offset++ ] ^= internal_initialization_vector[ 7 ]; +#else + for( block_index = 0; + block_index < 8; + block_index++ ) + { + output_data[ data_offset++ ] ^= internal_initialization_vector[ block_index ]; + } +#endif + data_offset -= 8; + + if( memory_copy( + internal_initialization_vector, + &( input_data[ data_offset ] ), + 8 ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_COPY_FAILED, + "%s: unable to copy encrypted input data to initialization vector.", + function ); + + goto on_error; + } + } + data_offset += 8; + } + if( memory_set( + internal_initialization_vector, + 0, + 8 ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to clear initialization vector.", + function ); + + goto on_error; + } + if( memory_set( + block_data, + 0, + 8 ) == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_MEMORY, + LIBCERROR_MEMORY_ERROR_SET_FAILED, + "%s: unable to clear block data.", + function ); + + goto on_error; + } + return( 1 ); + +on_error: + memory_set( + internal_initialization_vector, + 0, + 8 ); + + memory_set( + block_data, + 0, + 8 ); + + return( -1 ); +} + +/* De- or encrypts a block of data using DES3-ECB (Electronic CodeBook) + * The size must be a multitude of the DES3 block size (8 byte) + * Returns 1 if successful or -1 on error + */ +int libfcrypto_des3_crypt_ecb( + libfcrypto_des3_context_t *context, + int mode, + const uint8_t *input_data, + size_t input_data_size, + uint8_t *output_data, + size_t output_data_size, + libcerror_error_t **error ) +{ + libfcrypto_internal_des3_context_t *internal_context = NULL; + static char *function = "libfcrypto_des3_crypt_ecb"; + size_t data_offset = 0; + uint64_t value_64bit = 0; + + if( context == NULL ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, - "%s: invalid output data.", + "%s: invalid context.", function ); return( -1 ); } - if( output_data_size > (size_t) SSIZE_MAX ) + internal_context = (libfcrypto_internal_des3_context_t *) context; + + if( ( mode != LIBFCRYPTO_DES3_CRYPT_MODE_ENCRYPT ) + && ( mode != LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT ) ) { libcerror_error_set( error, LIBCERROR_ERROR_DOMAIN_ARGUMENTS, - LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, - "%s: invalid output data size value exceeds maximum.", + LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE, + "%s: unsupported mode.", function ); return( -1 ); } - if( output_data_size < input_data_size ) + if( input_data == NULL ) { libcerror_error_set( error, - LIBCERROR_ERROR_DOMAIN_RUNTIME, - LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, - "%s: invalid ouput data size smaller than input data size.", + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid input data.", + function ); + + return( -1 ); + } + /* Check if the input data size is a multitude of 8-byte + */ + if( ( ( input_data_size & (size_t) 0x07 ) != 0 ) + || ( input_data_size < 8 ) + || ( input_data_size > (size_t) SSIZE_MAX ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid input data size value out of bounds.", + function ); + + return( -1 ); + } + if( output_data == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid output data.", + function ); + + return( -1 ); + } + if( ( output_data_size < input_data_size ) + || ( output_data_size > (size_t) SSIZE_MAX ) ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, + "%s: invalid output data size value out of bounds.", function ); return( -1 ); @@ -783,3 +1139,38 @@ int libfcrypto_des3_crypt( return( 1 ); } +/* De- or encrypts a buffer of data using DES3 + * Returns 1 if successful or -1 on error + */ +int libfcrypto_des3_crypt( + libfcrypto_des3_context_t *context, + int mode, + const uint8_t *input_data, + size_t input_data_size, + uint8_t *output_data, + size_t output_data_size, + libcerror_error_t **error ) +{ + static char *function = "libfcrypto_des3_crypt"; + + if( libfcrypto_des3_crypt_ecb( + context, + mode, + input_data, + input_data_size, + output_data, + output_data_size, + error ) != 1 ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ENCRYPTION, + LIBCERROR_ENCRYPTION_ERROR_GENERIC, + "%s: unable to crypt data using DES3-ECB.", + function ); + + return( -1 ); + } + return( 1 ); +} + diff --git a/libfcrypto/libfcrypto_des3_context.h b/libfcrypto/libfcrypto_des3_context.h index f5c69aa..dd20a7b 100644 --- a/libfcrypto/libfcrypto_des3_context.h +++ b/libfcrypto/libfcrypto_des3_context.h @@ -67,6 +67,28 @@ int libfcrypto_internal_des3_context_crypt_block( uint64_t *output_value, libcerror_error_t **error ); +LIBFCRYPTO_EXTERN \ +int libfcrypto_des3_crypt_cbc( + libfcrypto_des3_context_t *context, + int mode, + const uint8_t *initialization_vector, + size_t initialization_vector_size, + const uint8_t *input_data, + size_t input_data_size, + uint8_t *output_data, + size_t output_data_size, + libcerror_error_t **error ); + +LIBFCRYPTO_EXTERN \ +int libfcrypto_des3_crypt_ecb( + libfcrypto_des3_context_t *context, + int mode, + const uint8_t *input_data, + size_t input_data_size, + uint8_t *output_data, + size_t output_data_size, + libcerror_error_t **error ); + LIBFCRYPTO_EXTERN \ int libfcrypto_des3_crypt( libfcrypto_des3_context_t *context, diff --git a/manuals/libfcrypto.3 b/manuals/libfcrypto.3 index 23c88d4..08ae6d9 100644 --- a/manuals/libfcrypto.3 +++ b/manuals/libfcrypto.3 @@ -44,7 +44,7 @@ DES3 context functions .Ft int .Fn libfcrypto_des3_context_set_key "libfcrypto_des3_context_t *context" "const uint8_t *key" "size_t key_bit_size" "libfcrypto_error_t **error" .Ft int -.Fn libfcrypto_des3_crypt "libfcrypto_des3_context_t *context" "int mode" "const uint8_t *input_data" "size_t input_data_size" "uint8_t *output_data" "size_t output_data_size" "libfcrypto_error_t **error" +.Fn libfcrypto_des3_crypt_ecb "libfcrypto_des3_context_t *context" "int mode" "const uint8_t *input_data" "size_t input_data_size" "uint8_t *output_data" "size_t output_data_size" "libfcrypto_error_t **error" .Pp RC4 context functions .Ft int diff --git a/pyfcrypto/pyfcrypto.c b/pyfcrypto/pyfcrypto.c index 045bb0c..d68c18d 100644 --- a/pyfcrypto/pyfcrypto.c +++ b/pyfcrypto/pyfcrypto.c @@ -64,12 +64,28 @@ PyMethodDef pyfcrypto_module_methods[] = { "\n" "De- or encrypts a block of data using Blowfish-ECB." }, + /* TODO remove deprecated crypt_des3 */ + { "crypt_des3", (PyCFunction) pyfcrypto_crypt_des3, METH_VARARGS | METH_KEYWORDS, "crypt_des3(context, mode, data) -> Bytes\n" "\n" - "De- or encrypts a block of data using 3DES." }, + "De- or encrypts a block of data using DES3." }, + + { "crypt_des3_cbc", + (PyCFunction) pyfcrypto_crypt_des3_cbc, + METH_VARARGS | METH_KEYWORDS, + "crypt_des3_cbc(context, mode, initialization_vector, data) -> Bytes\n" + "\n" + "De- or encrypts a block of data using DES3-CBC." }, + + { "crypt_des3_ecb", + (PyCFunction) pyfcrypto_crypt_des3_ecb, + METH_VARARGS | METH_KEYWORDS, + "crypt_des3_csb(context, mode, data) -> Bytes\n" + "\n" + "De- or encrypts a block of data using DES3-ECB." }, { "crypt_rc4", (PyCFunction) pyfcrypto_crypt_rc4, @@ -78,6 +94,8 @@ PyMethodDef pyfcrypto_module_methods[] = { "\n" "De- or encrypts a block of data using RC4." }, + /* TODO add crypt_serpent_cbc */ + { "crypt_serpent_ecb", (PyCFunction) pyfcrypto_crypt_serpent_ecb, METH_VARARGS | METH_KEYWORDS, diff --git a/pyfcrypto/pyfcrypto_crypt.c b/pyfcrypto/pyfcrypto_crypt.c index d6d5811..2d0b023 100644 --- a/pyfcrypto/pyfcrypto_crypt.c +++ b/pyfcrypto/pyfcrypto_crypt.c @@ -336,6 +336,290 @@ PyObject *pyfcrypto_crypt_des3( PYFCRYPTO_UNREFERENCED_PARAMETER( self ) + if( PyErr_WarnEx( + PyExc_DeprecationWarning, + "Call to deprecated function: crypt_des3", + 1 ) < 0 ) + { + return( NULL ); + } + if( PyArg_ParseTupleAndKeywords( + arguments, + keywords, + "OiO", + keyword_list, + &context_object, + &mode, + &input_data_string_object ) == 0 ) + { + return( NULL ); + } + result = PyObject_IsInstance( + context_object, + (PyObject *) &pyfcrypto_des3_context_type_object ); + + if( result == -1 ) + { + return( NULL ); + } + else if( result != 1 ) + { + PyErr_Format( + PyExc_TypeError, + "%s: unsupported type of argument context value.", + function ); + + return( NULL ); + } + pyfcrypto_des3_context = (pyfcrypto_des3_context_t *) context_object; + +#if PY_MAJOR_VERSION >= 3 + input_data = PyBytes_AsString( + input_data_string_object ); + + input_data_size = PyBytes_Size( + input_data_string_object ); +#else + input_data = PyString_AsString( + input_data_string_object ); + + input_data_size = PyString_Size( + input_data_string_object ); +#endif + if( ( input_data_size < 0 ) + || ( input_data_size > (Py_ssize_t) SSIZE_MAX ) ) + { + PyErr_Format( + PyExc_ValueError, + "%s: invalid argument input data size value out of bounds.", + function ); + + return( NULL ); + } +#if PY_MAJOR_VERSION >= 3 + output_data_string_object = PyBytes_FromStringAndSize( + NULL, + input_data_size ); + + output_data = PyBytes_AsString( + output_data_string_object ); +#else + output_data_string_object = PyString_FromStringAndSize( + NULL, + input_data_size ); + + output_data = PyString_AsString( + output_data_string_object ); +#endif + Py_BEGIN_ALLOW_THREADS + + result = libfcrypto_des3_crypt_ecb( + pyfcrypto_des3_context->des3_context, + mode, + (uint8_t *) input_data, + (size_t) input_data_size, + (uint8_t *) output_data, + (size_t) input_data_size, + &error ); + + Py_END_ALLOW_THREADS + + if( result != 1 ) + { + pyfcrypto_error_raise( + error, + PyExc_IOError, + "%s: unable to crypt data.", + function ); + + libcerror_error_free( + &error ); + + Py_DecRef( + (PyObject *) output_data_string_object ); + + return( NULL ); + } + return( output_data_string_object ); +} + +/* De- or encrypts a block of data using DES3-CBC (Cipher Block Chaining) + * The size of the data must be a multitude of the DES3 block size (8 byte) + * Returns 1 if successful or -1 on error + */ +PyObject *pyfcrypto_crypt_des3_cbc( + PyObject *self PYFCRYPTO_ATTRIBUTE_UNUSED, + PyObject *arguments, + PyObject *keywords ) +{ + libcerror_error_t *error = NULL; + pyfcrypto_des3_context_t *pyfcrypto_des3_context = NULL; + PyObject *context_object = NULL; + PyObject *initialization_vector_string_object = NULL; + PyObject *input_data_string_object = NULL; + PyObject *output_data_string_object = NULL; + static char *function = "pyfcrypto_crypt_des3_cbc"; + static char *keyword_list[] = { "context", "mode", "initialization_vector", "data", NULL }; + char *initialization_vector_data = NULL; + char *input_data = NULL; + char *output_data = NULL; + Py_ssize_t initialization_vector_data_size = 0; + Py_ssize_t input_data_size = 0; + int mode = 0; + int result = 0; + + PYFCRYPTO_UNREFERENCED_PARAMETER( self ) + + if( PyArg_ParseTupleAndKeywords( + arguments, + keywords, + "OiOO", + keyword_list, + &context_object, + &mode, + &initialization_vector_string_object, + &input_data_string_object ) == 0 ) + { + return( NULL ); + } + result = PyObject_IsInstance( + context_object, + (PyObject *) &pyfcrypto_des3_context_type_object ); + + if( result == -1 ) + { + return( NULL ); + } + else if( result != 1 ) + { + PyErr_Format( + PyExc_TypeError, + "%s: unsupported type of argument context value.", + function ); + + return( NULL ); + } + pyfcrypto_des3_context = (pyfcrypto_des3_context_t *) context_object; + +#if PY_MAJOR_VERSION >= 3 + initialization_vector_data = PyBytes_AsString( + initialization_vector_string_object ); + + initialization_vector_data_size = PyBytes_Size( + initialization_vector_string_object ); +#else + initialization_vector_data = PyString_AsString( + initialization_vector_string_object ); + + initialization_vector_data_size = PyString_Size( + initialization_vector_string_object ); +#endif + if( ( initialization_vector_data_size < 0 ) + || ( initialization_vector_data_size > (Py_ssize_t) SSIZE_MAX ) ) + { + PyErr_Format( + PyExc_ValueError, + "%s: invalid argument initialization vector data size value out of bounds.", + function ); + + return( NULL ); + } +#if PY_MAJOR_VERSION >= 3 + input_data = PyBytes_AsString( + input_data_string_object ); + + input_data_size = PyBytes_Size( + input_data_string_object ); +#else + input_data = PyString_AsString( + input_data_string_object ); + + input_data_size = PyString_Size( + input_data_string_object ); +#endif + if( ( input_data_size < 0 ) + || ( input_data_size > (Py_ssize_t) SSIZE_MAX ) ) + { + PyErr_Format( + PyExc_ValueError, + "%s: invalid argument input data size value out of bounds.", + function ); + + return( NULL ); + } +#if PY_MAJOR_VERSION >= 3 + output_data_string_object = PyBytes_FromStringAndSize( + NULL, + input_data_size ); + + output_data = PyBytes_AsString( + output_data_string_object ); +#else + output_data_string_object = PyString_FromStringAndSize( + NULL, + input_data_size ); + + output_data = PyString_AsString( + output_data_string_object ); +#endif + Py_BEGIN_ALLOW_THREADS + + result = libfcrypto_des3_crypt_cbc( + pyfcrypto_des3_context->des3_context, + mode, + (uint8_t *) initialization_vector_data, + (size_t) initialization_vector_data_size, + (uint8_t *) input_data, + (size_t) input_data_size, + (uint8_t *) output_data, + (size_t) input_data_size, + &error ); + + Py_END_ALLOW_THREADS + + if( result != 1 ) + { + pyfcrypto_error_raise( + error, + PyExc_IOError, + "%s: unable to crypt data.", + function ); + + libcerror_error_free( + &error ); + + Py_DecRef( + (PyObject *) output_data_string_object ); + + return( NULL ); + } + return( output_data_string_object ); +} + +/* De- or encrypts a block of data using DES3-ECB (Electronic CodeBook) + * The size of the data must be a multitude of the Blowfish block size (8 byte) + * Returns 1 if successful or -1 on error + */ +PyObject *pyfcrypto_crypt_des3_ecb( + PyObject *self PYFCRYPTO_ATTRIBUTE_UNUSED, + PyObject *arguments, + PyObject *keywords ) +{ + PyObject *context_object = NULL; + PyObject *input_data_string_object = NULL; + PyObject *output_data_string_object = NULL; + libcerror_error_t *error = NULL; + pyfcrypto_des3_context_t *pyfcrypto_des3_context = NULL; + static char *function = "pyfcrypto_crypt_des3_ecb"; + char *input_data = NULL; + static char *keyword_list[] = { "context", "mode", "data", NULL }; + char *output_data = NULL; + Py_ssize_t input_data_size = 0; + int mode = 0; + int result = 0; + + PYFCRYPTO_UNREFERENCED_PARAMETER( self ) + if( PyArg_ParseTupleAndKeywords( arguments, keywords, @@ -406,7 +690,7 @@ PyObject *pyfcrypto_crypt_des3( #endif Py_BEGIN_ALLOW_THREADS - result = libfcrypto_des3_crypt( + result = libfcrypto_des3_crypt_ecb( pyfcrypto_des3_context->des3_context, mode, (uint8_t *) input_data, diff --git a/pyfcrypto/pyfcrypto_crypt.h b/pyfcrypto/pyfcrypto_crypt.h index da688fb..298eeff 100644 --- a/pyfcrypto/pyfcrypto_crypt.h +++ b/pyfcrypto/pyfcrypto_crypt.h @@ -47,6 +47,16 @@ PyObject *pyfcrypto_crypt_des3( PyObject *arguments, PyObject *keywords ); +PyObject *pyfcrypto_crypt_des3_cbc( + PyObject *self, + PyObject *arguments, + PyObject *keywords ); + +PyObject *pyfcrypto_crypt_des3_ecb( + PyObject *self, + PyObject *arguments, + PyObject *keywords ); + PyObject *pyfcrypto_crypt_rc4( PyObject *self, PyObject *arguments, diff --git a/tests/fcrypto_test_des3_context.c b/tests/fcrypto_test_des3_context.c index 49ca44c..e8fb4c2 100644 --- a/tests/fcrypto_test_des3_context.c +++ b/tests/fcrypto_test_des3_context.c @@ -667,10 +667,10 @@ int fcrypto_test_internal_des3_context_crypt_block( #endif /* if defined( __GNUC__ ) && !defined( LIBFCRYPTO_DLL_IMPORT ) */ -/* Tests the libfcrypto_des3_crypt function +/* Tests the libfcrypto_des3_crypt_ecb function * Returns 1 if successful or 0 if not */ -int fcrypto_test_des3_crypt( +int fcrypto_test_des3_crypt_ecb( void ) { uint8_t key[ 8 ] = { @@ -724,7 +724,7 @@ int fcrypto_test_des3_crypt( /* Test decrypting a buffer of data */ - result = libfcrypto_des3_crypt( + result = libfcrypto_des3_crypt_ecb( des3_context, LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, input_data, @@ -754,7 +754,7 @@ int fcrypto_test_des3_crypt( /* Test error cases */ - result = libfcrypto_des3_crypt( + result = libfcrypto_des3_crypt_ecb( NULL, LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, input_data, @@ -775,7 +775,7 @@ int fcrypto_test_des3_crypt( libcerror_error_free( &error ); - result = libfcrypto_des3_crypt( + result = libfcrypto_des3_crypt_ecb( des3_context, -1, input_data, @@ -796,7 +796,7 @@ int fcrypto_test_des3_crypt( libcerror_error_free( &error ); - result = libfcrypto_des3_crypt( + result = libfcrypto_des3_crypt_ecb( des3_context, LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, NULL, @@ -817,7 +817,7 @@ int fcrypto_test_des3_crypt( libcerror_error_free( &error ); - result = libfcrypto_des3_crypt( + result = libfcrypto_des3_crypt_ecb( des3_context, LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, input_data, @@ -838,7 +838,7 @@ int fcrypto_test_des3_crypt( libcerror_error_free( &error ); - result = libfcrypto_des3_crypt( + result = libfcrypto_des3_crypt_ecb( des3_context, LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, input_data, @@ -859,7 +859,7 @@ int fcrypto_test_des3_crypt( libcerror_error_free( &error ); - result = libfcrypto_des3_crypt( + result = libfcrypto_des3_crypt_ecb( des3_context, LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, input_data, @@ -880,7 +880,7 @@ int fcrypto_test_des3_crypt( libcerror_error_free( &error ); - result = libfcrypto_des3_crypt( + result = libfcrypto_des3_crypt_ecb( des3_context, LIBFCRYPTO_DES3_CRYPT_MODE_DECRYPT, input_data, @@ -972,9 +972,11 @@ int main( #endif /* if defined( __GNUC__ ) && !defined( LIBFCRYPTO_DLL_IMPORT ) */ + /* TODO add tests for libfcrypto_des3_crypt_cbc */ + FCRYPTO_TEST_RUN( - "libfcrypto_des3_crypt", - fcrypto_test_des3_crypt ); + "libfcrypto_des3_crypt_ecb", + fcrypto_test_des3_crypt_ecb ); return( EXIT_SUCCESS ); diff --git a/tests/fcrypto_test_serpent_context.c b/tests/fcrypto_test_serpent_context.c index cbd12b4..91c5956 100644 --- a/tests/fcrypto_test_serpent_context.c +++ b/tests/fcrypto_test_serpent_context.c @@ -992,7 +992,7 @@ int fcrypto_test_serpent_crypt_ecb_nessie_128bit( return( result ); } -/* TODO implement test vectors +/* TODO implement more test vectors */ /* The main program @@ -1022,10 +1022,14 @@ int main( "libfcrypto_serpent_context_set_key", fcrypto_test_serpent_context_set_key ); +#if defined( __GNUC__ ) && !defined( LIBFCRYPTO_DLL_IMPORT ) + /* TODO add tests for libfcrypto_internal_serpent_context_encrypt_block */ /* TODO add tests for libfcrypto_internal_serpent_context_decrypt_block */ +#endif /* if defined( __GNUC__ ) && !defined( LIBFCRYPTO_DLL_IMPORT ) */ + /* TODO add tests for libfcrypto_serpent_crypt_cbc */ FCRYPTO_TEST_RUN(