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 }