Coverage Report

Created: 2024-11-21 07:03

/src/libtomcrypt/src/ciphers/xtea.c
Line
Count
Source (jump to first uncovered line)
1
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2
/* SPDX-License-Identifier: Unlicense */
3
4
/**
5
  @file xtea.c
6
  Implementation of eXtended TEA, Tom St Denis
7
*/
8
#include "tomcrypt_private.h"
9
10
#ifdef LTC_XTEA
11
12
const struct ltc_cipher_descriptor xtea_desc =
13
{
14
    "xtea",
15
    1,
16
    16, 16, 8, 32,
17
    &xtea_setup,
18
    &xtea_ecb_encrypt,
19
    &xtea_ecb_decrypt,
20
    &xtea_test,
21
    &xtea_done,
22
    &xtea_keysize,
23
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
24
};
25
26
int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
27
2
{
28
2
   ulong32 x, sum, K[4];
29
30
2
   LTC_ARGCHK(key != NULL);
31
2
   LTC_ARGCHK(skey != NULL);
32
33
   /* check arguments */
34
2
   if (keylen != 16) {
35
2
      return CRYPT_INVALID_KEYSIZE;
36
2
   }
37
38
0
   if (num_rounds != 0 && num_rounds != 32) {
39
0
      return CRYPT_INVALID_ROUNDS;
40
0
   }
41
42
   /* load key */
43
0
   LOAD32H(K[0], key+0);
44
0
   LOAD32H(K[1], key+4);
45
0
   LOAD32H(K[2], key+8);
46
0
   LOAD32H(K[3], key+12);
47
48
0
   for (x = sum = 0; x < 32; x++) {
49
0
       skey->xtea.A[x] = (sum + K[sum&3]) & 0xFFFFFFFFUL;
50
0
       sum = (sum + 0x9E3779B9UL) & 0xFFFFFFFFUL;
51
0
       skey->xtea.B[x] = (sum + K[(sum>>11)&3]) & 0xFFFFFFFFUL;
52
0
   }
53
54
#ifdef LTC_CLEAN_STACK
55
   zeromem(&K, sizeof(K));
56
#endif
57
58
0
   return CRYPT_OK;
59
0
}
60
61
/**
62
  Encrypts a block of text with LTC_XTEA
63
  @param pt The input plaintext (8 bytes)
64
  @param ct The output ciphertext (8 bytes)
65
  @param skey The key as scheduled
66
  @return CRYPT_OK if successful
67
*/
68
int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
69
0
{
70
0
   ulong32 y, z;
71
0
   int r;
72
73
0
   LTC_ARGCHK(pt   != NULL);
74
0
   LTC_ARGCHK(ct   != NULL);
75
0
   LTC_ARGCHK(skey != NULL);
76
77
0
   LOAD32H(y, &pt[0]);
78
0
   LOAD32H(z, &pt[4]);
79
0
   for (r = 0; r < 32; r += 4) {
80
0
       y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL;
81
0
       z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL;
82
83
0
       y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+1])) & 0xFFFFFFFFUL;
84
0
       z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+1])) & 0xFFFFFFFFUL;
85
86
0
       y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+2])) & 0xFFFFFFFFUL;
87
0
       z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+2])) & 0xFFFFFFFFUL;
88
89
0
       y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+3])) & 0xFFFFFFFFUL;
90
0
       z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+3])) & 0xFFFFFFFFUL;
91
0
   }
92
0
   STORE32H(y, &ct[0]);
93
0
   STORE32H(z, &ct[4]);
94
0
   return CRYPT_OK;
95
0
}
96
97
/**
98
  Decrypts a block of text with LTC_XTEA
99
  @param ct The input ciphertext (8 bytes)
100
  @param pt The output plaintext (8 bytes)
101
  @param skey The key as scheduled
102
  @return CRYPT_OK if successful
103
*/
104
int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
105
0
{
106
0
   ulong32 y, z;
107
0
   int r;
108
109
0
   LTC_ARGCHK(pt   != NULL);
110
0
   LTC_ARGCHK(ct   != NULL);
111
0
   LTC_ARGCHK(skey != NULL);
112
113
0
   LOAD32H(y, &ct[0]);
114
0
   LOAD32H(z, &ct[4]);
115
0
   for (r = 31; r >= 0; r -= 4) {
116
0
       z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL;
117
0
       y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL;
118
119
0
       z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-1])) & 0xFFFFFFFFUL;
120
0
       y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-1])) & 0xFFFFFFFFUL;
121
122
0
       z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-2])) & 0xFFFFFFFFUL;
123
0
       y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-2])) & 0xFFFFFFFFUL;
124
125
0
       z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-3])) & 0xFFFFFFFFUL;
126
0
       y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-3])) & 0xFFFFFFFFUL;
127
0
   }
128
0
   STORE32H(y, &pt[0]);
129
0
   STORE32H(z, &pt[4]);
130
0
   return CRYPT_OK;
131
0
}
132
133
/**
134
  Performs a self-test of the LTC_XTEA block cipher
135
  @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
136
*/
137
int xtea_test(void)
138
0
{
139
 #ifndef LTC_TEST
140
    return CRYPT_NOP;
141
 #else
142
0
    static const struct {
143
0
        unsigned char key[16], pt[8], ct[8];
144
0
    } tests[] = {
145
0
       {
146
0
         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147
0
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
148
0
         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
149
0
         { 0xde, 0xe9, 0xd4, 0xd8, 0xf7, 0x13, 0x1e, 0xd9 }
150
0
       }, {
151
0
         { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
152
0
           0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04 },
153
0
         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
154
0
         { 0xa5, 0x97, 0xab, 0x41, 0x76, 0x01, 0x4d, 0x72 }
155
0
       }, {
156
0
         { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04,
157
0
           0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06 },
158
0
         { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 },
159
0
         { 0xb1, 0xfd, 0x5d, 0xa9, 0xcc, 0x6d, 0xc9, 0xdc }
160
0
       }, {
161
0
         { 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
162
0
           0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
163
0
         { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
164
0
         { 0x70, 0x4b, 0x31, 0x34, 0x47, 0x44, 0xdf, 0xab }
165
0
       }, {
166
0
         { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
167
0
           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
168
0
         { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
169
0
         { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }
170
0
       }, {
171
0
         { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
172
0
           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
173
0
         { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
174
0
         { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }
175
0
       }, {
176
0
         { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
177
0
           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
178
0
         { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
179
0
         { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
180
0
       }, {
181
0
         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182
0
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
183
0
         { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
184
0
         { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }
185
0
       }, {
186
0
         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187
0
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
188
0
         { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
189
0
         { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }
190
0
       }, {
191
0
         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192
0
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
193
0
         { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 },
194
0
         { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
195
0
       }
196
0
    };
197
0
   unsigned char tmp[2][8];
198
0
   symmetric_key skey;
199
0
   int i, err, y;
200
0
   for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
201
0
       zeromem(&skey, sizeof(skey));
202
0
       if ((err = xtea_setup(tests[i].key, 16, 0, &skey)) != CRYPT_OK)  {
203
0
          return err;
204
0
       }
205
0
       xtea_ecb_encrypt(tests[i].pt, tmp[0], &skey);
206
0
       xtea_ecb_decrypt(tmp[0], tmp[1], &skey);
207
208
0
       if (compare_testvector(tmp[0], 8, tests[i].ct, 8, "XTEA Encrypt", i) != 0 ||
209
0
             compare_testvector(tmp[1], 8, tests[i].pt, 8, "XTEA Decrypt", i) != 0) {
210
0
          return CRYPT_FAIL_TESTVECTOR;
211
0
       }
212
213
      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
214
0
      for (y = 0; y < 8; y++) tmp[0][y] = 0;
215
0
      for (y = 0; y < 1000; y++) xtea_ecb_encrypt(tmp[0], tmp[0], &skey);
216
0
      for (y = 0; y < 1000; y++) xtea_ecb_decrypt(tmp[0], tmp[0], &skey);
217
0
      for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
218
0
   } /* for */
219
220
0
   return CRYPT_OK;
221
0
 #endif
222
0
}
223
224
/** Terminate the context
225
   @param skey    The scheduled key
226
*/
227
void xtea_done(symmetric_key *skey)
228
0
{
229
0
  LTC_UNUSED_PARAM(skey);
230
0
}
231
232
/**
233
  Gets suitable key size
234
  @param keysize [in/out] The length of the recommended key (in bytes).  This function will store the suitable size back in this variable.
235
  @return CRYPT_OK if the input key size is acceptable.
236
*/
237
int xtea_keysize(int *keysize)
238
0
{
239
0
   LTC_ARGCHK(keysize != NULL);
240
0
   if (*keysize < 16) {
241
0
      return CRYPT_INVALID_KEYSIZE;
242
0
   }
243
0
   *keysize = 16;
244
0
   return CRYPT_OK;
245
0
}
246
247
248
#endif
249
250
251