skipjackm.nc

来自「good best block cipher」· NC 代码 · 共 436 行

NC
436
字号
/* Implementation of Skipjack, adapted from TinySec:
 *
 * "Copyright (c) 2000-2002 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 * Authors: Naveen Sastry, Yee Wei Law
 * Date:    12/28/02
 * 
 * Ported From C to NesC by Evan Gaustad 12/1/2005
 * 
 * Note:
 * - Comparison between TinySec's and my version:
 *
 *   TinySec	No optimisation	Max speed optimisation
 *   Key setup	26113			25592
 *   Encryption	2969			1597
 *
 *   My			No optimisation	Max speed optimisation
 *   Key setup	187				187
 *   Encryption	2988			1583
 *   
 *   Instructions in overhead	Cycles
 *   mov.w	0x14(SP), R14		3
 *   mov.w	#0x2, R5			2
 *   add.w	R14,R5				1
 *   mov.w	R5,R13				1
 * 
 */

# includes "SkipJack.h";


// G-permutation: 4-round Feistal structure
#define G(key, b, bLeft, bRight)		\
     ( bLeft   = (b >> 8),				\
       bRight  = b,						\
       bLeft  ^= F[bRight ^ (key)[0]],	\
       bRight ^= F[bLeft  ^ (key)[1]],	\
       bLeft  ^= F[bRight ^ (key)[2]],	\
       bRight ^= F[bLeft  ^ (key)[3]],	\
       (bLeft << 8) | bRight)

#define G_INV(key, b, bLeft, bRight)	\
     ( bLeft   = (b >> 8),				\
       bRight  = b,						\
       bRight ^= F[bLeft  ^ (key)[3]],	\
       bLeft  ^= F[bRight ^ (key)[2]],	\
       bRight ^= F[bLeft  ^ (key)[1]],	\
       bLeft  ^= F[bRight ^ (key)[0]],	\
       (bLeft << 8) | bRight)

// Rule A:
#define RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight ) { \
    tmp = w4;                                \
    w4 = w3;                                 \
    w3 = w2;                                 \
    w2 = G(skey, w1, bLeft, bRight);         \
    w1 = w2 ^ tmp ^ counter;                 \
    counter++; }

#define RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight) { \
    tmp = w4;                                \
    w4 = w1 ^ w2 ^ counter;                  \
    w1 = G_INV(skey, w2, bLeft, bRight);     \
    w2 = w3;                                 \
    w3 = tmp;                                \
    counter--; }

// Rule B: 
#define RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight ) { \
    tmp = w1;                                \
    w1 = w4;                                 \
    w4 = w3;                                 \
    w3 = tmp ^ w2 ^ counter;                 \
    w2 = G(skey, tmp, bLeft, bRight);        \
    counter++; }

#define RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight ) { \
    tmp = w1;                                \
    w1 = G_INV(skey, w2, bLeft, bRight);     \
    w2 = w1 ^ w3 ^ counter;                  \
    w3 = w4;                                 \
    w4 = tmp;                                \
    counter--; }

#ifdef L_ENDIAN
#   define SKIPJACK_CTR64_INC(counter)\
    	c = ((u32)(counter)[4] << 24) ^ \
            ((u32)(counter)[5] << 16) ^ \
	        ((u32)(counter)[6] << 8) ^ \
            (u32)(counter)[7];\
    	c++;\
	    (counter)[4] = (u8)(c >> 24); \
        (counter)[5] = (u8)(c >> 16); \
    	(counter)[6] = (u8)(c >> 8); \
        (counter)[7] = (u8)c; 
#else
#   define SKIPJACK_CTR64_INC(counter)\
    	c = ((u32)(counter)[0] << 24) ^ \
            ((u32)(counter)[1] << 16) ^ \
	        ((u32)(counter)[2] << 8) ^ \
            (u32)(counter)[3];\
    	c++;\
    	(counter)[0] = (u8)(c >> 24); \
        (counter)[1] = (u8)(c >> 16); \
    	(counter)[2] = (u8)(c >> 8); \
        (counter)[3] = (u8)c; 
#endif

module SkipJackM {
  provides interface BlockCipher;
  //provides interface BlockCipherInfo;
}
implementation
{
    //void dumpBuffer (char * bufName, uint8_t * buf, uint8_t size);
	  
	const uint8_t F[256] = 
	{
	   0xA3, 0xD7, 0x09, 0x83, 0xF8, 0x48, 0xF6, 0xF4,
	   0xB3, 0x21, 0x15, 0x78, 0x99, 0xB1, 0xAF, 0xF9,
	   0xE7, 0x2D, 0x4D, 0x8A, 0xCE, 0x4C, 0xCA, 0x2E,
	   0x52, 0x95, 0xD9, 0x1E, 0x4E, 0x38, 0x44, 0x28,
	   0x0A, 0xDF, 0x02, 0xA0, 0x17, 0xF1, 0x60, 0x68,
	   0x12, 0xB7, 0x7A, 0xC3, 0xE9, 0xFA, 0x3D, 0x53,
	   0x96, 0x84, 0x6B, 0xBA, 0xF2, 0x63, 0x9A, 0x19,
	   0x7C, 0xAE, 0xE5, 0xF5, 0xF7, 0x16, 0x6A, 0xA2,
	   0x39, 0xB6, 0x7B, 0x0F, 0xC1, 0x93, 0x81, 0x1B,
	   0xEE, 0xB4, 0x1A, 0xEA, 0xD0, 0x91, 0x2F, 0xB8,
	   0x55, 0xB9, 0xDA, 0x85, 0x3F, 0x41, 0xBF, 0xE0,
	   0x5A, 0x58, 0x80, 0x5F, 0x66, 0x0B, 0xD8, 0x90,
	   0x35, 0xD5, 0xC0, 0xA7, 0x33, 0x06, 0x65, 0x69,
	   0x45, 0x00, 0x94, 0x56, 0x6D, 0x98, 0x9B, 0x76,
	   0x97, 0xFC, 0xB2, 0xC2, 0xB0, 0xFE, 0xDB, 0x20,
	   0xE1, 0xEB, 0xD6, 0xE4, 0xDD, 0x47, 0x4A, 0x1D,
	   0x42, 0xED, 0x9E, 0x6E, 0x49, 0x3C, 0xCD, 0x43,
	   0x27, 0xD2, 0x07, 0xD4, 0xDE, 0xC7, 0x67, 0x18,
	   0x89, 0xCB, 0x30, 0x1F, 0x8D, 0xC6, 0x8F, 0xAA,
	   0xC8, 0x74, 0xDC, 0xC9, 0x5D, 0x5C, 0x31, 0xA4,
	   0x70, 0x88, 0x61, 0x2C, 0x9F, 0x0D, 0x2B, 0x87,
	   0x50, 0x82, 0x54, 0x64, 0x26, 0x7D, 0x03, 0x40,
	   0x34, 0x4B, 0x1C, 0x73, 0xD1, 0xC4, 0xFD, 0x3B,
	   0xCC, 0xFB, 0x7F, 0xAB, 0xE6, 0x3E, 0x5B, 0xA5,
	   0xAD, 0x04, 0x23, 0x9C, 0x14, 0x51, 0x22, 0xF0,
	   0x29, 0x79, 0x71, 0x7E, 0xFF, 0x8C, 0x0E, 0xE2,
	   0x0C, 0xEF, 0xBC, 0x72, 0x75, 0x6F, 0x37, 0xA1,
	   0xEC, 0xD3, 0x8E, 0x62, 0x8B, 0x86, 0x10, 0xE8,
	   0x08, 0x77, 0x11, 0xBE, 0x92, 0x4F, 0x24, 0xC5,
	   0x32, 0x36, 0x9D, 0xCF, 0xF3, 0xA6, 0xBB, 0xAC,
	   0x5E, 0x6C, 0xA9, 0x13, 0x57, 0x25, 0xB5, 0xE3,
	   0xBD, 0xA8, 0x3A, 0x01, 0x05, 0x59, 0x2A, 0x46
	};
	
    /**
     *  command init - used to initialize the key, which is expanded and the
     *                 resulting key is stored in *context.
     *  parameters:
     *     *context - is a CipherContext containing the appropriate space for
     *                the encryption key:
     *                   OPTIMISE_SIZE 12 bytes
     *                   TINYSEC 10 bytes
     *                   SPEED_OPTIMIZE 38 bytes
     *     blockSize - size of input/output (bytes)
     *     keySize - key length (bytes)
     *     *key - pointer to key.
     *  output:
     *     *context will contain the expanded key and will be ready for use with
     *     the block cipher.
     */	
	command error_t BlockCipher.init(CipherContext * context, uint8_t 
                                      blockSize, uint8_t keySize, uint8_t * key)
    {
		SKIPJACK_KEY *skey = (SKIPJACK_KEY *)context;
		unsigned char *userKey = (unsigned char *)key;

		// SkipJack only supports keySize of 10 bytes and blockSize of 8 bytes
    	if(blockSize != 8 || keySize != 10 || context == NULL || key == NULL) {
    	    return FAIL;
    	}
		
    	// Expand Key
		#ifdef OPTIMISE_SIZE
			register int i;
			for (i = 0; i < 10; i++) {
				skey->ekey[i] = userKey[i];
			}
			skey->ekey[10] = userKey[0];
			skey->ekey[11] = userKey[1];
		#elif defined(TINYSEC)
			register int i;
			for (i = 0; i < 128; i++) {
				skey->ekey[i] = userKey[i % 10];
		    }
		#else
			skey->ekey[0] = skey->ekey[10] = skey->ekey[20] = skey->ekey[30] = userKey[0];
			skey->ekey[1] = skey->ekey[11] = skey->ekey[21] = skey->ekey[31] = userKey[1];
			skey->ekey[2] = skey->ekey[12] = skey->ekey[22] = skey->ekey[32] = userKey[2];
			skey->ekey[3] = skey->ekey[13] = skey->ekey[23] = skey->ekey[33] = userKey[3];
			skey->ekey[4] = skey->ekey[14] = skey->ekey[24] = skey->ekey[34] = userKey[4];
			skey->ekey[5] = skey->ekey[15] = skey->ekey[25] = skey->ekey[35] = userKey[5];
			skey->ekey[6] = skey->ekey[16] = skey->ekey[26] = skey->ekey[36] = userKey[6];
			skey->ekey[7] = skey->ekey[17] = skey->ekey[27] = skey->ekey[37] = userKey[7];
			skey->ekey[8] = skey->ekey[18] = skey->ekey[28] = userKey[8];
			skey->ekey[9] = skey->ekey[19] = skey->ekey[29] = userKey[9];
		#endif
    	return SUCCESS;	
    }	
    
    /**
     *  command encrypt - used to encrypt one block of plaintext and store
     *                    the resulting encrypted value in cipherBlock.
     *                    the init command must have been called prior to
     *                    execution of this function.
     *  parameters:
     *     *context - is a CipherContext containing the initialized key
     *     *plainBlock - block of plaintext to encrypt
     *     *cipherBlock - pointer to memory of blockSize bytes where the result
     *                    will be stored
     *
     *  output:
     *     *cipherBlock will contain the encrypted form of the plainBlock.
     */	
	async command error_t BlockCipher.encrypt(CipherContext *context,
					     					   uint8_t * plainBlock,
					     					   uint8_t * cipherBlock)
	{ 
		SKIPJACK_KEY *key = (SKIPJACK_KEY *)context;
		uint8_t *in = plainBlock;
		uint8_t *out = cipherBlock;

		register u8 counter = 1;	
	#ifdef OPTIMISE_SIZE	
		register signed char idx = 0;
	#else
		register const u8 *skey = (u8 *)key->ekey;
	#endif	
		register u16 w1, w2, w3, w4, tmp;
		register u8 bLeft, bRight;
		
		w1 = (u16)in[0]<<8 ^ (u16)in[1];
		w2 = (u16)in[2]<<8 ^ (u16)in[3];
		w3 = (u16)in[4]<<8 ^ (u16)in[5];
		w4 = (u16)in[6]<<8 ^ (u16)in[7];
		
	#ifdef OPTIMISE_SIZE
		// counter	key indices
		// 1		0,1,2,3
		// 2		4,5,6,7
		// 3		8,9,0,1 <-- this is why we need 10+2 bytes in the expanded key
		// 4		2,3,4,5
		// 5		6,7,8,9
		// ----------------
		// 6		0,1,2,3
		// ...
		while (counter <= 32) {
			if (counter <= 8 || (counter >= 17 && counter <= 24)) {
				RULE_A((key->ekey+idx), w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			} else {
				RULE_B((key->ekey+idx), w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			}
			idx += 4;
			if (idx >= 10)
				idx -= 10;
		}
	#else
		while (counter <= 8) {
			RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			skey += 4;
		}
	#ifndef TINYSEC
		skey = key->ekey+2;
	#endif	
		while (counter <= 16) {
			RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			skey += 4;
		}
	#ifndef TINYSEC	
		skey = key->ekey+4;
	#endif
		while (counter <= 24) {
			RULE_A(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			skey += 4;
		}
	#ifndef TINYSEC	
		skey = key->ekey+6;
	#endif
		while (counter <= 32) {
			RULE_B(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			skey += 4;
		}
	#endif
	
		out[0] = (u8)(w1 >> 8); out[1] = (u8)w1;
		out[2] = (u8)(w2 >> 8); out[3] = (u8)w2;
		out[4] = (u8)(w3 >> 8); out[5] = (u8)w3;
		out[6] = (u8)(w4 >> 8); out[7] = (u8)w4;
		
		return SUCCESS;	
	}
	
	
	
    /**
     *  command decrypt - used to decrypt one block of ciphertext and store
     *                    the resulting plaintext in *plainBlock.  The init
     *                    command must have been called prior to execution of 
     *                    this function.
     *  parameters:
     *     *context - is a CipherContext containing the key
     *     *plainBlock - pointer to memory of blockSize bytes where the 
     *                   resulting decrypted value will be stored.
     *     *cipherBlock - block of ciphertext to decrypt
     *
     *  output:
     *     *plainBlock will contain the decrypted form of the cipherBlock.
     */	
	async command error_t BlockCipher.decrypt(CipherContext * context,
					     uint8_t * cipherBlock,
					     uint8_t * plainBlock)
    {
    	
    	SKIPJACK_KEY *key = (SKIPJACK_KEY *)context;
		uint8_t *in = cipherBlock;
		uint8_t *out = plainBlock;
    	
    	register u8 counter = 32;	
	#ifdef OPTIMISE_SIZE	
		register signed char idx;
	#else	
		register const u8 *skey;
	#endif	
		register u16 w1, w2, w3, w4, tmp;
		register u8 bLeft, bRight;
		
		w1 = (u16)in[0]<<8 ^ (u16)in[1];
		w2 = (u16)in[2]<<8 ^ (u16)in[3];
		w3 = (u16)in[4]<<8 ^ (u16)in[5];
		w4 = (u16)in[6]<<8 ^ (u16)in[7];
		
	#ifdef OPTIMISE_SIZE
		// counter	key indices
		// 32		4,5,6,7
		// 31		0,1,2,3
		// 30		6,7,8,9
		// 29		2,3,4,5
		// 28		8,9,0,1
		// ----------------
		// 27		4,5,6,7
		// ...
		idx = 4;
		while (counter >= 1) {
			if (counter >= 25 || (counter >= 9 && counter <= 16)) {
				RULE_B_INV((key->ekey+idx), w1, w2, w3, w4, counter, tmp, bLeft, bRight );			
			} else {
				RULE_A_INV((key->ekey+idx), w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			}
			idx -= 4;
			if (idx < 0)
				idx += 10;
		}	
	#else
	#ifdef TINYSEC	
		skey = key->ekey+124;
	#else	
		skey = key->ekey+34;
	#endif	
		while (counter >= 25) {
			RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			skey -= 4;
		}
	#ifndef TINYSEC	
		skey = key->ekey+32;
	#endif
		while (counter >= 17) {
			RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			skey -= 4;
		}
	#ifndef TINYSEC	
		skey = key->ekey+30;
	#endif	
		while (counter >= 9) {
			RULE_B_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			skey -= 4;
		}
	#ifndef TINYSEC	
		skey = key->ekey+28;
	#endif
		while (counter >= 1) {
			RULE_A_INV(skey, w1, w2, w3, w4, counter, tmp, bLeft, bRight );
			skey -= 4;
		}
	#endif
		
		out[0] = (u8)(w1 >> 8); out[1] = (u8)w1;
		out[2] = (u8)(w2 >> 8); out[3] = (u8)w2;
		out[4] = (u8)(w3 >> 8); out[5] = (u8)w3;
		out[6] = (u8)(w4 >> 8); out[7] = (u8)w4;

    	return SUCCESS;	
    }
    
  /**
  * Debug function
  *
  void dumpBuffer (char * bufName, uint8_t * buf, uint8_t size)
    {
      uint8_t i = 0;
      // fixme watch buffer overrun
      char tmp[512];
      for (; i < size; i++) {
       // sprintf (tmp + i * 3, "%2x ", (char)buf[i] & 0xff);

      }
      dbg("DBG_USR1", "%s: {%s}\n", bufName, tmp);
    }
  */
}


⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?