1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis 2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic 4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner. 5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express 7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works. 8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com 10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @file skipjack.c 14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Skipjack Implementation by Tom St Denis 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h" 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef SKIPJACK 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectconst struct ltc_cipher_descriptor skipjack_desc = 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project "skipjack", 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 17, 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 10, 10, 8, 32, 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project &skipjack_setup, 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project &skipjack_ecb_encrypt, 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project &skipjack_ecb_decrypt, 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project &skipjack_test, 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project &skipjack_done, 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project &skipjack_keysize, 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}; 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic const unsigned char sbox[256] = { 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9, 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28, 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53, 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2, 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8, 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90, 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76, 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d, 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18, 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4, 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40, 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5, 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2, 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8, 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac, 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}; 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* simple x + 1 (mod 10) in one step. */ 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic const int keystep[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* simple x - 1 (mod 10) in one step */ 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic const int ikeystep[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 }; 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /** 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Initialize the Skipjack block cipher 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param key The symmetric key you wish to pass 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param keylen The key length in bytes 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param num_rounds The number of rounds desired (0 for default) 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param skey The key in as scheduled by this function. 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK if successful 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int x; 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(key != NULL); 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(skey != NULL); 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (keylen != 10) { 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_KEYSIZE; 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (num_rounds != 32 && num_rounds != 0) { 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_ROUNDS; 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* make sure the key is in range for platforms where CHAR_BIT != 8 */ 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (x = 0; x < 10; x++) { 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project skey->skipjack.key[x] = key[x] & 255; 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define RULE_A \ 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project tmp = g_func(w1, &kp, skey->skipjack.key); \ 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w1 = tmp ^ w4 ^ x; \ 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w4 = w3; w3 = w2; \ 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w2 = tmp; 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define RULE_B \ 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project tmp = g_func(w1, &kp, skey->skipjack.key); \ 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project tmp1 = w4; w4 = w3; \ 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w3 = w1 ^ w2 ^ x; \ 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w1 = tmp1; w2 = tmp; 101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define RULE_A1 \ 103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project tmp = w1 ^ w2 ^ x; \ 104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w1 = ig_func(w2, &kp, skey->skipjack.key); \ 105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w2 = w3; w3 = w4; w4 = tmp; 106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define RULE_B1 \ 108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project tmp = ig_func(w2, &kp, skey->skipjack.key); \ 109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w2 = tmp ^ w3 ^ x; \ 110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w3 = w4; w4 = w1; w1 = tmp; 111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic unsigned g_func(unsigned w, int *kp, unsigned char *key) 113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char g1,g2; 115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project g1 = (w >> 8) & 255; g2 = w & 255; 117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; 118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; 119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; 120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; 121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ((unsigned)g1<<8)|(unsigned)g2; 122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic unsigned ig_func(unsigned w, int *kp, unsigned char *key) 125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char g1,g2; 127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project g1 = (w >> 8) & 255; g2 = w & 255; 129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; 130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; 131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; 132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; 133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ((unsigned)g1<<8)|(unsigned)g2; 134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Encrypts a block of text with Skipjack 138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param pt The input plaintext (8 bytes) 139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param ct The output ciphertext (8 bytes) 140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param skey The key as scheduled 141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK if successful 142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK 144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int _skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else 146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned w1,w2,w3,w4,tmp,tmp1; 150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int x, kp; 151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(pt != NULL); 153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(ct != NULL); 154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(skey != NULL); 155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* load block */ 157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w1 = ((unsigned)pt[0]<<8)|pt[1]; 158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w2 = ((unsigned)pt[2]<<8)|pt[3]; 159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w3 = ((unsigned)pt[4]<<8)|pt[5]; 160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w4 = ((unsigned)pt[6]<<8)|pt[7]; 161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 8 rounds of RULE A */ 163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (x = 1, kp = 0; x < 9; x++) { 164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project RULE_A; 165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 8 rounds of RULE B */ 168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; x < 17; x++) { 169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project RULE_B; 170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 8 rounds of RULE A */ 173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; x < 25; x++) { 174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project RULE_A; 175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 8 rounds of RULE B */ 178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; x < 33; x++) { 179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project RULE_B; 180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* store block */ 183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ct[0] = (w1>>8)&255; ct[1] = w1&255; 184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ct[2] = (w2>>8)&255; ct[3] = w2&255; 185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ct[4] = (w3>>8)&255; ct[5] = w3&255; 186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ct[6] = (w4>>8)&255; ct[7] = w4&255; 187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK 192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int err = _skipjack_ecb_encrypt(pt, ct, skey); 195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project burn_stack(sizeof(unsigned) * 8 + sizeof(int) * 2); 196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Decrypts a block of text with Skipjack 202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param ct The input ciphertext (8 bytes) 203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param pt The output plaintext (8 bytes) 204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param skey The key as scheduled 205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK if successful 206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK 208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int _skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else 210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned w1,w2,w3,w4,tmp; 214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int x, kp; 215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(pt != NULL); 217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(ct != NULL); 218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(skey != NULL); 219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* load block */ 221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w1 = ((unsigned)ct[0]<<8)|ct[1]; 222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w2 = ((unsigned)ct[2]<<8)|ct[3]; 223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w3 = ((unsigned)ct[4]<<8)|ct[5]; 224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project w4 = ((unsigned)ct[6]<<8)|ct[7]; 225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 8 rounds of RULE B^-1 227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Note the value "kp = 8" comes from "kp = (32 * 4) mod 10" where 32*4 is 128 which mod 10 is 8 229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (x = 32, kp = 8; x > 24; x--) { 231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project RULE_B1; 232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 8 rounds of RULE A^-1 */ 235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; x > 16; x--) { 236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project RULE_A1; 237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 8 rounds of RULE B^-1 */ 241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; x > 8; x--) { 242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project RULE_B1; 243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 8 rounds of RULE A^-1 */ 246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; x > 0; x--) { 247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project RULE_A1; 248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* store block */ 251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pt[0] = (w1>>8)&255; pt[1] = w1&255; 252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pt[2] = (w2>>8)&255; pt[3] = w2&255; 253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pt[4] = (w3>>8)&255; pt[5] = w3&255; 254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pt[6] = (w4>>8)&255; pt[7] = w4&255; 255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK 260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int err = _skipjack_ecb_decrypt(ct, pt, skey); 263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project burn_stack(sizeof(unsigned) * 7 + sizeof(int) * 2); 264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Performs a self-test of the Skipjack block cipher 270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled 271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint skipjack_test(void) 273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project #ifndef LTC_TEST 275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_NOP; 276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project #else 277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project static const struct { 278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char key[10], pt[8], ct[8]; 279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } tests[] = { 280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project { 281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project { 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, 282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project { 0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa }, 283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project { 0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00 } 284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project }; 286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char buf[2][8]; 287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int x, y, err; 288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project symmetric_key key; 289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { 291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* setup key */ 292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = skipjack_setup(tests[x].key, 10, 0, &key)) != CRYPT_OK) { 293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* encrypt and decrypt */ 297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project skipjack_ecb_encrypt(tests[x].pt, buf[0], &key); 298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project skipjack_ecb_decrypt(buf[0], buf[1], &key); 299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* compare */ 301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (XMEMCMP(buf[0], tests[x].ct, 8) != 0 || XMEMCMP(buf[1], tests[x].pt, 8) != 0) { 302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_FAIL_TESTVECTOR; 303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ 306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < 8; y++) buf[0][y] = 0; 307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < 1000; y++) skipjack_ecb_encrypt(buf[0], buf[0], &key); 308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < 1000; y++) skipjack_ecb_decrypt(buf[0], buf[0], &key); 309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; 310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project #endif 314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** Terminate the context 317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param skey The scheduled key 318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid skipjack_done(symmetric_key *skey) 320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project Gets suitable key size 325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. 326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK if the input key size is acceptable. 327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint skipjack_keysize(int *keysize) 329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(keysize != NULL); 331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (*keysize < 10) { 332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_KEYSIZE; 333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else if (*keysize > 10) { 334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *keysize = 10; 335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_OK; 337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/skipjack.c,v $ */ 342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.12 $ */ 343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/11/08 23:01:06 $ */ 344