www.pudn.com > crypto1.rar > crypto1_c.htm, change:2011-07-28,size:5637b


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> 
<!-- saved from url=(0046)http://cryptolib.com/ciphers/crypto1/crypto1.c --> 
<HTML><HEAD> 
<META content="text/html; charset=gb2312" http-equiv=Content-Type> 
<META name=GENERATOR content="MSHTML 8.00.6001.19088"></HEAD> 
<BODY><PRE>// Software optimized 48-bit Philips/NXP Mifare "Classic" CRYPTO-1 stream cipher algorithm by I.C. Wiener 2007-2008. 
// For educational purposes only. 
// No warranties or guarantees of any kind. 
// This code is released into the public domain by its author. 
 
#include <stdio.h> 
 
// Basic macros: 
 
#define u8				unsigned char 
#define u32				unsigned long 
#define u64				unsigned long long 
#define rev8(x)			((((x)>>7)&1)^((((x)>>6)&1)<<1)^((((x)>>5)&1)<<2)^((((x)>>4)&1)<<3)^((((x)>>3)&1)<<4)^((((x)>>2)&1)<<5)^((((x)>>1)&1)<<6)^(((x)&1)<<7)) 
#define rev16(x)		(rev8 (x)^(rev8 (x>> 8)<< 8)) 
#define rev32(x)		(rev16(x)^(rev16(x>>16)<<16)) 
#define bit(x,n)		(((x)>>(n))&1) 
 
// Single bit CRYPTO-1 functions: 
 
// PRNG 
 
static u32 crypto1_next (u32 x, const u32 n) 
{ 
	u32		i; 
	 
	x = rev32(x); 
	for (i = 0; i < n; i++) x=(x<<1)+(((x>>15)^(x>>13)^(x>>12)^(x>>10))&1); 
	return rev32(x); 
} 
 
#define i4(x,a,b,c,d)	((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) 
 
static const u32 mf1_f4a = 0x9E98; 
static const u32 mf1_f4b = 0xB48E; 
static const u32 mf1_f5c = 0xEC57E80A; 
 
// Nonlinear output/feedback function 
 
static u32 nf20 (const u64 x) 
{ 
	u32		i5; 
	 
	i5 = ((mf1_f4b >> i4 (x, 9,11,13,15)) & 1)* 1 
	   + ((mf1_f4a >> i4 (x,17,19,21,23)) & 1)* 2 
	   + ((mf1_f4a >> i4 (x,25,27,29,31)) & 1)* 4 
	   + ((mf1_f4b >> i4 (x,33,35,37,39)) & 1)* 8 
	   + ((mf1_f4a >> i4 (x,41,43,45,47)) & 1)*16; 
	 
	return (mf1_f5c >> i5) & 1; 
} 
 
// Linear output/feedback function 
 
static u32 lf18 (const u64 x) 
{ 
	return  (((x >>  0) ^ (x >>  5) ^ (x >>  9) ^ (x >> 10) ^ (x >> 12) ^ (x >> 14) 
			^ (x >> 15) ^ (x >> 17) ^ (x >> 19) ^ (x >> 24) ^ (x >> 25) ^ (x >> 27) 
			^ (x >> 29) ^ (x >> 35) ^ (x >> 39) ^ (x >> 41) ^ (x >> 42) ^ (x >> 43)) & 1); 
} 
 
// Single CRYPTO-1 round 
 
// 0 - no feedback 
// 1 - linear feedback 
// 2 - nonlinear feedback 
// 3 - both 
 
static u32 crypto1_round (u64 *state, const u64 in_bit, const u32 fb) 
{ 
	u64		x = *state; 
	u32		lf, nf; 
	 
	lf = lf18(x); 
	nf = nf20 (x); 
	x = (x>>1) ^ ((in_bit ^ (fb&1?lf:0) ^ (fb&2?nf:0)) << 47); 
	*state = x; 
	return nf; 
} 
 
// 32 CRYPTO-1 rounds 
 
static u32 crypto1_word (u64 * x, const u32 in_word, const u32 fb) 
{ 
	u32		i, o; 
	 
	for (i = 0, o = 0; i < 32; i++) o += (u32) crypto1_round (x, bit(in_word,i^24), fb) << (i^24); 
	return o; 
} 
 
#define tests	8 
 
int main (void) 
{ 
	u32		i, k; 
	u64		s[tests]; 
	u64		key[tests] = {-1ULL>>16,  -1ULL>>16,  -1ULL>>16,  -1ULL>>16,  -1ULL>>16,  -1ULL>>16,  -1ULL>>16,  -1ULL>>16}; 
	u32		ID[tests] = {0x7BED1AFD, 0x7BED1AFD, 0x7BED1AFD, 0x7BED1AFD, 0x7BED1AFD, 0x7BED1AFD, 0x7BED1AFD, 0x7BED1AFD}; 
	u32		TC[tests] = {0x01020304, 0x02030405, 0x03040506, 0x04050607, 0x05060708, 0x06070809, 0x0708090A, 0x08090A0B}; 
	u32		RC[tests] = {0x12345678, 0x23456789, 0x3456789A, 0x456789AB, 0x56789ABC, 0x6789ABCD, 0x789ABCDE, 0x89ABCDEF}; 
	u32		RR[tests] = {0x8D3A9A9C, 0x525BF719, 0xB3B6BCF5, 0x8D58D582, 0x1A4389AD, 0x8E791939, 0x6D3566AF, 0x870B0215}; 
	u32		TR[tests] = {0x7208E6C6, 0xBBEF66AE, 0xC622FC7F, 0x21741A05, 0xE350ACD9, 0xD0240BF8, 0xF0B5A5C5, 0x8AD097B3}; 
	u32		KS[tests][5] = 
	{ 
		{0xF0293188, 0x96188BA7, 0x8743C386, 0x4BAFEEF2, 0x9F5B3C53}, 
		{0x6C5976CF, 0x4B2F94B8, 0x77B92595, 0xDDB19335, 0xB811C5A5}, 
		{0x7E55F18D, 0xE0AB17F7, 0xFFCF6559, 0x131E7093, 0x7145E26B}, 
		{0xBFDC7361, 0x9403B607, 0x26E4D8F2, 0xFEBAB9F0, 0x81AEB1C9}, 
		{0xD556A1EC, 0x8759D54D, 0xC5B10ACE, 0xB6A9C3CD, 0x94F5A51C}, 
		{0x0916465B, 0x0A9AE66B, 0x31EF4F79, 0x044D4505, 0xEE4125C4}, 
		{0x99C49847, 0x525B1DE4, 0xB7F78842, 0xF3A36608, 0x72E92768}, 
		{0xFEA22F39, 0x3B809753, 0x9893345F, 0x82371E6D, 0xBB9DEFAF} 
	}; 
	 
	for (k = 0; k < tests; k++) 
	{ 
	//	s[k] = key[k]; 
	//	crypto1_word (s+k, ID[k] ^ TC[k], 1); 
	//	crypto1_word (s+k, RC[k]        , 3); 
	//	RR[k] = crypto1_next (TC[k], 64) ^ crypto1_word (s+k, 0, 1); 
	//	TR[k] = crypto1_next (TC[k], 96) ^ crypto1_word (s+k, 0, 1); 
	//	KS[k][0] = 0x3002108B ^ crypto1_word (s+k, 0, 1); 
	//	for (i = 1; i < 5; i++) KS[k][i] = crypto1_word (s+k, 0, 1); 
		s[k] = key[k]; 
		crypto1_word (s+k, ID[k] ^ TC[k], 1); printf ("%08X ", TC[k]); 
		crypto1_word (s+k, RC[k]        , 3); printf ("%08X ", RC[k]); 
		printf ("UID: %08X\nTag Challenge: %08X\nReader Challenge: %08X\nReader Response: %08X\nTag Response:%08X\nTag Command:%08X\nTag Data: %08X %08X %08X %08X\n\n", 
			ID[k], TC[k], RC[k], RR[k], TR[k], KS[k][0], KS[k][1], KS[k][2], KS[k][3], KS[k][4]); 
		printf ("%s ", (crypto1_next (TC[k], 64) ^ crypto1_word (s+k, 0, 1)) == RR[k] ? "OK" : "??"); 
		printf ("%s ", (crypto1_next (TC[k], 96) ^ crypto1_word (s+k, 0, 1)) == TR[k] ? "OK" : "??"); 
		for (i = 0; i < 5; i++) printf ("%08X ", KS[k][i] ^ crypto1_word (s+k, 0, 1)); 
		printf ("\n\n"); 
	} 
	return 0; 
} 
</PRE></BODY></HTML>