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