Files
des_undes/undes.c
T

194 lines
5.0 KiB
C

/*
* UNDES V1.1.0 - reconstructed from undes.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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#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_INT32 plainLength;
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: undes <passwd> <file in> <file out>\n"
" undes --copyright\n"
" undes --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, "<file in> and <file out> 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 );
algorithm = CRYPT_ALGO_3DES;
mode = CRYPT_MODE_CBC;
firstTime = TRUE;
buffer = (unsigned char *) malloc( DES_BUFFER_SIZE );
if( buffer == NULL )
{
fprintf( stderr, "Can't allocate buffer\n" );
exit( 1 );
}
payload = buffer + DES_PREFIX_SIZE;
initLibrary();
queryAlgoModeInformation( algorithm, mode, &queryInfo );
keySize = queryInfo.keySize; /* 14 bytes */
ivSize = queryInfo.ivSize; /* 4 bytes */
i = 0;
while( i < keySize && password[ i ] != '\0' )
{
key[ i ] = (BYTE) password[ i ];
i++;
}
while( i < keySize )
key[ i++ ] = 0;
fileVersion = (DES_INT32) -1;
inputFd = fileno( input );
bytesRead = read( inputFd, &fileVersion, 4 );
checkRead( bytesRead );
checkVersion( fileVersion );
initCryptContext( &cryptInfo, algorithm, mode );
loadCryptContext( &cryptInfo, key, keySize );
queryContextInformation( &cryptInfo, &queryInfo );
ivSize = queryInfo.ivSize;
bytesRead = read( inputFd, iv, ivSize );
checkRead( bytesRead );
loadIV( &cryptInfo, iv, ivSize );
bytesRead = read( inputFd, passwordBlock, CRYPT_MAX_KEYSIZE );
checkRead( bytesRead );
bytesRead = read( inputFd, buffer, DES_BUFFER_SIZE );
checkRead( bytesRead );
while( bytesRead != 0 )
{
/*
* This ordering is intentional. DES encrypts the first data block
* before passwordBlock, although passwordBlock is stored first in the
* file. Decrypting in the same crypto order preserves CBC state.
*/
decryptBuffer( &cryptInfo, buffer, DES_BUFFER_SIZE );
memcpy( &plainLength, buffer, 4 );
if( plainLength < 0 )
plainLength = DES_PAYLOAD_SIZE;
if( firstTime )
{
decryptBuffer( &cryptInfo, passwordBlock, CRYPT_MAX_KEYSIZE );
i = 0;
while( i < keySize && passwordBlock[ i ] == key[ i ] )
i++;
if( i != keySize )
{
fprintf( stderr,
"Password is not correct, no decryption possible\n" );
exit( 1 );
}
firstTime = FALSE;
}
fwrite( payload, (DES_UINT16) plainLength, 1, output );
checkWrite( output );
fflush( output );
bytesRead = read( inputFd, buffer, DES_BUFFER_SIZE );
checkRead( bytesRead );
}
decryptBuffer( &cryptInfo, buffer, 0 );
destroyCryptContext( &cryptInfo );
endLibrary();
free( buffer );
if( input != stdin )
fclose( input );
if( output != stdout )
fclose( output );
return( 0 );
}