00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 #ifndef _CRT_SECURE_NO_DEPRECATE
00022 #define _CRT_SECURE_NO_DEPRECATE 1
00023 #endif
00024 
00025 #if defined(WIN32)
00026 #include <windows.h>
00027 #include <io.h>
00028 #else
00029 #include <sys/types.h>
00030 #include <unistd.h>
00031 #endif
00032 
00033 #include <string.h>
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <time.h>
00037 
00038 #include "xyssl/aes.h"
00039 #include "xyssl/sha2.h"
00040 
00041 #define MODE_ENCRYPT    0
00042 #define MODE_DECRYPT    1
00043 
00044 #define USAGE   \
00045     "\n  aescrypt2 <mode> <input filename> <output filename> <key>\n" \
00046     "\n   <mode>: 0 = encrypt, 1 = decrypt\n" \
00047     "\n  example: aescrypt2 0 file file.aes hex:E76B2413958B00E193\n" \
00048     "\n"
00049 
00050 int main( int argc, char *argv[] )
00051 {
00052     int ret = 1, i, n;
00053     int keylen, mode, lastn;
00054     FILE *fkey, *fin, *fout;
00055 
00056     char *p;
00057     unsigned char IV[16];
00058     unsigned char key[512];
00059     unsigned char digest[32];
00060     unsigned char buffer[1024];
00061 
00062     aes_context aes_ctx;
00063     sha2_context sha_ctx;
00064 
00065 #if defined(WIN32)
00066        LARGE_INTEGER li_size;
00067     __int64 filesize, offset;
00068 #else
00069       off_t filesize, offset;
00070 #endif
00071 
00072     
00073 
00074 
00075     if( argc != 5 )
00076     {
00077         printf( USAGE );
00078 
00079 #if defined(WIN32)
00080         printf( "\n  Press Enter to exit this program.\n" );
00081         fflush( stdout ); getchar();
00082 #endif
00083 
00084         goto exit;
00085     }
00086 
00087     mode = atoi( argv[1] );
00088 
00089     if( mode != MODE_ENCRYPT && mode != MODE_DECRYPT )
00090     {
00091         fprintf( stderr, "invalide operation mode\n" );
00092         goto exit;
00093     }
00094 
00095     if( strcmp( argv[2], argv[3] ) == 0 )
00096     {
00097         fprintf( stderr, "input and output filenames must differ\n" );
00098         goto exit;
00099     }
00100 
00101     if( ( fin = fopen( argv[2], "rb" ) ) == NULL )
00102     {
00103         fprintf( stderr, "fopen(%s,rb) failed\n", argv[2] );
00104         goto exit;
00105     }
00106 
00107     if( ( fout = fopen( argv[3], "wb+" ) ) == NULL )
00108     {
00109         fprintf( stderr, "fopen(%s,wb+) failed\n", argv[3] );
00110         goto exit;
00111     }
00112 
00113     
00114 
00115 
00116     if( ( fkey = fopen( argv[4], "rb" ) ) != NULL )
00117     {
00118         keylen = fread( key, 1, sizeof( key ), fkey );
00119         fclose( fkey );
00120     }
00121     else
00122     {
00123         if( memcmp( argv[4], "hex:", 4 ) == 0 )
00124         {
00125             p = &argv[4][4];
00126             keylen = 0;
00127 
00128             while( sscanf( p, "%02X", &n ) > 0 &&
00129                    keylen < (int) sizeof( key ) )
00130             {
00131                 key[keylen++] = (unsigned char) n;
00132                 p += 2;
00133             }
00134         }
00135         else
00136         {
00137             keylen = strlen( argv[4] );
00138 
00139             if( keylen > (int) sizeof( key ) )
00140                 keylen = (int) sizeof( key );
00141 
00142             memcpy( key, argv[4], keylen );
00143         }
00144     }
00145 
00146     memset( argv[4], 0, strlen( argv[4] ) );
00147 
00148 #if defined(WIN32)
00149     
00150 
00151 
00152     li_size.QuadPart = 0;
00153     li_size.LowPart  =
00154         SetFilePointer( (HANDLE) _get_osfhandle( _fileno( fin ) ),
00155                         li_size.LowPart, &li_size.HighPart, FILE_END );
00156 
00157     if( li_size.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR )
00158     {
00159         fprintf( stderr, "SetFilePointer(0,FILE_END) failed\n" );
00160         goto exit;
00161     }
00162 
00163     filesize = li_size.QuadPart;
00164 #else
00165     if( ( filesize = lseek( fileno( fin ), 0, SEEK_END ) ) < 0 )
00166     {
00167         perror( "lseek" );
00168         goto exit;
00169     }
00170 #endif
00171 
00172     if( fseek( fin, 0, SEEK_SET ) < 0 )
00173     {
00174         fprintf( stderr, "fseek(0,SEEK_SET) failed\n" );
00175         goto exit;
00176     }
00177 
00178     if( mode == MODE_ENCRYPT )
00179     {
00180         
00181 
00182 
00183 
00184         for( i = 0; i < 8; i++ )
00185             buffer[i] = (unsigned char)( filesize >> ( i << 3 ) );
00186 
00187         p = argv[2];
00188 
00189         sha2_starts( &sha_ctx, 0 );
00190         sha2_update( &sha_ctx, buffer, 8 );
00191         sha2_update( &sha_ctx, (unsigned char *) p, strlen( p ) );
00192         sha2_finish( &sha_ctx, digest );
00193 
00194         memcpy( IV, digest, 16 );
00195 
00196         
00197 
00198 
00199 
00200         lastn = (int)( filesize & 0x0F );
00201 
00202         IV[15] = (unsigned char)
00203             ( ( IV[15] & 0xF0 ) | lastn );
00204 
00205         
00206 
00207 
00208         if( fwrite( IV, 1, 16, fout ) != 16 )
00209         {
00210             fprintf( stderr, "fwrite(%d bytes) failed\n", 16 );
00211             goto exit;
00212         }
00213 
00214         
00215 
00216 
00217 
00218         memset( digest, 0,  32 );
00219         memcpy( digest, IV, 16 );
00220 
00221         for( i = 0; i < 8192; i++ )
00222         {
00223             sha2_starts( &sha_ctx, 0 );
00224             sha2_update( &sha_ctx, digest, 32 );
00225             sha2_update( &sha_ctx, key, keylen );
00226             sha2_finish( &sha_ctx, digest );
00227         }
00228 
00229         memset( key, 0, sizeof( key ) );
00230           aes_setkey_enc( &aes_ctx, digest, 256 );
00231         sha2_hmac_starts( &sha_ctx, digest, 32, 0 );
00232 
00233         
00234 
00235 
00236         for( offset = 0; offset < filesize; offset += 16 )
00237         {
00238             n = ( filesize - offset > 16 ) ? 16 : (int)
00239                 ( filesize - offset );
00240 
00241             if( fread( buffer, 1, n, fin ) != (size_t) n )
00242             {
00243                 fprintf( stderr, "fread(%d bytes) failed\n", n );
00244                 goto exit;
00245             }
00246 
00247             for( i = 0; i < 16; i++ )
00248                 buffer[i] = (unsigned char)( buffer[i] ^ IV[i] );
00249 
00250             aes_crypt_ecb( &aes_ctx, AES_ENCRYPT, buffer, buffer );
00251             sha2_hmac_update( &sha_ctx, buffer, 16 );
00252 
00253             if( fwrite( buffer, 1, 16, fout ) != 16 )
00254             {
00255                 fprintf( stderr, "fwrite(%d bytes) failed\n", 16 );
00256                 goto exit;
00257             }
00258 
00259             memcpy( IV, buffer, 16 );
00260         }
00261 
00262         
00263 
00264 
00265         sha2_hmac_finish( &sha_ctx, digest );
00266 
00267         if( fwrite( digest, 1, 32, fout ) != 32 )
00268         {
00269             fprintf( stderr, "fwrite(%d bytes) failed\n", 16 );
00270             goto exit;
00271         }
00272     }
00273 
00274     if( mode == MODE_DECRYPT )
00275     {
00276         unsigned char tmp[16];
00277 
00278         
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287         if( filesize < 48 )
00288         {
00289             fprintf( stderr, "File too short to be encrypted.\n" );
00290             goto exit;
00291         }
00292 
00293         if( ( filesize & 0x0F ) != 0 )
00294         {
00295             fprintf( stderr, "File size not a multiple of 16.\n" );
00296             goto exit;
00297         }
00298 
00299         
00300 
00301 
00302         filesize -= ( 16 + 32 );
00303 
00304         
00305 
00306 
00307         if( fread( buffer, 1, 16, fin ) != 16 )
00308         {
00309             fprintf( stderr, "fread(%d bytes) failed\n", 16 );
00310             goto exit;
00311         }
00312 
00313         memcpy( IV, buffer, 16 );
00314         lastn = IV[15] & 0x0F;
00315 
00316         
00317 
00318 
00319 
00320         memset( digest, 0,  32 );
00321         memcpy( digest, IV, 16 );
00322 
00323         for( i = 0; i < 8192; i++ )
00324         {
00325             sha2_starts( &sha_ctx, 0 );
00326             sha2_update( &sha_ctx, digest, 32 );
00327             sha2_update( &sha_ctx, key, keylen );
00328             sha2_finish( &sha_ctx, digest );
00329         }
00330 
00331         memset( key, 0, sizeof( key ) );
00332           aes_setkey_dec( &aes_ctx, digest, 256 );
00333         sha2_hmac_starts( &sha_ctx, digest, 32, 0 );
00334 
00335         
00336 
00337 
00338         for( offset = 0; offset < filesize; offset += 16 )
00339         {
00340             if( fread( buffer, 1, 16, fin ) != 16 )
00341             {
00342                 fprintf( stderr, "fread(%d bytes) failed\n", 16 );
00343                 goto exit;
00344             }
00345 
00346             memcpy( tmp, buffer, 16 );
00347  
00348             sha2_hmac_update( &sha_ctx, buffer, 16 );
00349             aes_crypt_ecb( &aes_ctx, AES_DECRYPT, buffer, buffer );
00350    
00351             for( i = 0; i < 16; i++ )
00352                 buffer[i] = (unsigned char)( buffer[i] ^ IV[i] );
00353 
00354             memcpy( IV, tmp, 16 );
00355 
00356             n = ( lastn > 0 && offset == filesize - 16 )
00357                 ? lastn : 16;
00358 
00359             if( fwrite( buffer, 1, n, fout ) != (size_t) n )
00360             {
00361                 fprintf( stderr, "fwrite(%d bytes) failed\n", n );
00362                 goto exit;
00363             }
00364         }
00365 
00366         
00367 
00368 
00369         sha2_hmac_finish( &sha_ctx, digest );
00370 
00371         if( fread( buffer, 1, 32, fin ) != 32 )
00372         {
00373             fprintf( stderr, "fread(%d bytes) failed\n", 32 );
00374             goto exit;
00375         }
00376 
00377         if( memcmp( digest, buffer, 32 ) != 0 )
00378         {
00379             fprintf( stderr, "HMAC check failed: wrong key, "
00380                              "or file corrupted.\n" );
00381             goto exit;
00382         }
00383     }
00384 
00385     ret = 0;
00386 
00387 exit:
00388 
00389     memset( buffer, 0, sizeof( buffer ) );
00390     memset( digest, 0, sizeof( digest ) );
00391 
00392     memset( &aes_ctx, 0, sizeof(  aes_context ) );
00393     memset( &sha_ctx, 0, sizeof( sha2_context ) );
00394 
00395     return( ret );
00396 }