1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis 2 * 3 * LibTomCrypt is a library that provides various cryptographic 4 * algorithms in a highly modular and flexible manner. 5 * 6 * The library is free for all purposes without any express 7 * guarantee it works. 8 * 9 * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com 10 */ 11 12 /** 13 @file xtea.c 14 Implementation of XTEA, Tom St Denis 15 */ 16 #include "tomcrypt.h" 17 18 #ifdef XTEA 19 20 const struct ltc_cipher_descriptor xtea_desc = 21 { 22 "xtea", 23 1, 24 16, 16, 8, 32, 25 &xtea_setup, 26 &xtea_ecb_encrypt, 27 &xtea_ecb_decrypt, 28 &xtea_test, 29 &xtea_done, 30 &xtea_keysize, 31 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 32 }; 33 34 int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) 35 { 36 unsigned long x, sum, K[4]; 37 38 LTC_ARGCHK(key != NULL); 39 LTC_ARGCHK(skey != NULL); 40 41 /* check arguments */ 42 if (keylen != 16) { 43 return CRYPT_INVALID_KEYSIZE; 44 } 45 46 if (num_rounds != 0 && num_rounds != 32) { 47 return CRYPT_INVALID_ROUNDS; 48 } 49 50 /* load key */ 51 LOAD32L(K[0], key+0); 52 LOAD32L(K[1], key+4); 53 LOAD32L(K[2], key+8); 54 LOAD32L(K[3], key+12); 55 56 for (x = sum = 0; x < 32; x++) { 57 skey->xtea.A[x] = (sum + K[sum&3]) & 0xFFFFFFFFUL; 58 sum = (sum + 0x9E3779B9UL) & 0xFFFFFFFFUL; 59 skey->xtea.B[x] = (sum + K[(sum>>11)&3]) & 0xFFFFFFFFUL; 60 } 61 62 #ifdef LTC_CLEAN_STACK 63 zeromem(&K, sizeof(K)); 64 #endif 65 66 return CRYPT_OK; 67 } 68 69 /** 70 Encrypts a block of text with XTEA 71 @param pt The input plaintext (8 bytes) 72 @param ct The output ciphertext (8 bytes) 73 @param skey The key as scheduled 74 @return CRYPT_OK if successful 75 */ 76 int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 77 { 78 unsigned long y, z; 79 int r; 80 81 LTC_ARGCHK(pt != NULL); 82 LTC_ARGCHK(ct != NULL); 83 LTC_ARGCHK(skey != NULL); 84 85 LOAD32L(y, &pt[0]); 86 LOAD32L(z, &pt[4]); 87 for (r = 0; r < 32; r += 4) { 88 y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; 89 z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; 90 91 y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+1])) & 0xFFFFFFFFUL; 92 z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+1])) & 0xFFFFFFFFUL; 93 94 y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+2])) & 0xFFFFFFFFUL; 95 z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+2])) & 0xFFFFFFFFUL; 96 97 y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+3])) & 0xFFFFFFFFUL; 98 z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+3])) & 0xFFFFFFFFUL; 99 } 100 STORE32L(y, &ct[0]); 101 STORE32L(z, &ct[4]); 102 return CRYPT_OK; 103 } 104 105 /** 106 Decrypts a block of text with XTEA 107 @param ct The input ciphertext (8 bytes) 108 @param pt The output plaintext (8 bytes) 109 @param skey The key as scheduled 110 @return CRYPT_OK if successful 111 */ 112 int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 113 { 114 unsigned long y, z; 115 int r; 116 117 LTC_ARGCHK(pt != NULL); 118 LTC_ARGCHK(ct != NULL); 119 LTC_ARGCHK(skey != NULL); 120 121 LOAD32L(y, &ct[0]); 122 LOAD32L(z, &ct[4]); 123 for (r = 31; r >= 0; r -= 4) { 124 z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; 125 y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; 126 127 z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-1])) & 0xFFFFFFFFUL; 128 y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-1])) & 0xFFFFFFFFUL; 129 130 z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-2])) & 0xFFFFFFFFUL; 131 y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-2])) & 0xFFFFFFFFUL; 132 133 z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-3])) & 0xFFFFFFFFUL; 134 y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-3])) & 0xFFFFFFFFUL; 135 } 136 STORE32L(y, &pt[0]); 137 STORE32L(z, &pt[4]); 138 return CRYPT_OK; 139 } 140 141 /** 142 Performs a self-test of the XTEA block cipher 143 @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled 144 */ 145 int xtea_test(void) 146 { 147 #ifndef LTC_TEST 148 return CRYPT_NOP; 149 #else 150 static const unsigned char key[16] = 151 { 0x78, 0x56, 0x34, 0x12, 0xf0, 0xcd, 0xcb, 0x9a, 152 0x48, 0x37, 0x26, 0x15, 0xc0, 0xbf, 0xae, 0x9d }; 153 static const unsigned char pt[8] = 154 { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; 155 static const unsigned char ct[8] = 156 { 0x75, 0xd7, 0xc5, 0xbf, 0xcf, 0x58, 0xc9, 0x3f }; 157 unsigned char tmp[2][8]; 158 symmetric_key skey; 159 int err, y; 160 161 if ((err = xtea_setup(key, 16, 0, &skey)) != CRYPT_OK) { 162 return err; 163 } 164 xtea_ecb_encrypt(pt, tmp[0], &skey); 165 xtea_ecb_decrypt(tmp[0], tmp[1], &skey); 166 167 if (XMEMCMP(tmp[0], ct, 8) != 0 || XMEMCMP(tmp[1], pt, 8) != 0) { 168 return CRYPT_FAIL_TESTVECTOR; 169 } 170 171 /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ 172 for (y = 0; y < 8; y++) tmp[0][y] = 0; 173 for (y = 0; y < 1000; y++) xtea_ecb_encrypt(tmp[0], tmp[0], &skey); 174 for (y = 0; y < 1000; y++) xtea_ecb_decrypt(tmp[0], tmp[0], &skey); 175 for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; 176 177 return CRYPT_OK; 178 #endif 179 } 180 181 /** Terminate the context 182 @param skey The scheduled key 183 */ 184 void xtea_done(symmetric_key *skey) 185 { 186 } 187 188 /** 189 Gets suitable key size 190 @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. 191 @return CRYPT_OK if the input key size is acceptable. 192 */ 193 int xtea_keysize(int *keysize) 194 { 195 LTC_ARGCHK(keysize != NULL); 196 if (*keysize < 16) { 197 return CRYPT_INVALID_KEYSIZE; 198 } 199 *keysize = 16; 200 return CRYPT_OK; 201 } 202 203 204 #endif 205 206 207 208 209 /* $Source: /cvs/libtom/libtomcrypt/src/ciphers/xtea.c,v $ */ 210 /* $Revision: 1.12 $ */ 211 /* $Date: 2006/11/08 23:01:06 $ */ 212