/home/dko/projects/mobilec/trunk/src/security/xyssl-0.9/programs/aes/aescrypt2.c

Go to the documentation of this file.
00001 /*
00002  * AES-256 file encryption program
00003  *
00004  * Copyright (C) 2006-2007 Christophe Devine
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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  * Parse the command-line arguments.
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  * Read the secret key and clean the command line.
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  * Support large files (> 2Gb) on Win32
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  * Generate the initialization vector as:
00182  * IV = SHA-256( filesize || filename )[0..15]
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  * The last four bits in the IV are actually used
00198  * to store the file size modulo the AES block size.
00199  */
00200 lastn = (int)( filesize & 0x0F );
00201 
00202 IV[15] = (unsigned char)
00203 ( ( IV[15] & 0xF0 ) | lastn );
00204 
00205 /*
00206  * Append the IV at the beginning of the output.
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  * Hash the IV and the secret key together 8192 times
00216  * using the result to setup the AES context and HMAC.
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  * Encrypt and write the ciphertext.
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  * Finally write the HMAC.
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  * The encrypted file must be structured as follows:
00280  *
00281  * 00 .. 15 Initialization Vector
00282  * 16 .. 31 AES Encrypted Block #1
00283  * ..
00284  * N*16 .. (N+1)*16 - 1 AES Encrypted Block #N
00285  * (N+1)*16 .. (N+1)*16 + 32 HMAC-SHA-256(ciphertext)
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  * Substract the IV + HMAC length.
00301  */
00302 filesize -= ( 16 + 32 );
00303 
00304 /*
00305  * Read the IV and original filesize modulo 16.
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  * Hash the IV and the secret key together 8192 times
00318  * using the result to setup the AES context and HMAC.
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  * Decrypt and write the plaintext.
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  * Verify the message authentication code.
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 }

Generated on Tue Oct 28 17:03:23 2008 for Mobile-C by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /