1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 /**
5 @file tea.c
6 Implementation of TEA, Steffen Jaeckel
7 */
8 #include "tomcrypt_private.h"
9
10 #ifdef LTC_TEA
11
12 const struct ltc_cipher_descriptor tea_desc =
13 {
14 "tea",
15 26,
16 16, 16, 8, 32,
17 &tea_setup,
18 &tea_ecb_encrypt,
19 &tea_ecb_decrypt,
20 &tea_test,
21 &tea_done,
22 &tea_keysize,
23 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
24 };
25
26 #define DELTA 0x9E3779B9uL
27 #define SUM 0xC6EF3720uL
28
tea_setup(const unsigned char * key,int keylen,int num_rounds,symmetric_key * skey)29 int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
30 {
31 LTC_ARGCHK(key != NULL);
32 LTC_ARGCHK(skey != NULL);
33
34 /* check arguments */
35 if (keylen != 16) {
36 return CRYPT_INVALID_KEYSIZE;
37 }
38
39 if (num_rounds != 0 && num_rounds != 32) {
40 return CRYPT_INVALID_ROUNDS;
41 }
42
43 /* load key */
44 LOAD32H(skey->tea.k[0], key+0);
45 LOAD32H(skey->tea.k[1], key+4);
46 LOAD32H(skey->tea.k[2], key+8);
47 LOAD32H(skey->tea.k[3], key+12);
48
49 return CRYPT_OK;
50 }
51
52 /**
53 Encrypts a block of text with TEA
54 @param pt The input plaintext (8 bytes)
55 @param ct The output ciphertext (8 bytes)
56 @param skey The key as scheduled
57 @return CRYPT_OK if successful
58 */
tea_ecb_encrypt(const unsigned char * pt,unsigned char * ct,const symmetric_key * skey)59 int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
60 {
61 ulong32 y, z, sum = 0;
62 const ulong32 delta = DELTA;
63 int r;
64
65 LTC_ARGCHK(pt != NULL);
66 LTC_ARGCHK(ct != NULL);
67 LTC_ARGCHK(skey != NULL);
68
69 LOAD32H(y, &pt[0]);
70 LOAD32H(z, &pt[4]);
71 for (r = 0; r < 32; r++) {
72 sum += delta;
73 y += ((z<<4) + skey->tea.k[0]) ^ (z + sum) ^ ((z>>5) + skey->tea.k[1]);
74 z += ((y<<4) + skey->tea.k[2]) ^ (y + sum) ^ ((y>>5) + skey->tea.k[3]);
75 }
76 STORE32H(y, &ct[0]);
77 STORE32H(z, &ct[4]);
78 return CRYPT_OK;
79 }
80
81 /**
82 Decrypts a block of text with TEA
83 @param ct The input ciphertext (8 bytes)
84 @param pt The output plaintext (8 bytes)
85 @param skey The key as scheduled
86 @return CRYPT_OK if successful
87 */
tea_ecb_decrypt(const unsigned char * ct,unsigned char * pt,const symmetric_key * skey)88 int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
89 {
90 ulong32 v0, v1, sum = SUM;
91 const ulong32 delta = DELTA;
92 int r;
93
94 LTC_ARGCHK(pt != NULL);
95 LTC_ARGCHK(ct != NULL);
96 LTC_ARGCHK(skey != NULL);
97
98 LOAD32H(v0, &ct[0]);
99 LOAD32H(v1, &ct[4]);
100
101 for (r = 0; r < 32; r++) {
102 v1 -= ((v0 << 4) + skey->tea.k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + skey->tea.k[3]);
103 v0 -= ((v1 << 4) + skey->tea.k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + skey->tea.k[1]);
104 sum -= delta;
105 }
106
107 STORE32H(v0, &pt[0]);
108 STORE32H(v1, &pt[4]);
109 return CRYPT_OK;
110 }
111
112 /**
113 Performs a self-test of the TEA block cipher
114 @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
115 */
tea_test(void)116 int tea_test(void)
117 {
118 #ifndef LTC_TEST
119 return CRYPT_NOP;
120 #else
121 static const struct {
122 const char *key, *pt, *ct;
123 } tests[] = {
124 {
125 "00000000000000000000000000000000",
126 "0000000000000000",
127 "41ea3a0a94baa940"
128 }, {
129 "32a1e65408b63bb9214105744ec5d2e2",
130 "5ada1d89a9c3801a",
131 "dd46249e28aa0b4b"
132 }, {
133 "60388adadf70a1f5d9cb4e097d2c6c57",
134 "7a6adb4d69c53e0f",
135 "44b71215cf25368a"
136 }, {
137 "4368d2249bd0321eb7c56d5b63a1bfac",
138 "5a5d7ca2e186c41a",
139 "91f56dff7281794f"
140 }, {
141 "5c60bff27072d01c4513c5eb8f3a38ab",
142 "80d9c4adcf899635",
143 "2bb0f1b3c023ed11"
144 }
145 };
146 unsigned char ptct[2][8];
147 unsigned char tmp[2][8];
148 unsigned char key[16];
149 unsigned long l;
150 symmetric_key skey;
151 size_t i;
152 int err, y;
153 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
154 zeromem(&skey, sizeof(skey));
155
156 l = sizeof(key);
157 if ((err = base16_decode(tests[i].key, XSTRLEN(tests[i].key), key, &l)) != CRYPT_OK) return err;
158 l = sizeof(ptct[0]);
159 if ((err = base16_decode(tests[i].pt, XSTRLEN(tests[i].pt), ptct[0], &l)) != CRYPT_OK) return err;
160 l = sizeof(ptct[1]);
161 if ((err = base16_decode(tests[i].ct, XSTRLEN(tests[i].ct), ptct[1], &l)) != CRYPT_OK) return err;
162
163 if ((err = tea_setup(key, 16, 0, &skey)) != CRYPT_OK) {
164 return err;
165 }
166 tea_ecb_encrypt(ptct[0], tmp[0], &skey);
167 tea_ecb_decrypt(tmp[0], tmp[1], &skey);
168
169 if (compare_testvector(tmp[0], 8, ptct[1], 8, "TEA Encrypt", i) != 0 ||
170 compare_testvector(tmp[1], 8, ptct[0], 8, "TEA Decrypt", i) != 0) {
171 return CRYPT_FAIL_TESTVECTOR;
172 }
173
174 /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
175 for (y = 0; y < 8; y++) tmp[0][y] = 0;
176 for (y = 0; y < 1000; y++) tea_ecb_encrypt(tmp[0], tmp[0], &skey);
177 for (y = 0; y < 1000; y++) tea_ecb_decrypt(tmp[0], tmp[0], &skey);
178 for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
179 } /* for */
180
181 return CRYPT_OK;
182 #endif
183 }
184
185 /** Terminate the context
186 @param skey The scheduled key
187 */
tea_done(symmetric_key * skey)188 void tea_done(symmetric_key *skey)
189 {
190 LTC_UNUSED_PARAM(skey);
191 }
192
193 /**
194 Gets suitable key size
195 @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
196 @return CRYPT_OK if the input key size is acceptable.
197 */
tea_keysize(int * keysize)198 int tea_keysize(int *keysize)
199 {
200 LTC_ARGCHK(keysize != NULL);
201 if (*keysize < 16) {
202 return CRYPT_INVALID_KEYSIZE;
203 }
204 *keysize = 16;
205 return CRYPT_OK;
206 }
207
208 #endif
209
210