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