#include "ruby.h" #include "mcrypt.h" #include "string.h" //#define MTRACE #ifdef MTRACE #include "mcheck.h" #endif static char ruby_mcrypt_c[] = "$Id: ruby-mcrypt.c,v 1.3 2001/06/20 12:39:55 hds Exp $"; // // New MCrypt object. /// static VALUE _mcrypt_new( VALUE class, VALUE algorithm, VALUE algorithm_dir, VALUE mode, VALUE mode_dir, VALUE password, VALUE ivec ) { VALUE obj; MCRYPT td; int keysize; char *key; int ivsize; char *iv; int i; char *a_dir; char *m_dir; Check_Type( algorithm, T_STRING ); if ( NIL_P( algorithm_dir ) ) { a_dir = NULL; } else { Check_Type( algorithm_dir, T_STRING ); a_dir = STR2CSTR( algorithm_dir ); } Check_Type( mode, T_STRING ); if ( NIL_P( mode_dir ) ) { m_dir = NULL; } else { Check_Type( mode_dir, T_STRING ); m_dir = STR2CSTR( mode_dir ); } Check_Type( password, T_STRING ); if ( !NIL_P( ivec ) ) { Check_Type( ivec, T_STRING ); } td = mcrypt_module_open( STR2CSTR( algorithm ), a_dir, STR2CSTR( mode ), m_dir ); if ( td == MCRYPT_FAILED ) { rb_raise( rb_eRuntimeError, "mcrypt_module_open() failed!" ); } keysize = mcrypt_enc_get_key_size( td ); key = malloc( keysize ); memset( key, 0, keysize ); memcpy( key, RSTRING( password )->ptr, RSTRING( password )->len ); if ( NIL_P( ivec ) ) { iv = NULL; } else { ivsize = mcrypt_enc_get_iv_size( td ); if ( ivsize == 0 ) { iv = NULL; } else { iv = malloc( ivsize ); memset( iv, 0, ivsize ); memcpy( iv, RSTRING( ivec )->ptr, RSTRING( ivec )->len ); } } i = mcrypt_generic_init( td, key, keysize, iv ); if ( i < 0 ) { rb_raise( rb_eRuntimeError, mcrypt_strerror( i ) ); } obj = Data_Wrap_Struct( class, 0, free, td ); if ( iv != NULL ) { free( iv ); } free( key ); return obj; } // // mcrypt_generic // VALUE _mcrypt_generic( VALUE self, VALUE data ) { MCRYPT td; VALUE str; int bs; int blocksize; char *blockbuffer; int rc; Data_Get_Struct( self, void, td ) ; if ( mcrypt_enc_is_block_mode( td ) == 0 ) { str = rb_str_dup( data ); rc = mcrypt_generic( td, RSTRING( str )->ptr, RSTRING( str )->len ); } else { bs = mcrypt_enc_get_block_size( td ); blocksize = (RSTRING( data )->len / bs)* bs; if ( (RSTRING( data)->len % bs) != 0 ) { blocksize += bs; } blockbuffer = malloc( blocksize ); memset( blockbuffer, 0, blocksize ); memcpy( blockbuffer, RSTRING( data )->ptr, RSTRING( data )->len ); rc = mcrypt_generic( td, blockbuffer, blocksize ); str = rb_str_new( blockbuffer, blocksize ); free( blockbuffer ); } if ( rc != 0 ) { rb_raise( rb_eRuntimeError, "mcrypt_generic() failed!" ); } return str; } // // mdecrypt_generic // VALUE _mdecrypt_generic( VALUE self, VALUE data ) { MCRYPT td; VALUE str; int bs; int blocksize; char *blockbuffer; int rc; Data_Get_Struct( self, void, td ) ; if ( mcrypt_enc_is_block_mode( td ) == 0 ) { str = rb_str_dup( data ); rc = mdecrypt_generic( td, RSTRING( str )->ptr, RSTRING( str )->len ); } else { bs = mcrypt_enc_get_block_size( td ); blocksize = (RSTRING( data )->len / bs)* bs; if ( (RSTRING( data)->len % bs) != 0 ) { blocksize += bs; } blockbuffer = malloc( blocksize ); memset( blockbuffer, 0, blocksize ); memcpy( blockbuffer, RSTRING( data )->ptr, RSTRING( data )->len ); rc = mdecrypt_generic( td, blockbuffer, blocksize ); str = rb_str_new( blockbuffer, blocksize ); free( blockbuffer ); } if ( rc != 0 ) { rb_raise( rb_eRuntimeError, "mdecrypt_generic() failed!" ); } return str; } // // mcrypt_enc_get_algorithms_name // VALUE _mcrypt_enc_get_algorithms_name( VALUE self ) { MCRYPT td; char *str; VALUE algo_name; Data_Get_Struct( self, void, td ) ; str = mcrypt_enc_get_algorithms_name( td ); algo_name = rb_str_new2( str ); mcrypt_free( str ); return algo_name; } // // mcrypt_enc_get_modes_name // VALUE _mcrypt_enc_get_modes_name( VALUE self ) { MCRYPT td; char *str; VALUE mode_name; Data_Get_Struct( self, void, td ) ; str = mcrypt_enc_get_modes_name( td ); mode_name = rb_str_new2( str ); mcrypt_free( str ); return mode_name; } // // mcrypt_generic_end // VALUE _mcrypt_generic_end( VALUE self ) { MCRYPT td; int rc; Data_Get_Struct( self, void, td ) ; rc = mcrypt_generic_end( td ); if ( rc < 0 ) { rb_raise( rb_eRuntimeError, mcrypt_strerror( rc ) ); } return Qnil; } // // mcrypt_list_algorithms // VALUE _mcrypt_list_algorithms ( VALUE class, VALUE libdir ) { char *l_dir; int size; char **algo_list; VALUE ary; int i; if ( NIL_P( libdir ) ) { l_dir = NULL; } else { Check_Type( libdir, T_STRING ); l_dir = STR2CSTR( libdir ); } algo_list = mcrypt_list_algorithms( l_dir, &size ); ary = rb_ary_new(); for ( i = 0; i < size; i++ ) { rb_ary_push( ary, rb_str_new2( algo_list[i] ) ); } mcrypt_free_p( algo_list, size ); return ary; } // // mcrypt_list_modes // VALUE _mcrypt_list_modes ( VALUE class, VALUE libdir ) { char *l_dir; int size; char **mode_list; VALUE ary; int i; if ( NIL_P( libdir ) ) { l_dir = NULL; } else { Check_Type( libdir, T_STRING ); l_dir = STR2CSTR( libdir ); } mode_list = mcrypt_list_modes( l_dir, &size ); ary = rb_ary_new(); for ( i = 0; i < size; i++ ) { rb_ary_push( ary, rb_str_new2( mode_list[i] ) ); } mcrypt_free_p( mode_list, size ); return ary; } // // mcrypt_enc_get_supported_key_sizes // VALUE _mcrypt_enc_get_supported_key_sizes( VALUE self ) { MCRYPT td; int sizes; int *sizes_list; VALUE ary; int i; Data_Get_Struct( self, void, td ) ; sizes_list = mcrypt_enc_get_supported_key_sizes( td, &sizes ); ary = rb_ary_new(); for ( i = 0; i < sizes; i++ ) { rb_ary_push( ary, INT2FIX( sizes_list[i] * 8 ) ); } mcrypt_free( sizes_list ); return ary; } // // mcrypt_enc_is_block_algorithm // VALUE _mcrypt_enc_is_block_algorithm( VALUE self ) { MCRYPT td; Data_Get_Struct( self, void, td ) ; if ( mcrypt_enc_is_block_algorithm( td ) ) { return Qtrue; } else { return Qfalse; } } // // mcrypt_enc_is_block_mode // VALUE _mcrypt_enc_is_block_mode( VALUE self ) { MCRYPT td; Data_Get_Struct( self, void, td ) ; if ( mcrypt_enc_is_block_mode( td ) ) { return Qtrue; } else { return Qfalse; } } // // mcrypt_enc_is_block_algorithm_mode // VALUE _mcrypt_enc_is_block_algorithm_mode( VALUE self ) { MCRYPT td; Data_Get_Struct( self, void, td ) ; if ( mcrypt_enc_is_block_algorithm_mode( td ) ) { return Qtrue; } else { return Qfalse; } } // // mcrypt_enc_get_block_size // VALUE _mcrypt_enc_get_block_size( VALUE self ) { MCRYPT td; Data_Get_Struct( self, void, td ) ; return INT2FIX( mcrypt_enc_get_block_size( td ) * 8 ); } // // Initialisation // void Init_MCrypt() { VALUE cMCrypt = rb_define_class( "MCrypt", rb_cObject ); #ifdef MTRACE mtrace(); #endif rb_define_singleton_method( cMCrypt, "new", _mcrypt_new, 6 ); rb_define_singleton_method( cMCrypt, "mcrypt_list_algorithms", _mcrypt_list_algorithms, 1 ); rb_define_singleton_method( cMCrypt, "mcrypt_list_modes", _mcrypt_list_modes, 1 ); rb_define_method( cMCrypt, "mcrypt_generic", _mcrypt_generic, 1 ); rb_define_method( cMCrypt, "mdecrypt_generic", _mdecrypt_generic, 1 ); rb_define_method( cMCrypt, "mcrypt_enc_get_algorithms_name", _mcrypt_enc_get_algorithms_name, 0 ); rb_define_method( cMCrypt, "mcrypt_enc_get_modes_name", _mcrypt_enc_get_modes_name, 0 ); rb_define_method( cMCrypt, "mcrypt_generic_end", _mcrypt_generic_end, 0 ); rb_define_method( cMCrypt, "mcrypt_enc_get_supported_key_sizes", _mcrypt_enc_get_supported_key_sizes, 0 ); rb_define_method( cMCrypt, "mcrypt_enc_is_block_algorithm", _mcrypt_enc_is_block_algorithm, 0 ); rb_define_method( cMCrypt, "mcrypt_enc_is_block_mode", _mcrypt_enc_is_block_mode, 0 ); rb_define_method( cMCrypt, "mcrypt_enc_is_block_algorithm_mode", _mcrypt_enc_is_block_algorithm_mode, 0 ); rb_define_method( cMCrypt, "mcrypt_enc_get_block_size", _mcrypt_enc_get_block_size, 0 ); } // // EOF // // Copyright 2001, Hans-Dieter Stich //