"Fossies" - the Fresh Open Source Software Archive

Member "zuluCrypt-5.7.0/plugins/network_key/crypt_buffer.c" (12 Sep 2019, 11888 Bytes) of package /linux/misc/zuluCrypt-5.7.0.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "crypt_buffer.c" see the Fossies "Dox" file reference documentation.

    1 
    2 /*
    3  * copyright: 2014-2015
    4  * name : Francis Banyikwa
    5  * email: mhogomchungu@gmail.com
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  *
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in
   15  *    the documentation and/or other materials provided with the
   16  *    distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   22  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
   24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 #include <stdio.h>
   32 #include <string.h>
   33 #include <fcntl.h>
   34 #include <unistd.h>
   35 
   36 #include "crypt_buffer.h"
   37 
   38 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
   39 #include <gcrypt.h>
   40 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
   41 
   42 #define KEY_LENGTH 32
   43 #define SALT_SIZE  16
   44 #define IV_SIZE    16
   45 #define LOAD_INFO_SIZE  32
   46 #define HMAC_SIZE 24
   47 #define MAGIC_STRING "TRUE"
   48 #define MAGIC_STRING_LENGTH 4
   49 
   50 #define PBKDF2_ITERATIONS 5000
   51 
   52 /*
   53  * This library takes a block of data and returns an encrypted version of the data.
   54  * This library also has the ability to reverse the above action.
   55  *
   56  * A user gives a password of specified size and the library coverts it to a 32 byte key using
   57  * pbkdf2 with iteration count of 5000 and a hash function of sha2.
   58  *
   59  * Data is encrypted using 256 bit AES in CBC mode.
   60  *
   61  * The format of the encrypted data:
   62  * 16 bytes from offset 0 stores pbkdf2 salt.
   63  * 16 bytes from offset 16 stores AES initialization vector.
   64  * 4  bytes from offset 32 stores the size of the load given by the user.
   65  * 4  bytes from offset 36 stores a string "TRUE" that is used to verify encryption key during decryption.
   66  * 24 bytes from offset 40 are used to store hmac hash value of the clear text.
   67  * The load the user gave to be stored encrypted starts from offset 64.The load will be padded up to a multiple of 32.
   68  *
   69  * Encrypted data starts at offset 32.
   70  *
   71  * The size of ciphertext will be ( 64 + 32n ) bytes where n is a number starting from 0.
   72  */
   73 
   74 struct crypt_buffer_ctx_1
   75 {
   76     char * buffer ;
   77     char * key ;
   78     size_t buffer_size ;
   79     size_t key_size ;
   80     int    fd ;
   81     gcry_cipher_hd_t h ;
   82     gcry_md_hd_t     m ;
   83 } ;
   84 
   85 static int _debug( crypt_buffer_ctx ctx,const char * e )
   86 {
   87 #if 0
   88     if( 0 && ctx ){;}
   89     puts( e ) ;
   90 #else
   91     if( 0 && ctx && e ){;}
   92 #endif
   93     return 0 ;
   94 }
   95 
   96 static int _failed( gcry_error_t r )
   97 {
   98     return r != GPG_ERR_NO_ERROR ;
   99 }
  100 
  101 static int _passed( gcry_error_t r )
  102 {
  103     return r == GPG_ERR_NO_ERROR ;
  104 }
  105 
  106 static int _failed_init( int fd,char * key,crypt_buffer_ctx c,gcry_cipher_hd_t h,gcry_md_hd_t m )
  107 {
  108     close( fd ) ;
  109 
  110     free( key ) ;
  111     free( c ) ;
  112 
  113     if( h != 0 ){
  114         gcry_cipher_close( h ) ;
  115     }
  116     if( m != 0 ){
  117         gcry_md_close( m ) ;
  118     }
  119 
  120     return 0 ;
  121 }
  122 
  123 int crypt_buffer_init( crypt_buffer_ctx * ctx,const void * k,size_t key_size )
  124 {
  125     gcry_error_t r ;
  126 
  127     gcry_cipher_hd_t h = 0 ;
  128     gcry_md_hd_t m = 0 ;
  129 
  130     crypt_buffer_ctx c ;
  131 
  132     void * key = NULL ;
  133 
  134     int fd = open( "/dev/urandom",O_RDONLY ) ;
  135 
  136     if( fd == -1 ){
  137         return 0 ;
  138     }
  139 
  140     if( gcry_control( GCRYCTL_INITIALIZATION_FINISHED_P ) == 0 ){
  141         gcry_check_version( NULL ) ;
  142         gcry_control( GCRYCTL_INITIALIZATION_FINISHED,0 ) ;
  143     }
  144 
  145     c = malloc( sizeof( struct crypt_buffer_ctx_1 ) ) ;
  146     if( c == NULL ){
  147         return _failed_init( fd,key,c,h,m ) ;
  148     }
  149 
  150     key = malloc( key_size ) ;
  151     if( key == NULL ){
  152         return _failed_init( fd,key,c,h,m ) ;
  153     }
  154 
  155     r = gcry_cipher_open( &h,GCRY_CIPHER_AES256,GCRY_CIPHER_MODE_CBC,0 ) ;
  156 
  157     if( _failed( r ) ){
  158         return _failed_init( fd,key,c,h,m ) ;
  159     }
  160 
  161     r = gcry_md_open( &m,GCRY_MD_SHA256,GCRY_MD_FLAG_HMAC ) ;
  162 
  163     if( _failed( r ) ){
  164         return _failed_init( fd,key,c,h,m ) ;
  165     }
  166 
  167     r = gcry_md_setkey( m,k,key_size ) ;
  168 
  169     if( _failed( r ) ){
  170         return _failed_init( fd,key,c,h,m ) ;
  171     }else{
  172         memcpy( key,k,key_size ) ;
  173 
  174         c->buffer      = NULL ;
  175         c->buffer_size = 0 ;
  176         c->h           = h ;
  177         c->m           = m ;
  178         c->key         = key ;
  179         c->key_size    = key_size ;
  180         c->fd          = fd ;
  181         *ctx           = c ;
  182         return 1 ;
  183     }
  184 }
  185 
  186 void crypt_buffer_uninit( crypt_buffer_ctx * ctx )
  187 {
  188     crypt_buffer_ctx t ;
  189 
  190     if( ctx != NULL && *ctx != NULL ){
  191         t = *ctx ;
  192         *ctx = NULL ;
  193         gcry_cipher_close( t->h ) ;
  194         gcry_md_close( t->m ) ;
  195         close( t->fd ) ;
  196         free( t->key ) ;
  197         free( t->buffer ) ;
  198         free( t ) ;
  199     }
  200 }
  201 
  202 static int _get_random_data( crypt_buffer_ctx ctx,char * buffer,size_t buffer_size )
  203 {
  204     ssize_t e = buffer_size ;
  205     ssize_t z = read( ctx->fd,buffer,buffer_size ) ;
  206     return z != e ;
  207 }
  208 
  209 static gcry_error_t _create_key( const char * salt,size_t salt_size,const char * input_key,
  210                  size_t input_key_length,char * output_key,size_t output_key_size )
  211 {
  212     return gcry_kdf_derive( input_key,input_key_length,GCRY_KDF_PBKDF2,GCRY_MD_SHA256,
  213                 salt,salt_size,PBKDF2_ITERATIONS,output_key_size,output_key ) ;
  214 }
  215 
  216 static int _set_gcrypt_handle( crypt_buffer_ctx ctx,const char * salt,size_t salt_size,const char * iv,size_t iv_size )
  217 {
  218     char key[ KEY_LENGTH ] ;
  219 
  220     gcry_error_t r ;
  221 
  222     gcry_cipher_hd_t handle = ctx->h ;
  223 
  224     r = gcry_cipher_reset( handle ) ;
  225 
  226     if( _passed( r ) ){
  227         r = _create_key( salt,salt_size,ctx->key,ctx->key_size,key,KEY_LENGTH ) ;
  228         if( _passed( r ) ){
  229             r = gcry_cipher_setkey( handle,key,KEY_LENGTH ) ;
  230             if( _passed( r ) ){
  231                 r = gcry_cipher_setiv( handle,iv,iv_size ) ;
  232                 if( _passed( r ) ){
  233                     return 1 ;
  234                 }else{
  235                     return _debug( ctx,"failed to set iv" ) ;
  236                 }
  237             }else{
  238                 return _debug( ctx,"failed to set key" ) ;
  239             }
  240         }else{
  241             return _debug( ctx,"failed to create key" ) ;
  242         }
  243     }else{
  244         return _debug( ctx,"failed to reset handle" ) ;
  245     }
  246 }
  247 
  248 static char * _expand_buffer( crypt_buffer_ctx h,size_t z )
  249 {
  250     char * e = NULL ;
  251 
  252     if( h == NULL ){
  253         return 0 ;
  254     }
  255 
  256     if( h->buffer_size < z ){
  257 
  258         e = realloc( h->buffer,z ) ;
  259 
  260         if( e != NULL ){
  261             h->buffer = e ;
  262             h->buffer_size = z ;
  263             return e ;
  264         }else{
  265             return NULL ;
  266         }
  267     }else{
  268         return h->buffer ;
  269     }
  270 }
  271 
  272 static unsigned char * _create_hmac( crypt_buffer_ctx ctx,const void * buffer,u_int32_t buffer_size )
  273 {
  274     gcry_md_reset( ctx->m ) ;
  275 
  276     gcry_md_write( ctx->m,buffer,buffer_size ) ;
  277 
  278     return gcry_md_read( ctx->m,0 ) ;
  279 }
  280 
  281 int crypt_buffer_encrypt( crypt_buffer_ctx ctx,const void * buffer,u_int32_t buffer_size,crypt_buffer_result * r )
  282 {
  283     char buff[ SALT_SIZE + IV_SIZE ] ;
  284 
  285     gcry_error_t z ;
  286 
  287     size_t len ;
  288     size_t k = buffer_size ;
  289 
  290     char * e ;
  291     unsigned char * f ;
  292     const char * salt = buff ;
  293     const char * iv   = buff + SALT_SIZE ;
  294 
  295     if( _get_random_data( ctx,buff,SALT_SIZE + IV_SIZE ) ){
  296         return _debug( ctx,"failed to get random data" ) ;
  297     }
  298 
  299     /*
  300      * make sure the block buffer we are going to encrypt is a multiple of 32
  301      */
  302     while( k % 32 != 0 ){
  303         k += 1 ;
  304     }
  305 
  306     e = _expand_buffer( ctx,k + SALT_SIZE + IV_SIZE + LOAD_INFO_SIZE ) ;
  307 
  308     if( e == NULL ){
  309         return _debug( ctx,"faile to expand memory buffer" ) ;
  310     }
  311 
  312     f = _create_hmac( ctx,buffer,buffer_size ) ;
  313 
  314     if( f == NULL ){
  315         return _debug( ctx,"failed to create hmac hash" ) ;
  316     }
  317 
  318     if( _set_gcrypt_handle( ctx,salt,SALT_SIZE,iv,IV_SIZE ) ){
  319 
  320         len = SALT_SIZE + IV_SIZE ;
  321         /*
  322          * 16 bytes from offset 0 contains pbkdf2 salt.
  323          * 16 bytes from offset 16 contains AES initialization vector.
  324          * The sum of the above makes the first 32 byte block.
  325          * This block is stored in clear text.
  326          */
  327         memcpy( e,buff,len ) ;
  328         /*
  329          * 4 bytes from offset 32 stores the size of the clear text we are going to encrypt
  330          */
  331         memcpy( e + len,&buffer_size,sizeof( u_int32_t ) ) ;
  332         /*
  333          * 4 bytes at offset 36 stores "TRUE" bytes to be used to verify decryption key
  334          */
  335         memcpy( e + len + sizeof( u_int32_t ),MAGIC_STRING,MAGIC_STRING_LENGTH ) ;
  336         /*
  337          * 24 bytes from offset 40 contains hmac digest of the cleartext
  338          *
  339          * These 24 bytes plus the 4 above and the 4 above it makes the second 32 byte block.
  340          * Ciphertext starts with this block.
  341          */
  342         memcpy( e + len + sizeof( u_int32_t ) + sizeof( u_int32_t ) ,f,HMAC_SIZE ) ;
  343         /*
  344          * User data to encrypt starts at the 64th bytes.
  345          * The 64th bytes marks the end of the header and the beginning of the load.
  346          */
  347         memcpy( e + len + LOAD_INFO_SIZE,buffer,buffer_size ) ;
  348 
  349         /*
  350          * Encryption starts at offset 32
  351          */
  352         z = gcry_cipher_encrypt( ctx->h,e + len,LOAD_INFO_SIZE + k,NULL,0 ) ;
  353 
  354         if( _passed( z ) ){
  355             r->buffer = ctx->buffer ;
  356             /*
  357              * SALT_SIZE + IV_SIZE + LOAD_INFO_SIZE will equal 64.
  358              * k will equal the size of the data we were asked to encrypt rounded up to a multiple of 32
  359              */
  360             r->length = k + SALT_SIZE + IV_SIZE + LOAD_INFO_SIZE ;
  361             return 1 ;
  362         }else{
  363             return _debug( ctx,"failed to encrypt data" ) ;
  364         }
  365     }else{
  366         return _debug( ctx,"failed to create encryption handle" ) ;
  367     }
  368 }
  369 
  370 /*
  371  * The password is assumed to be correct if the 4 bytes from offset 36 equal "TRUE"
  372  */
  373 static int _password_is_correct( const char * buffer )
  374 {
  375     return memcmp( buffer + sizeof( u_int32_t ),MAGIC_STRING,MAGIC_STRING_LENGTH ) == 0 ;
  376 }
  377 
  378 static u_int32_t _get_data_length( const char * buffer )
  379 {
  380     u_int32_t l ;
  381     memcpy( &l,buffer,sizeof( u_int32_t ) ) ;
  382     return l ;
  383 }
  384 
  385 static int _hmac_passed( crypt_buffer_ctx ctx,const char * e,u_int32_t buffer_size )
  386 {
  387     /*
  388      * calculate the hmac hash of the decrypted data.
  389      */
  390     unsigned char * f = _create_hmac( ctx,e + LOAD_INFO_SIZE,buffer_size ) ;
  391     /*
  392      * compare the hmac of the decrypted data against the stored hmac at offset 8 of the decrypted data.
  393      * This offset 8 is actually offset 40 since the decryption skipped the first 32 bytes of the salt and IV.
  394      */
  395     return memcmp( f,e + sizeof( u_int32_t ) + sizeof( u_int32_t ),HMAC_SIZE ) == 0 ;
  396 }
  397 
  398 int crypt_buffer_decrypt( crypt_buffer_ctx ctx,const void * buffer,u_int32_t buffer_size,crypt_buffer_result * r )
  399 {
  400     gcry_error_t z ;
  401 
  402     char * e ;
  403 
  404     const char * buff = buffer ;
  405     const char * salt = buff ;
  406     const char * iv   = buff + SALT_SIZE ;
  407 
  408     size_t len = buffer_size - ( SALT_SIZE + IV_SIZE ) ;
  409     ssize_t l  = buffer_size - ( SALT_SIZE + IV_SIZE + LOAD_INFO_SIZE ) ;
  410 
  411     if( l < 0 ){
  412         return _debug( ctx,"inconsistent data size detected" ) ;
  413     }
  414 
  415     e = _expand_buffer( ctx,buffer_size ) ;
  416 
  417     if( e == NULL ){
  418         return _debug( ctx,"failed to expand internal buffer" ) ;
  419     }
  420 
  421     if( _set_gcrypt_handle( ctx,salt,SALT_SIZE,iv,IV_SIZE ) ){
  422 
  423         /*
  424          * Skip to offset 32 and start decryption from there.Thats because the first 32 bytes
  425          * holds salt and IV and are stored unencrypted.
  426          */
  427         z = gcry_cipher_decrypt( ctx->h,e,len,buff + SALT_SIZE + IV_SIZE,len ) ;
  428 
  429         if( _passed( z ) ){
  430 
  431             if( _password_is_correct( e ) ){
  432 
  433                 len = _get_data_length( e ) ;
  434 
  435                 if( len <= buffer_size - ( SALT_SIZE + IV_SIZE + LOAD_INFO_SIZE ) ){
  436 
  437                     if( _hmac_passed( ctx,e,len ) ){
  438 
  439                         r->buffer = e + LOAD_INFO_SIZE ;
  440                         r->length = len ;
  441 
  442                         return 1 ;
  443                     }else{
  444                         return _debug( ctx,"hmac check failed" ) ;
  445                     }
  446                 }else{
  447                     return _debug( ctx,"inconsistency detected on stored data size" ) ;
  448                 }
  449             }else{
  450                 return _debug( ctx,"password check failed" ) ;
  451             }
  452         }else{
  453             return _debug( ctx,"decryption routine failed 1" ) ;
  454         }
  455     }else{
  456         return _debug( ctx,"decryption routine failed 2" ) ;
  457     }
  458 }