diff options
Diffstat (limited to 'lib/arc.c')
| -rw-r--r-- | lib/arc.c | 170 | 
1 files changed, 86 insertions, 84 deletions
| @@ -21,20 +21,20 @@  *                                                                           *  \***************************************************************************/ -/*  +/*     This file implements ArcFour-encryption, which will mainly be used to     save IM passwords safely in the new XML-format. Possibly other uses will     come up later. It's supposed to be quite reliable (thanks to the use of a     6-byte IV/seed), certainly compared to the old format. The only realistic     way to crack BitlBee passwords now is to use a sniffer to get your hands     on the user's password. -    +     If you see that something's wrong in this implementation (I asked a     couple of people to look at it already, but who knows), please tell me. -    +     The reason I picked ArcFour is because it's pretty simple but effective,     so it will work without adding several KBs or an extra library dependency. -    +     (ArcFour is an RC4-compatible cipher. See for details:     http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt)  */ @@ -56,37 +56,37 @@     many bytes we'll request before we'll really use them for encryption. */  #define ARC_CYCLES 1024 -struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles ) +struct arc_state *arc_keymaker(unsigned char *key, int kl, int cycles)  {  	struct arc_state *st;  	int i, j, tmp;  	unsigned char S2[256]; -	 -	st = g_malloc( sizeof( struct arc_state ) ); + +	st = g_malloc(sizeof(struct arc_state));  	st->i = st->j = 0; -	if( kl <= 0 ) -		kl = strlen( (char*) key ); -	 -	for( i = 0; i < 256; i ++ ) -	{ +	if (kl <= 0) { +		kl = strlen((char *) key); +	} + +	for (i = 0; i < 256; i++) {  		st->S[i] = i; -		S2[i] = key[i%kl]; +		S2[i] = key[i % kl];  	} -	 -	for( i = j = 0; i < 256; i ++ ) -	{ -		j = ( j + st->S[i] + S2[i] ) & 0xff; + +	for (i = j = 0; i < 256; i++) { +		j = (j + st->S[i] + S2[i]) & 0xff;  		tmp = st->S[i];  		st->S[i] = st->S[j];  		st->S[j] = tmp;  	} -	 -	memset( S2, 0, 256 ); + +	memset(S2, 0, 256);  	i = j = 0; -	 -	for( i = 0; i < cycles; i ++ ) -		arc_getbyte( st ); -	 + +	for (i = 0; i < cycles; i++) { +		arc_getbyte(st); +	} +  	return st;  } @@ -95,23 +95,23 @@ struct arc_state *arc_keymaker( unsigned char *key, int kl, int cycles )     a stream of bytes after you give it a key. Just get a byte from it and     xor it with your cleartext. To decrypt, just give it the same key again     and start xorring. -    +     The function above initializes the byte generator, the next function can     be used to get bytes from the generator (and shuffle things a bit).  */ -unsigned char arc_getbyte( struct arc_state *st ) +unsigned char arc_getbyte(struct arc_state *st)  {  	unsigned char tmp; -	 +  	/* Unfortunately the st-> stuff doesn't really improve readability here... */ -	st->i ++; +	st->i++;  	st->j += st->S[st->i];  	tmp = st->S[st->i];  	st->S[st->i] = st->S[st->j];  	st->S[st->j] = tmp;  	tmp = (st->S[st->i] + st->S[st->j]) & 0xff; -	 +  	return st->S[tmp];  } @@ -121,103 +121,105 @@ unsigned char arc_getbyte( struct arc_state *st )     by default) random bytes to the password before setting up the state     structures. These 6 bytes are also saved in the results, because of     course we'll need them in arc_decode(). -    +     Because the length of the resulting string is unknown to the caller,     it should pass a char**. Since the encode/decode functions allocate     memory for the string, make sure the char** points at a NULL-pointer     (or at least to something you already free()d), or you'll leak     memory. And of course, don't forget to free() the result when you     don't need it anymore. -    +     Both functions return the number of bytes in the result string. -    +     Note that if you use the pad_to argument, you will need zero-termi-     nation to find back the original string length after decryption. So     it shouldn't be used if your string contains \0s by itself!  */ -int arc_encode( char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to ) +int arc_encode(char *clear, int clear_len, unsigned char **crypt, char *password, int pad_to)  {  	struct arc_state *st;  	unsigned char *key;  	char *padded = NULL;  	int key_len, i, padded_len; -	 -	key_len = strlen( password ) + ARC_IV_LEN; -	if( clear_len <= 0 ) -		clear_len = strlen( clear ); -	 + +	key_len = strlen(password) + ARC_IV_LEN; +	if (clear_len <= 0) { +		clear_len = strlen(clear); +	} +  	/* Pad the string to the closest multiple of pad_to. This makes it  	   impossible to see the exact length of the password. */ -	if( pad_to > 0 && ( clear_len % pad_to ) > 0 ) -	{ -		padded_len = clear_len + pad_to - ( clear_len % pad_to ); -		padded = g_malloc( padded_len ); -		memcpy( padded, clear, clear_len ); -		 +	if (pad_to > 0 && (clear_len % pad_to) > 0) { +		padded_len = clear_len + pad_to - (clear_len % pad_to); +		padded = g_malloc(padded_len); +		memcpy(padded, clear, clear_len); +  		/* First a \0 and then random data, so we don't have to do  		   anything special when decrypting. */  		padded[clear_len] = 0; -		random_bytes( (unsigned char*) padded + clear_len + 1, padded_len - clear_len - 1 ); -		 +		random_bytes((unsigned char *) padded + clear_len + 1, padded_len - clear_len - 1); +  		clear = padded;  		clear_len = padded_len;  	} -	 +  	/* Prepare buffers and the key + IV */ -	*crypt = g_malloc( clear_len + ARC_IV_LEN ); -	key = g_malloc( key_len ); -	strcpy( (char*) key, password ); -	 +	*crypt = g_malloc(clear_len + ARC_IV_LEN); +	key = g_malloc(key_len); +	strcpy((char *) key, password); +  	/* Add the salt. Save it for later (when decrypting) and, of course,  	   add it to the encryption key. */ -	random_bytes( crypt[0], ARC_IV_LEN ); -	memcpy( key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN ); -	 +	random_bytes(crypt[0], ARC_IV_LEN); +	memcpy(key + key_len - ARC_IV_LEN, crypt[0], ARC_IV_LEN); +  	/* Generate the initial S[] from the IVed key. */ -	st = arc_keymaker( key, key_len, ARC_CYCLES ); -	g_free( key ); -	 -	for( i = 0; i < clear_len; i ++ ) -		crypt[0][i+ARC_IV_LEN] = clear[i] ^ arc_getbyte( st ); -	 -	g_free( st ); -	g_free( padded ); -	 +	st = arc_keymaker(key, key_len, ARC_CYCLES); +	g_free(key); + +	for (i = 0; i < clear_len; i++) { +		crypt[0][i + ARC_IV_LEN] = clear[i] ^ arc_getbyte(st); +	} + +	g_free(st); +	g_free(padded); +  	return clear_len + ARC_IV_LEN;  } -int arc_decode( unsigned char *crypt, int crypt_len, char **clear, const char *password ) +int arc_decode(unsigned char *crypt, int crypt_len, char **clear, const char *password)  {  	struct arc_state *st;  	unsigned char *key;  	int key_len, clear_len, i; -	 -	key_len = strlen( password ) + ARC_IV_LEN; + +	key_len = strlen(password) + ARC_IV_LEN;  	clear_len = crypt_len - ARC_IV_LEN; -	 -	if( clear_len < 0 ) -	{ -		*clear = g_strdup( "" ); + +	if (clear_len < 0) { +		*clear = g_strdup("");  		return -1;  	} -	 +  	/* Prepare buffers and the key + IV */ -	*clear = g_malloc( clear_len + 1 ); -	key = g_malloc( key_len ); -	strcpy( (char*) key, password ); -	for( i = 0; i < ARC_IV_LEN; i ++ ) -		key[key_len-ARC_IV_LEN+i] = crypt[i]; -	 +	*clear = g_malloc(clear_len + 1); +	key = g_malloc(key_len); +	strcpy((char *) key, password); +	for (i = 0; i < ARC_IV_LEN; i++) { +		key[key_len - ARC_IV_LEN + i] = crypt[i]; +	} +  	/* Generate the initial S[] from the IVed key. */ -	st = arc_keymaker( key, key_len, ARC_CYCLES ); -	g_free( key ); -	 -	for( i = 0; i < clear_len; i ++ ) -		clear[0][i] = crypt[i+ARC_IV_LEN] ^ arc_getbyte( st ); +	st = arc_keymaker(key, key_len, ARC_CYCLES); +	g_free(key); + +	for (i = 0; i < clear_len; i++) { +		clear[0][i] = crypt[i + ARC_IV_LEN] ^ arc_getbyte(st); +	}  	clear[0][i] = 0; /* Nice to have for plaintexts. */ -	 -	g_free( st ); -	 + +	g_free(st); +  	return clear_len;  } | 
