/* * DES V1.1.0 - reconstructed from des.exe * Original executable: (C) 1998 H.N.M. Dijkema, GPL * * IMPORTANT: despite the program name, the executable selects * CRYPT_ALGO_3DES + CRYPT_MODE_CBC, i.e. two-key triple DES in CBC mode. * * This is reconstructed source, not the original source text. Control flow, * constants, CRYPTLIB calls and file-format behaviour are derived from the * 16-bit Turbo C executable and verified against CRYPTLIB 0.99 source. */ #include #include #include #include #include "crypt.h" #include "des_common.h" int main( int argc, char **argv ) { char *password; char *inputName; char *outputName; FILE *input; FILE *output; unsigned char *buffer; unsigned char *payload; BYTE key[ CRYPT_MAX_KEYSIZE ]; BYTE iv[ CRYPT_MAX_IVSIZE ]; BYTE passwordBlock[ CRYPT_MAX_KEYSIZE ]; CRYPT_INFO cryptInfo; CRYPT_QUERY_INFO queryInfo; CRYPT_ALGO algorithm = CRYPT_ALGO_3DES; CRYPT_MODE mode = CRYPT_MODE_CBC; DES_INT32 fileVersion = DES_FILE_VERSION; int keySize; int ivSize; int bytesRead; int firstTime; int inputFd; int i; if( argc == 2 ) { if( strcmp( argv[ 1 ], "--copyright" ) == 0 ) { printf( "%s\n\n", desProgramVersion ); printf( "%s", desCopyrightText ); exit( 0 ); } if( strcmp( argv[ 1 ], "--version" ) == 0 ) { printf( "%s\n", desProgramVersion ); exit( 0 ); } } if( argc != 4 ) { fprintf( stderr, "usage: des \n" " des --copyright\n" " des --version\n" " '-' for file --> stdin/stdout\n" ); exit( argc == 1 ? 0 : 2 ); } password = argv[ 1 ]; inputName = argv[ 2 ]; outputName = argv[ 3 ]; if( strcmp( inputName, "-" ) != 0 && strcmp( inputName, outputName ) == 0 ) { fprintf( stderr, " and cannot be the same\n" ); exit( 1 ); } input = ( strcmp( inputName, "-" ) == 0 ) ? stdin : fopen( inputName, "rb" ); output = ( strcmp( outputName, "-" ) == 0 ) ? stdout : fopen( outputName, "wb" ); checkOpen( input, inputName ); checkOpen( output, outputName ); /* The executable writes exactly four bytes here. */ fwrite( &fileVersion, 4, 1, output ); algorithm = CRYPT_ALGO_3DES; mode = CRYPT_MODE_CBC; buffer = (unsigned char *) malloc( DES_BUFFER_SIZE ); if( buffer == NULL ) { fprintf( stderr, "Cannot allocate buffer\n" ); exit( 1 ); } payload = buffer + DES_PREFIX_SIZE; initLibrary(); queryAlgoModeInformation( algorithm, mode, &queryInfo ); keySize = queryInfo.keySize; /* 14 bytes for 3DES-CBC in 0.99 */ ivSize = queryInfo.ivSize; /* 4 bytes for 3DES-CBC in 0.99 */ i = 0; while( i < keySize && password[ i ] != '\0' ) { key[ i ] = (BYTE) password[ i ]; i++; } while( i < keySize ) key[ i++ ] = 0; initCryptContext( &cryptInfo, algorithm, mode ); loadCryptContext( &cryptInfo, key, keySize ); firstTime = TRUE; inputFd = fileno( input ); bytesRead = read( inputFd, payload, DES_PAYLOAD_SIZE ); checkRead( bytesRead ); while( bytesRead != 0 ) { DES_INT32 marker; if( bytesRead == DES_PAYLOAD_SIZE ) { marker = negativeMarker( payload ); if( marker == 0 ) marker = (DES_INT32) -1; memcpy( buffer, &marker, 4 ); marker = negativeMarker( payload + 4 ); memcpy( buffer + 4, &marker, 4 ); } else { marker = (DES_INT32) bytesRead; memcpy( buffer, &marker, 4 ); marker = negativeMarker( payload ); memcpy( buffer + 4, &marker, 4 ); } /* The executable always encrypts the complete 16 KiB buffer. */ encryptBuffer( &cryptInfo, buffer, DES_BUFFER_SIZE ); if( firstTime ) { /* * CRYPTLIB generates the IV on the first encryptBuffer() call. * Therefore it can only be retrieved after that call. */ queryContextInformation( &cryptInfo, &queryInfo ); ivSize = queryInfo.ivSize; retrieveIV( &cryptInfo, iv ); fwrite( iv, ivSize, 1, output ); checkWrite( output ); fflush( output ); /* * Only keySize bytes are assigned. The remaining bytes of this * 256-byte stack buffer are intentionally left as they were in the * original executable; UNDES compares only the first keySize bytes. */ for( i = 0; i < keySize; i++ ) passwordBlock[ i ] = key[ i ]; encryptBuffer( &cryptInfo, passwordBlock, CRYPT_MAX_KEYSIZE ); fwrite( passwordBlock, CRYPT_MAX_KEYSIZE, 1, output ); checkWrite( output ); fflush( output ); firstTime = FALSE; } fwrite( buffer, DES_BUFFER_SIZE, 1, output ); checkWrite( output ); fflush( output ); bytesRead = read( inputFd, payload, DES_PAYLOAD_SIZE ); checkRead( bytesRead ); } /* Courtesy close call used by CRYPTLIB block-cipher examples. */ encryptBuffer( &cryptInfo, buffer, 0 ); destroyCryptContext( &cryptInfo ); endLibrary(); free( buffer ); if( input != stdin ) fclose( input ); if( output != stdout ) fclose( output ); return( 0 ); }